mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-14 16:55:36 +08:00
Ref T637, allow 3 letter ICAOs in FP
* strict or lenient airport check * allow to enter 3 letter ICAO codes in FP
This commit is contained in:
@@ -123,7 +123,7 @@ namespace BlackGui
|
|||||||
if (m_current.isNull())
|
if (m_current.isNull())
|
||||||
{
|
{
|
||||||
const QString icao = this->getIcaoText();
|
const QString icao = this->getIcaoText();
|
||||||
if (CAirportIcaoCode::isValidIcaoDesignator(icao))
|
if (CAirportIcaoCode::isValidIcaoDesignator(icao, true))
|
||||||
{
|
{
|
||||||
const CAirport airport = sGui->getWebDataServices()->getAirportForIcaoDesignator(icao);
|
const CAirport airport = sGui->getWebDataServices()->getAirportForIcaoDesignator(icao);
|
||||||
if (!airport.isNull()) { this->setAirport(airport); }
|
if (!airport.isNull()) { this->setAirport(airport); }
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ namespace BlackGui
|
|||||||
if (m_current.isNull())
|
if (m_current.isNull())
|
||||||
{
|
{
|
||||||
const QString icao = this->getIcaoText();
|
const QString icao = this->getIcaoText();
|
||||||
if (CAirportIcaoCode::isValidIcaoDesignator(icao))
|
if (CAirportIcaoCode::isValidIcaoDesignator(icao, true))
|
||||||
{
|
{
|
||||||
const CAirport airport = sGui->getWebDataServices()->getAirportForIcaoDesignator(icao);
|
const CAirport airport = sGui->getWebDataServices()->getAirportForIcaoDesignator(icao);
|
||||||
if (!airport.isNull()) { this->setAirport(airport); }
|
if (!airport.isNull()) { this->setAirport(airport); }
|
||||||
|
|||||||
@@ -266,7 +266,7 @@ namespace BlackGui
|
|||||||
if (!this->canAccessContext()) { return; }
|
if (!this->canAccessContext()) { return; }
|
||||||
const CAirportIcaoCode icao(airportIcaoCode.isEmpty() ? ui->le_AtcStationsOnlineMetar->text().trimmed().toUpper() : airportIcaoCode.trimmed().toUpper());
|
const CAirportIcaoCode icao(airportIcaoCode.isEmpty() ? ui->le_AtcStationsOnlineMetar->text().trimmed().toUpper() : airportIcaoCode.trimmed().toUpper());
|
||||||
ui->le_AtcStationsOnlineMetar->setText(icao.asString());
|
ui->le_AtcStationsOnlineMetar->setText(icao.asString());
|
||||||
if (!icao.hasValidIcaoCode()) { return; }
|
if (!icao.hasValidIcaoCode(true)) { return; }
|
||||||
const CMetar metar(sGui->getIContextNetwork()->getMetarForAirport(icao));
|
const CMetar metar(sGui->getIContextNetwork()->getMetarForAirport(icao));
|
||||||
if (metar.hasMessage())
|
if (metar.hasMessage())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -399,6 +399,14 @@ namespace BlackGui
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
flightPlan.setDestinationAirportIcao(v);
|
flightPlan.setDestinationAirportIcao(v);
|
||||||
|
if (strict && !flightPlan.getDestinationAirportIcao().hasValidIcaoCode(true))
|
||||||
|
{
|
||||||
|
messages.push_back(CStatusMessage(this).validationError(u"Invalid destination ICAO code '%1'") << v);
|
||||||
|
}
|
||||||
|
else if (!flightPlan.getDestinationAirportIcao().hasValidIcaoCode(false))
|
||||||
|
{
|
||||||
|
messages.push_back(CStatusMessage(this).validationWarning(u"Wrong or missing '%1'") << ui->lbl_DestinationAirport->text());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// origin airport
|
// origin airport
|
||||||
@@ -411,6 +419,14 @@ namespace BlackGui
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
flightPlan.setOriginAirportIcao(v);
|
flightPlan.setOriginAirportIcao(v);
|
||||||
|
if (strict && !flightPlan.getOriginAirportIcao().hasValidIcaoCode(true))
|
||||||
|
{
|
||||||
|
messages.push_back(CStatusMessage(this).validationError(u"Invalid origin ICAO code '%1'") << v);
|
||||||
|
}
|
||||||
|
else if (!flightPlan.getOriginAirportIcao().hasValidIcaoCode(false))
|
||||||
|
{
|
||||||
|
messages.push_back(CStatusMessage(this).validationWarning(u"Wrong or missing '%1'") << ui->lbl_DestinationAirport->text());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TAS
|
// TAS
|
||||||
|
|||||||
@@ -61,32 +61,38 @@ namespace BlackGui
|
|||||||
|
|
||||||
// shortcuts
|
// shortcuts
|
||||||
QShortcut *filter = new QShortcut(CShortcut::keyDisplayFilter(), this);
|
QShortcut *filter = new QShortcut(CShortcut::keyDisplayFilter(), this);
|
||||||
connect(filter, &QShortcut::activated, this, &CViewBaseNonTemplate::displayFilterDialog);
|
bool s = connect(filter, &QShortcut::activated, this, &CViewBaseNonTemplate::displayFilterDialog);
|
||||||
|
Q_ASSERT_X(s, Q_FUNC_INFO, "Shortcut");
|
||||||
filter->setObjectName("Filter shortcut for " + this->objectName());
|
filter->setObjectName("Filter shortcut for " + this->objectName());
|
||||||
filter->setContext(Qt::WidgetShortcut);
|
filter->setContext(Qt::WidgetShortcut);
|
||||||
|
|
||||||
QShortcut *clearSelection = new QShortcut(CShortcut::keyClearSelection(), this);
|
QShortcut *clearSelection = new QShortcut(CShortcut::keyClearSelection(), this);
|
||||||
connect(clearSelection, &QShortcut::activated, this, &CViewBaseNonTemplate::clearSelection);
|
s = connect(clearSelection, &QShortcut::activated, this, &CViewBaseNonTemplate::clearSelection);
|
||||||
|
Q_ASSERT_X(s, Q_FUNC_INFO, "Shortcut");
|
||||||
clearSelection->setObjectName("Clear selection shortcut for " + this->objectName());
|
clearSelection->setObjectName("Clear selection shortcut for " + this->objectName());
|
||||||
clearSelection->setContext(Qt::WidgetShortcut);
|
clearSelection->setContext(Qt::WidgetShortcut);
|
||||||
|
|
||||||
QShortcut *saveJson = new QShortcut(CShortcut::keySaveViews(), this);
|
QShortcut *saveJson = new QShortcut(CShortcut::keySaveViews(), this);
|
||||||
connect(saveJson, &QShortcut::activated, this, &CViewBaseNonTemplate::saveJsonAction);
|
s = connect(saveJson, &QShortcut::activated, this, &CViewBaseNonTemplate::saveJsonAction);
|
||||||
|
Q_ASSERT_X(s, Q_FUNC_INFO, "Shortcut");
|
||||||
saveJson->setObjectName("Save JSON for " + this->objectName());
|
saveJson->setObjectName("Save JSON for " + this->objectName());
|
||||||
saveJson->setContext(Qt::WidgetShortcut);
|
saveJson->setContext(Qt::WidgetShortcut);
|
||||||
|
|
||||||
QShortcut *deleteRow = new QShortcut(CShortcut::keyDelete(), this);
|
QShortcut *deleteRow = new QShortcut(CShortcut::keyDelete(), this);
|
||||||
connect(deleteRow, &QShortcut::activated, this, &CViewBaseNonTemplate::removeSelectedRowsChecked);
|
s = connect(deleteRow, &QShortcut::activated, this, &CViewBaseNonTemplate::removeSelectedRowsChecked);
|
||||||
|
Q_ASSERT_X(s, Q_FUNC_INFO, "Shortcut");
|
||||||
deleteRow->setObjectName("Remove selected rows for " + this->objectName());
|
deleteRow->setObjectName("Remove selected rows for " + this->objectName());
|
||||||
deleteRow->setContext(Qt::WidgetShortcut);
|
deleteRow->setContext(Qt::WidgetShortcut);
|
||||||
|
|
||||||
QShortcut *copy = new QShortcut(CShortcut::keyCopy(), this);
|
QShortcut *copy = new QShortcut(CShortcut::keyCopy(), this);
|
||||||
connect(copy, &QShortcut::activated, this, &CViewBaseNonTemplate::copy);
|
s = connect(copy, &QShortcut::activated, this, &CViewBaseNonTemplate::copy);
|
||||||
|
Q_ASSERT_X(s, Q_FUNC_INFO, "Shortcut");
|
||||||
copy->setObjectName("Copy selection shortcut for " + this->objectName());
|
copy->setObjectName("Copy selection shortcut for " + this->objectName());
|
||||||
copy->setContext(Qt::WidgetShortcut);
|
copy->setContext(Qt::WidgetShortcut);
|
||||||
|
|
||||||
QShortcut *resize = new QShortcut(CShortcut::keyResizeView(), this);
|
QShortcut *resize = new QShortcut(CShortcut::keyResizeView(), this);
|
||||||
connect(resize, &QShortcut::activated, this, &CViewBaseNonTemplate::resizeToContents);
|
s = connect(resize, &QShortcut::activated, this, &CViewBaseNonTemplate::fullResizeToContents);
|
||||||
|
Q_ASSERT_X(s, Q_FUNC_INFO, "Shortcut");
|
||||||
resize->setObjectName("Resize view shortcut for " + this->objectName());
|
resize->setObjectName("Resize view shortcut for " + this->objectName());
|
||||||
resize->setContext(Qt::WidgetShortcut);
|
resize->setContext(Qt::WidgetShortcut);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ namespace BlackMisc
|
|||||||
return m_icaoCode;
|
return m_icaoCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CAirportIcaoCode::hasValidIcaoCode() const
|
bool CAirportIcaoCode::hasValidIcaoCode(bool strict) const
|
||||||
{
|
{
|
||||||
return CAirportIcaoCode::isValidIcaoDesignator(this->getIcaoCode());
|
return CAirportIcaoCode::isValidIcaoDesignator(this->getIcaoCode(), strict);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CAirportIcaoCode::equalsString(const QString &icaoCode) const
|
bool CAirportIcaoCode::equalsString(const QString &icaoCode) const
|
||||||
@@ -29,15 +29,15 @@ namespace BlackMisc
|
|||||||
QString CAirportIcaoCode::unifyAirportCode(const QString &icaoCode)
|
QString CAirportIcaoCode::unifyAirportCode(const QString &icaoCode)
|
||||||
{
|
{
|
||||||
const QString code = icaoCode.trimmed().toUpper();
|
const QString code = icaoCode.trimmed().toUpper();
|
||||||
if (code.length() != 4) return {};
|
if (!validCodeLength(icaoCode.length(), false)) return {};
|
||||||
if (containsChar(code, [](QChar c) { return !c.isLetterOrNumber(); })) { return {}; }
|
if (containsChar(code, [](QChar c) { return !c.isLetterOrNumber(); })) { return {}; }
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CAirportIcaoCode::isValidIcaoDesignator(const QString &icaoCode)
|
bool CAirportIcaoCode::isValidIcaoDesignator(const QString &icaoCode, bool strict)
|
||||||
{
|
{
|
||||||
const QString icao = unifyAirportCode(icaoCode);
|
const QString icao = unifyAirportCode(icaoCode);
|
||||||
return icao.length() == 4;
|
return validCodeLength(icao.length(), strict);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CAirportIcaoCode::containsNumbers(const QString &icaoCode)
|
bool CAirportIcaoCode::containsNumbers(const QString &icaoCode)
|
||||||
@@ -63,5 +63,16 @@ namespace BlackMisc
|
|||||||
return m_icaoCode.compare(compareValue.getIcaoCode(), Qt::CaseInsensitive);
|
return m_icaoCode.compare(compareValue.getIcaoCode(), Qt::CaseInsensitive);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CAirportIcaoCode::validCodeLength(int l, bool strict)
|
||||||
|
{
|
||||||
|
// FAA code 3
|
||||||
|
// ICAO code 4
|
||||||
|
if (strict) { return l == 4; }
|
||||||
|
return l >= 3 && l <= 6;
|
||||||
|
|
||||||
|
// https://en.wikipedia.org/wiki/Location_identifier#FAA_identifier says can be up to 5 characters
|
||||||
|
// https://en.wikipedia.org/wiki/ICAO_airport_code#Pseudo_ICAO-codes says France has some 6-character airport codes
|
||||||
|
// and ZZZZ can be used in a flight plan as ICAO code for any airport that doesn't have one
|
||||||
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ namespace BlackMisc
|
|||||||
bool isEmpty() const { return this->m_icaoCode.isEmpty(); }
|
bool isEmpty() const { return this->m_icaoCode.isEmpty(); }
|
||||||
|
|
||||||
//! Has valid code?
|
//! Has valid code?
|
||||||
bool hasValidIcaoCode() const;
|
bool hasValidIcaoCode(bool strict) const;
|
||||||
|
|
||||||
//! Get code.
|
//! Get code.
|
||||||
const QString &asString() const { return this->m_icaoCode; }
|
const QString &asString() const { return this->m_icaoCode; }
|
||||||
@@ -56,7 +56,7 @@ namespace BlackMisc
|
|||||||
static QString unifyAirportCode(const QString &icaoCode);
|
static QString unifyAirportCode(const QString &icaoCode);
|
||||||
|
|
||||||
//! Valid ICAO designator
|
//! Valid ICAO designator
|
||||||
static bool isValidIcaoDesignator(const QString &icaoCode);
|
static bool isValidIcaoDesignator(const QString &icaoCode, bool strict);
|
||||||
|
|
||||||
//! Containing numbers (normally indicator for small airfield/strip)
|
//! Containing numbers (normally indicator for small airfield/strip)
|
||||||
static bool containsNumbers(const QString &icaoCode);
|
static bool containsNumbers(const QString &icaoCode);
|
||||||
@@ -73,6 +73,9 @@ namespace BlackMisc
|
|||||||
//! \copydoc BlackMisc::Mixin::Index::comparePropertyByIndex
|
//! \copydoc BlackMisc::Mixin::Index::comparePropertyByIndex
|
||||||
int comparePropertyByIndex(const CPropertyIndex &index, const CAirportIcaoCode &compareValue) const;
|
int comparePropertyByIndex(const CPropertyIndex &index, const CAirportIcaoCode &compareValue) const;
|
||||||
|
|
||||||
|
//! Valid code lenght
|
||||||
|
static bool validCodeLength(int l, bool strict);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString m_icaoCode;
|
QString m_icaoCode;
|
||||||
|
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ namespace BlackMisc
|
|||||||
|
|
||||||
bool CUser::hasValidHomeBase() const
|
bool CUser::hasValidHomeBase() const
|
||||||
{
|
{
|
||||||
return m_homebase.hasValidIcaoCode();
|
return m_homebase.hasValidIcaoCode(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
CStatusMessageList CUser::validate() const
|
CStatusMessageList CUser::validate() const
|
||||||
|
|||||||
@@ -362,7 +362,7 @@ namespace BlackSimPlugin
|
|||||||
if (!pFacilityAirport) { break; }
|
if (!pFacilityAirport) { break; }
|
||||||
const QString icao(pFacilityAirport->Icao);
|
const QString icao(pFacilityAirport->Icao);
|
||||||
if (icao.isEmpty()) { continue; } // airfield without ICAO code
|
if (icao.isEmpty()) { continue; } // airfield without ICAO code
|
||||||
if (!CAirportIcaoCode::isValidIcaoDesignator(icao)) { continue; } // tiny airfields/strips in simulator
|
if (!CAirportIcaoCode::isValidIcaoDesignator(icao, true)) { continue; } // tiny airfields/strips in simulator
|
||||||
if (CAirportIcaoCode::containsNumbers(icao)) { continue; } // tiny airfields/strips in simulator
|
if (CAirportIcaoCode::containsNumbers(icao)) { continue; } // tiny airfields/strips in simulator
|
||||||
const CCoordinateGeodetic pos(pFacilityAirport->Latitude, pFacilityAirport->Longitude, pFacilityAirport->Altitude);
|
const CCoordinateGeodetic pos(pFacilityAirport->Latitude, pFacilityAirport->Longitude, pFacilityAirport->Altitude);
|
||||||
const CAirport airport(CAirportIcaoCode(icao), pos);
|
const CAirport airport(CAirportIcaoCode(icao), pos);
|
||||||
|
|||||||
Reference in New Issue
Block a user