refs #418, ICAO data for reader

* value objects and respective lists
* adjusted CAircraftIcao to use new classes
* some smaller fixes, Doxygen
* reader for values from database JSON values
  http://vatrep.vatsim-germany.org/service/allaircrafticao.php?rows=10000&sord=asc
* Related: Slightly improved signals for VATSIM reader
This commit is contained in:
Klaus Basan
2015-05-12 02:58:56 +02:00
committed by Mathew Sutcliffe
parent b494cb51b8
commit 069f4749f4
19 changed files with 1010 additions and 52 deletions

View File

@@ -16,7 +16,8 @@
#include "network_vatlib.h"
#include "vatsimbookingreader.h"
#include "vatsimdatafilereader.h"
#include "icaodatareader.h"
#include "airspace_monitor.h"
#include "blackmisc/networkutils.h"
#include "blackmisc/aviation/atcstationlist.h"
#include "blackmisc/logmessage.h"
@@ -66,12 +67,21 @@ namespace BlackCore
this->m_vatsimDataFileReader->readInBackgroundThread(); // first read
this->m_vatsimDataFileReader->setInterval(90 * 1000);
// 4. Update timer for data (network data such as frequency)
// 4. ICAO data reader
this->m_icaoDataReader = new CIcaoDataReader(this,
"http://vatrep.vatsim-germany.org/service/allaircrafticao.php?rows=20000&sord=asc",
"http://vatrep.vatsim-germany.org/service/allairlineicao.php?rows=20000&sord=asc");
connect(this->m_icaoDataReader, &CIcaoDataReader::readAircraftIcaoCodes, this, &CContextNetwork::ps_readAircraftIcaoCodes);
connect(this->m_icaoDataReader, &CIcaoDataReader::readAirlinesIcaoCodes, this, &CContextNetwork::ps_readAirlinesIcaoCodes);
this->m_icaoDataReader->start();
this->m_icaoDataReader->readInBackgroundThread();
// 5. Update timer for data (network data such as frequency)
this->m_dataUpdateTimer = new QTimer(this);
connect(this->m_dataUpdateTimer, &QTimer::timeout, this, &CContextNetwork::requestDataUpdates);
this->m_dataUpdateTimer->start(30 * 1000);
// 5. Airspace contents
// 6. Airspace contents
Q_ASSERT_X(this->getRuntime()->getCContextOwnAircraft(), Q_FUNC_INFO, "this and own aircraft context must be local");
this->m_airspace = new CAirspaceMonitor(this, this->getRuntime()->getCContextOwnAircraft(), this->m_network, this->m_vatsimBookingReader, this->m_vatsimDataFileReader);
connect(this->m_airspace, &CAirspaceMonitor::changedAtcStationsOnline, this, &CContextNetwork::changedAtcStationsOnline);
@@ -450,13 +460,25 @@ namespace BlackCore
m_airspace->analyzer()->setSimulatorRenderRestrictionsChanged(restricted, maxAircraft, maxRenderedDistance, maxRenderedBoundary);
}
void CContextNetwork::ps_dataFileRead()
void CContextNetwork::ps_dataFileRead(int lines)
{
if (this->isDebugEnabled()) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO; }
CLogMessage(this).info("Read VATSIM data file");
CLogMessage(this).info("Read VATSIM data file, %1 lines") << lines;
emit vatsimDataFileRead();
}
void CContextNetwork::ps_readAircraftIcaoCodes(int number)
{
if (this->isDebugEnabled()) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO; }
CLogMessage(this).info("Read %1 aircraft ICAO codes") << number;
}
void CContextNetwork::ps_readAirlinesIcaoCodes(int number)
{
if (this->isDebugEnabled()) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO; }
CLogMessage(this).info("Read %1 airline ICAO codes") << number;
}
void CContextNetwork::ps_checkForSupervisiorTextMessage(const CTextMessageList &messages)
{
if (messages.containsPrivateMessages())

View File

@@ -16,24 +16,25 @@
#include "blackcore/context_network.h"
#include "blackcore/context_settings.h"
#include "blackcore/context_runtime.h"
#include "blackmisc/simulation/remoteaircraftprovider.h"
#include "blackcore/dbus_server.h"
#include "blackcore/network.h"
#include "blackcore/airspace_monitor.h"
#include "blackmisc/simulation/remoteaircraftprovider.h"
#include "blackmisc/aviation/atcstationlist.h"
#include "blackmisc/aviation/aircraftsituationlist.h"
#include "blackmisc/setnetwork.h"
#include "blackmisc/network/clientlist.h"
#include "blackmisc/digestsignal.h"
#include "blackmisc/logmessage.h"
#include "blackmisc/aviation/aircraftsituationlist.h"
#include <QMap>
#include <QTimer>
namespace BlackCore
{
class CAirspaceMonitor;
class CVatsimBookingReader;
class CVatsimDataFileReader;
class CIcaoDataReader;
//! Network context implementation
class BLACKCORE_EXPORT CContextNetwork :
@@ -97,7 +98,7 @@ namespace BlackCore
virtual BlackMisc::Simulation::CAirspaceAircraftSnapshot getLatestAirspaceAircraftSnapshot() const override;
//! Network library
INetwork* network() const { return m_network; }
INetwork *network() const { return m_network; }
public slots:
//! \copydoc IContextNetwork::updateAircraftEnabled
@@ -248,6 +249,7 @@ namespace BlackCore
// for reading XML and VATSIM data files
CVatsimBookingReader *m_vatsimBookingReader = nullptr;
CVatsimDataFileReader *m_vatsimDataFileReader = nullptr;
CIcaoDataReader *m_icaoDataReader = nullptr;
QTimer *m_dataUpdateTimer = nullptr; //!< general updates such as ATIS, frequencies, see requestDataUpdates()
//! Get network settings
@@ -266,7 +268,13 @@ namespace BlackCore
void ps_receivedBookings(const BlackMisc::Aviation::CAtcStationList &bookedStations);
//! Data file has been read
void ps_dataFileRead();
void ps_dataFileRead(int lines);
//! Read ICAO codes
void ps_readAircraftIcaoCodes(int number);
//! Read ICAO codes
void ps_readAirlinesIcaoCodes(int number);
//! Check if a supervisor message was received
void ps_checkForSupervisiorTextMessage(const BlackMisc::Network::CTextMessageList &messages);
@@ -279,6 +287,6 @@ namespace BlackCore
void ps_simulatorRenderRestrictionsChanged(bool restricted, int maxAircraft, const BlackMisc::PhysicalQuantities::CLength &maxRenderedDistance, const BlackMisc::PhysicalQuantities::CLength &maxRenderedBoundary);
};
}
} // ns
#endif // guard

View File

@@ -0,0 +1,135 @@
/* Copyright (C) 2015
* swift project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
#include "blackmisc/sequence.h"
#include "blackmisc/logmessage.h"
#include "icaodatareader.h"
#include <QRegularExpression>
using namespace BlackMisc;
using namespace BlackMisc::Aviation;
namespace BlackCore
{
CIcaoDataReader::CIcaoDataReader(QObject *owner, const QString &aircraftIcaoUrl, const QString &airlineIcaoUrl) :
CThreadedReader(owner, "CIcaoDataReader"),
m_urlAircraftIcao(aircraftIcaoUrl), m_urlAirlineIcao(airlineIcaoUrl)
{
this->m_networkManagerAircraft = new QNetworkAccessManager(this);
this->m_networkManagerAirlines = new QNetworkAccessManager(this);
this->connect(this->m_networkManagerAircraft, &QNetworkAccessManager::finished, this, &CIcaoDataReader::ps_parseAircraftIcaoData);
this->connect(this->m_networkManagerAirlines, &QNetworkAccessManager::finished, this, &CIcaoDataReader::ps_parseAirlineIcaoData);
}
CAircraftIcaoCodeList CIcaoDataReader::getAircraftIcaoCodes() const
{
QReadLocker l(&m_lockAircraft);
return m_aircraftIcaos;
}
CAirlineIcaoCodeList CIcaoDataReader::getAirlineIcaoCodes() const
{
QReadLocker l(&m_lockAirline);
return m_airlineIcaos;
}
void CIcaoDataReader::readInBackgroundThread()
{
bool s = QMetaObject::invokeMethod(this, "ps_read");
Q_ASSERT_X(s, Q_FUNC_INFO, "Invoke failed");
Q_UNUSED(s);
}
void CIcaoDataReader::ps_read()
{
this->threadAssertCheck();
Q_ASSERT(this->m_networkManagerAircraft);
Q_ASSERT(this->m_networkManagerAirlines);
Q_ASSERT(!m_urlAircraftIcao.isEmpty());
Q_ASSERT(!m_urlAirlineIcao.isEmpty());
QNetworkRequest requestAircraft(m_urlAircraftIcao);
QNetworkRequest requestAirline(m_urlAirlineIcao);
this->m_networkManagerAircraft->get(requestAircraft);
this->m_networkManagerAirlines->get(requestAirline);
}
QJsonArray CIcaoDataReader::splitReplyIntoArray(QNetworkReply *nwReply) const
{
this->threadAssertCheck();
QJsonArray array;
if (this->isFinished())
{
CLogMessage(this).debug() << Q_FUNC_INFO;
CLogMessage(this).info("Terminated ICAO data parsing process"); // for users
return array; // stop, terminate straight away, ending thread
}
if (nwReply->error() == QNetworkReply::NoError)
{
const QString dataFileData = nwReply->readAll();
nwReply->close(); // close asap
if (dataFileData.isEmpty()) { return array; }
QJsonDocument jsonResponse = QJsonDocument::fromJson(dataFileData.toUtf8());
QJsonObject jsonObject = jsonResponse.object();
QJsonArray jsonArray = jsonObject["rows"].toArray();
return jsonArray;
}
CLogMessage(this).warning("Reading data failed %1 %2") << nwReply->errorString() << nwReply->url().toString();
nwReply->abort();
return array;
}
bool BlackCore::CIcaoDataReader::checkIfFinished() const
{
if (!this->isFinished()) { return false; }
CLogMessage(this).debug() << Q_FUNC_INFO;
CLogMessage(this).info("Terminated ICAO data parsing process"); // for users
return true;
}
void CIcaoDataReader::ps_parseAircraftIcaoData(QNetworkReply *nwReplyPtr)
{
// wrap pointer, make sure any exit cleans up reply
// required to use delete later as object is created in a different thread
QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> nwReply(nwReplyPtr);
QJsonArray array = this->splitReplyIntoArray(nwReply.data());
if (array.isEmpty()) { return; }
CAircraftIcaoCodeList codes = CAircraftIcaoCodeList::fromDatabaseJson(array);
// this part needs to be synchronized
int n;
{
QWriteLocker wl(&this->m_lockAircraft);
this->m_aircraftIcaos = codes;
n = codes.size();
}
emit readAircraftIcaoCodes(n);
}
void CIcaoDataReader::ps_parseAirlineIcaoData(QNetworkReply *nwReplyPtr)
{
QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> nwReply(nwReplyPtr);
QJsonArray array = this->splitReplyIntoArray(nwReply.data());
if (array.isEmpty()) { return; }
CAirlineIcaoCodeList codes = CAirlineIcaoCodeList::fromDatabaseJson(array);
// this part needs to be synchronized
int n;
{
QWriteLocker wl(&this->m_lockAirline);
this->m_airlineIcaos = codes;
n = codes.size();
}
emit readAirlinesIcaoCodes(n);
}
} // namespace

View File

@@ -0,0 +1,83 @@
/* Copyright (C) 2015
* swift project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
//! \file
#ifndef BLACKCORE_ICAODATAREADER_H
#define BLACKCORE_ICAODATAREADER_H
#include "blackcoreexport.h"
#include "blackmisc/aviation/aircrafticaocodelist.h"
#include "blackmisc/aviation/airlineicaocodelist.h"
#include "blackmisc/threadedreader.h"
#include <QObject>
#include <QTimer>
#include <QNetworkReply>
#include <QReadWriteLock>
namespace BlackCore
{
//! Read bookings from VATSIM
class BLACKCORE_EXPORT CIcaoDataReader : public BlackMisc::CThreadedReader
{
Q_OBJECT
public:
//! Constructor
explicit CIcaoDataReader(QObject *owner, const QString &aircraftIcaoUrl, const QString &airlineIcaoUrl);
//! Get aircraft ICAO information
//! \threadsafe
BlackMisc::Aviation::CAircraftIcaoCodeList getAircraftIcaoCodes() const;
//! Get airline ICAO information
//! \threadsafe
BlackMisc::Aviation::CAirlineIcaoCodeList getAirlineIcaoCodes() const;
//! Start reading in own thread
void readInBackgroundThread();
signals:
//! Codes have been read
void readAircraftIcaoCodes(int number);
//! Codes have been read
void readAirlinesIcaoCodes(int number);
private slots:
//! Aircraft have been read
void ps_parseAircraftIcaoData(QNetworkReply *nwReply);
//! Airlines have been read
void ps_parseAirlineIcaoData(QNetworkReply *nwReply);
//! Read / re-read data file
void ps_read();
private:
QNetworkAccessManager *m_networkManagerAircraft = nullptr;
QNetworkAccessManager *m_networkManagerAirlines = nullptr;
BlackMisc::Aviation::CAircraftIcaoCodeList m_aircraftIcaos;
BlackMisc::Aviation::CAirlineIcaoCodeList m_airlineIcaos;
QString m_urlAircraftIcao;
QString m_urlAirlineIcao;
mutable QReadWriteLock m_lockAirline;
mutable QReadWriteLock m_lockAircraft;
//! Check if terminated or error, otherwise split into array of objects
QJsonArray splitReplyIntoArray(QNetworkReply *nwReply) const;
//! Check if thread has been finished
bool checkIfFinished() const;
};
}
#endif // guard

View File

@@ -23,9 +23,7 @@
namespace BlackCore
{
/*!
* Read bookings from VATSIM
*/
//! Read bookings from VATSIM
class BLACKCORE_EXPORT CVatsimBookingReader : public BlackMisc::CThreadedReader
{
Q_OBJECT
@@ -46,10 +44,10 @@ namespace BlackCore
void ps_read();
private:
QString m_serviceUrl; /*!< URL of the service */
QString m_serviceUrl; //!< URL of the service
QNetworkAccessManager *m_networkManager = nullptr;
signals:
signals:
//! Bookings have been read and converted to BlackMisc::Aviation::CAtcStationList
void dataRead(const BlackMisc::Aviation::CAtcStationList &bookedStations);
};

View File

@@ -123,8 +123,8 @@ namespace BlackCore
CUserList CVatsimDataFileReader::getUsersForCallsigns(const CCallsignSet &callsigns)
{
CUserList users;
if (callsigns.isEmpty()) return users;
foreach(CCallsign callsign, callsigns)
if (callsigns.isEmpty()) { return users; }
for (const CCallsign &callsign : callsigns)
{
users.push_back(this->getPilotsForCallsign(callsign));
users.push_back(this->getControllersForCallsign(callsign));
@@ -135,7 +135,7 @@ namespace BlackCore
void CVatsimDataFileReader::readInBackgroundThread()
{
bool s = QMetaObject::invokeMethod(this, "ps_read");
Q_ASSERT(s);
Q_ASSERT_X(s, Q_FUNC_INFO, "Invoke failed");
Q_UNUSED(s);
}
@@ -181,7 +181,7 @@ namespace BlackCore
if (dataFileData.isEmpty()) return;
QStringList lines = dataFileData.split(QRegExp("[\r\n]"), QString::SkipEmptyParts);
if (lines.isEmpty()) return;
if (lines.isEmpty()) { return; }
// build on local vars for thread safety
CServerList voiceServers;
@@ -198,7 +198,7 @@ namespace BlackCore
if (this->isFinished())
{
CLogMessage(this).debug() << Q_FUNC_INFO;
CLogMessage(this).info("terminated booking parsing process"); // for users
CLogMessage(this).info("Terminated booking parsing process"); // for users
return; // stop, terminate straight away, ending thread
}
@@ -290,7 +290,7 @@ namespace BlackCore
}
else
{
Q_ASSERT_X(false, "CVatsimDataFileReader::loadFinished", "Wrong client type");
Q_ASSERT_X(false, Q_FUNC_INFO, "Wrong client type");
}
}
break;
@@ -335,18 +335,19 @@ namespace BlackCore
} // switch section
// this part needs to be synchronized
{
QWriteLocker wl(&this->m_lock);
this->setUpdateTimestamp(updateTimestampFromFile);
this->m_aircraft = aircraft;
this->m_atcStations = atcStations;
this->m_voiceServers = voiceServers;
this->m_fsdServers = fsdServers;
this->m_voiceCapabilities = voiceCapabilities;
}
} // for each line
// this part needs to be synchronized
{
QWriteLocker wl(&this->m_lock);
this->setUpdateTimestamp(updateTimestampFromFile);
this->m_aircraft = aircraft;
this->m_atcStations = atcStations;
this->m_voiceServers = voiceServers;
this->m_fsdServers = fsdServers;
this->m_voiceCapabilities = voiceCapabilities;
}
// warnings, if required
if (!illegalIcaoCodes.isEmpty())
{
@@ -354,7 +355,7 @@ namespace BlackCore
}
// data read finished
emit this->dataRead();
emit this->dataRead(lines.count());
}
else
{

View File

@@ -135,7 +135,7 @@ namespace BlackCore
signals:
//! Data have been read
void dataRead();
void dataRead(int lines);
};
}

View File

@@ -0,0 +1,180 @@
/* Copyright (C) 2015
* swift project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
#include "blackmisc/aviation/aircrafticaocode.h"
#include "blackmisc/propertyindex.h"
#include "blackmisc/blackmiscfreefunctions.h"
#include "blackmisc/variant.h"
#include <tuple>
#include <QRegularExpression>
namespace BlackMisc
{
namespace Aviation
{
CAircraftIcaoCode::CAircraftIcaoCode(const QString &icao, const QString &combinedType, const QString &manufacturer, const QString &model, const QString &wtc, bool military, bool realworld, bool legacy)
: m_aircraftDesignator(icao.trimmed().toUpper()), m_aircraftCombinedType(combinedType.trimmed().toUpper()), m_manufacturer(manufacturer.trimmed()),
m_modelDescription(model.trimmed()), m_wtc(wtc.trimmed().toUpper()), m_military(military), m_realworld(realworld), m_legacy(legacy)
{}
QString CAircraftIcaoCode::convertToQString(bool i18n) const
{
Q_UNUSED(i18n);
QString s(this->m_aircraftDesignator);
if (this->hasAircraftCombinedType()) s.append(" ").append(this->m_aircraftCombinedType);
if (this->hasValidWtc()) s.append(" ").append(this->m_wtc);
return s;
}
bool CAircraftIcaoCode::hasAircraftDesignator() const
{
return !this->m_aircraftDesignator.isEmpty();
}
bool CAircraftIcaoCode::hasKnownAircraftDesignator() const
{
return (this->hasAircraftDesignator() && this->getAircraftDesignator() != "ZZZZ");
}
QString CAircraftIcaoCode::getEngineType() const
{
if (this->m_aircraftCombinedType.length() != 3) return "";
return this->m_aircraftCombinedType.right(1);
}
bool CAircraftIcaoCode::isVtol() const
{
// special designators
if (this->m_aircraftDesignator.length() == 4)
{
if (
this->m_aircraftDesignator == "BALL" ||
this->m_aircraftDesignator == "SHIP" ||
this->m_aircraftDesignator == "GYRO" ||
this->m_aircraftDesignator == "UHEL"
) { return true; }
}
if (!m_aircraftCombinedType.isEmpty())
{
if (
this->m_aircraftCombinedType.startsWith('G') || // gyrocopter
this->m_aircraftCombinedType.startsWith('H') || // helicopter
this->m_aircraftCombinedType.startsWith('T') // tilt wing
) { return true; }
}
return false;
}
CVariant CAircraftIcaoCode::propertyByIndex(const BlackMisc::CPropertyIndex &index) const
{
if (index.isMyself()) { return this->toCVariant(); }
ColumnIndex i = index.frontCasted<ColumnIndex>();
switch (i)
{
case IndexAircraftDesignator:
return CVariant::fromValue(this->m_aircraftDesignator);
case IndexCombinedAircraftType:
return CVariant::fromValue(this->m_aircraftCombinedType);
case IndexModelDescription:
return CVariant::fromValue(this->m_modelDescription);
case IndexManufacturer:
return CVariant::fromValue(this->m_manufacturer);
case IndexWtc:
return CVariant::fromValue(this->m_wtc);
case IndexIsVtol:
return CVariant::fromValue(this->isVtol());
case IndexIsLegacy:
return CVariant::fromValue(this->m_legacy);
case IndexIsMilitary:
return CVariant::fromValue(this->m_military);
case IndexIsRealworld:
return CVariant::fromValue(this->m_realworld);
default:
return CValueObject::propertyByIndex(index);
}
}
void CAircraftIcaoCode::setPropertyByIndex(const CVariant &variant, const BlackMisc::CPropertyIndex &index)
{
if (index.isMyself())
{
this->convertFromCVariant(variant);
return;
}
ColumnIndex i = index.frontCasted<ColumnIndex>();
switch (i)
{
case IndexAircraftDesignator:
this->setAircraftDesignator(variant.value<QString>());
break;
case IndexCombinedAircraftType:
this->setAircraftCombinedType(variant.value<QString>());
break;
case IndexModelDescription:
this->setModelDescription(variant.value<QString>());
break;
case IndexManufacturer:
this->setManufacturer(variant.value<QString>());
break;
case IndexWtc:
this->setWtc(variant.value<QString>());
break;
case IndexIsLegacy:
this->m_legacy = variant.toBool();
break;
case IndexIsMilitary:
this->m_military = variant.toBool();
break;
default:
CValueObject::setPropertyByIndex(variant, index);
break;
}
}
bool CAircraftIcaoCode::isValidDesignator(const QString &designator)
{
static QRegularExpression regexp("^[A-Z]+[A-Z0-9]*$");
if (designator.length() < 2 || designator.length() > 5) { return false; }
return (regexp.match(designator).hasMatch());
}
bool CAircraftIcaoCode::isValidCombinedType(const QString &combinedType)
{
static QRegularExpression regexp("^[A-Z][0-9][A-Z]$");
if (combinedType.length() != 3) return false;
return (regexp.match(combinedType).hasMatch());
}
CAircraftIcaoCode CAircraftIcaoCode::fromDatabaseJson(const QJsonObject &json)
{
QJsonArray inner = json["cell"].toArray();
if (inner.isEmpty()) { return CAircraftIcaoCode(); }
QString combined(
inner.at(4).toString() +
inner.at(6).toString() +
inner.at(5).toString()
);
CAircraftIcaoCode code(
inner.at(1).toString(),
combined,
inner.at(2).toString(), // manufacturer
inner.at(3).toString(), // model
inner.at(7).toString(), // WTC
false, // mil
inner.at(8).toString().startsWith("Y"), // real
inner.at(9).toString().startsWith("Y") // legacy
);
return code;
}
} // namespace
} // namespace

View File

@@ -0,0 +1,142 @@
/* Copyright (C) 2015
* swift project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
//! \file
#ifndef BLACKMISC_AVIATION_AIRCRAFTICAOCODE_H
#define BLACKMISC_AVIATION_AIRCRAFTICAOCODE_H
#include "blackmisc/blackmiscexport.h"
#include "blackmisc/valueobject.h"
#include "blackmisc/propertyindex.h"
#include "blackmisc/blackmiscfreefunctions.h"
namespace BlackMisc
{
namespace Aviation
{
//! Value object for ICAO classification
class BLACKMISC_EXPORT CAircraftIcaoCode : public CValueObject<CAircraftIcaoCode>
{
public:
//! Properties by index
enum ColumnIndex
{
IndexAircraftDesignator = BlackMisc::CPropertyIndex::GlobalIndexCAircraftIcaoCode,
IndexCombinedAircraftType,
IndexManufacturer,
IndexModelDescription,
IndexWtc,
IndexIsRealworld,
IndexIsMilitary,
IndexIsLegacy,
IndexIsVtol
};
//! Default constructor.
CAircraftIcaoCode() = default;
//! Constructor
CAircraftIcaoCode(const QString &icao, const QString &combinedType, const QString &manufacturer,
const QString &model, const QString &wtc, bool military, bool realworld, bool legacy);
//! Get ICAO designator, e.g. "B737"
const QString &getAircraftDesignator() const { return m_aircraftDesignator; }
//! Set ICAO designator, e.g. "B737"
void setAircraftDesignator(const QString &icaoDesignator) { this->m_aircraftDesignator = icaoDesignator.trimmed().toUpper(); }
//! Aircraft designator?
bool hasAircraftDesignator() const;
//! Has designator and designator is not "ZZZZ"
bool hasKnownAircraftDesignator() const;
//! Get type, e.g. "L2J"
const QString &getAircraftCombinedType() const { return this->m_aircraftCombinedType; }
//! Combined type available?
bool hasAircraftCombinedType() const { return this->getAircraftCombinedType().length() == 3; }
//! Get engine type, e.g. "J"
QString getEngineType() const;
//! Set type
void setAircraftCombinedType(const QString &type) { this->m_aircraftCombinedType = type.trimmed().toUpper(); }
//! Get model description, e.g. "A-330-200"
const QString &getModelDescription() const { return m_modelDescription; }
//! Set the model description
void setModelDescription(const QString &modelDescription) { m_modelDescription = modelDescription.trimmed(); }
//! Get manufacturer, e.g. "Airbus"
const QString &getManufacturer() const { return m_manufacturer; }
//! Set the manufacturer
void setManufacturer(const QString &manufacturer) { m_manufacturer = manufacturer.trimmed(); }
//! Get WTC
const QString &getWtc() const { return m_wtc; }
//! Set WTC
void setWtc(const QString &wtc) { m_wtc = wtc.trimmed().toUpper(); }
//! Valid WTC code?
bool hasValidWtc() const { return !m_wtc.isEmpty(); }
//! Is VTOL aircraft (helicopter, tilt wing)
bool isVtol() const;
//! \copydoc CValueObject::propertyByIndex
CVariant propertyByIndex(const BlackMisc::CPropertyIndex &index) const;
//! \copydoc CValueObject::setPropertyByIndex
void setPropertyByIndex(const CVariant &variant, const BlackMisc::CPropertyIndex &index);
//! \copydoc CValueObject::convertToQString
QString convertToQString(bool i18n = false) const;
//! Valid designator?
static bool isValidDesignator(const QString &designator);
//! Valid combined type
static bool isValidCombinedType(const QString &combinedType);
//! From our database JSON format
static CAircraftIcaoCode fromDatabaseJson(const QJsonObject &json);
private:
BLACK_ENABLE_TUPLE_CONVERSION(CAircraftIcaoCode)
QString m_aircraftDesignator; //!< "B737"
QString m_aircraftCombinedType; //!< "L2J"
QString m_manufacturer; //!< "Airbus"
QString m_modelDescription; //!< "A-330-200"
QString m_wtc; //!< wake turbulence "M","H" "L/M", "L"
bool m_military = false;
bool m_realworld = true; //!< real world aircraft
bool m_legacy = true; //!< legacy code
};
} // namespace
} // namespace
Q_DECLARE_METATYPE(BlackMisc::Aviation::CAircraftIcaoCode)
BLACK_DECLARE_TUPLE_CONVERSION(BlackMisc::Aviation::CAircraftIcaoCode, (
o.m_aircraftDesignator,
o.m_aircraftCombinedType,
o.m_manufacturer,
o.m_modelDescription,
o.m_wtc,
o.m_military,
o.m_realworld,
o.m_legacy
))
#endif // guard

View File

@@ -0,0 +1,32 @@
/* Copyright (C) 2015
* swift project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
#include "aircrafticaocodelist.h"
namespace BlackMisc
{
namespace Aviation
{
CAircraftIcaoCodeList::CAircraftIcaoCodeList(const CSequence<CAircraftIcaoCode> &other) :
CSequence<CAircraftIcaoCode>(other)
{ }
CAircraftIcaoCodeList CAircraftIcaoCodeList::fromDatabaseJson(const QJsonArray &array)
{
CAircraftIcaoCodeList codes;
for (const QJsonValue &value : array)
{
codes.push_back(CAircraftIcaoCode::fromDatabaseJson(value.toObject()));
}
return codes;
}
} // namespace
} // namespace

View File

@@ -0,0 +1,51 @@
/* Copyright (C) 2015
* swift project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
//! \file
#ifndef BLACKMISC_AVIATION_AIRCRAFTICAOCODELIST_H
#define BLACKMISC_AVIATION_AIRCRAFTICAOCODELIST_H
#include "aircrafticaocode.h"
#include "blackmisc/blackmiscexport.h"
#include "blackmisc/collection.h"
#include "blackmisc/sequence.h"
#include <initializer_list>
namespace BlackMisc
{
namespace Aviation
{
//! Value object encapsulating a list of ICAO codes.
class BLACKMISC_EXPORT CAircraftIcaoCodeList :
public CSequence<CAircraftIcaoCode>,
public BlackMisc::Mixin::MetaType<CAircraftIcaoCodeList>
{
public:
BLACKMISC_DECLARE_USING_MIXIN_METATYPE(CAircraftIcaoCodeList)
//! Default constructor.
CAircraftIcaoCodeList() = default;
//! Construct from a base class object.
CAircraftIcaoCodeList(const CSequence<CAircraftIcaoCode> &other);
//! From our database JSON format
static CAircraftIcaoCodeList fromDatabaseJson(const QJsonArray &array);
};
} //namespace
} // namespace
Q_DECLARE_METATYPE(BlackMisc::Aviation::CAircraftIcaoCodeList)
Q_DECLARE_METATYPE(BlackMisc::CCollection<BlackMisc::Aviation::CAircraftIcaoCode>)
Q_DECLARE_METATYPE(BlackMisc::CSequence<BlackMisc::Aviation::CAircraftIcaoCode>)
#endif //guard

View File

@@ -0,0 +1,113 @@
/* Copyright (C) 2013
* swift project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
#include "blackmisc/aviation/airlineicaocode.h"
#include "blackmisc/propertyindex.h"
#include "blackmisc/blackmiscfreefunctions.h"
#include "blackmisc/variant.h"
#include <tuple>
#include <QRegularExpression>
namespace BlackMisc
{
namespace Aviation
{
CAirlineIcaoCode::CAirlineIcaoCode(const QString &airlineDesignator)
: m_designator(airlineDesignator.trimmed().toUpper())
{}
CAirlineIcaoCode::CAirlineIcaoCode(const QString &airlineDesignator, const QString &airlineName, const QString &country, const QString &telephony, bool virtualAirline)
: m_designator(airlineDesignator), m_name(airlineName), m_country(country), m_telephonyDesignator(telephony), m_isVa(virtualAirline)
{}
QString CAirlineIcaoCode::convertToQString(bool i18n) const
{
Q_UNUSED(i18n);
QString s(this->m_designator);
return s;
}
CVariant CAirlineIcaoCode::propertyByIndex(const BlackMisc::CPropertyIndex &index) const
{
if (index.isMyself()) { return this->toCVariant(); }
ColumnIndex i = index.frontCasted<ColumnIndex>();
switch (i)
{
case IndexAirlineDesignator:
return CVariant::fromValue(this->m_designator);
case IndexAirlineCountry:
return CVariant::fromValue(this->m_country);
case IndexAirlineName:
return CVariant::fromValue(this->m_name);
case IndexTelephonyDesignator:
return CVariant::fromValue(this->m_telephonyDesignator);
case IndexIsVirtualAirline:
return CVariant::fromValue(this->m_isVa);
default:
return CValueObject::propertyByIndex(index);
}
}
void CAirlineIcaoCode::setPropertyByIndex(const CVariant &variant, const BlackMisc::CPropertyIndex &index)
{
if (index.isMyself())
{
this->convertFromCVariant(variant);
return;
}
ColumnIndex i = index.frontCasted<ColumnIndex>();
switch (i)
{
case IndexAirlineDesignator:
this->setDesignator(variant.value<QString>());
break;
case IndexAirlineCountry:
this->setCountry(variant.value<QString>());
break;
case IndexAirlineName:
this->setName(variant.value<QString>());
break;
case IndexTelephonyDesignator:
this->setTelephonyDesignator(variant.value<QString>());
break;
case IndexIsVirtualAirline:
this->setVirtualAirline(variant.toBool());
break;
default:
CValueObject::setPropertyByIndex(variant, index);
break;
}
}
bool CAirlineIcaoCode::isValidAirlineDesignator(const QString &airline)
{
static QRegularExpression regexp("^[A-Z]+[A-Z0-9]*$");
if (airline.length() < 2 || airline.length() > 5) return false;
return (regexp.match(airline).hasMatch());
}
CAirlineIcaoCode CAirlineIcaoCode::fromDatabaseJson(const QJsonObject &json)
{
QJsonArray inner = json["cell"].toArray();
if (inner.isEmpty()) { return CAirlineIcaoCode(); }
CAirlineIcaoCode code(
inner.at(1).toString(),
inner.at(3).toString(), // name
inner.at(4).toString(), // country
inner.at(2).toString(), // telephony
inner.at(5).toString().startsWith("Y") // VA
);
return code;
}
} // namespace
} // namespace

View File

@@ -0,0 +1,115 @@
/* Copyright (C) 2013
* swift project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
//! \file
#ifndef BLACKMISC_AVIATION_AIRLINEICAOCODE_H
#define BLACKMISC_AVIATION_AIRLINEICAOCODE_H
#include "blackmisc/blackmiscexport.h"
#include "blackmisc/valueobject.h"
#include "blackmisc/propertyindex.h"
#include "blackmisc/blackmiscfreefunctions.h"
namespace BlackMisc
{
namespace Aviation
{
//! Value object for ICAO classification
class BLACKMISC_EXPORT CAirlineIcaoCode : public CValueObject<CAirlineIcaoCode>
{
public:
//! Properties by index
enum ColumnIndex
{
IndexAirlineDesignator = BlackMisc::CPropertyIndex::GlobalIndexCAirlineIcaoCode,
IndexAirlineName,
IndexAirlineCountry,
IndexTelephonyDesignator,
IndexIsVirtualAirline
};
//! Default constructor.
CAirlineIcaoCode() = default;
//! Constructor.
CAirlineIcaoCode(const QString &airlineDesignator);
//! Constructor.
CAirlineIcaoCode(const QString &airlineDesignator, const QString &airlineName, const QString &country, const QString &telephony, bool virtualAirline);
//! Get airline, e.g. "DLH"
const QString &getDesignator() const { return this->m_designator; }
//! Set airline, e.g. "DLH"
void setDesignator(const QString &icaoDesignator) { this->m_designator = icaoDesignator.trimmed().toUpper(); }
//! Get country, e.g. "France"
const QString &getCountry() const { return this->m_country; }
//! Set country
void setCountry(const QString &country) { this->m_country = country.trimmed(); }
//! Get name, e.g. "Lufthansa"
const QString &getName() const { return this->m_name; }
//! Set name
void setName(const QString &name) { this->m_name = name.trimmed(); }
//! Telephony designator such as "Speedbird"
const QString &getTelephonyDesignator() const { return this->m_telephonyDesignator; }
//! Telephony designator such as "Speedbird"
void setTelephonyDesignator(const QString &telephony) { this->m_telephonyDesignator = telephony.trimmed().toUpper(); }
//! Virtual airline
bool isVirtualAirline() const { return m_isVa; }
//! Virtual airline
void setVirtualAirline(bool va) { m_isVa = va; }
//! Airline available?
bool hasDesignator() const { return !this->m_designator.isEmpty(); }
//! \copydoc CValueObject::convertToQString
QString convertToQString(bool i18n = false) const;
//! \copydoc CValueObject::propertyByIndex
CVariant propertyByIndex(const BlackMisc::CPropertyIndex &index) const;
//! \copydoc CValueObject::setPropertyByIndex
void setPropertyByIndex(const CVariant &variant, const BlackMisc::CPropertyIndex &index);
//! Valid designator?
static bool isValidAirlineDesignator(const QString &airline);
//! From our DB JSON
static CAirlineIcaoCode fromDatabaseJson(const QJsonObject &json);
private:
BLACK_ENABLE_TUPLE_CONVERSION(CAirlineIcaoCode)
QString m_designator; //!< "DLH"
QString m_name; //!< "Lufthansa"
QString m_country; //!< "Poland"
QString m_telephonyDesignator; //!< "Speedbird"
bool m_isVa = false;
};
} // namespace
} // namespace
Q_DECLARE_METATYPE(BlackMisc::Aviation::CAirlineIcaoCode)
BLACK_DECLARE_TUPLE_CONVERSION(BlackMisc::Aviation::CAirlineIcaoCode, (
o.m_designator,
o.m_name,
o.m_country,
o.m_telephonyDesignator,
o.m_isVa
))
#endif // guard

View File

@@ -0,0 +1,30 @@
/* Copyright (C) 2015
* swift project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
#include "airlineicaocodelist.h"
namespace BlackMisc
{
namespace Aviation
{
CAirlineIcaoCodeList::CAirlineIcaoCodeList(const CSequence<CAirlineIcaoCode> &other) :
CSequence<CAirlineIcaoCode>(other)
{ }
CAirlineIcaoCodeList CAirlineIcaoCodeList::fromDatabaseJson(const QJsonArray &array)
{
CAirlineIcaoCodeList codes;
for (const QJsonValue &value : array)
{
codes.push_back(CAirlineIcaoCode::fromDatabaseJson(value.toObject()));
}
return codes;
}
} // namespace
} // namespace

View File

@@ -0,0 +1,50 @@
/* Copyright (C) 2015
* swift project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
//! \file
#ifndef BLACKMISC_AVIATION_AIRLINEICAOCODELIST_H
#define BLACKMISC_AVIATION_AIRLINEICAOCODELIST_H
#include "airlineicaocode.h"
#include "blackmisc/blackmiscexport.h"
#include "blackmisc/collection.h"
#include "blackmisc/sequence.h"
#include <initializer_list>
namespace BlackMisc
{
namespace Aviation
{
//! Value object encapsulating a list of ICAO codes.
class BLACKMISC_EXPORT CAirlineIcaoCodeList :
public CSequence<CAirlineIcaoCode>,
public BlackMisc::Mixin::MetaType<CAirlineIcaoCodeList>
{
public:
BLACKMISC_DECLARE_USING_MIXIN_METATYPE(CAirlineIcaoCodeList)
//! Default constructor.
CAirlineIcaoCodeList() = default;
//! Construct from a base class object.
CAirlineIcaoCodeList(const CSequence<CAirlineIcaoCode> &other);
//! From our DB JSON
static CAirlineIcaoCodeList fromDatabaseJson(const QJsonArray &array);
};
} //namespace
} // namespace
Q_DECLARE_METATYPE(BlackMisc::Aviation::CAirlineIcaoCodeList)
Q_DECLARE_METATYPE(BlackMisc::CCollection<BlackMisc::Aviation::CAirlineIcaoCode>)
Q_DECLARE_METATYPE(BlackMisc::CSequence<BlackMisc::Aviation::CAirlineIcaoCode>)
#endif //guard

View File

@@ -20,7 +20,7 @@ namespace BlackMisc
{
namespace Aviation
{
//! Value object encapsulating information of a callsign.
//! Value object encapsulating information of airport ICAO data.
class BLACKMISC_EXPORT CAirportIcao : public CValueObject<CAirportIcao>
{
public:

View File

@@ -51,15 +51,18 @@ namespace BlackMisc
GlobalIndexCNameVariantPair = 300,
GlobalIndexTimestampBased = 400,
GlobalIndexCCallsign = 1000,
GlobalIndexCAircraftIcao = 1100,
GlobalIndexCAircraft = 1200,
GlobalIndexCAircraftSituation = 1300,
GlobalIndexCAtcStation = 1400,
GlobalIndexCAirport = 1500,
GlobalIndexCAircraftParts = 1600,
GlobalIndexCAircraftLights = 1700,
GlobalIndexCAircraft = 1100,
GlobalIndexCAircraftSituation = 1200,
GlobalIndexCAtcStation = 1300,
GlobalIndexCAirport = 1400,
GlobalIndexCAircraftParts = 1500,
GlobalIndexCAircraftLights = 1600,
GlobalIndexCModulator = 2000,
GlobalIndexCTransponder = 2100,
GlobalIndexCAircraftIcao = 2500,
GlobalIndexCAircraftIcaoCode = 2600,
GlobalIndexCAirlineIcaoCode = 2700,
GlobalIndexCAirportIcaoCode = 2800,
GlobalIndexICoordinateGeodetic = 3000,
GlobalIndexCCoordinateGeodetic = 3100,
GlobalIndexCClient = 4000,

View File

@@ -11,7 +11,6 @@
namespace BlackMisc
{
CThreadedReader::CThreadedReader(QObject *owner, const QString &name) :
CContinuousWorker(owner, name),
m_updateTimer(new QTimer(this))

View File

@@ -22,10 +22,8 @@
namespace BlackMisc
{
/*!
* Support for threaded based reading and parsing tasks such
* as data files via http, or file system and parsing (such as FSX models)
*/
//! Support for threaded based reading and parsing tasks such
//! as data files via http, or file system and parsing (such as FSX models)
class BLACKMISC_EXPORT CThreadedReader : public CContinuousWorker
{
public:
@@ -47,11 +45,9 @@ namespace BlackMisc
//! \copydoc CContinuousWorker::cleanup
virtual void cleanup() override;
/*!
* Set the update time
* \param updatePeriodMs <=0 stops the timer
* \threadsafe
*/
//! Set the update time
//! \param updatePeriodMs <=0 stops the timer
//! \threadsafe
void setInterval(int updatePeriodMs);
//! Get the timer interval (ms)