refs #219, load flight plan

* fixed issue with parsing, only default locale is used. Now user's local possible
* allow to load FP for other callsigns as well (voice capabilities)
* Improved handling of CTime, inclusive bug fixes and time formatting
* Max. lengths for FP fields as const value (so we can change it if required)
* Load FP from GUI component
* Samples for PQ classes
* Adjusted depending classes (e.g. client)
This commit is contained in:
Klaus Basan
2014-06-05 02:33:03 +02:00
parent e823f87bab
commit 226edda23b
17 changed files with 293 additions and 147 deletions

View File

@@ -15,9 +15,11 @@ namespace BlackMiscTest
*/
int CSamplesPhysicalQuantities::samples()
{
QVariant parsedPq = CPqString::parseToVariant("100 km/h");
parsedPq = CPqString::parseToVariant("-33ft");
parsedPq = CPqString::parseToVariant("666");
CSpeed parsedPq1 = CPqString::parseToVariant("100 km/h").value<CSpeed>();
CLength parsedPq2 = CPqString::parseToVariant("-33ft").value<CLength>();
QVariant parsedPq3 = CPqString::parseToVariant("666");
qDebug() << "parsed" << parsedPq1 << parsedPq2 << parsedPq3;
CSpeed speedParsed = CPqString::parse<CSpeed>("111.33ft/s");
CFrequency frequencyParsed = CPqString::parse<CFrequency>("122.8MHz");
qDebug() << "parsed" << speedParsed << speedParsed.valueRoundedWithUnit(2, true) << frequencyParsed << frequencyParsed.valueRoundedWithUnit(2, true);

View File

@@ -252,26 +252,29 @@ void Client::sendFlightPlanCmd(QTextStream &args)
QString flightRulesString;
QString route;
args >> equipmentIcao >> originAirportIcao >> destinationAirportIcao >> alternateAirportIcao >> takeoffTimePlanned >> takeoffTimeActual
>> enrouteTime >> fuelTime >> cruiseAltitude >> cruiseTrueAirspeed >> flightRulesString >> route;
>> enrouteTime >> fuelTime >> cruiseAltitude >> cruiseTrueAirspeed >> flightRulesString >> route;
BlackMisc::Aviation::CFlightPlan::FlightRules flightRules;
if (flightRulesString == "IFR") { flightRules = BlackMisc::Aviation::CFlightPlan::IFR; }
else if (flightRulesString == "SVFR") { flightRules = BlackMisc::Aviation::CFlightPlan::SVFR; }
else { flightRules = BlackMisc::Aviation::CFlightPlan::VFR; }
BlackMisc::Aviation::CFlightPlan fp(equipmentIcao, originAirportIcao, destinationAirportIcao, alternateAirportIcao,
QDateTime::fromString(takeoffTimePlanned, "hhmm"), QDateTime::fromString(takeoffTimeActual, "hhmm"),
BlackMisc::PhysicalQuantities::CTime(enrouteTime, BlackMisc::PhysicalQuantities::CTimeUnit::hrmin()),
BlackMisc::PhysicalQuantities::CTime(fuelTime, BlackMisc::PhysicalQuantities::CTimeUnit::hrmin()),
BlackMisc::Aviation::CAltitude(cruiseAltitude, BlackMisc::Aviation::CAltitude::MeanSeaLevel, BlackMisc::PhysicalQuantities::CLengthUnit::ft()),
BlackMisc::PhysicalQuantities::CSpeed(cruiseTrueAirspeed, BlackMisc::PhysicalQuantities::CSpeedUnit::kts()),
flightRules, route, args.readAll());
BlackMisc::Aviation::CFlightPlan
fp(equipmentIcao, originAirportIcao, destinationAirportIcao, alternateAirportIcao,
QDateTime::fromString(takeoffTimePlanned, "hhmm"), QDateTime::fromString(takeoffTimeActual, "hhmm"),
BlackMisc::PhysicalQuantities::CTime(enrouteTime, BlackMisc::PhysicalQuantities::CTimeUnit::hrmin()),
BlackMisc::PhysicalQuantities::CTime(fuelTime, BlackMisc::PhysicalQuantities::CTimeUnit::hrmin()),
BlackMisc::Aviation::CAltitude(cruiseAltitude, BlackMisc::Aviation::CAltitude::MeanSeaLevel, BlackMisc::PhysicalQuantities::CLengthUnit::ft()),
BlackMisc::PhysicalQuantities::CSpeed(cruiseTrueAirspeed, BlackMisc::PhysicalQuantities::CSpeedUnit::kts()),
flightRules, route, args.readAll());
emit sendFlightPlan(fp);
}
void Client::sendFlightPlanQueryCmd(QTextStream &)
void Client::sendFlightPlanQueryCmd(QTextStream &args)
{
emit sendFlightPlanQuery();
QString callsign;
args >> callsign;
emit sendFlightPlanQuery(callsign);
}
void Client::sendServerQueryCmd(QTextStream &args)
@@ -331,13 +334,13 @@ void Client::setOwnAircraftCmd(QTextStream &args)
QString xpdrMode;
args >> lat >> lon >> alt >> hdg >> pitch >> bank >> gs >> com1 >> com2 >> xpdrCode >> xpdrMode;
BlackMisc::Aviation::CAircraft aircraft("", BlackMisc::Network::CUser(), BlackMisc::Aviation::CAircraftSituation(
BlackMisc::Geo::CCoordinateGeodetic(lat, lon, 0),
BlackMisc::Aviation::CAltitude(alt, BlackMisc::Aviation::CAltitude::MeanSeaLevel, BlackMisc::PhysicalQuantities::CLengthUnit::ft()),
BlackMisc::Aviation::CHeading(hdg, BlackMisc::Aviation::CHeading::True, BlackMisc::PhysicalQuantities::CAngleUnit::deg()),
BlackMisc::PhysicalQuantities::CAngle(pitch, BlackMisc::PhysicalQuantities::CAngleUnit::deg()),
BlackMisc::PhysicalQuantities::CAngle(bank, BlackMisc::PhysicalQuantities::CAngleUnit::deg()),
BlackMisc::PhysicalQuantities::CSpeed(gs, BlackMisc::PhysicalQuantities::CSpeedUnit::kts())
));
BlackMisc::Geo::CCoordinateGeodetic(lat, lon, 0),
BlackMisc::Aviation::CAltitude(alt, BlackMisc::Aviation::CAltitude::MeanSeaLevel, BlackMisc::PhysicalQuantities::CLengthUnit::ft()),
BlackMisc::Aviation::CHeading(hdg, BlackMisc::Aviation::CHeading::True, BlackMisc::PhysicalQuantities::CAngleUnit::deg()),
BlackMisc::PhysicalQuantities::CAngle(pitch, BlackMisc::PhysicalQuantities::CAngleUnit::deg()),
BlackMisc::PhysicalQuantities::CAngle(bank, BlackMisc::PhysicalQuantities::CAngleUnit::deg()),
BlackMisc::PhysicalQuantities::CSpeed(gs, BlackMisc::PhysicalQuantities::CSpeedUnit::kts())
));
aircraft.setCom1System(BlackMisc::Aviation::CComSystem("COM1", BlackMisc::PhysicalQuantities::CFrequency(com1, BlackMisc::PhysicalQuantities::CFrequencyUnit::MHz())));
aircraft.setCom2System(BlackMisc::Aviation::CComSystem("COM2", BlackMisc::PhysicalQuantities::CFrequency(com2, BlackMisc::PhysicalQuantities::CFrequencyUnit::MHz())));
aircraft.setTransponder(BlackMisc::Aviation::CTransponder("Transponder", xpdrCode, xpdrMode));
@@ -351,7 +354,7 @@ void Client::setOwnAircraftPositionCmd(QTextStream &args)
double alt;
args >> lat >> lon >> alt;
emit setOwnAircraftPosition(BlackMisc::Geo::CCoordinateGeodetic(lat, lon, 0),
BlackMisc::Aviation::CAltitude(alt, BlackMisc::Aviation::CAltitude::MeanSeaLevel, BlackMisc::PhysicalQuantities::CLengthUnit::ft()));
BlackMisc::Aviation::CAltitude(alt, BlackMisc::Aviation::CAltitude::MeanSeaLevel, BlackMisc::PhysicalQuantities::CLengthUnit::ft()));
}
void Client::setOwnAircraftSituationCmd(QTextStream &args)
@@ -365,13 +368,13 @@ void Client::setOwnAircraftSituationCmd(QTextStream &args)
double gs;
args >> lat >> lon >> alt >> hdg >> pitch >> bank >> gs;
emit setOwnAircraftSituation(BlackMisc::Aviation::CAircraftSituation(
BlackMisc::Geo::CCoordinateGeodetic(lat, lon, 0),
BlackMisc::Aviation::CAltitude(alt, BlackMisc::Aviation::CAltitude::MeanSeaLevel, BlackMisc::PhysicalQuantities::CLengthUnit::ft()),
BlackMisc::Aviation::CHeading(hdg, BlackMisc::Aviation::CHeading::True, BlackMisc::PhysicalQuantities::CAngleUnit::deg()),
BlackMisc::PhysicalQuantities::CAngle(pitch, BlackMisc::PhysicalQuantities::CAngleUnit::deg()),
BlackMisc::PhysicalQuantities::CAngle(bank, BlackMisc::PhysicalQuantities::CAngleUnit::deg()),
BlackMisc::PhysicalQuantities::CSpeed(gs, BlackMisc::PhysicalQuantities::CSpeedUnit::kts())
));
BlackMisc::Geo::CCoordinateGeodetic(lat, lon, 0),
BlackMisc::Aviation::CAltitude(alt, BlackMisc::Aviation::CAltitude::MeanSeaLevel, BlackMisc::PhysicalQuantities::CLengthUnit::ft()),
BlackMisc::Aviation::CHeading(hdg, BlackMisc::Aviation::CHeading::True, BlackMisc::PhysicalQuantities::CAngleUnit::deg()),
BlackMisc::PhysicalQuantities::CAngle(pitch, BlackMisc::PhysicalQuantities::CAngleUnit::deg()),
BlackMisc::PhysicalQuantities::CAngle(bank, BlackMisc::PhysicalQuantities::CAngleUnit::deg()),
BlackMisc::PhysicalQuantities::CSpeed(gs, BlackMisc::PhysicalQuantities::CSpeedUnit::kts())
));
}
void Client::setOwnAircraftAvionicsCmd(QTextStream &args)
@@ -513,23 +516,24 @@ void Client::metarReplyReceived(const QString &data)
std::cout << "METAR " << data.toStdString() << std::endl;
}
void Client::flightPlanReplyReceived(const BlackMisc::Aviation::CFlightPlan &flightPlan)
void Client::flightPlanReplyReceived(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Aviation::CFlightPlan &flightPlan)
{
std::string rules;
switch (flightPlan.getFlightRules())
{
default:
case BlackMisc::Aviation::CFlightPlan::IFR: rules = "IFR"; break;
case BlackMisc::Aviation::CFlightPlan::VFR: rules = "VFR"; break;
case BlackMisc::Aviation::CFlightPlan::SVFR: rules = "SVFR"; break;
default:
case BlackMisc::Aviation::CFlightPlan::IFR: rules = "IFR"; break;
case BlackMisc::Aviation::CFlightPlan::VFR: rules = "VFR"; break;
case BlackMisc::Aviation::CFlightPlan::SVFR: rules = "SVFR"; break;
}
std::cout << "FLIGHTPLAN " << flightPlan.getEquipmentIcao().toStdString() << " " << flightPlan.getOriginAirportIcao() << " "
<< flightPlan.getDestinationAirportIcao() << " " << flightPlan.getAlternateAirportIcao() << " "
<< flightPlan.getTakeoffTimePlannedHourMin().toStdString() << " " << flightPlan.getTakeoffTimeActualHourMin().toStdString() << " "
<< flightPlan.getEnrouteTime() << " " << flightPlan.getFuelTime() << " "
<< flightPlan.getCruiseAltitude() << " " << flightPlan.getCruiseTrueAirspeed() << " " << rules << " "
<< flightPlan.getRoute().toStdString() << " " << flightPlan.getRemarks().toStdString() << "\n";
std::cout << "FLIGHTPLAN " << callsign
<< flightPlan.getEquipmentIcao().toStdString() << " " << flightPlan.getOriginAirportIcao() << " "
<< flightPlan.getDestinationAirportIcao() << " " << flightPlan.getAlternateAirportIcao() << " "
<< flightPlan.getTakeoffTimePlannedHourMin().toStdString() << " " << flightPlan.getTakeoffTimeActualHourMin().toStdString() << " "
<< flightPlan.getEnrouteTime() << " " << flightPlan.getFuelTime() << " "
<< flightPlan.getCruiseAltitude() << " " << flightPlan.getCruiseTrueAirspeed() << " " << rules << " "
<< flightPlan.getRoute().toStdString() << " " << flightPlan.getRemarks().toStdString() << "\n";
}
void Client::pilotDisconnected(const BlackMisc::Aviation::CCallsign &callsign)
@@ -565,5 +569,5 @@ void Client::customPacketReceived(const BlackMisc::Aviation::CCallsign &callsign
void Client::statusMessage(const BlackMisc::CStatusMessage &message)
{
std::cout << "STATUS " << message.getSeverityAsString().toStdString() << " " << message.getTypeAsString().toStdString() << " "
<< message.getMessage().toStdString() << "\n";
<< message.getMessage().toStdString() << "\n";
}

View File

@@ -74,7 +74,7 @@ signals: //to send to INetwork
void sendAtcQuery(const BlackMisc::Aviation::CCallsign &callsign);
void sendAtisQuery(const BlackMisc::Aviation::CCallsign &callsign);
void sendFlightPlan(const BlackMisc::Aviation::CFlightPlan &fp);
void sendFlightPlanQuery();
void sendFlightPlanQuery(const BlackMisc::Aviation::CCallsign &callsign);
void sendRealNameQuery(const BlackMisc::Aviation::CCallsign &callsign);
void sendCapabilitiesQuery(const BlackMisc::Aviation::CCallsign &callsign);
void sendIcaoCodesQuery(const BlackMisc::Aviation::CCallsign &callsign);
@@ -103,7 +103,7 @@ public slots: //to receive from INetwork
void capabilitiesReplyReceived(const BlackMisc::Aviation::CCallsign &callsign, quint32 flags);
void kicked(const QString &msg);
void metarReplyReceived(const QString &data);
void flightPlanReplyReceived(const BlackMisc::Aviation::CFlightPlan &flightPlan);
void flightPlanReplyReceived(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Aviation::CFlightPlan &flightPlan);
void pilotDisconnected(const BlackMisc::Aviation::CCallsign &callsign);
void icaoCodesReplyReceived(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Aviation::CAircraftIcao &icaoData);
void pongReceived(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::PhysicalQuantities::CTime &elapsedTime);

View File

@@ -251,7 +251,7 @@ namespace BlackCore
* \pre Network must be connected when calling this function.
* \sa flightPlanReplyReceived
*/
virtual void sendFlightPlanQuery() = 0;
virtual void sendFlightPlanQuery(const BlackMisc::Aviation::CCallsign &callsign) = 0;
//! @}
////////////////////////////////////////////////////////////////
@@ -320,7 +320,7 @@ namespace BlackCore
* \pre Network must be connected when calling this function.
* \sa metarReplyReceived
*/
virtual void sendMetarQuery(const QString &airportICAO) = 0;
virtual void sendMetarQuery(const BlackMisc::Aviation::CAirportIcao &airportIcao) = 0;
/*!
* Send a message querying the weather data for the airport with a specific ICAO code.
@@ -329,7 +329,7 @@ namespace BlackCore
* \sa windDataReplyReceived
* \sa cloudDataReplyReceived
*/
virtual void sendWeatherDataQuery(const QString &airportICAO) = 0;
virtual void sendWeatherDataQuery(const BlackMisc::Aviation::CAirportIcao &airportIcao) = 0;
signals:
//! @}
@@ -377,7 +377,7 @@ namespace BlackCore
* We received a reply to one of our flight plan queries, containing our up-to-date flight plan.
* \sa sendFlightPlanQuery
*/
void flightPlanReplyReceived(const BlackMisc::Aviation::CFlightPlan &flightPlan);
void flightPlanReplyReceived(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Aviation::CFlightPlan &flightPlan);
//! @}
////////////////////////////////////////////////////////////////

View File

@@ -390,7 +390,7 @@ namespace BlackCore
void CNetworkVatlib::presetIcaoCodes(const BlackMisc::Aviation::CAircraftIcao &icao)
{
Q_ASSERT_X(isDisconnected(), "CNetworkVatlib", "Can't change ICAO codes while still connected");
m_icaoCodes = icao;
m_icaoCode = icao;
}
void CNetworkVatlib::presetLoginMode(LoginMode mode)
@@ -617,20 +617,28 @@ namespace BlackCore
{
Cvatlib_Network::FlightPlan vatlibFP;
QString route = QString(flightPlan.getRoute()).replace(" ", ".");
QString remarks = QString(flightPlan.getRemarks()).replace(":", ";");
remarks.truncate(100);
QString remarks = QString(flightPlan.getRemarks()).replace(":", ";").trimmed();
QString alt = flightPlan.getCruiseAltitude().isFlightLevel() ?
flightPlan.getCruiseAltitude().toQString() :
flightPlan.getCruiseAltitude().valueRoundedWithUnit(0);
alt = alt.remove('.').remove(','); // remove any separators
QByteArray acTypeTemp, altAptTemp, cruiseAltTemp, depAptTemp, destAptTemp, routeTemp, remarksTemp;
vatlibFP.acType = acTypeTemp = toFSD(flightPlan.getEquipmentIcao());
vatlibFP.altApt = altAptTemp = toFSD(flightPlan.getAlternateAirportIcao().asString());
vatlibFP.cruiseAlt = cruiseAltTemp = toFSD(QByteArray::number(flightPlan.getCruiseAltitude().value(CLengthUnit::ft()), 'f', 0));
vatlibFP.cruiseAlt = cruiseAltTemp = toFSD(alt);
vatlibFP.depApt = depAptTemp = toFSD(flightPlan.getOriginAirportIcao().asString());
vatlibFP.depTimeActual = flightPlan.getTakeoffTimeActual().toUTC().toString("hhmm").toInt();
vatlibFP.depTimePlanned = flightPlan.getTakeoffTimePlanned().toUTC().toString("hhmm").toInt();
vatlibFP.destApt = destAptTemp = toFSD(flightPlan.getDestinationAirportIcao().asString());
vatlibFP.enrouteHrs = flightPlan.getEnrouteTime().valueRounded(CTimeUnit::h(), 0);
vatlibFP.enrouteMins = int(flightPlan.getEnrouteTime().valueRounded(CTimeUnit::hrmin(), 0)) % 60;
vatlibFP.fuelHrs = flightPlan.getFuelTime().valueRounded(CTimeUnit::h(), 0);
vatlibFP.fuelMins = int(flightPlan.getFuelTime().valueRounded(CTimeUnit::hrmin(), 0)) % 60;
QList<int> timeParts = flightPlan.getEnrouteTime().getHrsMinSecParts();
vatlibFP.enrouteHrs = timeParts[CTime::Hours];
vatlibFP.enrouteMins = timeParts[CTime::Minutes];
timeParts = flightPlan.getFuelTime().getHrsMinSecParts();
vatlibFP.fuelHrs = timeParts[CTime::Hours];
vatlibFP.fuelMins = timeParts[CTime::Minutes];
vatlibFP.remarks = remarksTemp = toFSD(remarks);
vatlibFP.route = routeTemp = toFSD(route);
vatlibFP.trueCruiseSpeed = flightPlan.getCruiseTrueAirspeed().valueRounded(CSpeedUnit::kts());
@@ -646,13 +654,13 @@ namespace BlackCore
catch (...) { exceptionDispatcher(Q_FUNC_INFO); }
}
void CNetworkVatlib::sendFlightPlanQuery()
void CNetworkVatlib::sendFlightPlanQuery(const BlackMisc::Aviation::CCallsign &callsign)
{
Q_ASSERT_X(isConnected(), "CNetworkVatlib", "Can't send to server when disconnected");
try
{
m_net->SendInfoQuery(Cvatlib_Network::infoQuery_FP, toFSD(m_callsign));
m_net->SendInfoQuery(Cvatlib_Network::infoQuery_FP, toFSD(callsign));
}
catch (...) { exceptionDispatcher(Q_FUNC_INFO); }
}
@@ -713,21 +721,21 @@ namespace BlackCore
{
try
{
const QByteArray acTypeICAObytes = toFSD(m_icaoCodes.getAircraftDesignator());
const QByteArray airlineICAObytes = toFSD(m_icaoCodes.getAirlineDesignator());
const QByteArray liverybytes = toFSD(m_icaoCodes.getLivery());
const QByteArray acTypeICAObytes = toFSD(m_icaoCode.getAircraftDesignator());
const QByteArray airlineICAObytes = toFSD(m_icaoCode.getAirlineDesignator());
const QByteArray liverybytes = toFSD(m_icaoCode.getLivery());
std::vector<const char *> keysValues;
if (!m_icaoCodes.getAircraftDesignator().isEmpty())
if (!m_icaoCode.getAircraftDesignator().isEmpty())
{
keysValues.push_back(m_net->acinfo_Equipment);
keysValues.push_back(acTypeICAObytes);
}
if (m_icaoCodes.hasAirlineDesignator())
if (m_icaoCode.hasAirlineDesignator())
{
keysValues.push_back(m_net->acinfo_Airline);
keysValues.push_back(airlineICAObytes);
}
if (m_icaoCodes.hasLivery())
if (m_icaoCode.hasLivery())
{
keysValues.push_back(m_net->acinfo_Livery);
keysValues.push_back(liverybytes);
@@ -749,24 +757,24 @@ namespace BlackCore
catch (...) { exceptionDispatcher(Q_FUNC_INFO); }
}
void CNetworkVatlib::sendMetarQuery(const QString &airportICAO)
void CNetworkVatlib::sendMetarQuery(const BlackMisc::Aviation::CAirportIcao &airportIcao)
{
Q_ASSERT_X(isConnected(), "CNetworkVatlib", "Can't send to server when disconnected");
try
{
m_net->RequestMetar(toFSD(airportICAO));
m_net->RequestMetar(toFSD(airportIcao.asString()));
}
catch (...) { exceptionDispatcher(Q_FUNC_INFO); }
}
void CNetworkVatlib::sendWeatherDataQuery(const QString &airportICAO)
void CNetworkVatlib::sendWeatherDataQuery(const BlackMisc::Aviation::CAirportIcao &airportIcao)
{
Q_ASSERT_X(isConnected(), "CNetworkVatlib", "Can't send to server when disconnected");
try
{
m_net->RequestWeatherData(toFSD(airportICAO));
m_net->RequestWeatherData(toFSD(airportIcao.asString()));
}
catch (...) { exceptionDispatcher(Q_FUNC_INFO); }
}
@@ -998,11 +1006,6 @@ namespace BlackCore
void CNetworkVatlib::onFlightPlanReceived(Cvatlib_Network *, const char *callsign, Cvatlib_Network::FlightPlan fp, void *cbvar)
{
if (cbvar_cast(cbvar)->m_callsign != cbvar_cast(cbvar)->fromFSD(callsign))
{
return; // ignore other pilots' flightplans
}
BlackMisc::Aviation::CFlightPlan::FlightRules rules = BlackMisc::Aviation::CFlightPlan::VFR;
switch (fp.fpRules)
{
@@ -1013,20 +1016,25 @@ namespace BlackCore
}
auto cruiseAltString = cbvar_cast(cbvar)->fromFSD(fp.cruiseAlt);
if (! cruiseAltString.contains(QRegExp("[A-Z][a-z]")))
static const QRegExp withUnit("\\D+");
if (!cruiseAltString.isEmpty() && withUnit.indexIn(cruiseAltString) < 0)
{
cruiseAltString += "ft";
}
BlackMisc::Aviation::CAltitude cruiseAlt;
cruiseAlt.parseFromString(cruiseAltString);
QString depTimePlanned = QString("0000").append(QString::number(fp.depTimePlanned)).right(4);
QString depTimeActual = QString("0000").append(QString::number(fp.depTimeActual)).right(4);
BlackMisc::Aviation::CFlightPlan flightPlan(
cbvar_cast(cbvar)->fromFSD(fp.acType),
cbvar_cast(cbvar)->fromFSD(fp.depApt),
cbvar_cast(cbvar)->fromFSD(fp.destApt),
cbvar_cast(cbvar)->fromFSD(fp.altApt),
QDateTime::fromString(QString::number(fp.depTimePlanned), "hhmm"),
QDateTime::fromString(QString::number(fp.depTimeActual), "hhmm"),
QDateTime::fromString(depTimePlanned, "hhmm"),
QDateTime::fromString(depTimeActual, "hhmm"),
BlackMisc::PhysicalQuantities::CTime(fp.enrouteHrs * 60 + fp.enrouteMins, BlackMisc::PhysicalQuantities::CTimeUnit::min()),
BlackMisc::PhysicalQuantities::CTime(fp.fuelHrs * 60 + fp.fuelMins, BlackMisc::PhysicalQuantities::CTimeUnit::min()),
cruiseAlt,
@@ -1036,7 +1044,7 @@ namespace BlackCore
cbvar_cast(cbvar)->fromFSD(fp.remarks)
);
emit cbvar_cast(cbvar)->flightPlanReplyReceived(flightPlan);
emit cbvar_cast(cbvar)->flightPlanReplyReceived(callsign, flightPlan);
}
void CNetworkVatlib::onTemperatureDataReceived(Cvatlib_Network *, Cvatlib_Network::TempLayer /** layers **/ [4], INT /** pressure **/, void * /** cbvar **/)

View File

@@ -3,10 +3,6 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*!
\file
*/
#ifndef BLACKCORE_NETWORK_VATLIB_H
#define BLACKCORE_NETWORK_VATLIB_H
@@ -64,7 +60,7 @@ namespace BlackCore
virtual void sendAtcQuery(const BlackMisc::Aviation::CCallsign &callsign) override;
virtual void sendAtisQuery(const BlackMisc::Aviation::CCallsign &callsign) override;
virtual void sendFlightPlan(const BlackMisc::Aviation::CFlightPlan &flightPlan) override;
virtual void sendFlightPlanQuery() override;
virtual void sendFlightPlanQuery(const BlackMisc::Aviation::CCallsign &callsign) override;
// Aircraft slots
virtual void sendCapabilitiesQuery(const BlackMisc::Aviation::CCallsign &callsign) override;
@@ -79,14 +75,11 @@ namespace BlackCore
const BlackMisc::Aviation::CTransponder &xpdr) override;
// Weather slots
virtual void sendMetarQuery(const QString &airportICAO) override;
virtual void sendWeatherDataQuery(const QString &airportICAO) override;
virtual void sendMetarQuery(const BlackMisc::Aviation::CAirportIcao &airportIcao) override;
virtual void sendWeatherDataQuery(const BlackMisc::Aviation::CAirportIcao &airportIcao) override;
// some helper methods
//!
/*!
* \brief Create the data load for FSIPI(R) packages / FsInn
* \details FSIPI(R) queries
@@ -171,7 +164,7 @@ namespace BlackCore
Cvatlib_Network::connStatus m_status;
BlackMisc::Network::CServer m_server;
BlackMisc::Aviation::CCallsign m_callsign;
BlackMisc::Aviation::CAircraftIcao m_icaoCodes;
BlackMisc::Aviation::CAircraftIcao m_icaoCode;
BlackMisc::Aviation::CAircraft m_ownAircraft; // not using callsign, user, or icao parts of this member because they can't be changed when connected
QMap<BlackMisc::Aviation::CCallsign, BlackMisc::Aviation::CInformationMessage> m_atisParts;

View File

@@ -3,6 +3,7 @@
using namespace BlackMisc;
using namespace BlackMisc::Aviation;
using namespace BlackMisc::PhysicalQuantities;
namespace BlackGui
{
@@ -11,7 +12,7 @@ namespace BlackGui
{
ui->setupUi(this);
connect(this->ui->pb_Send, &QPushButton::pressed, this, &CFlightPlanComponent::sendFlightPlan);
connect(this->ui->pb_Load, &QPushButton::pressed, this, &CFlightPlanComponent::loadFlightPlan);
connect(this->ui->pb_Load, &QPushButton::pressed, this, &CFlightPlanComponent::loadFlightPlanFromNetwork);
connect(this->ui->pb_Reset, &QPushButton::pressed, this, &CFlightPlanComponent::resetFlightPlan);
connect(this->ui->pb_ValidateFlightPlan, &QPushButton::pressed, this, &CFlightPlanComponent::validateFlightPlan);
@@ -56,7 +57,7 @@ namespace BlackGui
this->ui->le_PilotsName->setText(aircraftData.getPilot().getRealName());
}
void CFlightPlanComponent::prefillWithFlightPlanData(const BlackMisc::Aviation::CFlightPlan &flightPlan)
void CFlightPlanComponent::fillWithFlightPlanData(const BlackMisc::Aviation::CFlightPlan &flightPlan)
{
this->ui->le_AlternateAirport->setText(flightPlan.getAlternateAirportIcao().asString());
this->ui->le_DestinationAirport->setText(flightPlan.getAlternateAirportIcao().asString());
@@ -66,8 +67,13 @@ namespace BlackGui
this->ui->le_TakeOffTimePlanned->setText(flightPlan.getTakeoffTimePlannedHourMin());
this->ui->le_FuelOnBoard->setText(flightPlan.getFuelTimeHourMin());
this->ui->le_EstimatedTimeEnroute->setText(flightPlan.getEnrouteTimeHourMin());
this->ui->le_CrusingAltitude->setText(flightPlan.getCruiseAltitude().toQString());
this->ui->le_CruiseTrueAirspeed->setText(flightPlan.getCruiseTrueAirspeed().valueRoundedWithUnit(BlackMisc::PhysicalQuantities::CSpeedUnit::kts(), 0));
CAltitude cruiseAlt = flightPlan.getCruiseAltitude();
if (cruiseAlt.isFlightLevel())
this->ui->le_CrusingAltitude->setText(cruiseAlt.toQString());
else
this->ui->le_CrusingAltitude->setText(cruiseAlt.valueRoundedWithUnit(BlackMisc::PhysicalQuantities::CLengthUnit::ft(), 0));
}
CFlightPlan CFlightPlanComponent::getFlightPlan() const
@@ -97,16 +103,26 @@ namespace BlackGui
v = ui->pte_Route->toPlainText().trimmed();
if (v.isEmpty())
{
QString m = QString("Missing %1").arg(this->ui->lbl_Route->text());
QString m = QString("Missing flight plan route");
messages.push_back(CStatusMessage::getValidationError(m));
}
else if (v.length() > CFlightPlan::MaxRouteLength)
{
QString m = QString("Flight plan route length exceeded (%1 chars max.)").arg(CFlightPlan::MaxRouteLength);
messages.push_back(CStatusMessage::getValidationError(m));
}
else
flightPlan.setRoute(v);
v = ui->pte_Remarks->toPlainText().trimmed();
if (v.length() > 100)
if (v.isEmpty())
{
QString m = QString("Length exceeded (100 chars max.) %1").arg(this->ui->lbl_Remarks->text());
QString m = QString("No remarks, voice capabilities are mandatory");
messages.push_back(CStatusMessage::getValidationError(m));
}
else if (v.length() > CFlightPlan::MaxRemarksLength)
{
QString m = QString("Flight plan remarks length exceeded (%1 chars max.)").arg(CFlightPlan::MaxRemarksLength);
messages.push_back(CStatusMessage::getValidationError(m));
}
else
@@ -139,8 +155,15 @@ namespace BlackGui
else
flightPlan.setTakeoffTimePlanned(v);
static const QRegExp withUnit("\\D+");
v = ui->le_CrusingAltitude->text().trimmed();
CAltitude cruisingAltitude(v);
if (!v.isEmpty() && withUnit.indexIn(v) < 0)
{
v += "ft";
this->ui->le_CrusingAltitude->setText(v);
}
CAltitude cruisingAltitude(v, CPqString::SeparatorsLocale);
if (v.isEmpty() || cruisingAltitude.isNull())
{
QString m = QString("Wrong %1").arg(this->ui->lbl_CrusingAltitude->text());
@@ -171,7 +194,7 @@ namespace BlackGui
v = this->ui->le_CruiseTrueAirspeed->text();
BlackMisc::PhysicalQuantities::CSpeed cruiseTAS;
cruiseTAS.parseFromString(v);
cruiseTAS.parseFromString(v, CPqString::SeparatorsLocale);
if (cruiseTAS.isNull())
{
QString m = QString("Wrong TAS, %1").arg(this->ui->lbl_CruiseTrueAirspeed->text());
@@ -204,14 +227,14 @@ namespace BlackGui
CStatusMessage m;
if (this->getIContextNetwork()->isConnected())
{
flightPlan.setWhenLastSent(QDateTime::currentDateTimeUtc());
flightPlan.setWhenLastSentOrLoaded(QDateTime::currentDateTimeUtc());
this->getIContextNetwork()->sendFlightPlan(flightPlan);
this->ui->le_LastSent->setText(flightPlan.whenLastSent().toString());
this->ui->le_LastSent->setText(flightPlan.whenLastSentOrLoaded().toString());
m = CStatusMessage::getInfoMessage("Sent flight plan", CStatusMessage::TypeTrafficNetwork);
}
else
{
flightPlan.setWhenLastSent(QDateTime());
flightPlan.setWhenLastSentOrLoaded(QDateTime()); // empty
this->ui->le_LastSent->clear();
m = CStatusMessage::getErrorMessage("No errors, but not connected, cannot send flight plan", CStatusMessage::TypeTrafficNetwork);
}
@@ -258,9 +281,30 @@ namespace BlackGui
this->ui->le_TakeOffTimePlanned->setText(QDateTime::currentDateTimeUtc().addSecs(30 * 60).toString("hh:mm"));
}
void CFlightPlanComponent::loadFlightPlan()
void CFlightPlanComponent::loadFlightPlanFromNetwork()
{
if (!this->getIContextNetwork())
{
this->sendStatusMessage(CStatusMessage::getInfoMessage("Cannot load flight plan, network not available", CStatusMessage::TypeTrafficNetwork));
return;
}
if (!this->getIContextNetwork()->isConnected())
{
this->sendStatusMessage(CStatusMessage::getWarningMessage("Cannot load flight plan, network not connected", CStatusMessage::TypeTrafficNetwork));
return;
}
CAircraft ownAircraft = this->getIContextOwnAircraft()->getOwnAircraft();
CFlightPlan loadedPlan = this->getIContextNetwork()->loadFlightPlanFromNetwork(ownAircraft.getCallsign());
if (loadedPlan.wasSentOrLoaded())
{
this->fillWithFlightPlanData(loadedPlan);
this->sendStatusMessage(CStatusMessage::getInfoMessage("Updated with loaded flight plan", CStatusMessage::TypeTrafficNetwork));
}
else
{
this->sendStatusMessage(CStatusMessage::getWarningMessage("No flight plan data", CStatusMessage::TypeTrafficNetwork));
}
}
void CFlightPlanComponent::buildRemarkString()

View File

@@ -27,7 +27,7 @@ namespace BlackGui
void prefillWithAircraftData(const BlackMisc::Aviation::CAircraft &aircraftData);
//! Prefill with aircraft dara
void prefillWithFlightPlanData(const BlackMisc::Aviation::CFlightPlan &flightPlan);
void fillWithFlightPlanData(const BlackMisc::Aviation::CFlightPlan &flightPlan);
//! Get this flight plan
BlackMisc::Aviation::CFlightPlan getFlightPlan() const;
@@ -55,7 +55,7 @@ namespace BlackGui
void resetFlightPlan();
//! Load Flightplan
void loadFlightPlan();
void loadFlightPlanFromNetwork();
//! Validate Flightplan
void validateFlightPlan();

View File

@@ -17,15 +17,15 @@ namespace BlackMisc
/*
* Constructor
*/
CAltitude::CAltitude(const QString &altitudeAsString) : BlackMisc::PhysicalQuantities::CLength(0, BlackMisc::PhysicalQuantities::CLengthUnit::m()), m_datum(MeanSeaLevel)
CAltitude::CAltitude(const QString &altitudeAsString, BlackMisc::PhysicalQuantities::CPqString::SeparatorMode mode) : BlackMisc::PhysicalQuantities::CLength(0, BlackMisc::PhysicalQuantities::CLengthUnit::m()), m_datum(MeanSeaLevel)
{
this->parseFromString(altitudeAsString);
this->parseFromString(altitudeAsString, mode);
}
/*
* Own implementation for streaming
*/
QString CAltitude::convertToQString(bool /* i18n */) const
QString CAltitude::convertToQString(bool i18n) const
{
if (this->m_datum == FlightLevel)
{
@@ -34,7 +34,7 @@ namespace BlackMisc
}
else
{
QString s = this->CLength::convertToQString();
QString s = this->CLength::valueRoundedWithUnit(CLengthUnit::ft(), i18n);
return s.append(this->isMeanSeaLevel() ? " MSL" : " AGL");
}
}
@@ -156,6 +156,14 @@ namespace BlackMisc
* Parse value
*/
void CAltitude::parseFromString(const QString &value)
{
this->parseFromString(value, BlackMisc::PhysicalQuantities::CPqString::SeparatorsCLocale);
}
/*
* Parse value
*/
void CAltitude::parseFromString(const QString &value, BlackMisc::PhysicalQuantities::CPqString::SeparatorMode mode)
{
QString v = value.trimmed();
@@ -184,7 +192,7 @@ namespace BlackMisc
rd = AboveGround;
}
CLength l = BlackMisc::PhysicalQuantities::CPqString::parse<CLength>(v);
CLength l = BlackMisc::PhysicalQuantities::CPqString::parse<CLength>(v, mode);
*this = CAltitude(l, rd);
}

View File

@@ -64,7 +64,7 @@ namespace BlackMisc
CAltitude(double value, ReferenceDatum datum, const BlackMisc::PhysicalQuantities::CLengthUnit &unit) : BlackMisc::PhysicalQuantities::CLength(value, unit), m_datum(datum) {}
//! Altitude as string
CAltitude(const QString &altitudeAsString);
CAltitude(const QString &altitudeAsString, BlackMisc::PhysicalQuantities::CPqString::SeparatorMode mode = BlackMisc::PhysicalQuantities::CPqString::SeparatorsLocale);
//! Constructor by CLength
CAltitude(BlackMisc::PhysicalQuantities::CLength altitude, ReferenceDatum datum) : BlackMisc::PhysicalQuantities::CLength(altitude), m_datum(datum) {}
@@ -102,9 +102,12 @@ namespace BlackMisc
//! \copydoc CValueObject::fromJson
void fromJson(const QJsonObject &json) override;
//! \copydoc CValueObject::parseFromString
//! \copydoc CValueObject::parseFromString(const QString &value)
void parseFromString(const QString &value) override;
//! \copydoc CValueObject::parseFromString(const QString &value, BlackMisc::PhysicalQuantities::CPqString::SeparatorMode mode)
void parseFromString(const QString &value, BlackMisc::PhysicalQuantities::CPqString::SeparatorMode mode) override;
//! Register metadata
static void registerMetadata();

View File

@@ -37,6 +37,9 @@ namespace BlackMisc
SVFR //!< Special VFR (reserved for ATC use)
};
static const int MaxRemarksLength = 150; //!< Max remarks length
static const int MaxRouteLength = 150; //!< Max route length
/*!
* Default constructor
*/
@@ -50,8 +53,12 @@ namespace BlackMisc
const CAltitude &cruiseAltitude, const PhysicalQuantities::CSpeed &cruiseTrueAirspeed, FlightRules flightRules, const QString &route, const QString &remarks)
: m_equipmentIcao(equipmentIcao), 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), m_remarks(remarks.left(100))
{}
m_cruiseAltitude(cruiseAltitude), m_cruiseTrueAirspeed(cruiseTrueAirspeed), m_flightRules(flightRules),
m_route(route.trimmed().left(MaxRouteLength).toUpper()), m_remarks(remarks.trimmed().left(MaxRemarksLength).toUpper())
{
m_enrouteTime.switchUnit(BlackMisc::PhysicalQuantities::CTimeUnit::hrmin());
m_fuelTime.switchUnit(BlackMisc::PhysicalQuantities::CTimeUnit::hrmin());
}
//! Set ICAO aircraft equipment code string (e.g. "T/A320/F")
void setEquipmentIcao(const QString &equipmentIcao) { m_equipmentIcao = equipmentIcao; }
@@ -87,10 +94,10 @@ namespace BlackMisc
void setTakeoffTimeActual(QString time) { m_takeoffTimeActual = QDateTime::currentDateTimeUtc(); m_takeoffTimeActual.setTime(QTime::fromString(time, "hh:mm"));}
//! Set planned enroute flight time
void setEnrouteTime(const PhysicalQuantities::CTime &enrouteTime) { m_enrouteTime = enrouteTime; }
void setEnrouteTime(const PhysicalQuantities::CTime &enrouteTime) { m_enrouteTime = enrouteTime; m_enrouteTime.switchUnit(BlackMisc::PhysicalQuantities::CTimeUnit::hrmin());}
//! Set amount of fuel load in time
void setFuelTime(const PhysicalQuantities::CTime &fuelTime) { m_fuelTime = fuelTime; }
void setFuelTime(const PhysicalQuantities::CTime &fuelTime) { m_fuelTime = fuelTime; m_fuelTime.switchUnit(BlackMisc::PhysicalQuantities::CTimeUnit::hrmin());}
//! Set amount of fuel load in time hh:mm
void setFuelTime(const QString &fuelTime) { m_fuelTime = PhysicalQuantities::CTime(fuelTime); }
@@ -105,13 +112,13 @@ namespace BlackMisc
void setFlightRule(FlightRules flightRules) { m_flightRules = flightRules; }
//! Set route string
void setRoute(const QString &route) { m_route = route; }
void setRoute(const QString &route) { m_route = route.trimmed().left(MaxRouteLength).toUpper(); }
//! Set remarks string (max 100 characters)
void setRemarks(const QString &remarks) { m_remarks = remarks.left(100); }
void setRemarks(const QString &remarks) { m_remarks = remarks.trimmed().left(MaxRemarksLength).toUpper(); }
//! When last sent
void setWhenLastSent(const QDateTime &dateTime) { m_lastSent = dateTime; }
void setWhenLastSentOrLoaded(const QDateTime &dateTime) { m_lastSentOrLoaded = dateTime; }
//! Get ICAO aircraft equipment code string
const QString &getEquipmentIcao() const { return m_equipmentIcao; }
@@ -147,7 +154,7 @@ namespace BlackMisc
const PhysicalQuantities::CTime &getFuelTime() const { return m_fuelTime; }
//! Get amount of fuel load in time
QString getFuelTimeHourMin() const { return m_enrouteTime.valueRoundedWithUnit(BlackMisc::PhysicalQuantities::CTimeUnit::hrmin()); }
QString getFuelTimeHourMin() const { return m_fuelTime.valueRoundedWithUnit(BlackMisc::PhysicalQuantities::CTimeUnit::hrmin()); }
//! Cruising altitudes
const BlackMisc::Aviation::CAltitude &getCruiseAltitude() const { return m_cruiseAltitude; }
@@ -162,10 +169,16 @@ namespace BlackMisc
const QString &getRoute() const { return m_route; }
//! When last sent
const QDateTime &whenLastSent() const { return m_lastSent; }
const QDateTime &whenLastSentOrLoaded() const { return m_lastSentOrLoaded; }
//! Flight plan already sent
bool wasSent() const { return m_lastSent.isValid() && !m_lastSent.isNull(); }
bool wasSentOrLoaded() const { return m_lastSentOrLoaded.isValid() && !m_lastSentOrLoaded.isNull(); }
//! \brief Received before n ms
qint64 timeDiffSentOrLoadedMs() const
{
return this->m_lastSentOrLoaded.msecsTo(QDateTime::currentDateTimeUtc());
}
//! Get remarks string
const QString &getRemarks() const { return m_remarks; }
@@ -219,13 +232,13 @@ namespace BlackMisc
FlightRules m_flightRules;
QString m_route;
QString m_remarks;
QDateTime m_lastSent;
QDateTime m_lastSentOrLoaded;
};
} // namespace
} // namespace
Q_DECLARE_METATYPE(BlackMisc::Aviation::CFlightPlan)
BLACK_DECLARE_TUPLE_CONVERSION(BlackMisc::Aviation::CFlightPlan, (o.m_equipmentIcao, o.m_originAirportIcao, o.m_destinationAirportIcao, o.m_alternateAirportIcao,
o.m_takeoffTimePlanned, o.m_takeoffTimeActual, o.m_enrouteTime, o.m_fuelTime, o.m_cruiseAltitude, tie(o.m_cruiseTrueAirspeed, o.m_flightRules, o.m_route, o.m_remarks, o.m_lastSent)))
o.m_takeoffTimePlanned, o.m_takeoffTimeActual, o.m_enrouteTime, o.m_fuelTime, o.m_cruiseAltitude, tie(o.m_cruiseTrueAirspeed, o.m_flightRules, o.m_route, o.m_remarks, o.m_lastSentOrLoaded)))
#endif // guard

View File

@@ -234,10 +234,16 @@ namespace BlackMisc
//! \copydoc CValueObject::fromJson
virtual void fromJson(const QJsonObject &json) override;
//! Parse to string, with specified separator
virtual void parseFromString(const QString &value, CPqString::SeparatorMode mode)
{
this->parseFromString(value, mode);
}
//! \copydoc CValueObject::parseFromString
virtual void parseFromString(const QString &value) override
{
*this = CPqString::parse<PQ>(value);
*this = CPqString::parse<PQ>(value, CPqString::SeparatorsCLocale);
}
//! Register metadata of unit and quantity

View File

@@ -93,17 +93,36 @@ namespace BlackMisc
/*
* Parse
*/
QVariant CPqString::parseToVariant(const QString &value)
QVariant CPqString::parseToVariant(const QString &value, SeparatorMode mode)
{
static QRegExp rx("([0-9]+)\\s*(\\D*)$");
QVariant v;
if (value.isEmpty()) return v;
QRegExp rx("^([-+]?[0-9]*\\.?[0-9]+)\\s*(\\D*)$");
if (rx.indexIn(value) < 0) return v;
QString number = rx.cap(1).trimmed();
if (rx.indexIn(value) < 0) return v; // not a valid number
QString unit = rx.cap(2).trimmed();
QString number = QString(value).replace(unit, "");
unit = unit.trimmed(); // trim after replace, not before
if (unit.isEmpty() || number.isEmpty()) return v;
bool success;
double numberD = number.toDouble(&success);
double numberD;
switch (mode)
{
case SeparatorsLocale:
numberD = QLocale::system().toDouble(number, &success);
break;
case SeparatorsCLocale:
numberD = number.toDouble(&success);
break;
case SeparatorsBestGuess:
numberD = number.toDouble(&success);
if (!success) numberD = QLocale::system().toDouble(number, &success);
break;
default:
qFatal("Wrong mode");
break;
}
if (!success) return v;
if (CMeasurementUnit::isValidUnitSymbol<CAccelerationUnit>(unit))

View File

@@ -42,13 +42,25 @@ namespace BlackMisc
virtual bool isA(int metaTypeId) const override;
public:
//! Number separators / group separators
enum SeparatorMode
{
SeparatorsCLocale, //!< 100,000.00
SeparatorsLocale, //!< depending on QLocale, e.g. 100.000,00 in Germany
SeparatorsBestGuess //!< try to figure out
};
//! Group and digit separator
enum SeparatorIndex
{
Group,
Digit
};
//! Default constructor
CPqString() {}
/*!
* Constructor
* \param value such as 10km/h
*/
//! Constructor, for values such as 10km/h
CPqString(const QString &value) : m_string(value) {}
//! \copydoc CValueObject::toQVariant
@@ -73,15 +85,15 @@ namespace BlackMisc
static void registerMetadata();
//! Parse a string value like "100m", "10.3Mhz"
static QVariant parseToVariant(const QString &value);
static QVariant parseToVariant(const QString &value, SeparatorMode mode = SeparatorsCLocale);
//! Parse into concrete type
template <class PQ> static PQ parse(const QString &value)
template <class PQ> static PQ parse(const QString &value, SeparatorMode mode = SeparatorsCLocale)
{
PQ invalid;
invalid.setNull();
if (value.isEmpty()) return invalid;
QVariant qv = CPqString::parseToVariant(value);
QVariant qv = CPqString::parseToVariant(value, mode);
if (!qv.isNull() && qv.canConvert<PQ>())
{
return qv.value<PQ>();

View File

@@ -4,12 +4,26 @@ namespace BlackMisc
{
namespace PhysicalQuantities
{
CTime::CTime(int hours, int minutes, int seconds) : CPhysicalQuantity(0, CTimeUnit::nullUnit())
{
double value = hours + minutes / 100.0 + seconds / 10000.0;
if (minutes == 0 && seconds == 0)
{
(*this) = CTime(hours, CTimeUnit::h());
}
else
{
if (seconds == 0)
(*this) = CTime(value, CTimeUnit::hrmin());
else
(*this) = CTime(value, CTimeUnit::hms());
}
}
CTime::CTime(const QTime &time) : CPhysicalQuantity(0, CTimeUnit::nullUnit())
{
int seconds = QTime(0, 0, 0).secsTo(time);
CTime converted(seconds, CTimeUnit::s());
converted.switchUnit(CTimeUnit::hms());
*this = converted;
CTime converted(time.hour(), time.minute(), time.second());
(*this) = converted;
}
void CTime::parseFromString(const QString &time)
@@ -22,12 +36,7 @@ namespace BlackMisc
t = QTime::fromString(ts, "hh:mm");
else if (ts.length() == 8)
t = QTime::fromString(ts, "hh:mm:ss");
CTime parsed(t);
if (ts.length() == 5)
parsed.switchUnit(CTimeUnit::hrmin());
else if (ts.length() == 8)
parsed.switchUnit(CTimeUnit::hms());
*this = parsed;
(*this) = CTime(t);
}
else
CPhysicalQuantity::parseFromString(ts);
@@ -37,9 +46,19 @@ namespace BlackMisc
{
CTime copy(*this);
copy.setUnit(CTimeUnit::hms());
QString s = copy.toQString(false);
QTime t = QTime::fromString(s, "hh:mm:ss");
QString s = copy.toQString(false).replace('h', ':').replace('m', ':').replace('s', "");
QTime t = s.length() == 8 ?
QTime::fromString(s, "hh:mm:ss") :
QTime::fromString(s, "hh:mm");
return t;
}
QList<int> CTime::getHrsMinSecParts() const
{
QTime t = this->toQTime();
QList<int> parts;
parts << t.hour() << t.minute() << t.second();
return parts;
}
}
}

View File

@@ -19,12 +19,24 @@ namespace BlackMisc
class CTime : public CPhysicalQuantity<CTimeUnit, CTime>
{
public:
//! Parts
enum Parts
{
Hours = 0,
Minutes,
Seconds
};
//! Default constructor
CTime() : CPhysicalQuantity(0, CTimeUnit::defaultUnit()) {}
//! Init by double value
CTime(double value, const CTimeUnit &unit) : CPhysicalQuantity(value, unit) {}
//! By hours, minutes, seconds
CTime(int hours, int minutes, int seconds = 0);
//! By Qt time
CTime(const QTime &time);
@@ -43,6 +55,9 @@ namespace BlackMisc
//! To Qt time
QTime toQTime() const;
//! Parts hh, mm, ss
QList<int> getHrsMinSecParts() const;
};
} // namespace

View File

@@ -62,7 +62,7 @@ namespace BlackMisc
double se = CMath::trunc((value - hr - mi / 100.0) * 1000000) / 100.0;
const char *fmt = value < 0 ? "-%L1h%L2m%L3s" : "%L1h%L2m%L3s";
s = i18n ? QCoreApplication::translate("CMeasurementUnit", fmt) : fmt;
s = s.arg(fabs(hr), 0, 'f', 0).arg(fabs(mi), 2, 'f', 0, '0').arg(fabs(se), 2, 'f', digits, '0');
s = s.arg(fabs(hr), 2, 'f', 0, '0').arg(fabs(mi), 2, 'f', 0, '0').arg(fabs(se), 2, 'f', digits, '0');
}
else if ((*this) == CTimeUnit::hrmin())
{
@@ -72,7 +72,7 @@ namespace BlackMisc
double mi = CMath::trunc((value - hr) * 100.0);
const char *fmt = value < 0 ? "-%L1h%L2m" : "%L1h%L2m";
s = i18n ? QCoreApplication::translate("CMeasurementUnit", fmt) : fmt;
s = s.arg(fabs(hr), 0, 'f', 0).arg(fabs(mi), 2, 'f', digits, '0');
s = s.arg(fabs(hr), 2, 'f', 0, '0').arg(fabs(mi), 2, 'f', digits, '0');
}
else if ((*this) == CTimeUnit::minsec())
{
@@ -82,7 +82,7 @@ namespace BlackMisc
double se = CMath::trunc((value - mi) * 100.0);
const char *fmt = value < 0 ? "-%L2m%L3s" : "%L2m%L3s";
s = i18n ? QCoreApplication::translate("CMeasurementUnit", fmt) : fmt;
s = s.arg(fabs(mi), 0, 'f', 0).arg(fabs(se), 2, 'f', digits, '0');
s = s.arg(fabs(mi), 2, 'f', 0, '0').arg(fabs(se), 2, 'f', digits, '0');
}
else
{