feat: Add ICAOEQ capability to FSD client

This commit is contained in:
Lars Toenning
2023-12-27 21:51:08 +01:00
parent cdd4690adf
commit 23e2dc9057
20 changed files with 817 additions and 964 deletions

View File

@@ -283,7 +283,7 @@ namespace BlackCore::Context
}
m_fsdClient->setClientIdAndKey(static_cast<quint16>(clientId), clientKey.toLocal8Bit());
m_fsdClient->setClientCapabilities(Capabilities::AircraftInfo | Capabilities::FastPos | Capabilities::VisPos | Capabilities::AtcInfo | Capabilities::AircraftConfig);
m_fsdClient->setClientCapabilities(Capabilities::AircraftInfo | Capabilities::FastPos | Capabilities::VisPos | Capabilities::AtcInfo | Capabilities::AircraftConfig | Capabilities::IcaoEquipment);
m_fsdClient->setServer(server);
m_fsdClient->setPilotRating(PilotRating::Student);

View File

@@ -208,6 +208,12 @@ namespace BlackCore::Data
//! NCEP GFS Forecasts (0.25 degree grid) data url
BlackMisc::Network::CUrl getNcepGlobalForecastSystemUrl25() const { return m_ncepGlobalForecastSystemUrl25; }
//! COM/NAV equipment code help URL
BlackMisc::Network::CUrl getComNavEquipmentHelpUrl() const { return m_comNavEquipmentHelpUrl; }
//! SSR equipment code help URL
BlackMisc::Network::CUrl getSsrEquipmentHelpUrl() const { return m_ssrEquipmentHelpUrl; }
//! \copydoc BlackMisc::Mixin::String::toQString
QString convertToQString(bool i18n = false) const;
@@ -252,6 +258,8 @@ namespace BlackCore::Data
BlackMisc::Network::CServerList m_predefinedServers; //!< Predefined servers loaded from setup file
BlackMisc::Network::CUrl m_ncepGlobalForecastSystemUrl; //!< NCEP GFS url 0.5 degree resolution
BlackMisc::Network::CUrl m_ncepGlobalForecastSystemUrl25; //!< NCEP GFS url 0.25 degree resolution
BlackMisc::Network::CUrl m_comNavEquipmentHelpUrl; //!< Help URL for COM/NAV equipment codes
BlackMisc::Network::CUrl m_ssrEquipmentHelpUrl; //!< Help URL for SSR equipment codes
// transient members, to be switched on/off via GUI or set from reader
bool m_dbDebugFlag = false; //!< can trigger DEBUG on the server, so you need to know what you are doing
@@ -281,6 +289,8 @@ namespace BlackCore::Data
BLACK_METAMEMBER(mappingMinimumVersion),
BLACK_METAMEMBER(ncepGlobalForecastSystemUrl),
BLACK_METAMEMBER(ncepGlobalForecastSystemUrl25),
BLACK_METAMEMBER(comNavEquipmentHelpUrl),
BLACK_METAMEMBER(ssrEquipmentHelpUrl),
BLACK_METAMEMBER(dbDebugFlag, BlackMisc::DisabledForJson)
);
};

View File

@@ -168,7 +168,10 @@ namespace BlackCore::Fsd
Stealth = (1 << 8),
/*! Aircraft Config */
AircraftConfig = (1 << 9)
AircraftConfig = (1 << 9),
/*! Process aircraft ICAO in flightplan as ICAO equipment code (e.g. B737/M-SDE2E3FGHIRWXY/LB1) */
IcaoEquipment = (1 << 10)
};
//! @{

View File

@@ -33,7 +33,7 @@ namespace BlackCore::Fsd
//! @{
//! Properties
FlightType m_flightType {};
QString m_aircraftIcaoType;
QString m_aircraftIcaoType; //!< Contains the full equipment string in FAA or ICAO format, depending on the server
int m_trueCruisingSpeed = 0;
QString m_depAirport;
int m_estimatedDepTime = 0;

View File

@@ -706,11 +706,21 @@ namespace BlackCore::Fsd
const QString alt = flightPlan.getCruiseAltitude().asFpVatsimAltitudeString();
// const QString alt = flightPlan.getCruiseAltitude().asFpAltitudeString();
QString act = flightPlan.getCombinedPrefixIcaoSuffix();
if (act.isEmpty()) { act = flightPlan.getAircraftIcao().getDesignator(); } // fallback
FlightType flightType = getFlightType(flightPlan.getFlightRules());
QString act;
if (m_server.getFsdSetup().shouldSendFlightPlanEquipmentInIcaoFormat())
{
act = flightPlan.getAircraftInfo().asIcaoString();
}
else
{
act = flightPlan.getAircraftInfo().asFaaString();
}
Q_ASSERT_X(!act.isEmpty(), Q_FUNC_INFO, "Aircraft type must not be empty");
const QList<int> timePartsEnroute = flightPlan.getEnrouteTime().getHrsMinSecParts();
const QList<int> timePartsFuel = flightPlan.getFuelTime().getHrsMinSecParts();
const FlightPlan fp(getOwnCallsignAsString(), "SERVER", flightType, act,
@@ -909,6 +919,7 @@ namespace BlackCore::Fsd
if (m_capabilities & Capabilities::VisPos) responseData.push_back(toQString(Capabilities::VisPos) % "=1");
if (m_capabilities & Capabilities::Stealth) responseData.push_back(toQString(Capabilities::Stealth) % "=1");
if (m_capabilities & Capabilities::AircraftConfig) responseData.push_back(toQString(Capabilities::AircraftConfig) % "=1");
if (m_capabilities & Capabilities::IcaoEquipment) responseData.push_back(toQString(Capabilities::IcaoEquipment) % "=1");
const ClientResponse clientResponse(ownCallsign, receiver, ClientQueryType::Capabilities, responseData);
sendQueudedMessage(clientResponse);
}
@@ -1382,7 +1393,7 @@ namespace BlackCore::Fsd
const CCallsign callsign(fp.sender(), CCallsign::Aircraft);
const CFlightPlan flightPlan(
callsign,
fp.m_aircraftIcaoType,
CFlightPlanAircraftInfo(fp.m_aircraftIcaoType),
fp.m_depAirport,
fp.m_destAirport,
fp.m_altAirport,

View File

@@ -453,6 +453,7 @@ namespace BlackCore::Fsd
case Capabilities::FastPos: return "FASTPOS";
case Capabilities::Stealth: return "STEALTH";
case Capabilities::AircraftConfig: return "ACCONFIG";
case Capabilities::IcaoEquipment: return "ICAOEQ";
}
return {};
@@ -479,6 +480,8 @@ namespace BlackCore::Fsd
return Capabilities::Stealth;
else if (str == "ACCONFIG")
return Capabilities::AircraftConfig;
else if (str == "ICAOEQ")
return Capabilities::IcaoEquipment;
return Capabilities::None;
}

View File

@@ -305,11 +305,11 @@ namespace BlackCore::Vatsim
const CSpeed groundspeed(pilot["groundspeed"].toInt(), CSpeedUnit::kts());
const CAircraftSituation situation(callsign, position, heading, {}, {}, groundspeed);
CSimulatedAircraft aircraft(callsign, user, situation);
const QString icaoAndEquipment(pilot["flight_plan"]["aircraft"].toString().trimmed());
const QString icao(CFlightPlan::aircraftIcaoCodeFromEquipmentCode(icaoAndEquipment));
if (CAircraftIcaoCode::isValidDesignator(icao))
const QString icaoAndEquipment(pilot["flight_plan"]["aircraft"].toString().trimmed()); // in ICAO format
CFlightPlanAircraftInfo info(icaoAndEquipment);
if (info.getAircraftIcao().hasValidDesignator())
{
aircraft.setAircraftIcaoCode(icao);
aircraft.setAircraftIcaoCode(info.getAircraftIcao());
}
else if (!icaoAndEquipment.isEmpty())
{

View File

@@ -35,6 +35,7 @@
#include <QCheckBox>
#include <QComboBox>
#include <QDateTime>
#include <QDesktopServices>
#include <QLabel>
#include <QLineEdit>
#include <QPlainTextEdit>
@@ -48,6 +49,7 @@
#include <QFile>
#include <QMessageBox>
#include <Qt>
#include <QWidgetAction>
using namespace BlackMisc;
using namespace BlackMisc::Aviation;
@@ -70,6 +72,12 @@ namespace BlackGui::Components
ui->setupUi(this);
this->setCurrentIndex(0);
// Initialize wake turbulence category selection
for (const WakeTurbulenceEntry &item : std::as_const(m_wakeTurbulenceCategories))
{
ui->cb_Wtc->addItem(item.m_name);
}
// fix style
this->tabBar()->setExpanding(false);
this->tabBar()->setUsesScrollButtons(true);
@@ -80,6 +88,9 @@ namespace BlackGui::Components
this->setForceSmall(true);
this->showKillButton(false);
setupNavComContextMenu();
setupSsrContextMenu();
// rules
ui->cb_FlightRule->clear();
ui->cb_FlightRule->addItems(CFlightPlan::flightRules());
@@ -93,15 +104,8 @@ namespace BlackGui::Components
ui->le_AirlineOperator->setValidator(new CUpperCaseValidator(ui->le_AirlineOperator));
ui->le_AircraftRegistration->setValidator(new CUpperCaseValidator(ui->le_AircraftRegistration));
CUpperCaseValidator *ucv = new CUpperCaseValidator(true, 0, 1, ui->le_EquipmentSuffix);
ucv->setRestrictions(CFlightPlan::equipmentCodes());
ui->le_EquipmentSuffix->setValidator(ucv);
ui->le_EquipmentSuffix->setToolTip(ui->tbr_EquipmentCodes->toHtml());
QCompleter *completer = new QCompleter(CFlightPlan::equipmentCodesInfo(), ui->le_EquipmentSuffix);
completer->setMaxVisibleItems(10);
completer->popup()->setMinimumWidth(225);
completer->setCompletionMode(QCompleter::PopupCompletion);
ui->le_EquipmentSuffix->setCompleter(completer);
ui->le_NavComEquipment->setReadOnly(true);
ui->le_SsrEquipment->setReadOnly(true);
CUpperCaseEventFilter *ef = new CUpperCaseEventFilter(ui->pte_Route);
ef->setOnlyAscii();
@@ -151,13 +155,19 @@ namespace BlackGui::Components
connect(ui->pb_GetFromGenerator, &QPushButton::pressed, this, &CFlightPlanComponent::copyRemarksConfirmed, Qt::QueuedConnection);
connect(ui->pb_RemarksGenerator, &QPushButton::clicked, this, &CFlightPlanComponent::currentTabGenerator, Qt::QueuedConnection);
connect(ui->tb_HelpEquipment, &QToolButton::clicked, this, &CFlightPlanComponent::showEquipmentCodesTab, Qt::QueuedConnection);
connect(
ui->tb_EditNavComEquipment, &QToolButton::clicked, this, [this]() { m_navComEquipmentMenu->popup(QCursor::pos()); }, Qt::QueuedConnection);
connect(
ui->tb_NavComHelp, &QToolButton::clicked, this, []() { QDesktopServices::openUrl(sGui->getGlobalSetup().getComNavEquipmentHelpUrl()); }, Qt::QueuedConnection);
connect(
ui->tb_EditSsrEquipment, &QToolButton::clicked, this, [this]() { m_ssrEquipmentMenu->popup(QCursor::pos()); }, Qt::QueuedConnection);
connect(
ui->tb_SsrHelp, &QToolButton::clicked, this, []() { QDesktopServices::openUrl(sGui->getGlobalSetup().getSsrEquipmentHelpUrl()); }, Qt::QueuedConnection);
connect(ui->tb_AltitudeDialog, &QToolButton::clicked, this, &CFlightPlanComponent::altitudeDialog, Qt::QueuedConnection);
connect(ui->le_AircraftType, &QLineEdit::editingFinished, this, &CFlightPlanComponent::aircraftTypeChanged, Qt::QueuedConnection);
connect(ui->le_EquipmentSuffix, &QLineEdit::editingFinished, this, &CFlightPlanComponent::buildPrefixIcaoSuffix, Qt::QueuedConnection);
connect(ui->cb_Heavy, &QCheckBox::released, this, &CFlightPlanComponent::prefixCheckBoxChanged, Qt::QueuedConnection);
connect(ui->cb_Tcas, &QCheckBox::released, this, &CFlightPlanComponent::prefixCheckBoxChanged, Qt::QueuedConnection);
connect(ui->pb_Remarks, &QPushButton::pressed, this, &CFlightPlanComponent::remarksHistory, Qt::QueuedConnection);
connect(ui->pb_AddRemarks, &QPushButton::pressed, this, &CFlightPlanComponent::remarksHistory, Qt::QueuedConnection);
@@ -225,13 +235,10 @@ namespace BlackGui::Components
if (aircraft.getAircraftIcaoCode().isLoadedFromDb() && aircraft.getAircraftIcaoCode().hasValidWtc())
{
const QString wtc = toSingleLetterCode(aircraft.getAircraftIcaoCode().getWtc());
const bool heavyFlag = (wtc.startsWith("H", Qt::CaseInsensitive) || wtc.startsWith("S", Qt::CaseInsensitive));
ui->cb_Heavy->setChecked(heavyFlag);
updateWakeTurbulenceCategorySelector(aircraft.getAircraftIcaoCode().getWtc());
}
this->prefillWithUserData(aircraft.getPilot());
this->buildPrefixIcaoSuffix();
}
void CFlightPlanComponent::prefillWithUserData(const CUser &user)
@@ -276,7 +283,7 @@ namespace BlackGui::Components
else if (flightPlan.getFlightRules() == CFlightPlan::UNKNOWN)
{
ui->cb_FlightRule->setCurrentText(CFlightPlan::flightRulesToString(CFlightPlan::IFR));
const CStatusMessage m = CStatusMessage(this).validationWarning(u"Unknown fligh rule, setting to default");
const CStatusMessage m = CStatusMessage(this).validationWarning(u"Unknown flight rule, setting to default");
this->showOverlayMessage(m);
}
@@ -285,6 +292,14 @@ namespace BlackGui::Components
const QString rem = flightPlan.getRemarks();
this->setRemarksUIValues(rem);
}
updateWakeTurbulenceCategorySelector(flightPlan.getAircraftInfo().getWtc());
m_navComEquipment = flightPlan.getAircraftInfo().getComNavEquipment();
updateNavComEquipmentUi();
m_ssrEquipment = flightPlan.getAircraftInfo().getSsrEquipment();
updateSsrEquipmentUi();
}
const QStringList &CFlightPlanComponent::getLogCategories()
@@ -331,22 +346,9 @@ namespace BlackGui::Components
{
messages.push_back(CStatusMessage(this).validationWarning(u"Are you sure '%1' is a valid type?") << v);
}
flightPlan.setAircraftIcao(this->getAircraftIcaoCode());
// prefix / equipment code
v = this->getPrefix();
if (!v.isEmpty() && !CFlightPlan::prefixCodes().contains(v))
{
messages.push_back(CStatusMessage(this).validation(severity, u"Invalid prefix"));
}
flightPlan.setPrefix(v);
v = this->getEquipmentSuffix();
if (!v.isEmpty() && !CFlightPlan::equipmentCodes().contains(v))
{
messages.push_back(CStatusMessage(this).validation(severity, u"Invalid equipment code"));
}
flightPlan.setEquipmentSuffix(v);
CFlightPlanAircraftInfo info(this->getAircraftIcaoCode(), m_navComEquipment, m_ssrEquipment, getSelectedWakeTurbulenceCategory());
flightPlan.setAircraftInfo(info);
// route
v = ui->pte_Route->toPlainText().trimmed();
@@ -781,43 +783,6 @@ namespace BlackGui::Components
this->initCompleters();
}
void CFlightPlanComponent::buildPrefixIcaoSuffix()
{
ui->le_PrefixIcaoSuffix->setText(this->getCombinedPrefixIcaoSuffix());
}
void CFlightPlanComponent::prefixCheckBoxChanged()
{
QObject *sender = QObject::sender();
if (sender == ui->cb_Heavy)
{
if (ui->cb_Heavy->isChecked())
{
const QPointer<CFlightPlanComponent> myself(this);
QTimer::singleShot(10, this, [=] {
if (!myself) { return; }
ui->cb_Tcas->setChecked(false);
this->buildPrefixIcaoSuffix();
});
return;
}
}
else if (sender == ui->cb_Tcas)
{
if (ui->cb_Tcas->isChecked())
{
const QPointer<CFlightPlanComponent> myself(this);
QTimer::singleShot(10, this, [=] {
if (!myself) { return; }
ui->cb_Heavy->setChecked(false);
this->buildPrefixIcaoSuffix();
});
return;
}
}
this->buildPrefixIcaoSuffix();
}
void CFlightPlanComponent::aircraftTypeChanged()
{
const CAircraftIcaoCode icao = this->getAircraftIcaoCode();
@@ -825,10 +790,7 @@ namespace BlackGui::Components
QPointer<CFlightPlanComponent> myself(this);
QTimer::singleShot(25, this, [=] {
if (!myself || !sGui || sGui->isShuttingDown()) { return; }
const bool heavy = icao.getWtc() == BlackMisc::Aviation::WakeTurbulenceCategory::HEAVY;
ui->cb_Heavy->setChecked(heavy);
if (heavy) { ui->cb_Tcas->setChecked(false); }
this->buildPrefixIcaoSuffix();
updateWakeTurbulenceCategorySelector(icao.getWtc());
});
}
@@ -842,13 +804,6 @@ namespace BlackGui::Components
this->prefillWithAircraftData(aircraft, true);
}
QString CFlightPlanComponent::getPrefix() const
{
if (ui->cb_Heavy->isChecked()) { return QStringLiteral("H"); }
else if (ui->cb_Tcas->isChecked()) { return QStringLiteral("T"); }
return {};
}
CAircraftIcaoCode CFlightPlanComponent::getAircraftIcaoCode() const
{
const QString designator(ui->le_AircraftType->text());
@@ -861,21 +816,6 @@ namespace BlackGui::Components
return designator;
}
QString CFlightPlanComponent::getEquipmentSuffix() const
{
return ui->le_EquipmentSuffix->text().trimmed().toUpper();
}
QString CFlightPlanComponent::getCombinedPrefixIcaoSuffix() const
{
return CFlightPlan::concatPrefixIcaoSuffix(this->getPrefix(), this->getAircraftIcaoCode().getDesignator(), this->getEquipmentSuffix());
}
void CFlightPlanComponent::showEquipmentCodesTab()
{
this->setCurrentWidget(ui->tb_EquipmentCodes);
}
bool CFlightPlanComponent::isVfr() const
{
const bool vfr = CFlightPlan::isVFRRules(ui->cb_FlightRule->currentText());
@@ -1093,6 +1033,118 @@ namespace BlackGui::Components
}
}
void CFlightPlanComponent::setupNavComContextMenu()
{
m_navComEquipmentMenu = new QMenu(ui->tb_EditNavComEquipment);
auto list = new QListWidget(m_navComEquipmentMenu);
list->setSelectionMode(QAbstractItemView::MultiSelection);
list->addItems(BlackMisc::Aviation::CComNavEquipment::allEquipmentLetters());
connect(list, &QListWidget::itemSelectionChanged, this, &CFlightPlanComponent::updateNavComEquipmentFromSelection);
auto action = new QWidgetAction(ui->tb_EditNavComEquipment);
action->setDefaultWidget(list);
m_navComEquipmentMenu->addAction(action);
updateNavComEquipmentUi();
}
void CFlightPlanComponent::setupSsrContextMenu()
{
m_ssrEquipmentMenu = new QMenu(ui->tb_EditSsrEquipment);
auto list = new QListWidget(m_ssrEquipmentMenu);
list->setSelectionMode(QAbstractItemView::MultiSelection);
list->addItems(BlackMisc::Aviation::CSsrEquipment::allEquipmentLetters());
connect(list, &QListWidget::itemSelectionChanged, this, &CFlightPlanComponent::updateSsrEquipmentFromSelection);
auto action = new QWidgetAction(ui->tb_EditSsrEquipment);
action->setDefaultWidget(list);
m_ssrEquipmentMenu->addAction(action);
updateSsrEquipmentUi();
}
void CFlightPlanComponent::updateNavComEquipmentFromSelection()
{
const QListWidget *list = getMenuEquipmentList(m_navComEquipmentMenu);
QString equipmentString;
for (auto equipment : list->selectedItems())
{
equipmentString.append(equipment->text());
}
m_navComEquipment = CComNavEquipment(equipmentString);
updateNavComEquipmentUi();
}
void CFlightPlanComponent::updateSsrEquipmentFromSelection()
{
const QListWidget *list = getMenuEquipmentList(m_ssrEquipmentMenu);
QString ssrEquipmentString;
for (auto equipment : list->selectedItems())
{
ssrEquipmentString.append(equipment->text());
}
m_ssrEquipment = CSsrEquipment(ssrEquipmentString);
updateSsrEquipmentUi();
}
QListWidget *CFlightPlanComponent::getMenuEquipmentList(QMenu *menu)
{
Q_ASSERT_X(menu->actions().size() == 1, Q_FUNC_INFO, "should only contain a single action");
const QWidgetAction *action = qobject_cast<QWidgetAction *>(menu->actions().at(0));
Q_ASSERT_X(action, Q_FUNC_INFO, "equipment menu contains invalid action item");
auto list = qobject_cast<QListWidget *>(action->defaultWidget());
Q_ASSERT_X(list, Q_FUNC_INFO, "Action widget contains invalid widget");
return list;
}
void CFlightPlanComponent::updateSsrEquipmentUi()
{
ui->le_SsrEquipment->setText(m_ssrEquipment.toQString());
updateListSelection(m_ssrEquipmentMenu, m_ssrEquipment.enabledOptions());
}
void CFlightPlanComponent::updateNavComEquipmentUi()
{
ui->le_NavComEquipment->setText(m_navComEquipment.toQString());
updateListSelection(m_navComEquipmentMenu, m_navComEquipment.enabledOptions());
}
void CFlightPlanComponent::updateListSelection(QMenu *menu, const QStringList &enabledOptions)
{
QListWidget *list = getMenuEquipmentList(menu);
list->blockSignals(true);
list->clearSelection();
for (const auto &enabledOption : enabledOptions)
{
auto item = list->findItems(enabledOption, Qt::MatchExactly);
Q_ASSERT_X(item.size() == 1, Q_FUNC_INFO, "Expected exactly one item per option");
list->setItemSelected(item[0], true);
}
list->blockSignals(false);
}
void CFlightPlanComponent::updateWakeTurbulenceCategorySelector(const BlackMisc::Aviation::CWakeTurbulenceCategory &wtc)
{
if (wtc.isUnknown()) return; // Unknown should not be shown to the user
const auto it = std::find_if(m_wakeTurbulenceCategories.cbegin(), m_wakeTurbulenceCategories.cend(), [&wtc](const WakeTurbulenceEntry &item) { return item.m_wtc == wtc; });
Q_ASSERT_X(it != m_wakeTurbulenceCategories.cend(), Q_FUNC_INFO, "Invalid wake turbulence category selected");
const int newIndex = static_cast<int>(std::distance(m_wakeTurbulenceCategories.cbegin(), it));
ui->cb_Wtc->setCurrentIndex(newIndex);
}
CWakeTurbulenceCategory CFlightPlanComponent::getSelectedWakeTurbulenceCategory() const
{
return m_wakeTurbulenceCategories.at(ui->cb_Wtc->currentIndex()).m_wtc;
}
bool CFlightPlanComponent::consolidateRemarks(QStringList &remarks, const QString &newRemarks)
{
if (newRemarks.isEmpty()) { return false; }

View File

@@ -11,6 +11,8 @@
#include "blackmisc/simulation/data/lastmodel.h"
#include "blackmisc/simulation/simulatedaircraft.h"
#include "blackmisc/aviation/flightplan.h"
#include "blackmisc/aviation/comnavequipment.h"
#include "blackmisc/aviation/ssrequipment.h"
#include "blackmisc/network/data/lastserver.h"
#include "blackmisc/network/user.h"
#include "blackmisc/directories.h"
@@ -27,6 +29,7 @@
#include <QtGlobal>
#include <QFileDialog>
#include <QNetworkReply>
#include <QListWidget>
namespace Ui
{
@@ -99,8 +102,12 @@ namespace BlackGui::Components
CAltitudeDialog *m_altitudeDialog = nullptr;
CStringListDialog *m_fpRemarksDialog = nullptr;
CSimBriefDownloadDialog *m_simBriefDialog = nullptr;
QMenu *m_navComEquipmentMenu = nullptr;
QMenu *m_ssrEquipmentMenu = nullptr;
BlackMisc::Aviation::CFlightPlan m_sentFlightPlan; //!< my flight plan
BlackMisc::Simulation::CAircraftModel m_model; //!< currently used model
BlackMisc::Aviation::CComNavEquipment m_navComEquipment; //!< current NAV/COM equipment
BlackMisc::Aviation::CSsrEquipment m_ssrEquipment; //!< current SSR equipment
BlackMisc::CIdentifier m_identifier { "FlightPlanComponent", this }; //!< Flightplan identifier
BlackMisc::CSetting<BlackMisc::Settings::TDirectorySettings> m_directories { this }; //!< the swift directories
BlackMisc::CSetting<FlightPlanSettings::TRemarksHistory> m_remarksHistory { this }; //!< remarks history
@@ -108,6 +115,19 @@ namespace BlackGui::Components
BlackMisc::CDataReadOnly<BlackMisc::Simulation::Data::TLastModel> m_lastAircraftModel { this }; //!< recently used aircraft model
BlackMisc::CDataReadOnly<BlackMisc::Network::Data::TLastServer> m_lastServer { this }; //!< recently used server (VATSIM, other)
struct WakeTurbulenceEntry
{
QString m_name; //!< Name displayed to the user
BlackMisc::Aviation::CWakeTurbulenceCategory m_wtc; //!< Wake turbulence category
};
const QList<WakeTurbulenceEntry> m_wakeTurbulenceCategories = {
{ "Light", BlackMisc::Aviation::CWakeTurbulenceCategory::LIGHT },
{ "Medium", BlackMisc::Aviation::CWakeTurbulenceCategory::MEDIUM },
{ "Heavy", BlackMisc::Aviation::CWakeTurbulenceCategory::HEAVY },
{ "Super", BlackMisc::Aviation::CWakeTurbulenceCategory::SUPER }
}; //!< Mapping CWakeTurbulenceCategory <=> UI name that is shown to the user
//! Validate, generates status messages
BlackMisc::CStatusMessageList validateAndInitializeFlightPlan(BlackMisc::Aviation::CFlightPlan &fligtPlan);
@@ -204,30 +224,15 @@ namespace BlackGui::Components
//! GUI init complete
void swiftWebDataRead();
//! Build "H/B737/F"
void buildPrefixIcaoSuffix();
//! Prefix check box changed
void prefixCheckBoxChanged();
//! Aircraft type changed
void aircraftTypeChanged();
//! Sync.with simulator
void syncWithSimulator();
//! Get prefix
QString getPrefix() const;
//! Aircraft type as ICAO code
BlackMisc::Aviation::CAircraftIcaoCode getAircraftIcaoCode() const;
//! Get equipment code (1 char)
QString getEquipmentSuffix() const;
//! Something like "H/B737/F"
QString getCombinedPrefixIcaoSuffix() const;
//! Show tab of equipment codes
void showEquipmentCodesTab();
@@ -264,6 +269,36 @@ namespace BlackGui::Components
//! Response from SimBrief
void handleSimBriefResponse(QNetworkReply *nwReplyPtr);
//! Setup NAV/COM context menu
void setupNavComContextMenu();
//! Setup SSR context menu
void setupSsrContextMenu();
//! Update the current NAV/COM equipment from the menu selection
void updateNavComEquipmentFromSelection();
//! Update the current SSR equipment from the menu selection
void updateSsrEquipmentFromSelection();
//! Update the selection and label according to current NAV/COM equipment
void updateNavComEquipmentUi();
//! Update the selection and label according to current SSR equipment
void updateSsrEquipmentUi();
//! Update the wake turbulence category selector
void updateWakeTurbulenceCategorySelector(const BlackMisc::Aviation::CWakeTurbulenceCategory &wtc);
//! Get the selected wake turbulence category
BlackMisc::Aviation::CWakeTurbulenceCategory getSelectedWakeTurbulenceCategory() const;
//! Helper to get the QListWidget from a given NAV/COM or SSR menu
static QListWidget *getMenuEquipmentList(QMenu *menu);
//! Helper to mark all options in \p enabledOptions as "selected" in the QListWidget, contained in the NAV/COM or SSR \p menu
static void updateListSelection(QMenu *menu, const QStringList &enabledOptions);
//! Consolidate the new remarks list, latest on front
static bool consolidateRemarks(QStringList &remarks, const QString &newRemarks);
};

File diff suppressed because it is too large Load Diff

View File

@@ -34,7 +34,7 @@ namespace BlackGui::Editors
ui->cb_AircraftPartsSend->isChecked(), ui->cb_AircraftPartsReceive->isChecked(),
ui->cb_GndFlagSend->isChecked(), ui->cb_GndFlagReceive->isChecked(),
ui->cb_FastPositionSend->isChecked(), ui->cb_FastPositionReceive->isChecked(),
ui->cb_VisualPositionSend->isChecked(), ui->cb_EuroscopeSimData->isChecked());
ui->cb_VisualPositionSend->isChecked(), ui->cb_EuroscopeSimData->isChecked(), ui->cb_IcaoEquipment->isChecked());
s.setForce3LetterAirlineCodes(ui->cb_3LetterAirlineICAO->isChecked());
return s;
}
@@ -56,6 +56,7 @@ namespace BlackGui::Editors
ui->cb_FastPositionSend->setChecked(d & CFsdSetup::SendInterimPositions);
ui->cb_3LetterAirlineICAO->setChecked(setup.force3LetterAirlineCodes());
ui->cb_EuroscopeSimData->setChecked(d & CFsdSetup::ReceiveEuroscopeSimData);
ui->cb_IcaoEquipment->setChecked(d & CFsdSetup::SendFplWithIcaoEquipment);
}
void CFsdSetupForm::setAlwaysAllowOverride(bool allow)

View File

@@ -29,6 +29,34 @@
<property name="spacing">
<number>4</number>
</property>
<item row="0" column="1">
<widget class="QLabel" name="lbl_FsdSetup">
<property name="text">
<string>FSD setup:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QCheckBox" name="cb_AircraftPartsSend">
<property name="text">
<string>send</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QCheckBox" name="cb_AircraftPartsReceive">
<property name="text">
<string>receive</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QCheckBox" name="cb_Override">
<property name="text">
<string>override</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLabel" name="lbl_AircraftParts">
<property name="toolTip">
@@ -39,20 +67,6 @@
</property>
</widget>
</item>
<item row="5" column="3">
<widget class="QCheckBox" name="cb_FastPositionSend">
<property name="text">
<string>send</string>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QCheckBox" name="cb_GndFlagSend">
<property name="text">
<string>send</string>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QLabel" name="lbl_GndFlag">
<property name="text">
@@ -60,13 +74,6 @@
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QCheckBox" name="cb_AircraftPartsReceive">
<property name="text">
<string>receive</string>
</property>
</widget>
</item>
<item row="6" column="3">
<widget class="QCheckBox" name="cb_FastPositionReceive">
<property name="text">
@@ -81,34 +88,13 @@
</property>
</widget>
</item>
<item row="6" column="2">
<widget class="QCheckBox" name="cb_GndFlagReceive">
<property name="text">
<string>receive</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QCheckBox" name="cb_AircraftPartsSend">
<item row="5" column="2">
<widget class="QCheckBox" name="cb_GndFlagSend">
<property name="text">
<string>send</string>
</property>
</widget>
</item>
<item row="4" column="5">
<widget class="QLabel" name="lbl_TextCodec">
<property name="text">
<string>Text codec</string>
</property>
</widget>
</item>
<item row="5" column="5">
<widget class="QLineEdit" name="le_TextCodec">
<property name="placeholderText">
<string>e.g. &quot;latin1&quot;</string>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QPushButton" name="pb_SetDefaults">
<property name="text">
@@ -116,20 +102,6 @@
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QCheckBox" name="cb_Override">
<property name="text">
<string>override</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="lbl_FsdSetup">
<property name="text">
<string>FSD setup:</string>
</property>
</widget>
</item>
<item row="6" column="5">
<widget class="QCheckBox" name="cb_3LetterAirlineICAO">
<property name="toolTip">
@@ -140,10 +112,24 @@
</property>
</widget>
</item>
<item row="5" column="4">
<widget class="QCheckBox" name="cb_VisualPositionSend">
<item row="5" column="3">
<widget class="QCheckBox" name="cb_FastPositionSend">
<property name="text">
<string>Send visual pos.</string>
<string>send</string>
</property>
</widget>
</item>
<item row="4" column="5">
<widget class="QLabel" name="lbl_TextCodec">
<property name="text">
<string>Text codec</string>
</property>
</widget>
</item>
<item row="6" column="2">
<widget class="QCheckBox" name="cb_GndFlagReceive">
<property name="text">
<string>receive</string>
</property>
</widget>
</item>
@@ -157,21 +143,43 @@
</property>
</widget>
</item>
<item row="5" column="5">
<widget class="QLineEdit" name="le_TextCodec">
<property name="placeholderText">
<string>e.g. &quot;latin1&quot;</string>
</property>
</widget>
</item>
<item row="5" column="4">
<widget class="QCheckBox" name="cb_VisualPositionSend">
<property name="text">
<string>Send visual pos.</string>
</property>
</widget>
</item>
<item row="5" column="6">
<widget class="QCheckBox" name="cb_IcaoEquipment">
<property name="text">
<string>ICAO Equipment</string>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>cb_Override</tabstop>
<tabstop>pb_SetDefaults</tabstop>
<tabstop>cb_AircraftPartsSend</tabstop>
<tabstop>cb_AircraftPartsReceive</tabstop>
<tabstop>cb_GndFlagSend</tabstop>
<tabstop>cb_GndFlagReceive</tabstop>
<tabstop>cb_FastPositionSend</tabstop>
<tabstop>cb_FastPositionReceive</tabstop>
<tabstop>cb_VisualPositionSend</tabstop>
<tabstop>cb_EuroscopeSimData</tabstop>
<tabstop>le_TextCodec</tabstop>
<tabstop>cb_IcaoEquipment</tabstop>
<tabstop>cb_AircraftPartsReceive</tabstop>
<tabstop>cb_GndFlagReceive</tabstop>
<tabstop>cb_FastPositionReceive</tabstop>
<tabstop>cb_EuroscopeSimData</tabstop>
<tabstop>cb_3LetterAirlineICAO</tabstop>
<tabstop>pb_SetDefaults</tabstop>
</tabstops>
<resources/>
<connections/>

View File

@@ -210,12 +210,12 @@ namespace BlackMisc::Aviation
return cats;
}
CFlightPlan::CFlightPlan(const CCallsign &callsign, const QString &equipmentIcao, const CAirportIcaoCode &originAirportIcao, const CAirportIcaoCode &destinationAirportIcao,
CFlightPlan::CFlightPlan(const CCallsign &callsign, const CFlightPlanAircraftInfo &aircraftInfo, const CAirportIcaoCode &originAirportIcao, const CAirportIcaoCode &destinationAirportIcao,
const CAirportIcaoCode &alternateAirportIcao, const QDateTime &takeoffTimePlanned, const QDateTime &takeoffTimeActual, const PhysicalQuantities::CTime &enrouteTime,
const PhysicalQuantities::CTime &fuelTime, const CAltitude &cruiseAltitude, const PhysicalQuantities::CSpeed &cruiseTrueAirspeed, CFlightPlan::FlightRules flightRules,
const QString &route, const QString &remarks)
: m_callsign(callsign),
m_equipmentSuffix(equipmentIcao), m_originAirportIcao(originAirportIcao), m_destinationAirportIcao(destinationAirportIcao), m_alternateAirportIcao(alternateAirportIcao),
m_aircraftInfo(aircraftInfo), m_originAirportIcao(originAirportIcao), m_destinationAirportIcao(destinationAirportIcao), m_alternateAirportIcao(alternateAirportIcao),
m_takeoffTimePlanned(takeoffTimePlanned), m_takeoffTimeActual(takeoffTimeActual), m_enrouteTime(enrouteTime), m_fuelTime(fuelTime),
m_cruiseAltitude(cruiseAltitude), m_cruiseTrueAirspeed(cruiseTrueAirspeed), m_flightRules(flightRules),
m_route(route.trimmed().left(MaxRouteLength).toUpper()),
@@ -232,12 +232,9 @@ namespace BlackMisc::Aviation
m_callsign.setTypeHint(CCallsign::Aircraft);
}
void CFlightPlan::setEquipmentIcao(const QString &equipmentIcao)
void CFlightPlan::setAircraftInfo(const CFlightPlanAircraftInfo &aircraftInfo)
{
const QStringList parts = CFlightPlan::splitEquipmentCode(equipmentIcao);
m_aircraftIcao = CAircraftIcaoCode::isValidDesignator(parts[1]) ? parts[1] : "";
m_prefix = parts[0];
m_equipmentSuffix = parts[2];
m_aircraftInfo = aircraftInfo;
}
void CFlightPlan::setTakeoffTimePlanned(const QDateTime &takeoffTimePlanned)
@@ -298,28 +295,6 @@ namespace BlackMisc::Aviation
return UNKNOWN;
}
void CFlightPlan::setPrefix(const QString &prefix)
{
m_prefix = prefix;
m_prefix.remove('/');
}
void CFlightPlan::setHeavy()
{
this->setPrefix("H");
}
void CFlightPlan::setEquipmentSuffix(const QString &suffix)
{
m_equipmentSuffix = suffix;
m_equipmentSuffix.remove('/');
}
QString CFlightPlan::getCombinedPrefixIcaoSuffix() const
{
return CFlightPlan::concatPrefixIcaoSuffix(m_prefix, m_aircraftIcao.getDesignator(), m_equipmentSuffix);
}
QVariant CFlightPlan::propertyByIndex(CPropertyIndexRef index) const
{
if (index.isMyself()) { return QVariant::fromValue(*this); }
@@ -374,7 +349,7 @@ namespace BlackMisc::Aviation
QString CFlightPlan::buildString(bool i18n, const QString &separator) const
{
const QString s = m_callsign.toQString(i18n) % u" aircraft: " % m_equipmentSuffix % separator % u"origin: " % m_originAirportIcao.toQString(i18n) % u" destination: " % m_destinationAirportIcao.toQString(i18n) % u" alternate: " % m_alternateAirportIcao.toQString(i18n) % separator % u"takeoff planed: " % m_takeoffTimePlanned.toString("ddhhmm") % u" actual: " % m_takeoffTimeActual.toString("ddhhmm") % separator % u"enroute time: " % m_enrouteTime.toQString(i18n) % u" fuel time:" % m_fuelTime.toQString(i18n) % separator % u"altitude: " % m_cruiseAltitude.toQString(i18n) % u" speed: " % m_cruiseTrueAirspeed.toQString(i18n) % separator % u"route: " % m_route % separator % u"remarks: " % this->getRemarks();
const QString s = m_callsign.toQString(i18n) % u" aircraft: " % m_aircraftInfo.asIcaoString() % separator % u"origin: " % m_originAirportIcao.toQString(i18n) % u" destination: " % m_destinationAirportIcao.toQString(i18n) % u" alternate: " % m_alternateAirportIcao.toQString(i18n) % separator % u"takeoff planed: " % m_takeoffTimePlanned.toString("ddhhmm") % u" actual: " % m_takeoffTimeActual.toString("ddhhmm") % separator % u"enroute time: " % m_enrouteTime.toQString(i18n) % u" fuel time:" % m_fuelTime.toQString(i18n) % separator % u"altitude: " % m_cruiseAltitude.toQString(i18n) % u" speed: " % m_cruiseTrueAirspeed.toQString(i18n) % separator % u"route: " % m_route % separator % u"remarks: " % this->getRemarks();
return s;
}
@@ -402,17 +377,7 @@ namespace BlackMisc::Aviation
const QString voice = fpDom.attribute("VoiceType");
fp.setVoiceCapabilities(voice);
const QString prefix = fpDom.attribute("EquipmentPrefix");
if (prefix.isEmpty())
{
const bool heavy = stringToBool(fpDom.attribute("IsHeavy"));
if (heavy) { fp.setHeavy(); }
}
else
{
fp.setPrefix(prefix);
}
fp.setEquipmentSuffix(fpDom.attribute("EquipmentSuffix"));
// Ignoring equipment prefix, suffix and IsHeavy flag
const int fuelMins = fpDom.attribute("FuelMinutes").toInt() + 60 * fpDom.attribute("FuelHours").toInt();
const CTime fuelTime(fuelMins, CTimeUnit::min());
@@ -474,8 +439,7 @@ namespace BlackMisc::Aviation
const CSpeed airspeed(airspeedKts, CSpeedUnit::kts());
fp.setCruiseTrueAirspeed(airspeed);
const bool heavy = stringToBool(values.value("Heavy"));
if (heavy) { fp.setHeavy(); }
// Ignoring Heavy flag
return fp;
}
@@ -730,101 +694,6 @@ namespace BlackMisc::Aviation
return unknown;
}
QString CFlightPlan::aircraftIcaoCodeFromEquipmentCode(const QString &equipmentCodeAndAircraft)
{
return splitEquipmentCode(equipmentCodeAndAircraft)[1].trimmed().toUpper();
}
QStringList CFlightPlan::splitEquipmentCode(const QString &equipmentCodeAndAircraft)
{
static const QStringList empty({ "", "", "" });
if (empty.isEmpty()) { return empty; }
QStringList firstSplit = equipmentCodeAndAircraft.split('-');
if (firstSplit.size() >= 2)
{
// format like B789/H-SDE1E2E3FGHIJ2J3J4J5M1RWXY/LB1D1
QString equipment = firstSplit[1];
QStringList split = firstSplit[0].split('/');
if (split.size() >= 3)
{
return { split[2], split[1], equipment.isEmpty() ? split[0] : equipment }; // "F/B789/H"
}
else if (split.size() >= 2)
{
if (split[0].size() <= 1) // "H/B789"
{
return { split[0], split[1], equipment };
}
else // "B789/H"
{
return { split[1], split[0], equipment };
}
}
else // "B789"
{
return { {}, split[0], equipment };
}
}
QStringList split = equipmentCodeAndAircraft.split('/');
if (split.length() >= 3)
{
if (split[1].size() == 1 && CAircraftIcaoCode::isValidDesignator(split[0]))
{
using std::swap;
swap(split[0], split[1]); // "A359/H/L"
}
return split; // "H/B738/F"
}
if (split.length() == 2)
{
if (split[0].length() == 1)
{
// we assume prefix + ICAO
// e.g. "H/B748"
split.push_back("");
return split;
}
else
{
// we assume ICAO + suffix
// e.g. "B748/F"
split.push_front("");
return split;
}
}
// one part only
if (split[0].length() > 1 && CAircraftIcaoCode::isValidDesignator(split[0]))
{
QStringList sl(empty);
sl[1] = split[0]; // only ICAO
return sl;
}
if (split[0].length() != 1) { return empty; } // something invalid
// one part, one char only. hard to tell
QStringList sl(empty);
if (faaEquipmentCodes().contains(split[0]))
{
sl[2] = split[0]; // return as equipment code
return sl;
}
sl[0] = split[0];
return sl;
}
QString CFlightPlan::concatPrefixIcaoSuffix(const QString &prefix, const QString &icao, const QString &suffix)
{
QString s = prefix;
if (!icao.isEmpty())
{
s += (s.isEmpty() ? u"" : u"/") % icao;
}
if (suffix.isEmpty()) { return s; }
if (s.isEmpty()) { return suffix; }
return s % u'/' % suffix;
}
CFlightPlan::FlightRules CFlightPlan::stringToFlightRules(const QString &flightRules)
{
if (flightRules.length() < 3) { return UNKNOWN; }
@@ -864,83 +733,6 @@ namespace BlackMisc::Aviation
return CFlightPlan::isIFRRules(r);
}
const QStringList &CFlightPlan::faaEquipmentCodes()
{
// List of FAA Aircraft Equipment Codes For US Domestic Flights
static const QStringList e({ "X", "T", "U", "D", "B", "A", "M", "N", "P", "Y", "C", "I", "L", "G", "Z", "I", "W", "L" });
return e;
}
const QStringList &CFlightPlan::faaEquipmentCodesInfo()
{
static const QStringList e(
{ "X No transponder",
"T Transponder with no Mode C",
"U Transponder with Mode C",
"D DME: No transponder",
"B DME: Transponder with no Mode C",
"A DME: Transponder with Mode C",
"M TACAN only: No transponder",
"N TACAN only: Transponder with no Mode C",
"P TACAN only: Transponder with Mode C",
"Y Basic RNAV: LORAN, VOR/DME, or INS with no transponder",
"C Basic RNAV: LORAN, VOR/DME, or INS, transponder with no Mode C",
"I Basic RNAV: LORAN, VOR/DME, or INS, transponder with Mode C",
"L Advanced RNAV: RNAV capability with Global Navigation Satellite System (GNSS)",
"G Advanced RNAV: RNAV capability with GNSS and without RVSM",
"Z Advanced RNAV: RNAV capability without GNSS and with RVSM",
"I Advanced RNAV: RNAV capability without GNSS and without RVSM",
"W RVSM",
"L RVSM and /G" });
return e;
}
const QStringList &CFlightPlan::squawkBoxEquipmentCodes()
{
static const QStringList e({ "E", "F", "G", "R", "J", "K", "L", "Q" });
return e;
}
const QStringList &CFlightPlan::squawkBoxEquipmentCodesInfo()
{
static const QStringList e(
{ "E Flight Management System (FMS) with DME/DME and IRU positioning updating",
"F Flight Management System (FMS) with DME/DME positioning updating",
"G Global Navigation Satellite System (GNSS), including GPS or Wide Area Augmentation System",
"R Required navigation performance, the aircraft meets the RNP type prescribed for the route segment(s), route(s) and or area concerned",
"J RVSM + E",
"L RVSM + F",
"L RVSM + G",
"Q RVSM + E" });
return e;
}
const QStringList &CFlightPlan::equipmentCodes()
{
static const QStringList e = [] {
QSet<QString> el(CFlightPlan::faaEquipmentCodes().begin(), CFlightPlan::faaEquipmentCodes().end());
el.unite(QSet<QString>(CFlightPlan::squawkBoxEquipmentCodes().begin(), CFlightPlan::squawkBoxEquipmentCodes().end()));
return el.values();
}();
return e;
}
const QStringList &CFlightPlan::equipmentCodesInfo()
{
static const QStringList e = [] {
QStringList info(CFlightPlan::faaEquipmentCodesInfo());
info.append(CFlightPlan::squawkBoxEquipmentCodesInfo());
return info;
}();
return e;
}
const QStringList &CFlightPlan::prefixCodes()
{
static const QStringList p({ "T", "H" });
return p;
}
CIcons::IconIndex CFlightPlan::toIcon() const
{
return CIcons::StandardIconAppFlightPlan16;

View File

@@ -12,6 +12,7 @@
#include "blackmisc/aviation/airlineicaocode.h"
#include "blackmisc/aviation/callsign.h"
#include "blackmisc/aviation/selcal.h"
#include "blackmisc/aviation/flightplanaircraftinfo.h"
#include "blackmisc/network/voicecapabilities.h"
#include "blackmisc/network/url.h"
#include "blackmisc/pq/speed.h"
@@ -185,16 +186,15 @@ namespace BlackMisc::Aviation
//! Constructor
CFlightPlan(const CCallsign &callsign,
const QString &equipmentIcao, const CAirportIcaoCode &originAirportIcao, const CAirportIcaoCode &destinationAirportIcao, const CAirportIcaoCode &alternateAirportIcao,
const CFlightPlanAircraftInfo &aircraftInfo, const CAirportIcaoCode &originAirportIcao, const CAirportIcaoCode &destinationAirportIcao, const CAirportIcaoCode &alternateAirportIcao,
const QDateTime &takeoffTimePlanned, const QDateTime &takeoffTimeActual, const PhysicalQuantities::CTime &enrouteTime, const PhysicalQuantities::CTime &fuelTime,
const CAltitude &cruiseAltitude, const PhysicalQuantities::CSpeed &cruiseTrueAirspeed, FlightRules flightRules, const QString &route, const QString &remarks);
//! Callsign (of aircraft)
void setCallsign(const CCallsign &callsign);
//! Set single char ICAO aircraft equipment code like used in "T/A320/F" (here "F")
//! \remark function can handle full codes like "T/A320/F" of just the "F"
void setEquipmentIcao(const QString &equipmentIcao);
//! Set information about the aircraft used in this flightplan
void setAircraftInfo(const CFlightPlanAircraftInfo &aircraftInfo);
//! Set origin airport ICAO code
void setOriginAirportIcao(const QString &originAirportIcao) { m_originAirportIcao = originAirportIcao; }
@@ -360,32 +360,8 @@ namespace BlackMisc::Aviation
//! Set FP remarks
void setFlightPlanRemarks(const CFlightPlanRemarks &remarks) { m_remarks = remarks; }
//! Get ICAO aircraft equipment prefix H/B737/F "H"
const QString &getPrefix() const { return m_prefix; }
//! Set ICAO aircraft equipment prefix H/B737/F "H"
void setPrefix(const QString &prefix);
//! Mark as heavy
void setHeavy();
//! Get ICAO aircraft equipment suffix H/B737/F "F"
const QString &getEquipmentSuffix() const { return m_equipmentSuffix; }
//! Set ICAO aircraft equipment suffix H/B737/F "F"
void setEquipmentSuffix(const QString &suffix);
//! Get aircraft ICAO H/B737/F "B737"
const CAircraftIcaoCode &getAircraftIcao() const { return m_aircraftIcao; }
//! Set aircraft ICAO code H/B737/F "B737"
void setAircraftIcao(const CAircraftIcaoCode &icao) { m_aircraftIcao = icao; }
//! Has aircraft ICAO?
bool hasAircraftIcao() const { return m_aircraftIcao.hasDesignator(); }
//! Full string like "H/B737/F"
QString getCombinedPrefixIcaoSuffix() const;
//! Get ICAO aircraft NAV/COM equipment
CFlightPlanAircraftInfo getAircraftInfo() const { return m_aircraftInfo; }
//! \copydoc BlackMisc::Mixin::Index::propertyByIndex
QVariant propertyByIndex(CPropertyIndexRef index) const;
@@ -441,42 +417,9 @@ namespace BlackMisc::Aviation
static bool isIFRRules(const QString &rule);
//! @}
//! Get aircraft ICAO code from equipment code like
//! \remark we expect something like "H/B772/F" "B773" "B773/F"
static QString aircraftIcaoCodeFromEquipmentCode(const QString &equipmentCodeAndAircraft);
//! Get the 3 parts of "H/B772/F", returned as prefix, ICAO, suffix
static QStringList splitEquipmentCode(const QString &equipmentCodeAndAircraft);
//! Concat the 3 parts to "H/B772/F"
static QString concatPrefixIcaoSuffix(const QString &prefix, const QString &icao, const QString &suffix);
//! Equipment codes 1 character
static const QStringList &faaEquipmentCodes();
//! Codes plus info
static const QStringList &faaEquipmentCodesInfo();
//! SquawkBox equipment codes
static const QStringList &squawkBoxEquipmentCodes();
//! Codes plus info
static const QStringList &squawkBoxEquipmentCodesInfo();
//! All equipment codes
static const QStringList &equipmentCodes();
//! Equipment codes info
static const QStringList &equipmentCodesInfo();
//! Prefix codes "H" .. Heavy, "T" .. TCAS
static const QStringList &prefixCodes();
private:
CCallsign m_callsign; //!< aircraft callsign
CAircraftIcaoCode m_aircraftIcao; //!< Aircraft ICAO code
QString m_prefix; //!< e.g. "T/A320/F" -> the "T"
QString m_equipmentSuffix; //!< e.g. "T/A320/F" -> the "F"
CFlightPlanAircraftInfo m_aircraftInfo; //!< Aircraft information
CAirportIcaoCode m_originAirportIcao;
CAirportIcaoCode m_destinationAirportIcao;
CAirportIcaoCode m_alternateAirportIcao;
@@ -497,9 +440,7 @@ namespace BlackMisc::Aviation
BLACK_METACLASS(
CFlightPlan,
// callsign will be current flight
BLACK_METAMEMBER(aircraftIcao),
BLACK_METAMEMBER(prefix),
BLACK_METAMEMBER(equipmentSuffix),
BLACK_METAMEMBER(aircraftInfo),
BLACK_METAMEMBER(originAirportIcao),
BLACK_METAMEMBER(destinationAirportIcao),
BLACK_METAMEMBER(alternateAirportIcao),

View File

@@ -125,6 +125,7 @@
<file>icons/pastel/16/folder-pink.png</file>
<file>icons/pastel/16/folder-purple.png</file>
<file>icons/pastel/16/undo.png</file>
<file>icons/pastel/16/pencil.png</file>
</qresource>
<qresource prefix="/vatsim">
<file>icons/vatsim/C1.png</file>

View File

@@ -37,7 +37,7 @@ namespace BlackMisc::Network
QString CFsdSetup::sendReceiveDetailsToString(SendReceiveDetails details)
{
static const QString ds("Send parts; %1 gnd: %2 interim: %3 Receive parts: %4 gnd: %5 interim: %6 3letter: %7");
static const QString ds("Send parts; %1 gnd: %2 interim: %3 Receive parts: %4 gnd: %5 interim: %6 3letter: %7 ICAO equipment %8");
return ds.arg(boolToYesNo(details.testFlag(SendAircraftParts)),
boolToYesNo(details.testFlag(SendGndFlag)),
boolToYesNo(details.testFlag(SendInterimPositions)),
@@ -45,10 +45,11 @@ namespace BlackMisc::Network
boolToYesNo(details.testFlag(ReceiveAircraftParts)),
boolToYesNo(details.testFlag(ReceiveGndFlag)),
boolToYesNo(details.testFlag(ReceiveInterimPositions)),
boolToYesNo(details.testFlag(Force3LetterAirlineICAO)));
boolToYesNo(details.testFlag(Force3LetterAirlineICAO)),
boolToYesNo(details.testFlag(SendFplWithIcaoEquipment)));
}
void CFsdSetup::setSendReceiveDetails(bool partsSend, bool partsReceive, bool gndSend, bool gndReceive, bool interimSend, bool interimReceive, bool visualSend, bool euroscopeSimDataReceive)
void CFsdSetup::setSendReceiveDetails(bool partsSend, bool partsReceive, bool gndSend, bool gndReceive, bool interimSend, bool interimReceive, bool visualSend, bool euroscopeSimDataReceive, bool icaoEquipment)
{
SendReceiveDetails s = Nothing;
if (partsSend) { s |= SendAircraftParts; }
@@ -59,6 +60,7 @@ namespace BlackMisc::Network
if (interimReceive) { s |= ReceiveInterimPositions; }
if (visualSend) { s |= SendVisualPositions; }
if (euroscopeSimDataReceive) { s |= ReceiveEuroscopeSimData; }
if (icaoEquipment) { s |= SendFplWithIcaoEquipment; }
this->setSendReceiveDetails(s);
}

View File

@@ -43,6 +43,7 @@ namespace BlackMisc::Network
Force3LetterAirlineICAO = 1 << 6, //!< force 3 letter airline ICAO code
SendVisualPositions = 1 << 7, //!< visual positions out
ReceiveEuroscopeSimData = 1 << 8, //!< euroscope SIMDATA in
SendFplWithIcaoEquipment = 1 << 9, //!< send flightplan with ICAO equipment code instead of FAA code
AllSending = SendAircraftParts | SendInterimPositions | SendVisualPositions | SendGndFlag, //!< all out
AllReceive = ReceiveAircraftParts | ReceiveInterimPositions | ReceiveGndFlag, //!< all in
All = AllReceive | AllSending, //!< all
@@ -51,7 +52,7 @@ namespace BlackMisc::Network
AllReceiveWithoutGnd = AllReceive - ReceiveGndFlag, //!< all in, but no gnd.flag
AllInterimPositions = SendInterimPositions | ReceiveInterimPositions, //!< all interim positions
AllWithoutGnd = AllReceiveWithoutGnd | AllSendingWithoutGnd, //!< all, but no gnd.flag
VATSIMDefault = AllParts | Force3LetterAirlineICAO | SendVisualPositions
VATSIMDefault = AllParts | Force3LetterAirlineICAO | SendVisualPositions | SendFplWithIcaoEquipment
};
Q_DECLARE_FLAGS(SendReceiveDetails, SendReceiveDetailsFlag)
@@ -90,7 +91,7 @@ namespace BlackMisc::Network
void removeSendReceiveDetails(SendReceiveDetails sendReceive) { m_sendReceive &= ~sendReceive; }
//! Set send / receive details
void setSendReceiveDetails(bool partsSend, bool partsReceive, bool gndSend, bool gndReceive, bool interimSend, bool interimReceive, bool visualSend, bool euroscopeSimDataReceive);
void setSendReceiveDetails(bool partsSend, bool partsReceive, bool gndSend, bool gndReceive, bool interimSend, bool interimReceive, bool visualSend, bool euroscopeSimDataReceive, bool icaoEquipment);
//! @{
//! FSD setup flags
@@ -103,6 +104,7 @@ namespace BlackMisc::Network
bool receiveGndFlag() const { return this->getSendReceiveDetails().testFlag(ReceiveGndFlag); }
bool receiveInterimPositions() const { return this->getSendReceiveDetails().testFlag(ReceiveInterimPositions); }
bool receiveEuroscopeSimData() const { return this->getSendReceiveDetails().testFlag(ReceiveEuroscopeSimData); }
bool shouldSendFlightPlanEquipmentInIcaoFormat() const { return this->getSendReceiveDetails().testFlag(SendFplWithIcaoEquipment); }
//! @}
//! @{

View File

@@ -77,8 +77,9 @@ namespace BlackMisc::Test
const CFlightPlan &CTestData::getFlightPlan()
{
static const CFlightPlanAircraftInfo info("T/A320/F");
static const CFlightPlan fp(CCallsign("DAMBZ", CCallsign::Aircraft),
"T/A320/F", "EDDF", "EDDM", "EDDN",
info, "EDDF", "EDDM", "EDDN",
QDateTime::currentDateTimeUtc(), QDateTime::currentDateTime().addSecs(600),
CTime(1.0, CTimeUnit::h()), CTime(2.0, CTimeUnit::h()),
CAltitude(10000, CAltitude::MeanSeaLevel, CLengthUnit::ft()), CSpeed(400, CSpeedUnit::kts()), CFlightPlan::IFR,