diff --git a/resources/share/shared/bootstrap/bootstrap.json b/resources/share/shared/bootstrap/bootstrap.json index 33c00c8ac..48907f080 100644 --- a/resources/share/shared/bootstrap/bootstrap.json +++ b/resources/share/shared/bootstrap/bootstrap.json @@ -66,5 +66,11 @@ } ] }, + "comNavEquipmentHelpUrl": { + "url": "https://en.wikipedia.org/wiki/Equipment_codes#Radio_communication,_navigation_and_approach_aid_equipment_and_capabilities" + }, + "ssrEquipmentHelpUrl": { + "url": "https://en.wikipedia.org/wiki/Equipment_codes#Surveillance_equipment_codes" + }, "wasLoadedFromFile": false } diff --git a/src/blackcore/context/contextnetworkimpl.cpp b/src/blackcore/context/contextnetworkimpl.cpp index f680a4c23..6ed000efb 100644 --- a/src/blackcore/context/contextnetworkimpl.cpp +++ b/src/blackcore/context/contextnetworkimpl.cpp @@ -283,7 +283,7 @@ namespace BlackCore::Context } m_fsdClient->setClientIdAndKey(static_cast(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); diff --git a/src/blackcore/data/globalsetup.h b/src/blackcore/data/globalsetup.h index 06b413efc..090d4d332 100644 --- a/src/blackcore/data/globalsetup.h +++ b/src/blackcore/data/globalsetup.h @@ -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) ); }; diff --git a/src/blackcore/fsd/enums.h b/src/blackcore/fsd/enums.h index 4ec3998e8..0314cd8cd 100644 --- a/src/blackcore/fsd/enums.h +++ b/src/blackcore/fsd/enums.h @@ -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) }; //! @{ diff --git a/src/blackcore/fsd/flightplan.h b/src/blackcore/fsd/flightplan.h index fc8452a7a..bb3085b99 100644 --- a/src/blackcore/fsd/flightplan.h +++ b/src/blackcore/fsd/flightplan.h @@ -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; diff --git a/src/blackcore/fsd/fsdclient.cpp b/src/blackcore/fsd/fsdclient.cpp index 0b20a42d7..03e613b38 100644 --- a/src/blackcore/fsd/fsdclient.cpp +++ b/src/blackcore/fsd/fsdclient.cpp @@ -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 timePartsEnroute = flightPlan.getEnrouteTime().getHrsMinSecParts(); const QList 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, diff --git a/src/blackcore/fsd/serializer.cpp b/src/blackcore/fsd/serializer.cpp index 43cd18934..da291468b 100644 --- a/src/blackcore/fsd/serializer.cpp +++ b/src/blackcore/fsd/serializer.cpp @@ -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; } diff --git a/src/blackcore/vatsim/vatsimdatafilereader.cpp b/src/blackcore/vatsim/vatsimdatafilereader.cpp index a8a6f49c6..afaf96bac 100644 --- a/src/blackcore/vatsim/vatsimdatafilereader.cpp +++ b/src/blackcore/vatsim/vatsimdatafilereader.cpp @@ -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()) { diff --git a/src/blackgui/components/flightplancomponent.cpp b/src/blackgui/components/flightplancomponent.cpp index cf051c3e5..80f812b7a 100644 --- a/src/blackgui/components/flightplancomponent.cpp +++ b/src/blackgui/components/flightplancomponent.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -48,6 +49,7 @@ #include #include #include +#include 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 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 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 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(menu->actions().at(0)); + Q_ASSERT_X(action, Q_FUNC_INFO, "equipment menu contains invalid action item"); + auto list = qobject_cast(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(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; } diff --git a/src/blackgui/components/flightplancomponent.h b/src/blackgui/components/flightplancomponent.h index 587bb8324..d6decea11 100644 --- a/src/blackgui/components/flightplancomponent.h +++ b/src/blackgui/components/flightplancomponent.h @@ -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 #include #include +#include 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 m_directories { this }; //!< the swift directories BlackMisc::CSetting m_remarksHistory { this }; //!< remarks history @@ -108,6 +115,19 @@ namespace BlackGui::Components BlackMisc::CDataReadOnly m_lastAircraftModel { this }; //!< recently used aircraft model BlackMisc::CDataReadOnly 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 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); }; diff --git a/src/blackgui/components/flightplancomponent.ui b/src/blackgui/components/flightplancomponent.ui index 49031df2c..664c24dc6 100644 --- a/src/blackgui/components/flightplancomponent.ui +++ b/src/blackgui/components/flightplancomponent.ui @@ -86,322 +86,7 @@ 4 - - - - - IFR - - - - - VFR - - - - - SVFR - - - - - DVFR - - - - - - - - 4 - - - ICAO, e.g. EDDF - - - - - - - 40 - - - e.g. 100 kts - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Equipment - - - 3. Eqpt. - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - H/ heavy prefix - - - Heavy - - - - - - - T/ TCAS prefix - - - TCAS - - - - - - - - - - 12. Fuel on board - - - true - - - - - - - goto generator page - - - goto gen. - - - - - - - Aircraft type - - - 3. Aircraft - - - false - - - true - - - - - - - - 16777215 - 75 - - - - true - - - - - - - 11.remarks - - - - - - - pilot's name - - - 14. Pilot / homebase - - - true - - - - - - - copy from generator page - - - from gen. - - - - - - - - - equipment code help - - - equipment code help - - - ... - - - - :/pastel/icons/pastel/16/help.png:/pastel/icons/pastel/16/help.png - - - - - - - 1 - - - equip.code - - - - - - - - - 1. Type - - - - - - - 99:99 - - - 00:00 - - - 5 - - - - - - - Estimated time enroute - - - 10. Est.time enroute - - - true - - - - - - - True airspeed - - - 4. TAS - - - true - - - - - - - true - - - homebase (read only) - - - - - - - true - - - sent time will go here (read only) - - - - - - - ICAO, e.g. A321 - - - - - - - Sent - - - - - - - 5. Departure airport - - - true - - - - - - - true - - - pilot's name (read only) - - - - + @@ -417,17 +102,116 @@ - - + + + + + + + + + Edit + + + Edit Nav/Com equipment code + + + ... + + + + :/pastel/icons/pastel/16/pencil.png:/pastel/icons/pastel/16/pencil.png + + + + + + + equip.code + + + + + + + + + + Full voice + + + + + Text only + + + + + Receive voice + + + + + + - 13. Alternate airport + 2. Callsign + + + false true - + + + + pilot's name + + + 17. Pilot / homebase + + + true + + + + + + + + 16777215 + 75 + + + + true + + + + + + + 9. Departure time + + + true + + + + + + + 40 + + + e.g. 100 kts + + + + 99:99 @@ -443,23 +227,63 @@ - - + + + + + + + + + altitude formats + + + altitude formats + + + ... + + + + :/pastel/icons/pastel/16/help.png:/pastel/icons/pastel/16/help.png + + + + + + + + + Estimated time enroute + - 9. Destination airport + 13. Est.time enroute true - - + + + + 99:99 + + + 00:00 + + + 5 + + + + + true - P/ICAO/S + homebase (read only) @@ -508,20 +332,40 @@ - - - - 4 + + + + goto generator page - - ICAO, e.g. EDDF + + goto gen. - - + + - 2. Callsign + Sent + + + + + + + copy from generator page + + + from gen. + + + + + + + Aircraft type + + + 3. Aircraft false @@ -531,47 +375,234 @@ - - + + - 7. Cruising altitude + 1. Type + + + + + + + + IFR + + + + + VFR + + + + + SVFR + + + + + DVFR + + + + + + + + 99:99 + + + 00:00 + + + hh:mm e.g. 02:30 + + + + + + + 12. Destination airport true - - - - - Full voice - - - - - Text only - - - - - Receive voice - - + + + + ICAO, e.g. A321 + + + + + + + 4 + + + ICAO, e.g. EDDF + - + + + 10. Cruising altitude + + + true + + + + + + + True airspeed + + + 7. TAS + + + true + + + + + + + 8. Departure airport + + + true + + + + + + + true + + + pilot's name (read only) + + + + + + + 14. Fuel on board + + + true + + + + + + + 4 + + + ICAO, e.g. EDDF + + + + + + + 4 + + + ICAO, e.g. EDDF + + + + + + + 15. Alternate airport + + + true + + + + + + + 16. remarks + + + + + + + true + + + sent time will go here (read only) + + + + + + + 4. Wake Turbulence Category + + + + + + + 11. Route + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + - + - + - altitude formats + Edit - altitude formats + Edit SSR equipment code + + + ... + + + + :/pastel/icons/pastel/16/pencil.png:/pastel/icons/pastel/16/pencil.png + + + + + + + + + + + 5. NAV/COM Equipment + + + + + + + NAV/COM equipment overview + + + NAV/COM equipment overview ... @@ -584,48 +615,33 @@ - - - - 4 - - - ICAO, e.g. EDDF - - - - - - - 6. Departure time - - - true - - - - - - - 8. Route - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - - 99:99 - - - 00:00 - - - hh:mm e.g. 02:30 - - + + + + + + 6. SSR Equipment + + + + + + + SSR equipment overview + + + SSR equipment overview + + + ... + + + + :/pastel/icons/pastel/16/help.png:/pastel/icons/pastel/16/help.png + + + + @@ -819,8 +835,8 @@ 0 0 - 382 - 477 + 345 + 520 @@ -1167,68 +1183,6 @@ - - - Equipment codes - - - - 4 - - - 4 - - - 4 - - - 4 - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.1pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">FAA equipment codes</span><span style=" font-size:8pt;"> (Wikipedia) </span></p> -<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">NO DME:</li> -<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 2;"><li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">/X No transponder</li> -<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">/T Transponder with no Mode C</li> -<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">/U Transponder with Mode C</li></ul> -<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">DME:</li> -<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 2;"><li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">/D No transponder</li> -<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">/B Transponder with no Mode C</li> -<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">/A Transponder with Mode C</li></ul> -<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">TACAN only:</li> -<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 2;"><li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">/M No transponder</li> -<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">/N Transponder with no Mode C</li> -<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">/P Transponder with Mode C</li></ul> -<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Basic RNAV:</li> -<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 2;"><li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">/Y LORAN, VOR/DME, or INS with no transponder</li> -<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">/C LORAN, VOR/DME, or INS, transponder with no Mode C</li> -<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">/I LORAN, VOR/DME, or INS, transponder with Mode C</li></ul> -<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Advanced RNAV with Transponder and mode C:</li> -<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 2;"><li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">/L RNAV capability with Global Navigation Satellite System (GNSS), including GPS or Wide Area Augmentation System (WAAS) with en route and terminal capability, and with RVSM</li> -<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">/G RNAV capability with GNSS and without RVSM</li> -<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">/Z RNAV capability without GNSS and with RVSM</li> -<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">/I RNAV capability without GNSS and without RVSM</li></ul> -<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">RVSM (Reduced Vertical Separation Minimum):</li></ul> -<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 2;"><li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">/W RVSM</li> -<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">/L RVSM and /G </li></ul> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">SquawkBox codes</span><span style=" font-size:8pt;"> (complemtary, obsolete)</span><span style=" font-size:8pt; font-weight:600;"> </span></p> -<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">/E Flight Management System (FMS) with DME/DME and IRU positioning updating</li> -<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">/F Flight Management System (FMS) with DME/DME positioning updating</li> -<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">/G Global Navigation Satellite System (GNSS), including GPS or Wide Area Augmentation System</li> -<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">/R Required navigation performance, the aircraft meets the RNP type prescribed for the route segment(s), route(s) and or area concerned </li> -<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">/J /K /L /Q same as /E /F /G /R with RVSM</li></ul> -<p style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span></p></body></html> - - - - - @@ -1244,26 +1198,23 @@ p, li { white-space: pre-wrap; } - sa_FlightPlanTabMain - cb_Heavy - cb_Tcas - le_PrefixIcaoSuffix - le_EquipmentSuffix - tb_HelpEquipment - pte_Route + cb_FlightRule + le_Callsign + le_AircraftType + cb_Wtc + tb_EditNavComEquipment + tb_EditSsrEquipment + le_CruiseTrueAirspeed le_OriginAirport le_TakeOffTimePlanned lep_CrusingAltitude - tb_AltitudeDialog + pte_Route le_DestinationAirport le_EstimatedTimeEnroute le_FuelOnBoard le_AlternateAirport - pb_Remarks - cb_VoiceCapabilitiesFirstPage - pb_RemarksGenerator - pb_GetFromGenerator pte_Remarks + pb_GetFromGenerator le_PilotsName le_PilotsHomeBase le_LastSent @@ -1292,12 +1243,16 @@ p, li { white-space: pre-wrap; } pb_AddRemarks pte_AdditionalRemarks pb_CopyOver - tbr_EquipmentCodes - le_CruiseTrueAirspeed tb_SyncWithSimulator - le_Callsign - le_AircraftType - cb_FlightRule + le_NavComEquipment + tb_AltitudeDialog + sa_FlightPlanTabMain + cb_VoiceCapabilitiesFirstPage + pb_Remarks + le_SsrEquipment + pb_RemarksGenerator + tb_NavComHelp + tb_SsrHelp diff --git a/src/blackgui/editors/fsdsetupform.cpp b/src/blackgui/editors/fsdsetupform.cpp index b4d3d41ae..e2525b03c 100644 --- a/src/blackgui/editors/fsdsetupform.cpp +++ b/src/blackgui/editors/fsdsetupform.cpp @@ -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) diff --git a/src/blackgui/editors/fsdsetupform.ui b/src/blackgui/editors/fsdsetupform.ui index 31d34a9c7..160de85df 100644 --- a/src/blackgui/editors/fsdsetupform.ui +++ b/src/blackgui/editors/fsdsetupform.ui @@ -29,6 +29,34 @@ 4 + + + + FSD setup: + + + + + + + send + + + + + + + receive + + + + + + + override + + + @@ -39,20 +67,6 @@ - - - - send - - - - - - - send - - - @@ -60,13 +74,6 @@ - - - - receive - - - @@ -81,34 +88,13 @@ - - - - receive - - - - - + + send - - - - Text codec - - - - - - - e.g. "latin1" - - - @@ -116,20 +102,6 @@ - - - - override - - - - - - - FSD setup: - - - @@ -140,10 +112,24 @@ - - + + - Send visual pos. + send + + + + + + + Text codec + + + + + + + receive @@ -157,21 +143,43 @@ + + + + e.g. "latin1" + + + + + + + Send visual pos. + + + + + + + ICAO Equipment + + + cb_Override - pb_SetDefaults cb_AircraftPartsSend - cb_AircraftPartsReceive cb_GndFlagSend - cb_GndFlagReceive cb_FastPositionSend - cb_FastPositionReceive cb_VisualPositionSend - cb_EuroscopeSimData le_TextCodec + cb_IcaoEquipment + cb_AircraftPartsReceive + cb_GndFlagReceive + cb_FastPositionReceive + cb_EuroscopeSimData cb_3LetterAirlineICAO + pb_SetDefaults diff --git a/src/blackmisc/aviation/flightplan.cpp b/src/blackmisc/aviation/flightplan.cpp index 4a5646bf7..4b596d001 100644 --- a/src/blackmisc/aviation/flightplan.cpp +++ b/src/blackmisc/aviation/flightplan.cpp @@ -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 el(CFlightPlan::faaEquipmentCodes().begin(), CFlightPlan::faaEquipmentCodes().end()); - el.unite(QSet(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; diff --git a/src/blackmisc/aviation/flightplan.h b/src/blackmisc/aviation/flightplan.h index 4cea80b32..588d9fede 100644 --- a/src/blackmisc/aviation/flightplan.h +++ b/src/blackmisc/aviation/flightplan.h @@ -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), diff --git a/src/blackmisc/blackmisc.qrc b/src/blackmisc/blackmisc.qrc index 3bea210a4..b67bfe331 100644 --- a/src/blackmisc/blackmisc.qrc +++ b/src/blackmisc/blackmisc.qrc @@ -125,6 +125,7 @@ icons/pastel/16/folder-pink.png icons/pastel/16/folder-purple.png icons/pastel/16/undo.png + icons/pastel/16/pencil.png icons/vatsim/C1.png diff --git a/src/blackmisc/network/fsdsetup.cpp b/src/blackmisc/network/fsdsetup.cpp index d4c39678b..128a28c8b 100644 --- a/src/blackmisc/network/fsdsetup.cpp +++ b/src/blackmisc/network/fsdsetup.cpp @@ -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); } diff --git a/src/blackmisc/network/fsdsetup.h b/src/blackmisc/network/fsdsetup.h index d85c3feca..299a5cdf7 100644 --- a/src/blackmisc/network/fsdsetup.h +++ b/src/blackmisc/network/fsdsetup.h @@ -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); } //! @} //! @{ diff --git a/src/blackmisc/test/testdata.cpp b/src/blackmisc/test/testdata.cpp index c8baac61e..bd6e5c904 100644 --- a/src/blackmisc/test/testdata.cpp +++ b/src/blackmisc/test/testdata.cpp @@ -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, diff --git a/tests/blackcore/fsd/testfsdclient/testfsdclient.cpp b/tests/blackcore/fsd/testfsdclient/testfsdclient.cpp index 0aeeb27d9..1e30edb76 100644 --- a/tests/blackcore/fsd/testfsdclient/testfsdclient.cpp +++ b/tests/blackcore/fsd/testfsdclient/testfsdclient.cpp @@ -87,7 +87,8 @@ namespace BlackFsdTest void testSendTextMessage2(); void testSendRadioMessage1(); void testSendRadioMessage2(); - void testSendFlightPlan(); + void testSendFlightPlanFaa(); + void testSendFlightPlanIcao(); void testSendPlaneInfoRequest(); void testSendPlaneInformation1(); void testSendPlaneInformation2(); @@ -669,15 +670,17 @@ namespace BlackFsdTest QCOMPARE(fsdMessage.getRawMessage(), "FSD Sent=>#TMABCD:@24050&@35725:hey dude!"); } - void CTestFSDClient::testSendFlightPlan() + void CTestFSDClient::testSendFlightPlanFaa() { + // Server without ICAOEQ capability is set by default (in init()) QSignalSpy spy(m_client, &CFSDClient::rawFsdMessage); QDateTime takeoffTimePlanned = QDateTime::fromString("1530", "hhmm"); takeoffTimePlanned.setTimeSpec(Qt::UTC); QDateTime takeoffTimeActual = QDateTime::fromString("1535", "hhmm"); takeoffTimeActual.setTimeSpec(Qt::UTC); CAltitude flightLevel(35000, CAltitude::FlightLevel, CLengthUnit::ft()); - CFlightPlan fp({}, "B744", "EGLL", "KORD", "NONE", + CFlightPlanAircraftInfo info("H/B744/L"); + CFlightPlan fp({}, info, "EGLL", "KORD", "NONE", takeoffTimePlanned, takeoffTimeActual, CTime(8.25, CTimeUnit::h()), CTime(9.5, CTimeUnit::h()), flightLevel, CSpeed(420, CSpeedUnit::kts()), CFlightPlan::VFR, @@ -688,7 +691,34 @@ namespace BlackFsdTest QList arguments = spy.takeFirst(); QCOMPARE(arguments.size(), 1); CRawFsdMessage fsdMessage = arguments.at(0).value(); - QCOMPARE(fsdMessage.getRawMessage(), "FSD Sent=>$FPABCD:SERVER:V:B744:420:EGLL:1530:1535:FL350:KORD:8:15:9:30:NONE:UNIT TEST:EGLL.KORD"); + QCOMPARE(fsdMessage.getRawMessage(), "FSD Sent=>$FPABCD:SERVER:V:H/B744/L:420:EGLL:1530:1535:FL350:KORD:8:15:9:30:NONE:UNIT TEST:EGLL.KORD"); + } + + void CTestFSDClient::testSendFlightPlanIcao() + { + CServer server = localTestServer(); + server.setFsdSetup(CFsdSetup(CFsdSetup::SendFplWithIcaoEquipment)); + m_client->setServer(server); + + QSignalSpy spy(m_client, &CFSDClient::rawFsdMessage); + QDateTime takeoffTimePlanned = QDateTime::fromString("1530", "hhmm"); + takeoffTimePlanned.setTimeSpec(Qt::UTC); + QDateTime takeoffTimeActual = QDateTime::fromString("1535", "hhmm"); + takeoffTimeActual.setTimeSpec(Qt::UTC); + CAltitude flightLevel(35000, CAltitude::FlightLevel, CLengthUnit::ft()); + CFlightPlanAircraftInfo info("B748/H-SDE3FGHIM1M2RWXY/LB1"); + CFlightPlan fp({}, info, "EGLL", "KORD", "NONE", + takeoffTimePlanned, takeoffTimeActual, + CTime(8.25, CTimeUnit::h()), CTime(9.5, CTimeUnit::h()), + flightLevel, CSpeed(420, CSpeedUnit::kts()), CFlightPlan::VFR, + "EGLL.KORD", "Unit Test"); + m_client->sendFlightPlan(fp); + + QCOMPARE(spy.count(), 1); + QList arguments = spy.takeFirst(); + QCOMPARE(arguments.size(), 1); + CRawFsdMessage fsdMessage = arguments.at(0).value(); + QCOMPARE(fsdMessage.getRawMessage(), "FSD Sent=>$FPABCD:SERVER:V:B748/H-SDE3FGHIM1M2RWXY/LB1:420:EGLL:1530:1535:FL350:KORD:8:15:9:30:NONE:UNIT TEST:EGLL.KORD"); } void CTestFSDClient::testSendPlaneInfoRequest()