diff --git a/src/blackmisc/avaircraft.cpp b/src/blackmisc/avaircraft.cpp new file mode 100644 index 000000000..0069ab688 --- /dev/null +++ b/src/blackmisc/avaircraft.cpp @@ -0,0 +1,266 @@ +#include "avaircraft.h" +#include "blackmisc/blackmiscfreefunctions.h" +#include "blackmisc/pqconstants.h" + +using namespace BlackMisc::PhysicalQuantities; + +namespace BlackMisc +{ + namespace Aviation + { + /* + * Convert to string + */ + QString CAircraft::convertToQString(bool i18n) const + { + QString s(this->m_callsign.toQString(i18n)); + s.append(" ").append(this->m_pilot.toQString(i18n)); + s.append(" ").append(this->m_situation.toQString(i18n)); + s.append(" ").append(this->m_com1system.toQString(i18n)); + s.append(" ").append(this->m_com2system.toQString(i18n)); + s.append(" ").append(this->m_transponder.toQString(i18n)); + return s; + } + + /* + * Marshall to DBus + */ + void CAircraft::marshallToDbus(QDBusArgument &argument) const + { + argument << this->m_callsign; + argument << this->m_pilot; + argument << this->m_situation; + argument << this->m_com1system; + argument << this->m_com2system; + argument << this->m_transponder; + argument << this->m_icao; + argument << this->m_distanceToPlane; + } + + /* + * Unmarshall from DBus + */ + void CAircraft::unmarshallFromDbus(const QDBusArgument &argument) + { + argument >> this->m_callsign; + argument >> this->m_pilot; + argument >> this->m_situation; + argument >> this->m_com1system; + argument >> this->m_com2system; + argument >> this->m_transponder; + argument >> this->m_icao; + argument >> this->m_distanceToPlane; + } + + /* + * All relevant information + */ + const PhysicalQuantities::CLength &CAircraft::calculcateDistanceToPlane(const Geo::CCoordinateGeodetic &position) + { + this->m_distanceToPlane = Geo::greatCircleDistance(position, this->m_situation.getPosition()); + return this->m_distanceToPlane; + } + + /* + * All relevant information? + */ + bool CAircraft::isValidForLogin() const + { + if (this->m_callsign.asString().isEmpty()) return false; + if (!this->m_pilot.isValid()) return false; + return true; + } + + /* + * Meaningful values + */ + void CAircraft::initComSystems() + { + CComSystem com1("COM1", CPhysicalQuantitiesConstants::FrequencyUnicom(), CPhysicalQuantitiesConstants::FrequencyUnicom()); + CComSystem com2("COM2", CPhysicalQuantitiesConstants::FrequencyUnicom(), CPhysicalQuantitiesConstants::FrequencyUnicom()); + this->setCom1System(com1); + this->setCom2System(com2); + } + + /* + * Meaningful values + */ + void CAircraft::initTransponder() + { + CTransponder xpdr("TRANSPONDER", 7000, CTransponder::ModeS); + this->setTransponder(xpdr); + } + + /* + * Equal? + */ + bool CAircraft::operator ==(const CAircraft &other) const + { + if (this == &other) return true; + return this->getValueHash() == other.getValueHash(); + } + + /* + * Unequal? + */ + bool CAircraft::operator !=(const CAircraft &other) const + { + return !((*this) == other); + } + + /* + * Hash + */ + uint CAircraft::getValueHash() const + { + QList hashs; + hashs << qHash(this->m_callsign); + hashs << qHash(this->m_pilot); + hashs << qHash(this->m_situation); + hashs << qHash(this->m_com1system); + hashs << qHash(this->m_com2system); + hashs << qHash(this->m_transponder); + hashs << qHash(this->m_icao); + return BlackMisc::calculateHash(hashs, "CAircraft"); + } + + /* + * Compare + */ + int CAircraft::compare(const QVariant &qv) const + { + Q_ASSERT(qv.canConvert()); + Q_ASSERT(!qv.isNull() && qv.isValid()); + CAircraft aircraft = qv.value(); + return this->getCallsign().compare(aircraft.getCallsign()); + } + + /* + * Property by index + */ + QVariant CAircraft::propertyByIndex(int index) const + { + if (index >= static_cast(CAircraftIcao::IndexIcaoDesignator)) + return this->m_icao.propertyByIndex(index); + + if (index >= static_cast(CAircraftSituation::IndexPosition)) + return this->m_situation.propertyByIndex(index); + + switch (index) + { + case IndexCallsign: + return QVariant::fromValue(this->m_callsign); + case IndexCallsignAsString: + return QVariant::fromValue(this->m_callsign.toQString(true)); + case IndexCallsignAsStringAsSet: + return QVariant(this->m_callsign.getStringAsSet()); + case IndexPilotId: + return QVariant::fromValue(this->m_pilot.getId()); + case IndexPilotRealname: + return QVariant::fromValue(this->m_pilot.getRealname()); + case IndexDistance: + return this->m_distanceToPlane.toQVariant(); + case IndexCom1System: + return this->m_com1system.toQVariant(); + case IndexFrequencyCom1: + return this->m_com1system.getFrequencyActive().toQVariant(); + case IndexTransponder: + return this->m_transponder.toQVariant(); + case IndexTansponderFormatted: + return QVariant::fromValue(this->m_transponder.getTransponderCodeAndModeFormatted()); + case IndexSituation: + return this->m_situation.toQVariant(); + case IndexIcao: + return this->m_icao.toQVariant(); + default: + break; + } + + Q_ASSERT_X(false, "CAircraft", "index unknown"); + QString m = QString("no property, index ").append(QString::number(index)); + return QVariant::fromValue(m); + } + + /* + * Property as string by index + */ + QString CAircraft::propertyByIndexAsString(int index, bool i18n) const + { + QVariant qv = this->propertyByIndex(index); + // special treatment + // this is required as it is possible an ATC station is not containing all + // properties + switch (index) + { + case IndexFrequencyCom1: + if (!CComSystem::isValidCivilAviationFrequency(qv.value())) + { + return ""; + } + break; + case IndexDistance: + { + CLength distance = qv.value(); + if (distance.isNegativeWithEpsilonConsidered()) return ""; + return distance.toQString(i18n); + } + default: + break; + } + return BlackMisc::qVariantToString(qv, i18n); + } + + /* + * Property by index (setter) + */ + void CAircraft::setPropertyByIndex(const QVariant &variant, int index) + { + if (index >= static_cast(CAircraftIcao::IndexIcaoDesignator)) + return this->m_icao.setPropertyByIndex(variant, index); + + if (index >= static_cast(CAircraftSituation::IndexPosition)) + return this->m_situation.setPropertyByIndex(variant, index); + + switch (index) + { + case IndexCallsign: + this->setCallsign(variant.value()); + break; + case IndexCallsignAsString: + this->m_callsign = CCallsign(variant.value()); + break; + case IndexPilotRealname: + this->m_pilot.setRealname(variant.value()); + break; + case IndexCom1System: + this->setCom1System(variant.value()); + break; + case IndexFrequencyCom1: + this->m_com1system.setFrequencyActive(variant.value()); + break; + case IndexTransponder: + this->setTransponder(variant.value()); + break; + case IndexIcao: + this->setIcaoInfo(variant.value()); + break; + case IndexSituation: + this->setSituation(variant.value()); + break; + default: + Q_ASSERT_X(false, "CAircraft", "index unknown"); + break; + } + } + + /* + * Register metadata + */ + void CAircraft::registerMetadata() + { + qRegisterMetaType(); + qDBusRegisterMetaType(); + } + + } // namespace +} // namespace diff --git a/src/blackmisc/avaircraft.h b/src/blackmisc/avaircraft.h new file mode 100644 index 000000000..00ee1652f --- /dev/null +++ b/src/blackmisc/avaircraft.h @@ -0,0 +1,369 @@ +/* Copyright (C) 2013 VATSIM Community / authors + * This Source Code Form is subject to the terms of the Mozilla Public + * 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 BLACKMISC_AIRCRAFT_H +#define BLACKMISC_AIRCRAFT_H +#include "nwuser.h" +#include "avaircraftsituation.h" +#include "avaircrafticao.h" +#include "avcallsign.h" +#include "aviotransponder.h" +#include "aviocomsystem.h" +#include "valueobject.h" + +namespace BlackMisc +{ + namespace Aviation + { + /*! + * Value object encapsulating information of an aircraft + */ + class CAircraft : public BlackMisc::CValueObject, public BlackMisc::Geo::ICoordinateGeodetic + { + public: + /*! + * Default constructor. + */ + CAircraft() : m_distanceToPlane(-1.0, BlackMisc::PhysicalQuantities::CLengthUnit::NM()) {} + + /*! + * Constructor. + */ + CAircraft(const QString &callsign, const BlackMisc::Network::CUser &user, const CAircraftSituation &situation) + : m_callsign(callsign), m_pilot(user), m_situation(situation), m_distanceToPlane(-1.0, BlackMisc::PhysicalQuantities::CLengthUnit::NM()) {} + + /*! + * \brief QVariant, required for DBus QVariant lists + * \return + */ + virtual QVariant toQVariant() const + { + return QVariant::fromValue(*this); + } + + /*! + * Get callsign. + * \return + */ + const CCallsign &getCallsign() const { return m_callsign; } + + /*! + * Get callsign. + * \return + */ + QString getCallsignAsString() const { return m_callsign.asString(); } + + /*! + * Set callsign + * \param callsign + */ + void setCallsign(const CCallsign &callsign) { this->m_callsign = callsign; } + + /*! + * Get situation. + * \return + */ + const CAircraftSituation &getSituation() const { return m_situation; } + + /*! + * Set situation. + * \param + */ + void setSituation(const CAircraftSituation &situation) { m_situation = situation; } + + /*! + * Get user + * \return + */ + const BlackMisc::Network::CUser &getPilot() const { return m_pilot; } + + /*! + * \brief Set user + * \param password + */ + void setPilot(const BlackMisc::Network::CUser &user) { m_pilot = user; } + + /*! + * Get ICAO info + * \return + */ + const CAircraftIcao &getIcaoInfo() const { return m_icao; } + + /*! + * \brief Set ICAO info + * \param icao + */ + void setIcaoInfo(const CAircraftIcao &icao) { m_icao = icao; } + + /*! + * Get the distance to own plane + * \return + */ + const BlackMisc::PhysicalQuantities::CLength &getDistanceToPlane() const { return m_distanceToPlane; } + + /*! + * Set distance to own plane + * \param range + */ + void setDistanceToPlane(const BlackMisc::PhysicalQuantities::CLength &distance) { this->m_distanceToPlane = distance; } + + /*! + * \brief Valid distance? + * \return + */ + bool hasValidDistance() const { return !this->m_distanceToPlane.isNegativeWithEpsilonConsidered();} + + /*! + * \brief Calculcate distance to plane, set it, and also return it + * \param position + * \return + */ + const BlackMisc::PhysicalQuantities::CLength &calculcateDistanceToPlane(const BlackMisc::Geo::CCoordinateGeodetic &position); + + /*! + * \brief Get position + * \return + */ + BlackMisc::Geo::CCoordinateGeodetic getPosition() const { return this->m_situation.getPosition(); } + + /*! + * \brief Set position + * \param position + */ + void setPosition(const BlackMisc::Geo::CCoordinateGeodetic &position) { this->m_situation.setPosition(position); } + + /*! + * \brief Get altitude + * \return + */ + const BlackMisc::Aviation::CAltitude &getAltitude() const { return this->m_situation.getAltitude(); } + + /*! + * \brief Set altitude + * \param altitude + */ + void setAltitude(const BlackMisc::Aviation::CAltitude &altitude) { this->m_situation.setAltitude(altitude); } + + /*! + * \brief Get groundspeed + * \return + */ + const BlackMisc::PhysicalQuantities::CSpeed &getGroundSpeed() const { return this->m_situation.getGroundSpeed(); } + + /*! + * \brief Get latitude + * \return + */ + virtual const BlackMisc::Geo::CLatitude &latitude() const { return this->m_situation.latitude(); } + + /*! + * \brief Get longitude + * \return + */ + virtual const BlackMisc::Geo::CLongitude &longitude() const { return this->m_situation.longitude(); } + + /*! + * \brief Get height + * \return + */ + const BlackMisc::PhysicalQuantities::CLength &getHeight() const { return this->m_situation.getHeight(); } + + /*! + * \brief Get heading + * \return + */ + const BlackMisc::Aviation::CHeading &getHeading() const { return this->m_situation.getHeading(); } + + /*! + * \brief Get pitch + * \return + */ + const BlackMisc::PhysicalQuantities::CAngle &getPitch() const { return this->m_situation.getPitch(); } + + /*! + * \brief Get bank + * \return + */ + const BlackMisc::PhysicalQuantities::CAngle &getBank() const { return this->m_situation.getBank(); } + + /*! + * \brief Get COM1 system + * \return + */ + const BlackMisc::Aviation::CComSystem &getCom1System() const { return this->m_com1system; } + + /*! + * \brief Get COM2 system + * \return + */ + const BlackMisc::Aviation::CComSystem &getCom2System() const { return this->m_com2system; } + + /*! + * \brief Set COM1 system + */ + void setCom1System(const CComSystem &comSystem) { this->m_com1system = comSystem; } + + /*! + * \brief Set COM2 system + */ + void setCom2System(const CComSystem &comSystem) { this->m_com2system = comSystem; } + + /*! + * \brief Get transponder + * \return + */ + const BlackMisc::Aviation::CTransponder &getTransponder() const { return this->m_transponder; } + + /*! + * \brief Set transponder + */ + void setTransponder(const CTransponder &transponder) { this->m_transponder = transponder; } + + /*! + * \brief Get transponder code + * \return + */ + QString getTransponderCodeFormatted() const { return this->m_transponder.getTransponderCodeFormatted(); } + + /*! + * \brief Get transponder code + * \return + */ + qint32 getTransponderCode() const { return this->m_transponder.getTransponderCode(); } + + /*! + * \brief Get transponder mode + * \return + */ + BlackMisc::Aviation::CTransponder::TransponderMode getTransponderMode() const { return this->m_transponder.getTransponderMode(); } + + /*! + * \brief Is valid for login + * \return + */ + bool isValidForLogin() const; + + /*! + * \brief Meaningful default settings for COM Systems + */ + void initComSystems(); + + /*! + * \brief Meaningful default settings for Transponder + */ + void initTransponder(); + + /*! + * \brief Equal operator == + * \param other + * \return + */ + bool operator ==(const CAircraft &other) const; + + /*! + * \brief Unequal operator == + * \param other + * \return + */ + bool operator !=(const CAircraft &other) const; + + /*! + * \brief Value hash + */ + virtual uint getValueHash() const; + + /*! + * \copydoc BlackObject::compare + */ + virtual int compare(const QVariant &qv) const; + + /*! + * \brief Register metadata + */ + static void registerMetadata(); + + /*! + * \brief Properties by index + */ + enum ColumnIndex + { + IndexCallsign = 0, + IndexCallsignAsString, + IndexCallsignAsStringAsSet, + IndexPilotId, + IndexPilotRealname, + IndexDistance, + IndexCom1System, + IndexFrequencyCom1, + IndexTransponder, + IndexTansponderFormatted, + IndexSituation, + IndexIcao + }; + + /*! + * \brief Property by index + * \param index + * \return + */ + virtual QVariant propertyByIndex(int index) const; + + /*! + * \brief Property by index as string + * \param index + * \param i18n + * \return + */ + virtual QString propertyByIndexAsString(int index, bool i18n) const; + + /*! + * \brief Property by index (setter) + * \param variant + * \param index + */ + virtual void setPropertyByIndex(const QVariant &variant, int index); + + protected: + /*! + * \brief Rounded value as string + * \param i18n + * \return + */ + virtual QString convertToQString(bool i18n = false) const; + + /*! + * \brief Stream to DBus << + * \param argument + */ + virtual void marshallToDbus(QDBusArgument &argument) const; + + /*! + * \brief Stream from DBus >> + * \param argument + */ + virtual void unmarshallFromDbus(const QDBusArgument &argument); + + private: + CCallsign m_callsign; + BlackMisc::Network::CUser m_pilot; + CAircraftSituation m_situation; + BlackMisc::Aviation::CComSystem m_com1system; + BlackMisc::Aviation::CComSystem m_com2system; + BlackMisc::Aviation::CTransponder m_transponder; + CAircraftIcao m_icao; + BlackMisc::PhysicalQuantities::CLength m_distanceToPlane; + + + }; + } // namespace +} // namespace + +Q_DECLARE_METATYPE(BlackMisc::Aviation::CAircraft) + +#endif // guard diff --git a/src/blackmisc/avaircrafticao.cpp b/src/blackmisc/avaircrafticao.cpp new file mode 100644 index 000000000..f5ea876c0 --- /dev/null +++ b/src/blackmisc/avaircrafticao.cpp @@ -0,0 +1,163 @@ +#include "avaircrafticao.h" +#include "blackmisc/blackmiscfreefunctions.h" + +namespace BlackMisc +{ + namespace Aviation + { + /* + * Convert to string + */ + QString CAircraftIcao::convertToQString(bool /** i18n **/) const + { + QString s(this->m_designator); + s.append(" ").append(this->m_type); + if (this->hasAirline()) s.append(" ").append(this->m_airline); + if (this->hasAirline()) s.append(" ").append(this->m_airline); + if (this->hasLivery()) s.append(" ").append(this->m_livery); + if (this->hasColor()) s.append(" ").append(this->m_color); + return s; + } + + /* + * Marshall to DBus + */ + void CAircraftIcao::marshallToDbus(QDBusArgument &argument) const + { + argument << this->m_designator; + argument << this->m_airline; + argument << this->m_livery; + argument << this->m_type; + argument << this->m_color; + } + + /* + * Unmarshall from DBus + */ + void CAircraftIcao::unmarshallFromDbus(const QDBusArgument &argument) + { + argument >> this->m_designator; + argument >> this->m_airline; + argument >> this->m_livery; + argument >> this->m_type; + argument >> this->m_color; + } + + /* + * Equal? + */ + QString CAircraftIcao::asString() const + { + if (this->m_designator.isEmpty()) return ""; + QString s(this->m_designator); + if (!this->m_airline.isEmpty()) + { + s.append(" (").append(this->m_airline).append(")"); + return s; + } + if (!this->m_color.isEmpty()) + { + s.append(" (").append(this->m_color).append(")"); + return s; + } + return s; + } + + bool CAircraftIcao::operator ==(const CAircraftIcao &other) const + { + if (this == &other) return true; + return this->getValueHash() == other.getValueHash(); + } + + /* + * Unequal? + */ + bool CAircraftIcao::operator !=(const CAircraftIcao &other) const + { + return !((*this) == other); + } + + /* + * Hash + */ + uint CAircraftIcao::getValueHash() const + { + QList hashs; + hashs << qHash(this->m_designator); + hashs << qHash(this->m_airline); + hashs << qHash(this->m_type); + hashs << qHash(this->m_color); + return BlackMisc::calculateHash(hashs, "CAircraftIcao"); + } + + /* + * Property by index + */ + QVariant CAircraftIcao::propertyByIndex(int index) const + { + switch (index) + { + case IndexIcaoDesignator: + return QVariant::fromValue(this->m_designator); + case IndexAirline: + return QVariant::fromValue(this->m_airline); + case IndexType: + return QVariant::fromValue(this->m_type); + case IndexColor: + return QVariant::fromValue(this->m_color); + case IndexAsString: + return QVariant::fromValue(this->asString()); + default: + break; + } + + Q_ASSERT_X(false, "CAircraftIcao", "index unknown"); + QString m = QString("no property, index ").append(QString::number(index)); + return QVariant::fromValue(m); + } + + /* + * Property as string by index + */ + QString CAircraftIcao::propertyByIndexAsString(int index, bool i18n) const + { + QVariant qv = this->propertyByIndex(index); + return BlackMisc::qVariantToString(qv, i18n); + } + + /* + * Property by index + */ + void CAircraftIcao::setPropertyByIndex(const QVariant &variant, int index) + { + switch (index) + { + case IndexIcaoDesignator: + this->setDesignator(variant.value()); + break; + case IndexAirline: + this->setAirline(variant.value()); + break; + case IndexType: + this->setType(variant.value()); + break; + case IndexColor: + this->setColor(variant.value()); + break; + default: + Q_ASSERT_X(false, "CAircraftIcao", "index unknown"); + break; + } + } + + /* + * Register metadata + */ + void CAircraftIcao::registerMetadata() + { + qRegisterMetaType(); + qDBusRegisterMetaType(); + } + + } // namespace +} // namespace diff --git a/src/blackmisc/avaircrafticao.h b/src/blackmisc/avaircrafticao.h new file mode 100644 index 000000000..4ae39dc22 --- /dev/null +++ b/src/blackmisc/avaircrafticao.h @@ -0,0 +1,240 @@ +/* Copyright (C) 2013 VATSIM Community / authors + * This Source Code Form is subject to the terms of the Mozilla Public + * 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 BLACKMISC_AIRCRAFTICAO_H +#define BLACKMISC_AIRCRAFTICAO_H + +#include "valueobject.h" + +namespace BlackMisc +{ + namespace Aviation + { + /*! + * Value object encapsulating information for ICAO classification + */ + class CAircraftIcao : public BlackMisc::CValueObject + { + public: + /*! + * Default constructor. + */ + CAircraftIcao() {} + + /*! + * Constructor. + * \param icao + * \param type + * \param airline + * \param livery + * \param color + */ + CAircraftIcao(const QString &icao, const QString &type, const QString &airline, const QString &livery, const QString &color) + : m_designator(icao), m_type(type), m_airline(airline), m_livery(livery), m_color(color) {} + + /*! + * \brief QVariant, required for DBus QVariant lists + * \return + */ + virtual QVariant toQVariant() const + { + return QVariant::fromValue(*this); + } + + /*! + * Get ICAO designator, e.g. "B737" + * \return + */ + const QString &getDesignator() const { return m_designator; } + + /*! + * Set callsign + * \param callsign + */ + void setDesignator(const QString &icaoDesignator) { this->m_designator = icaoDesignator.trimmed().toUpper(); } + + /*! + * \brief Get airline + * \return + */ + const QString &getAirline() const { return this->m_airline; } + + /*! + * \brief Set airline + * \param airline + */ + void setAirline(const QString &airline) { this->m_airline = airline.trimmed().toUpper(); } + + /*! + * \brief Airline? + * \return + */ + bool hasAirline() const { return !this->m_airline.isEmpty(); } + + /*! + * \brief Get livery + * \return + */ + const QString &getLivery() const { return this->m_livery; } + + /*! + * \brief Set airline + * \param livery + */ + void setLivery(const QString &livery) { this->m_livery = livery; } + + /*! + * \brief Livery? + * \return + */ + bool hasLivery() const { return !this->m_livery.isEmpty(); } + + /*! + * \brief Get livery or color + * \return + */ + const QString &getLiveryOrColor() const { return this->hasLivery() ? this->m_livery : this->m_color; } + + /*! + * \brief Get color + * \return + */ + const QString &getColor() const { return this->m_color; } + + /*! + * \brief Set color + * \param color + */ + void setColor(const QString &color) { this->m_color = color.trimmed().toUpper(); } + + /*! + * \brief Color? + * \return + */ + bool hasColor() const { return !this->m_color.isEmpty(); } + + /*! + * \brief Get type + * \return + */ + const QString &getType() const { return this->m_type; } + + /*! + * \brief Get engine type + * \return + */ + QString getEngineType() const + { + if (this->m_type.length() != 3) return ""; + return this->m_type.right(1); + } + + /*! + * \brief As string for GUI representation + * \return + */ + QString asString() const; + + /*! + * \brief Set type + * \param type + */ + void setType(const QString &type) { this->m_type = type.trimmed().toUpper(); } + + /*! + * \brief Equal operator == + * \param other + * @return + */ + bool operator ==(const CAircraftIcao &other) const; + + /*! + * \brief Unequal operator == + * \param other + * @return + */ + bool operator !=(const CAircraftIcao &other) const; + + /*! + * \brief Value hash + */ + virtual uint getValueHash() const; + + /*! + * \brief Register metadata + */ + static void registerMetadata(); + + /*! + * \brief Properties by index + */ + enum ColumnIndex + { + IndexIcaoDesignator = 2000, // used, so it can be chained in aircraft + IndexType, + IndexAirline, + IndexColor, + IndexAsString + }; + + /*! + * \brief Property by index + * \param index + * \return + */ + virtual QVariant propertyByIndex(int index) const; + + /*! + * \brief Property by index as string + * \param index + * \param i18n + * \return + */ + virtual QString propertyByIndexAsString(int index, bool i18n) const; + + /*! + * \brief Property by index (setter) + * \param variant + * \param index + */ + virtual void setPropertyByIndex(const QVariant &variant, int index); + + protected: + /*! + * \brief Rounded value as string + * \param i18n + * \return + */ + virtual QString convertToQString(bool i18n = false) const; + + /*! + * \brief Stream to DBus << + * \param argument + */ + virtual void marshallToDbus(QDBusArgument &argument) const; + + /*! + * \brief Stream from DBus >> + * \param argument + */ + virtual void unmarshallFromDbus(const QDBusArgument &argument); + + private: + QString m_designator; + QString m_type; + QString m_airline; + QString m_livery; + QString m_color; + }; + } // namespace +} // namespace + +Q_DECLARE_METATYPE(BlackMisc::Aviation::CAircraftIcao) + +#endif // guard diff --git a/src/blackmisc/avaircraftlist.cpp b/src/blackmisc/avaircraftlist.cpp new file mode 100644 index 000000000..997f0e4c4 --- /dev/null +++ b/src/blackmisc/avaircraftlist.cpp @@ -0,0 +1,59 @@ +/* Copyright (C) 2013 VATSIM Community / authors + * This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +#include "avaircraftlist.h" +#include "predicates.h" +using namespace BlackMisc::PhysicalQuantities; + +namespace BlackMisc +{ + namespace Aviation + { + /* + * Empty constructor + */ + CAircraftList::CAircraftList() { } + + /* + * Construct from base class object + */ + CAircraftList::CAircraftList(const CSequence &other) : + CSequence(other) + { } + + /* + * Register metadata + */ + void CAircraftList::registerMetadata() + { + qRegisterMetaType>(); + qDBusRegisterMetaType>(); + qRegisterMetaType>(); + qDBusRegisterMetaType>(); + qRegisterMetaType(); + qDBusRegisterMetaType(); + } + + /* + * Find by callsign + */ + CAircraftList CAircraftList::findByCallsign(const CCallsign &callsign) const + { + return this->findBy(&CAircraft::getCallsign, callsign); + } + + /* + * Aircrafts within range + */ + CAircraftList CAircraftList::findWithinRange(const BlackMisc::Geo::ICoordinateGeodetic &coordinate, const PhysicalQuantities::CLength &range) const + { + return this->findBy([&](const CAircraft & aircraft) + { + return BlackMisc::Geo::greatCircleDistance(aircraft, coordinate) <= range; + }); + } + + } // namespace +} // namespace diff --git a/src/blackmisc/avaircraftlist.h b/src/blackmisc/avaircraftlist.h new file mode 100644 index 000000000..b60467dbd --- /dev/null +++ b/src/blackmisc/avaircraftlist.h @@ -0,0 +1,79 @@ +/* Copyright (C) 2013 VATSIM Community / authors + * This Source Code Form is subject to the terms of the Mozilla Public + * 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 BLACKMISC_AIRCRAFTLIST_H +#define BLACKMISC_AIRCRAFTLIST_H + +#include "avaircraft.h" +#include "collection.h" +#include "sequence.h" +#include +#include +#include + +namespace BlackMisc +{ + namespace Aviation + { + /*! + * Value object encapsulating a list of aircraft stations. + */ + class CAircraftList : public CSequence + { + public: + /*! + * \brief Empty constructor. + */ + CAircraftList(); + + /*! + * \brief Construct from a base class object. + * \param other + */ + CAircraftList(const CSequence &other); + + /*! + * \brief QVariant, required for DBus QVariant lists + * \return + */ + virtual QVariant toQVariant() const + { + return QVariant::fromValue(*this); + } + + /*! + * \brief Find 0..n stations by callsign + * \param callsign + * \return + */ + CAircraftList findByCallsign(const CCallsign &callsign) const; + + /*! + * \brief Find 0..n stations within range of given coordinate + * \param coordinate + * \param range + * \return + */ + CAircraftList findWithinRange(const BlackMisc::Geo::ICoordinateGeodetic &coordinate, const BlackMisc::PhysicalQuantities::CLength &range) const; + + /*! + * \brief Register metadata + */ + static void registerMetadata(); + + }; + + } //namespace +} // namespace + +Q_DECLARE_METATYPE(BlackMisc::Aviation::CAircraftList) +Q_DECLARE_METATYPE(BlackMisc::CCollection) +Q_DECLARE_METATYPE(BlackMisc::CSequence) + +#endif //guard diff --git a/src/blackmisc/avaircraftsituation.cpp b/src/blackmisc/avaircraftsituation.cpp new file mode 100644 index 000000000..aae2813b1 --- /dev/null +++ b/src/blackmisc/avaircraftsituation.cpp @@ -0,0 +1,174 @@ +#include "avaircraftsituation.h" +#include "blackmisc/blackmiscfreefunctions.h" + +using namespace BlackMisc::PhysicalQuantities; +using namespace BlackMisc::Geo; + +namespace BlackMisc +{ + namespace Aviation + { + /* + * Convert to string + */ + QString CAircraftSituation::convertToQString(bool i18n) const + { + QString s(this->m_position.toQString(i18n)); + s.append(" altitude: ").append(this->m_altitude.toQString(i18n)); + s.append(" bank: ").append(this->m_bank.toQString(i18n)); + s.append(" pitch: ").append(this->m_pitch.toQString(i18n)); + s.append(" gs: ").append(this->m_groundspeed.toQString(i18n)); + s.append(" heading: ").append(this->m_heading.toQString(i18n)); + s.append(" ts: ").append(this->m_timestamp.toString("dd hh:mm:ss")); + return s; + } + + /* + * Marshall to DBus + */ + void CAircraftSituation::marshallToDbus(QDBusArgument &argument) const + { + argument << this->m_position; + argument << this->m_altitude; + argument << this->m_heading; + argument << this->m_pitch; + argument << this->m_bank; + argument << this->m_groundspeed; + argument << this->m_timestamp; + } + + /* + * Unmarshall from DBus + */ + void CAircraftSituation::unmarshallFromDbus(const QDBusArgument &argument) + { + argument >> this->m_position; + argument >> this->m_altitude; + argument >> this->m_heading; + argument >> this->m_pitch; + argument >> this->m_bank; + argument >> this->m_groundspeed; + argument >> this->m_timestamp; + } + + /* + * Equal? + */ + bool CAircraftSituation::operator ==(const CAircraftSituation &other) const + { + if (this == &other) return true; + return this->getValueHash() == other.getValueHash(); + } + + /* + * Unequal? + */ + bool CAircraftSituation::operator !=(const CAircraftSituation &other) const + { + return !((*this) == other); + } + + /* + * Hash + */ + uint CAircraftSituation::getValueHash() const + { + QList hashs; + hashs << qHash(this->m_position); + hashs << qHash(this->m_altitude); + hashs << qHash(this->m_heading); + hashs << qHash(this->m_groundspeed); + hashs << qHash(this->m_pitch); + hashs << qHash(this->m_bank); + return BlackMisc::calculateHash(hashs, "CAircraftSituation"); + } + + /* + * Property by index + */ + QVariant CAircraftSituation::propertyByIndex(int index) const + { + switch (index) + { + case IndexPosition: + return QVariant::fromValue(this->m_position); + case IndexPositionLatitude: + return QVariant::fromValue(this->latitude()); + case IndexPositionLongitude: + return QVariant::fromValue(this->longitude()); + case IndexPositionHeight: + return QVariant::fromValue(this->getHeight()); + case IndexAltitude: + return QVariant::fromValue(this->m_altitude); + case IndexHeading: + return QVariant::fromValue(this->m_heading); + case IndexPitch: + return QVariant::fromValue(this->m_pitch); + case IndexBank: + return QVariant::fromValue(this->m_bank); + case IndexGroundspeed: + return QVariant::fromValue(this->m_groundspeed); + case IndexTimeStamp: + return QVariant::fromValue(this->m_timestamp); + case IndexTimeStampFormatted: + return QVariant::fromValue(this->m_groundspeed.toQString("dd hh:mm:ss")); + default: + break; + } + + Q_ASSERT_X(false, "CAircraftSituation", "index unknown"); + QString m = QString("no property, index ").append(QString::number(index)); + return QVariant::fromValue(m); + } + + /* + * Property as string by index + */ + QString CAircraftSituation::propertyByIndexAsString(int index, bool i18n) const + { + QVariant qv = this->propertyByIndex(index); + return BlackMisc::qVariantToString(qv, i18n); + } + + /* + * Property by index + */ + void CAircraftSituation::setPropertyByIndex(const QVariant &variant, int index) + { + switch (index) + { + case IndexPosition: + this->setPosition(variant.value()); + break; + case IndexAltitude: + this->setAltitude(variant.value()); + break; + case IndexPitch: + this->setPitch(variant.value()); + break; + case IndexBank: + this->setBank(variant.value()); + break; + case IndexGroundspeed: + this->setGroundspeed(variant.value()); + break; + case IndexPositionHeight: + this->setHeight(variant.value()); + break; + default: + Q_ASSERT_X(false, "CAircraftSituation", "index unknown (setter)"); + break; + } + } + + /* + * Register metadata + */ + void CAircraftSituation::registerMetadata() + { + qRegisterMetaType(); + qDBusRegisterMetaType(); + } + + } // namespace +} // namespace diff --git a/src/blackmisc/avaircraftsituation.h b/src/blackmisc/avaircraftsituation.h new file mode 100644 index 000000000..a814b50c0 --- /dev/null +++ b/src/blackmisc/avaircraftsituation.h @@ -0,0 +1,265 @@ +/* Copyright (C) 2013 VATSIM Community / authors + * This Source Code Form is subject to the terms of the Mozilla Public + * 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 BLACKMISC_AIRCRAFTSITUATION_H +#define BLACKMISC_AIRCRAFTSITUATION_H + +#include "coordinategeodetic.h" +#include "avaltitude.h" +#include "avheading.h" +#include "pqspeed.h" +#include "valueobject.h" +#include + +namespace BlackMisc +{ + namespace Aviation + { + /*! + * Value object encapsulating information of an aircraft's situation + */ + class CAircraftSituation : public BlackMisc::CValueObject, public BlackMisc::Geo::ICoordinateGeodetic + { + public: + /*! + * Default constructor. + */ + CAircraftSituation() : m_timestamp(QDateTime::currentDateTimeUtc()) {} + + /*! + * Constructor. + * \param position + * \param altitude + * \param heading + * \param pitch + * \param bank + * \param gs + * \param parent + */ + CAircraftSituation(const BlackMisc::Geo::CCoordinateGeodetic &position, const BlackMisc::Aviation::CAltitude &altitude, + const BlackMisc::Aviation::CHeading &heading = BlackMisc::Aviation::CHeading(), + const BlackMisc::PhysicalQuantities::CAngle &pitch = BlackMisc::PhysicalQuantities::CAngle(), + const BlackMisc::PhysicalQuantities::CAngle &bank = BlackMisc::PhysicalQuantities::CAngle(), + const BlackMisc::PhysicalQuantities::CSpeed &gs = BlackMisc::PhysicalQuantities::CSpeed()) + : m_position(position), m_altitude(altitude), m_heading(heading), m_pitch(pitch), m_bank(bank), m_groundspeed(gs), + m_timestamp(QDateTime::currentDateTimeUtc()) {} + + + /*! + * \brief Properties by index + */ + enum ColumnIndex + { + IndexPosition = 1000, // used, so it can be chained in aircraft + IndexPositionLatitude, + IndexPositionLongitude, + IndexPositionHeight, + IndexAltitude, + IndexHeading, + IndexBank, + IndexPitch, + IndexGroundspeed, + IndexTimeStamp, + IndexTimeStampFormatted + }; + + /*! + * \brief Property by index + * \param index + * \return + */ + virtual QVariant propertyByIndex(int index) const; + + /*! + * \brief Property by index as string + * \param index + * \param i18n + * \return + */ + virtual QString propertyByIndexAsString(int index, bool i18n) const; + + /*! + * \brief Property by index + * \param variant + * \param index + */ + virtual void setPropertyByIndex(const QVariant &variant, int index); + + /*! + * \brief QVariant, required for DBus QVariant lists + * \return + */ + virtual QVariant toQVariant() const + { + return QVariant::fromValue(*this); + } + + /*! + * \brief Get position + * \return + */ + const BlackMisc::Geo::CCoordinateGeodetic &getPosition() const { return this->m_position; } + + /*! + * \brief Set position + * \param position + */ + void setPosition(const BlackMisc::Geo::CCoordinateGeodetic &position) { this->m_position = position; } + + /*! + * \brief Get latitude + * \return + */ + virtual const BlackMisc::Geo::CLatitude &latitude() const { return this->m_position.latitude(); } + + /*! + * \brief Get longitude + * \return + */ + virtual const BlackMisc::Geo::CLongitude &longitude() const { return this->m_position.longitude(); } + + /*! + * \brief Get height + * \return + */ + const BlackMisc::PhysicalQuantities::CLength &getHeight() const { return this->m_position.height(); } + + /*! + * \brief Set height + * \param + */ + void setHeight(const BlackMisc::PhysicalQuantities::CLength &height) { this->m_position.setHeight(height); } + + /*! + * \brief Get heading + * \return + */ + const BlackMisc::Aviation::CHeading &getHeading() const { return this->m_heading; } + + /*! + * \brief Set heading + * \param + */ + void setHeading(const BlackMisc::Aviation::CHeading &heading) { this->m_heading = heading; } + + /*! + * \brief Get altitude (true) + * \return + */ + const BlackMisc::Aviation::CAltitude &getAltitude() const { return this->m_altitude; } + + /*! + * \brief Set altitude + * \param + */ + void setAltitude(const BlackMisc::Aviation::CAltitude &altitude) { this->m_altitude = altitude; } + + /*! + * \brief Get pitch + * \return + */ + const BlackMisc::PhysicalQuantities::CAngle &getPitch() const { return this->m_pitch; } + + /*! + * \brief Set pitch + * \param + */ + void setPitch(const BlackMisc::PhysicalQuantities::CAngle &pitch) { this->m_pitch = pitch; } + + /*! + * \brief Get bank + * \return + */ + const BlackMisc::PhysicalQuantities::CAngle &getBank() const { return this->m_bank; } + + /*! + * \brief Set bank + * \param + */ + void setBank(const BlackMisc::PhysicalQuantities::CAngle &bank) { this->m_bank = bank; } + + /*! + * \brief Get groundspeed + * \return + */ + const BlackMisc::PhysicalQuantities::CSpeed &getGroundSpeed() const { return this->m_groundspeed; } + + /*! + * \brief Set groundspeed + * \param + */ + void setGroundspeed(const BlackMisc::PhysicalQuantities::CSpeed &groundspeed) { this->m_groundspeed = groundspeed; } + + /*! + * \brief Timestamp + * \return + */ + const QDateTime &getTimestamp() const { return this->m_timestamp;} + + /*! + * \brief Equal operator == + * \param other + * @return + */ + bool operator ==(const CAircraftSituation &other) const; + + /*! + * \brief Unequal operator == + * \param other + * @return + */ + bool operator !=(const CAircraftSituation &other) const; + + /*! + * \brief Value hash + */ + virtual uint getValueHash() const; + + /*! + * \brief Register metadata + */ + static void registerMetadata(); + + + protected: + /*! + * \brief Rounded value as string + * \param i18n + * \return + */ + virtual QString convertToQString(bool i18n = false) const; + + /*! + * \brief Stream to DBus << + * \param argument + */ + virtual void marshallToDbus(QDBusArgument &argument) const; + + /*! + * \brief Stream from DBus >> + * \param argument + */ + virtual void unmarshallFromDbus(const QDBusArgument &argument); + + private: + BlackMisc::Geo::CCoordinateGeodetic m_position; + BlackMisc::Aviation::CAltitude m_altitude; + BlackMisc::Aviation::CHeading m_heading; + BlackMisc::PhysicalQuantities::CAngle m_pitch; + BlackMisc::PhysicalQuantities::CAngle m_bank; + BlackMisc::PhysicalQuantities::CSpeed m_groundspeed; + QDateTime m_timestamp; + + }; + } // namespace +} // namespace + +Q_DECLARE_METATYPE(BlackMisc::Aviation::CAircraftSituation) + +#endif // guard diff --git a/src/blackmisc/avallclasses.h b/src/blackmisc/avallclasses.h index bc37c9a3f..1e99f4f56 100644 --- a/src/blackmisc/avallclasses.h +++ b/src/blackmisc/avallclasses.h @@ -13,5 +13,11 @@ #include "blackmisc/avionavsystem.h" #include "blackmisc/aviotransponder.h" #include "blackmisc/avtrack.h" +#include "blackmisc/avcallsign.h" +#include "blackmisc/avatcstation.h" +#include "blackmisc/avatcstationlist.h" +#include "blackmisc/avaircraft.h" +#include "blackmisc/avaircraftlist.h" +#include "blackmisc/avinformationmessage.h" #endif // guard diff --git a/src/blackmisc/avatcstation.cpp b/src/blackmisc/avatcstation.cpp new file mode 100644 index 000000000..2df39d957 --- /dev/null +++ b/src/blackmisc/avatcstation.cpp @@ -0,0 +1,466 @@ +#include "avatcstation.h" +#include "aviocomsystem.h" +#include "blackmiscfreefunctions.h" + +using namespace BlackMisc::PhysicalQuantities; +using namespace BlackMisc::Geo; +using namespace BlackMisc::Network; + +namespace BlackMisc +{ + namespace Aviation + { + + /* + * Constructor + */ + CAtcStation::CAtcStation() : + m_distanceToPlane(-1.0, CLengthUnit::NM()), m_isOnline(false), m_atis(CInformationMessage::ATIS), m_metar(CInformationMessage::METAR) + { + // void + } + + /* + * Constructor + */ + CAtcStation::CAtcStation(const QString &callsign) : + m_callsign(callsign), m_distanceToPlane(-1.0, CLengthUnit::NM()), m_isOnline(false), m_atis(CInformationMessage::ATIS), m_metar(CInformationMessage::METAR) + { + // void + } + + /* + * Constructor + */ + CAtcStation::CAtcStation(const CCallsign &callsign, const CUser &controller, const CFrequency &frequency, const CCoordinateGeodetic &pos, const CLength &range, bool isOnline, + const QDateTime &bookedFromUtc, const QDateTime &bookedUntilUtc, const CInformationMessage &atis, const CInformationMessage &metar) : + m_callsign(callsign), m_controller(controller), m_frequency(frequency), m_position(pos), + m_range(range), m_distanceToPlane(-1.0, CLengthUnit::NM()), m_isOnline(isOnline), + m_bookedFromUtc(bookedFromUtc), m_bookedUntilUtc(bookedUntilUtc), m_atis(atis), m_metar(metar) + { + // void + } + + /* + * Convert to string + */ + QString CAtcStation::convertToQString(bool i18n) const + { + QString s = i18n ? + QCoreApplication::translate("Aviation", "ATC station") : + "ATC station"; + s.append(' ').append(this->m_callsign.toQString(i18n)); + + // position + s.append(' ').append(this->m_position.toQString(i18n)); + + // Online? + s.append(' '); + if (this->m_isOnline) + { + i18n ? s.append(QCoreApplication::translate("Aviation", "online")) : s.append("online"); + } + else + { + i18n ? s.append(QCoreApplication::translate("Aviation", "offline")) : s.append("offline"); + } + + // controller name + if (!this->m_controller.isValid()) + { + s.append(' '); + s.append(this->m_controller.toQString(i18n)); + } + + // frequency + s.append(' '); + s.append(this->m_frequency.toQString(i18n)); + + // ATIS + if (this->hasAtis()) + { + s.append(' '); + s.append(this->m_atis.toQString(i18n)); + } + + // METAR + if (this->hasMetar()) + { + s.append(' '); + s.append(this->m_metar.toQString(i18n)); + } + + // range + s.append(' '); + i18n ? s.append(s.append(QCoreApplication::translate("Aviation", "range"))) : s.append("range"); + s.append(": "); + s.append(this->m_range.toQString(i18n)); + + // distance to plane + if (this->m_distanceToPlane.isPositiveWithEpsilonConsidered()) + { + i18n ? s.append(QCoreApplication::translate("Aviation", "distance")) : s.append("distance"); + s.append(' '); + s.append(this->m_distanceToPlane.toQString(i18n)); + } + + // from / to + if (!this->hasBookingTimes()) return s; + + // append from + s.append(' '); + i18n ? s.append(s.append(QCoreApplication::translate("Aviation", "from(UTC)"))) : s.append("from(UTC)"); + s.append(": "); + if (this->m_bookedFromUtc.isNull()) + { + s.append('-'); + } + else + { + s.append(this->m_bookedFromUtc.toString("yy-MM-dd HH:mm")); + } + + // append to + s.append(' '); + i18n ? s.append(s.append(QCoreApplication::translate("Aviation", "until(UTC)"))) : s.append("to(UTC)"); + s.append(": "); + if (this->m_bookedFromUtc.isNull()) + { + s.append('-'); + } + else + { + s.append(this->m_bookedUntilUtc.toString("yy-MM-dd HH:mm")); + } + return s; + + // force strings for translation in resource files + (void)QT_TRANSLATE_NOOP("Aviation", "ATC station"); + (void)QT_TRANSLATE_NOOP("Aviation", "online"); + (void)QT_TRANSLATE_NOOP("Aviation", "offline"); + (void)QT_TRANSLATE_NOOP("Aviation", "from(UTC)"); + (void)QT_TRANSLATE_NOOP("Aviation", "until(UTC)"); + (void)QT_TRANSLATE_NOOP("Aviation", "range"); + (void)QT_TRANSLATE_NOOP("Aviation", "distance"); + + } + + /* + * Marshall to DBus + */ + void CAtcStation::marshallToDbus(QDBusArgument &argument) const + { + argument << this->m_callsign; + argument << this->m_frequency; + argument << this->m_controller; + argument << this->m_position; + argument << this->m_range; + argument << this->m_distanceToPlane; + argument << this->m_isOnline; + argument << this->m_bookedFromUtc; + argument << this->m_bookedUntilUtc; + argument << this->m_atis; + argument << this->m_metar; + } + + /* + * Unmarshall from DBus + */ + void CAtcStation::unmarshallFromDbus(const QDBusArgument &argument) + { + argument >> this->m_callsign; + argument >> this->m_frequency; + argument >> this->m_controller; + argument >> this->m_position; + argument >> this->m_range; + argument >> this->m_distanceToPlane; + argument >> this->m_isOnline; + argument >> this->m_bookedFromUtc; + argument >> this->m_bookedUntilUtc; + argument >> this->m_atis; + argument >> this->m_metar; + } + + /* + * Register metadata + */ + void CAtcStation::registerMetadata() + { + qRegisterMetaType(); + qDBusRegisterMetaType(); + } + + /* + * Equal? + */ + bool CAtcStation::operator ==(const CAtcStation &other) const + { + if (this == &other) return true; + + if (other.getCallsign() != this->getCallsign() || + other.getRange() != this->getRange() || + other.getFrequency() != this->getFrequency() || + other.getPosition() != this->getPosition()) return false; + + if (other.getController() != this->getController()) return false; + if (other.getAtis() != this->getAtis()) return false; + if (other.getMetar() != this->getMetar()) return false; + + return this->getBookedFromUtc() == other.getBookedFromUtc() && + this->getBookedUntilUtc() == other.getBookedUntilUtc(); + } + + /* + * Unequal? + */ + bool CAtcStation::operator !=(const CAtcStation &other) const + { + return !((*this) == other); + } + + /* + * SyncronizeControllerData + */ + void CAtcStation::syncronizeControllerData(CAtcStation &otherStation) + { + if (this->m_controller == otherStation.getController()) return; + CUser otherController = otherStation.getController(); + this->m_controller.syncronizeData(otherController); + otherStation.setController(otherController); + } + + /* + * Distance to planne + */ + const CLength &CAtcStation::calculcateDistanceToPlane(const CCoordinateGeodetic &position) + { + this->m_distanceToPlane = greatCircleDistance(this->m_position, position); + return this->m_distanceToPlane; + } + + /* + * Booked now + */ + bool CAtcStation::isBookedNow() const + { + if (!this->hasValidBookingTimes()) return false; + QDateTime now = QDateTime::currentDateTimeUtc(); + if (this->m_bookedFromUtc > now) return false; + if (now > this->m_bookedUntilUtc) return false; + return true; + } + + /*! + * \brief When booked? + * \return + */ + CTime CAtcStation::bookedWhen() const + { + if (!this->hasValidBookingTimes()) return CTime(-365.0, CTimeUnit::d()); + QDateTime now = QDateTime::currentDateTimeUtc(); + qint64 diffMs; + if (this->m_bookedFromUtc > now) + { + // future + diffMs = now.msecsTo(this->m_bookedFromUtc); + return CTime(diffMs / 1000.0, CTimeUnit::s()); + } + else if (this->m_bookedUntilUtc > now) + { + // now + return CTime(0.0, CTimeUnit::s()); + } + else + { + // past + diffMs = m_bookedUntilUtc.msecsTo(now); + return CTime(-diffMs / 1000.0, CTimeUnit::s()); + } + } + + /* + * Hash + */ + uint CAtcStation::getValueHash() const + { + QList hashs; + hashs << this->m_callsign.getValueHash(); + hashs << this->m_frequency.getValueHash(); + hashs << this->m_controller.getValueHash(); + hashs << this->m_position.getValueHash(); + hashs << this->m_range.getValueHash(); + hashs << this->m_distanceToPlane.getValueHash(); + hashs << this->m_metar.getValueHash(); + hashs << this->m_atis.getValueHash(); + hashs << qHash(this->m_isOnline ? 1 : 3); + hashs << qHash(this->m_bookedFromUtc); + hashs << qHash(this->m_bookedUntilUtc); + return BlackMisc::calculateHash(hashs, "CAtcStation"); + } + + /* + * Property by index + */ + QVariant CAtcStation::propertyByIndex(int index) const + { + switch (index) + { + case IndexBookedFrom: + return QVariant(this->m_bookedFromUtc); + case IndexBookedUntil: + return QVariant(this->m_bookedUntilUtc); + case IndexCallsign: + return this->m_callsign.toQVariant(); + case IndexCallsignAsString: + return QVariant(this->m_callsign.asString()); + case IndexCallsignAsStringAsSet: + return QVariant(this->m_callsign.getStringAsSet()); + case IndexController: + return this->m_controller.toQVariant(); + case IndexControllerRealname: + return QVariant(this->getControllerRealname()); + case IndexControllerId: + return QVariant(this->getControllerId()); + case IndexFrequency: + return this->m_frequency.toQVariant(); + case IndexIsOnline: + return QVariant(this->m_isOnline); + case IndexLatitude: + return this->latitude().toQVariant(); + case IndexDistance: + return this->m_distanceToPlane.toQVariant(); + case IndexLongitude: + return this->longitude().toQVariant(); + case IndexPosition: + return this->m_position.toQVariant(); + case IndexRange: + return this->m_range.toQVariant(); + case IndexAtis: + return this->m_atis.toQVariant(); + case IndexAtisMessage: + return QVariant(this->m_atis.getMessage()); + case IndexMetar: + return this->m_metar.toQVariant(); + case IndexMetarMessage: + return QVariant(this->m_metar.getMessage()); + default: + break; + } + + Q_ASSERT_X(false, "CAtcStation", "index unknown"); + QString m = QString("no property, index ").append(QString::number(index)); + return QVariant::fromValue(m); + } + + /* + * Set property as index + */ + void CAtcStation::setPropertyByIndex(const QVariant &variant, int index) + { + switch (index) + { + case IndexBookedFrom: + this->setBookedFromUtc(variant.value()); + break; + case IndexBookedUntil: + this->setBookedUntilUtc(variant.value()); + break; + case IndexCallsign: + this->setCallsign(variant.value()); + break; + case IndexCallsignAsString: + this->setCallsign(CCallsign(variant.value())); + break; + case IndexController: + this->setController(variant.value()); + break; + case IndexControllerRealname: + this->setControllerRealname(variant.value()); + break; + case IndexControllerId: + this->setControllerId(variant.value()); + break; + case IndexFrequency: + this->setFrequency(variant.value()); + break; + case IndexIsOnline: + this->setOnline(variant.value()); + break; + case IndexPosition: + this->setPosition(variant.value()); + break; + case IndexRange: + this->setRange(variant.value()); + break; + case IndexDistance: + this->setDistanceToPlane(variant.value()); + break; + case IndexAtis: + this->setAtis(variant.value()); + break; + case IndexAtisMessage: + this->setAtisMessage(variant.value()); + break; + case IndexMetar: + this->setMetar(variant.value()); + break; + case IndexMetarMessage: + this->setMetarMessage(variant.value()); + break; + default: + Q_ASSERT_X(false, "CAtcStation", "index unknown (setter)"); + break; + } + } + + /* + * Compare + */ + int CAtcStation::compare(const QVariant &qv) const + { + Q_ASSERT(qv.canConvert()); + Q_ASSERT(!qv.isNull() && qv.isValid()); + CAtcStation atc = qv.value(); + return this->getCallsign().compare(atc.getCallsign()); + } + + /* + * Property as string by index + */ + QString CAtcStation::propertyByIndexAsString(int index, bool i18n) const + { + QVariant qv = this->propertyByIndex(index); + // special treatment + // this is required as it is possible an ATC station is not containing all + // properties + switch (index) + { + case IndexFrequency: + if (!CComSystem::isValidCivilAviationFrequency(qv.value())) + { + return ""; + } + break; + case IndexDistance: + { + CLength distance = qv.value(); + if (distance.isNegativeWithEpsilonConsidered()) return ""; + return distance.toQString(i18n); + } + + case IndexBookedFrom: + case IndexBookedUntil: + { + QDateTime dt = qv.value(); + if (dt.isNull() || !dt.isValid()) return ""; + return dt.toString("yyyy-MM-dd HH:mm"); + break; + } + default: + break; + } + return BlackMisc::qVariantToString(qv, i18n); + } + + } // namespace +} // namespace diff --git a/src/blackmisc/avatcstation.h b/src/blackmisc/avatcstation.h new file mode 100644 index 000000000..6d14abe8e --- /dev/null +++ b/src/blackmisc/avatcstation.h @@ -0,0 +1,478 @@ +/* Copyright (C) 2013 VATSIM Community / authors + * This Source Code Form is subject to the terms of the Mozilla Public + * 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 BLACKMISC_ATCSTATION_H +#define BLACKMISC_ATCSTATION_H +#include "valuemap.h" +#include "pqfrequency.h" +#include "pqlength.h" +#include "pqtime.h" +#include "nwuser.h" +#include "coordinategeodetic.h" +#include "avcallsign.h" +#include "avinformationmessage.h" +#include +#include +#include + +namespace BlackMisc +{ + namespace Aviation + { + /*! + * Value object encapsulating information about an ATC station. + */ + class CAtcStation : public BlackMisc::CValueObject, public BlackMisc::Geo::ICoordinateGeodetic + { + + public: + /*! + * \brief Properties by index + */ + enum ColumnIndex + { + IndexCallsign = 0, + IndexCallsignAsString, + IndexCallsignAsStringAsSet, + IndexController, + IndexControllerRealname, + IndexControllerId, + IndexFrequency, + IndexPosition, + IndexRange, + IndexDistance, + IndexIsOnline, + IndexBookedFrom, + IndexBookedUntil, + IndexLatitude, + IndexLongitude, + IndexAtis, + IndexAtisMessage, + IndexMetar, + IndexMetarMessage + }; + + /*! + * Default constructor. + */ + CAtcStation(); + + /*! + * \brief Simplified constructor + * \param callsign + */ + CAtcStation(const QString &callsign); + + /*! + * \brief ATC station + * \param callsign + * \param controllerName + * \param freq + * \param pos + * \param range + * \param isOnline + * \param bookedFromUtc + * \param bookedUntilUtc + * \param atis + */ + CAtcStation(const CCallsign &callsign, const BlackMisc::Network::CUser &controller, + const BlackMisc::PhysicalQuantities::CFrequency &frequency, + const BlackMisc::Geo::CCoordinateGeodetic &pos, const BlackMisc::PhysicalQuantities::CLength &range, + bool isOnline = false, const QDateTime &bookedFromUtc = QDateTime(), const QDateTime &bookedUntilUtc = QDateTime(), + const CInformationMessage &atis = CInformationMessage(CInformationMessage::ATIS), const CInformationMessage &metar = CInformationMessage(CInformationMessage::METAR)); + + /*! + * \brief Virtual method to return QVariant, used with DBUS QVariant lists + * \return + */ + virtual QVariant toQVariant() const + { + return QVariant::fromValue(*this); + } + + /*! + * \brief Equal operator == + * \param other + * @return + */ + bool operator ==(const CAtcStation &other) const; + + /*! + * \brief Unequal operator == + * \param other + * @return + */ + bool operator !=(const CAtcStation &other) const; + + /*! + * \brief Has booking times? + * \return + */ + bool hasBookingTimes() const + { + return !(this->m_bookedFromUtc.isNull() && this->m_bookedUntilUtc.isNull()); + } + + /*! + * \brief Has ATIS? + * \return + */ + bool hasAtis() const + { + return this->m_atis.hasMessage(); + } + + /*! + * \brief Has Metar? + * \return + */ + bool hasMetar() const + { + return this->m_metar.hasMessage(); + } + + /*! + * Get callsign. + * \return + */ + const CCallsign &getCallsign() const { return m_callsign; } + + /*! + * Get callsign. + * \return + */ + QString getCallsignAsString() const { return m_callsign.asString(); } + + /*! + * Set callsign + * \param callsign + */ + void setCallsign(const CCallsign &callsign) { this->m_callsign = callsign; } + + /*! + * Get controller + * \return + */ + const BlackMisc::Network::CUser &getController() const { return m_controller; } + + /*! + * Get controller name. + * \return + */ + QString getControllerRealname() const { return m_controller.getRealname(); } + + /*! + * Get controller name. + * \return + */ + QString getControllerId() const { return m_controller.getId(); } + + /*! + * Set controller + * \param controller + */ + void setController(const BlackMisc::Network::CUser &controller) { this->m_controller = controller; } + + /*! + * Set controller's name + * \param controllerName + */ + void setControllerRealname(const QString &controllerName) { this->m_controller.setRealname(controllerName); } + + /*! + * Set controller's id + * \param controllerId + */ + void setControllerId(const QString &controllerId) { this->m_controller.setId(controllerId); } + + /*! + * \brief Has valid realname? + * \return + */ + bool hasValidRealname() const { return this->m_controller.hasValidRealname(); } + + /*! + * \brief Has valid id? + * \return + */ + bool hasValidId() const { return this->m_controller.hasValidId(); } + + /*! + * Get frequency. + * \return + */ + const BlackMisc::PhysicalQuantities::CFrequency &getFrequency() const { return m_frequency; } + + /*! + * Set frequency + * \param frequency + */ + void setFrequency(const BlackMisc::PhysicalQuantities::CFrequency &frequency) { this->m_frequency = frequency; } + + /*! + * Get the position of the center of the controller's area of visibility. + * \return + */ + const BlackMisc::Geo::CCoordinateGeodetic &getPosition() const { return m_position; } + + /*! + * Set position + * \param position + */ + void setPosition(const BlackMisc::Geo::CCoordinateGeodetic &position) { this->m_position = position; } + + /*! + * \brief Syncronize controller data + * Updates two stations (namely a booked and online ATC station) with complementary data + * \param otherStation + */ + void syncronizeControllerData(CAtcStation &otherStation); + + /*! + * Get the radius of the controller's area of visibility. + * \return + */ + const BlackMisc::PhysicalQuantities::CLength &getRange() const { return m_range; } + + /*! + * Set range + * \param range + */ + void setRange(const BlackMisc::PhysicalQuantities::CLength &range) { this->m_range = range; } + + /*! + * Get the distance to own plane + * \return + */ + const BlackMisc::PhysicalQuantities::CLength &getDistanceToPlane() const { return m_distanceToPlane; } + + /*! + * Set distance to own plane + * \param range + */ + void setDistanceToPlane(const BlackMisc::PhysicalQuantities::CLength &distance) { this->m_distanceToPlane = distance; } + + /*! + * \brief Valid distance? + * \return + */ + bool hasValidDistance() const { return !this->m_distanceToPlane.isNegativeWithEpsilonConsidered();} + + /*! + * \brief Calculcate distance to plane, set it, and also return it + * \param position + * \return + */ + const BlackMisc::PhysicalQuantities::CLength &calculcateDistanceToPlane(const BlackMisc::Geo::CCoordinateGeodetic &position); + + /*! + * \brief Is station online (or just booked) + * \return + */ + bool isOnline() const { return m_isOnline; } + + /*! + * Set online + * \param online + */ + void setOnline(bool online) { this->m_isOnline = online; } + + /*! + * Booked date/time if any. + * This represents the closest booking within a time frame as there can be multiple bookings. + * \return + */ + const QDateTime &getBookedFromUtc() const { return m_bookedFromUtc; } + + /*! + * Set booked from + * \param until + */ + void setBookedFromUtc(const QDateTime &from) { this->m_bookedFromUtc = from; } + + /*! + * Booked date/time if any. + * This represents the closest booking within a time frame as there can be multiple bookings. + * \return + */ + const QDateTime &getBookedUntilUtc() const { return m_bookedUntilUtc; } + + /*! + * \brief Has valid booking times? + * \return + */ + bool hasValidBookingTimes() const + { + return !this->m_bookedFromUtc.isNull() && this->m_bookedFromUtc.isValid() && + !this->m_bookedUntilUtc.isNull() && this->m_bookedUntilUtc.isValid(); + } + + /*! + * \brief Transfer booking times + * \param otherStation + */ + void setBookedFromUntil(const CAtcStation &otherStation) + { + this->setBookedFromUtc(otherStation.getBookedFromUtc()); + this->setBookedUntilUtc(otherStation.getBookedUntilUtc()); + } + + /*! + * \brief Booked now + * \return + */ + bool isBookedNow() const; + + /*! + * When booked, 0 means now, + * negative values mean booking in past, + * positive values mean booking in future, + * no booking dates will result in - 1 year + * \return + */ + BlackMisc::PhysicalQuantities::CTime bookedWhen() const; + + /*! + * \brief Get atis + * \return + */ + const CInformationMessage &getAtis() const { return m_atis; } + + /*! + * \brief Set ATIS + * \param msg + */ + void setAtis(const CInformationMessage &atis) { this->m_atis = atis;} + + /*! + * \brief Set ATIS Message + * \param atis + */ + void setAtisMessage(const QString &atis) { this->m_atis.addMessage(atis); } + + /*! + * \brief Get METAR + * \return + */ + const CInformationMessage &getMetar() const { return m_metar; } + + /*! + * \brief Set METAR + * \param msg + */ + void setMetar(const CInformationMessage &metar) { this->m_metar = metar;} + + /*! + * \brief Set METAR Message + * \param msg + */ + void setMetarMessage(const QString &metar) { this->m_metar.addMessage(metar); } + + /*! + * Set booked until + * \param until + */ + void setBookedUntilUtc(const QDateTime &until) { this->m_bookedUntilUtc = until; } + + /*! + * \brief Latitude + * \return + */ + virtual const BlackMisc::Geo::CLatitude &latitude() const + { + return this->getPosition().latitude(); + } + + /*! + * \brief Longitude + * \return + */ + virtual const BlackMisc::Geo::CLongitude &longitude() const + { + return this->getPosition().longitude(); + } + + /*! + * \brief Hash value + * \return + */ + virtual uint getValueHash() const; + + /*! + * \brief Property by index + * \param index + * \return + */ + virtual QVariant propertyByIndex(int index) const; + + /*! + * \brief Property by index (setting) + * \param variant + * \return + */ + virtual void setPropertyByIndex(const QVariant &variant, int index); + + /*! + * \brief Property by index as String + * \param index + * \param i18n + * \return + */ + virtual QString propertyByIndexAsString(int index, bool i18n = false) const; + + /*! + * \brief Register metadata + */ + static void registerMetadata(); + + /*! + * \copydoc BlackObject::compare + */ + virtual int compare(const QVariant &qv) const; + + protected: + /*! + * \brief Meaningful string representation + * \param i18n + * \return + */ + virtual QString convertToQString(bool i18n = false) const; + + /*! + * \brief Stream to DBus << + * \param argument + */ + virtual void marshallToDbus(QDBusArgument &argument) const; + + /*! + * \brief Stream from DBus >> + * \param argument + */ + virtual void unmarshallFromDbus(const QDBusArgument &argument); + + private: + CCallsign m_callsign; + BlackMisc::Network::CUser m_controller; + BlackMisc::PhysicalQuantities::CFrequency m_frequency; + BlackMisc::Geo::CCoordinateGeodetic m_position; + BlackMisc::PhysicalQuantities::CLength m_range; + BlackMisc::PhysicalQuantities::CLength m_distanceToPlane; + bool m_isOnline; + QDateTime m_bookedFromUtc; + QDateTime m_bookedUntilUtc; + CInformationMessage m_atis; + CInformationMessage m_metar; + }; + + } // namespace +} // namespace + +Q_DECLARE_METATYPE(BlackMisc::Aviation::CAtcStation) + +#endif // guard diff --git a/src/blackmisc/avatcstationlist.cpp b/src/blackmisc/avatcstationlist.cpp new file mode 100644 index 000000000..eede624a2 --- /dev/null +++ b/src/blackmisc/avatcstationlist.cpp @@ -0,0 +1,145 @@ +/* Copyright (C) 2013 VATSIM Community / authors + * This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +#include "avatcstationlist.h" +#include "predicates.h" +using namespace BlackMisc::PhysicalQuantities; + +namespace BlackMisc +{ + namespace Aviation + { + /* + * Empty constructor + */ + CAtcStationList::CAtcStationList() { } + + /* + * Construct from base class object + */ + CAtcStationList::CAtcStationList(const CSequence &other) : + CSequence(other) + { } + + /* + * Register metadata + */ + void CAtcStationList::registerMetadata() + { + qRegisterMetaType>(); + qDBusRegisterMetaType>(); + qRegisterMetaType>(); + qDBusRegisterMetaType>(); + qRegisterMetaType(); + qDBusRegisterMetaType(); + } + + /* + * Find by callsign + */ + CAtcStationList CAtcStationList::findByCallsign(const CCallsign &callsign) const + { + return this->findBy(&CAtcStation::getCallsign, callsign); + } + + /* + * Stations within range + */ + CAtcStationList CAtcStationList::findWithinRange(const BlackMisc::Geo::ICoordinateGeodetic &coordinate, const PhysicalQuantities::CLength &range) const + { + return this->findBy([&](const CAtcStation & atcStation) + { + return greatCircleDistance(atcStation, coordinate) <= range; + }); + } + + /* + * Distances to own plane + */ + void CAtcStationList::calculateDistancesToPlane(const Geo::CCoordinateGeodetic &position) + { + std::for_each(this->begin(), this->end(), [ & ](CAtcStation &station) + { + station.calculcateDistanceToPlane(position); + }); + } + + /* + * Merge with booking + */ + int CAtcStationList::mergeWithBooking(CAtcStation &booking) + { + int c = 0; + booking.setOnline(false); // reset + + for (auto i = this->begin(); i != this->end(); ++i) + { + CAtcStation currentOnline = *i; + if (currentOnline.getCallsign() != booking.getCallsign()) continue; + + // from online to booking + booking.setOnline(true); + booking.setFrequency(currentOnline.getFrequency()); + + // from booking to online + if (!currentOnline.isBookedNow() && booking.hasValidBookingTimes()) + { + if (currentOnline.hasValidBookingTimes()) + { + if (booking.isBookedNow()) + { + // can't get any better + currentOnline.setBookedFromUntil(booking); + } + else + { + // we already have some booking dates + CTime timeDiffBooking = booking.bookedWhen(); + CTime timeDiffOnline = currentOnline.bookedWhen(); + if (timeDiffBooking.isNegativeWithEpsilonConsidered() && timeDiffOnline.isNegativeWithEpsilonConsidered()) + { + // both in past + if (timeDiffBooking > timeDiffOnline) + currentOnline.setBookedFromUntil(booking); + } + else if (timeDiffBooking.isPositiveWithEpsilonConsidered() && timeDiffOnline.isPositiveWithEpsilonConsidered()) + { + // both in future + if (timeDiffBooking < timeDiffOnline) + currentOnline.setBookedFromUntil(booking); + } + else if (timeDiffBooking.isPositiveWithEpsilonConsidered() && timeDiffOnline.isNegativeWithEpsilonConsidered()) + { + // future booking is better than past booking + currentOnline.setBookedFromUntil(booking); + } + } + } + else + { + // no booking info so far + currentOnline.setBookedFromUntil(booking); + } + } + + // both ways + currentOnline.syncronizeControllerData(booking); + if (currentOnline.hasValidDistance()) + booking.setDistanceToPlane(currentOnline.getDistanceToPlane()); + else if (booking.hasValidDistance()) + currentOnline.setDistanceToPlane(booking.getDistanceToPlane()); + + // update + *i = currentOnline; + c++; + } + + // normally 1 expected, as I should find one online station + // for this booking + return c; + } + + } // namespace +} // namespace diff --git a/src/blackmisc/avatcstationlist.h b/src/blackmisc/avatcstationlist.h new file mode 100644 index 000000000..e26ba7316 --- /dev/null +++ b/src/blackmisc/avatcstationlist.h @@ -0,0 +1,91 @@ +/* Copyright (C) 2013 VATSIM Community / authors + * This Source Code Form is subject to the terms of the Mozilla Public + * 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 BLACKMISC_ATCSTATIONLIST_H +#define BLACKMISC_ATCSTATIONLIST_H + +#include "avatcstation.h" +#include "collection.h" +#include "sequence.h" +#include +#include +#include + +namespace BlackMisc +{ + namespace Aviation + { + /*! + * Value object encapsulating a list of ATC stations. + */ + class CAtcStationList : public CSequence + { + public: + /*! + * \brief Empty constructor. + */ + CAtcStationList(); + + /*! + * \brief Construct from a base class object. + * \param other + */ + CAtcStationList(const CSequence &other); + + /*! + * \brief QVariant, required for DBus QVariant lists + * \return + */ + virtual QVariant toQVariant() const + { + return QVariant::fromValue(*this); + } + + /*! + * \brief Find 0..n stations by callsign + * \param callsign + * \return + */ + CAtcStationList findByCallsign(const CCallsign &callsign) const; + + /*! + * \brief Find 0..n stations within range of given coordinate + * \param coordinate + * \param range + * \return + */ + CAtcStationList findWithinRange(const BlackMisc::Geo::ICoordinateGeodetic &coordinate, const BlackMisc::PhysicalQuantities::CLength &range) const; + + /*! + * \brief Update distances to own plane + * \param position + */ + void calculateDistancesToPlane(const BlackMisc::Geo::CCoordinateGeodetic &position); + + /*! + * \brief Register metadata + */ + static void registerMetadata(); + + /*! + * \brief Merge with ATC station representing booking information + * \param booking + * \return + */ + int mergeWithBooking(CAtcStation &booking); + }; + + } //namespace +} // namespace + +Q_DECLARE_METATYPE(BlackMisc::Aviation::CAtcStationList) +Q_DECLARE_METATYPE(BlackMisc::CCollection) +Q_DECLARE_METATYPE(BlackMisc::CSequence) + +#endif //guard diff --git a/src/blackmisc/avcallsign.cpp b/src/blackmisc/avcallsign.cpp new file mode 100644 index 000000000..acf1817e2 --- /dev/null +++ b/src/blackmisc/avcallsign.cpp @@ -0,0 +1,114 @@ +#include "avcallsign.h" + +namespace BlackMisc +{ + namespace Aviation + { + /* + * Convert to string + */ + QString CCallsign::convertToQString(bool /** i18n **/) const + { + return this->m_callsign; + } + + /* + * Marshall to DBus + */ + void CCallsign::marshallToDbus(QDBusArgument &argument) const + { + argument << this->m_callsignAsSet; + } + + /* + * Unmarshall from DBus + */ + void CCallsign::unmarshallFromDbus(const QDBusArgument &argument) + { + argument >> this->m_callsignAsSet; + this->m_callsign = CCallsign::unifyCallsign(this->m_callsignAsSet); + } + + /* + * Unify the callsign + */ + QString CCallsign::unifyCallsign(const QString &callsign) + { + QString unified = callsign.toUpper(); + unified = unified.remove(QRegExp("[^a-zA-Z\\d\\s]")); + return unified; + } + + /* + * Equals callsign? + */ + bool CCallsign::equalsString(const QString &callsignString) const + { + if (callsignString.isEmpty()) return false; + if (this->isEmpty()) return false; + if (callsignString == this->m_callsign || callsignString == this->m_callsignAsSet) return true; + return false; + } + + /* + * Equal? + */ + bool CCallsign::operator ==(const CCallsign &other) const + { + if (this == &other) return true; + return other.asString() == this->asString(); + } + + /* + * Unequal? + */ + bool CCallsign::operator !=(const CCallsign &other) const + { + return !((*this) == other); + } + + /* + * Less than? + */ + bool CCallsign::operator <(const CCallsign &other) const + { + return this->m_callsign < other.m_callsign; + } + + /* + * Hash + */ + uint CCallsign::getValueHash() const + { + return qHash(this->m_callsign); + } + + /* + * Compare + */ + int CCallsign::compare(const QVariant &qv) const + { + Q_ASSERT(qv.canConvert()); + Q_ASSERT(!qv.isNull() && qv.isValid()); + return this->compare(qv.value()); + } + + /* + * Compare + */ + int CCallsign::compare(const CCallsign &callsign) const + { + return this->m_callsign.compare(callsign.asString(), Qt::CaseInsensitive); + } + + /* + * Register metadata + */ + void CCallsign::registerMetadata() + { + qRegisterMetaType(); + qDBusRegisterMetaType(); + } + + } // namespace +} // namespace diff --git a/src/blackmisc/avcallsign.h b/src/blackmisc/avcallsign.h new file mode 100644 index 000000000..2639e7f44 --- /dev/null +++ b/src/blackmisc/avcallsign.h @@ -0,0 +1,164 @@ +/* Copyright (C) 2013 VATSIM Community / authors + * This Source Code Form is subject to the terms of the Mozilla Public + * 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 BLACKMISC_CALLSIGN_H +#define BLACKMISC_CALLSIGN_H +#include "valueobject.h" + +namespace BlackMisc +{ + namespace Aviation + { + /*! + * Value object encapsulating information of a callsign. + */ + class CCallsign : public BlackMisc::CValueObject + { + + public: + /*! + * Default constructor. + */ + CCallsign() {} + + /*! + * Constructor. + */ + CCallsign(const QString &callsign) + : m_callsignAsSet(callsign), m_callsign(CCallsign::unifyCallsign(callsign)) + {} + + /*! + * Constructor. + * Needed to disambiguate implicit conversion from string literal. + */ + CCallsign(const char *callsign) + : m_callsignAsSet(callsign), m_callsign(CCallsign::unifyCallsign(callsign)) + {} + + /*! + * \brief Virtual method to return QVariant, used with DBUS QVariant lists + * \return + */ + virtual QVariant toQVariant() const + { + return QVariant::fromValue(*this); + } + + /*! + * \brief Is empty? + * \return + */ + bool isEmpty() const { return this->m_callsignAsSet.isEmpty(); } + + /*! + * Get callsign. + * \return + */ + const QString &asString() const { return m_callsign; } + + /*! + * Get callsign. + * \return + */ + const QString &getStringAsSet() const { return m_callsignAsSet; } + + /*! + * \brief Get ICAO code, if this possible + * \return + */ + QString getIcaoCode() const { return m_callsign.left(4).toUpper(); } + + /*! + * \brief Equals callsign string? + * \param callsignString + * \return + */ + bool equalsString(const QString &callsignString) const; + + /*! + * \brief Equal operator == + * \param other + * \return + */ + bool operator ==(const CCallsign &other) const; + + /*! + * \brief Unequal operator == + * \param other + * \return + */ + bool operator !=(const CCallsign &other) const; + + /*! + * \brief Less than operator < for sorting + * \param other + * \return + */ + bool operator <(const CCallsign &other) const; + + /*! + * \brief Value hash + * \return + */ + virtual uint getValueHash() const; + + /*! + * \copydoc BlackObject::compare + */ + virtual int compare(const QVariant &qv) const; + + /*! + * Compare with other callsign + * \return + */ + virtual int compare(const CCallsign &callsign) const; + + /*! + * \brief Register metadata + */ + static void registerMetadata(); + + protected: + /*! + * \brief Rounded value as string + * \param i18n + * \return + */ + virtual QString convertToQString(bool i18n = false) const; + + /*! + * \brief Stream to DBus << + * \param argument + */ + virtual void marshallToDbus(QDBusArgument &argument) const; + + /*! + * \brief Stream from DBus >> + * \param argument + */ + virtual void unmarshallFromDbus(const QDBusArgument &argument); + + /*! + * \brief Unify the callsign + * \param callsign + * \return + */ + static QString unifyCallsign(const QString &callsign); + + private: + QString m_callsignAsSet; + QString m_callsign; + }; + } // namespace +} // namespace + +Q_DECLARE_METATYPE(BlackMisc::Aviation::CCallsign) + +#endif // guard diff --git a/src/blackmisc/avinformationmessage.cpp b/src/blackmisc/avinformationmessage.cpp new file mode 100644 index 000000000..cc9df1e80 --- /dev/null +++ b/src/blackmisc/avinformationmessage.cpp @@ -0,0 +1,141 @@ +#include "avinformationmessage.h" +#include "blackmiscfreefunctions.h" + +namespace BlackMisc +{ + namespace Aviation + { + /* + * Convert to string + */ + QString CInformationMessage::convertToQString(bool /** i18n **/) const + { + return this->m_message; + } + + /* + * Marshall to DBus + */ + void CInformationMessage::marshallToDbus(QDBusArgument &argument) const + { + argument << this->m_message; + argument << static_cast(this->m_type); + argument << this->m_receivedTimestamp; + } + + /* + * Unmarshall from DBus + */ + void CInformationMessage::unmarshallFromDbus(const QDBusArgument &argument) + { + uint type; + argument >> this->m_message; + argument >> type; + argument >> this->m_receivedTimestamp; + this->m_type = static_cast(type); + } + + /* + * Equal? + */ + bool CInformationMessage::operator ==(const CInformationMessage &other) const + { + if (this == &other) return true; + return this->m_message == other.m_message && + this->m_receivedTimestamp == other.m_receivedTimestamp && + this->m_type == other.m_type; + } + + /* + * Unequal? + */ + bool CInformationMessage::operator !=(const CInformationMessage &other) const + { + return !((*this) == other); + } + + /* + * Set / append ATIS message + */ + void CInformationMessage::addMessage(const QString &message) + { + const QString np = message.trimmed(); + if (np.isEmpty()) return; + + // detect the stupid z1, z2, z3 placeholders + // TODO: Anything better as this stupid code here? + const QString test = np.toLower().remove(QRegExp("[\\n\\t\\r]")); + if (test == "z") return; + if (test.startsWith("z") && test.length() == 2) return; + if (test.length() == 1) return; + + // set message + bool outdated = this->isOutdated(); + if (outdated) this->m_message.clear(); + if (!this->m_message.isEmpty()) this->m_message.append("\n"); + this->m_message.append(np); + this->m_receivedTimestamp = QDateTime::currentDateTimeUtc(); + } + + /* + * Outdated? New ATIS, or just a part + */ + bool CInformationMessage::isOutdated() const + { + // everything received within this timespan is considered to be the + // same ATIS values + // FSD sends messages as parts + qint64 diff = this->m_receivedTimestamp.msecsTo(QDateTime::currentDateTimeUtc()); + return (diff > 1000 * 10); // n seconds + } + + /* + * Register metadata + */ + void CInformationMessage::registerMetadata() + { + qRegisterMetaType(); + qDBusRegisterMetaType(); + } + + /* + * Hash + */ + uint CInformationMessage::getValueHash() const + { + QList hashs; + hashs << qHash(this->m_message); + return BlackMisc::calculateHash(hashs, "CAtis"); + } + + /* + * Type as string + */ + const QString &CInformationMessage::getTypeAsString() const + { + switch (this->m_type) + { + case ATIS: + { + static const QString atis("ATIS"); + return atis; + } + case METAR: + { + static const QString metar("METAR"); + return metar; + } + case TAF: + { + static const QString taf("TAF"); + return taf; + } + default: + { + static const QString ds("unknown"); + return ds; + } + } + } + } // namespace +} // namespace diff --git a/src/blackmisc/avinformationmessage.h b/src/blackmisc/avinformationmessage.h new file mode 100644 index 000000000..0105eb034 --- /dev/null +++ b/src/blackmisc/avinformationmessage.h @@ -0,0 +1,182 @@ +/* Copyright (C) 2013 VATSIM Community / authors + * This Source Code Form is subject to the terms of the Mozilla Public + * 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 BLACKMISC_INFORMATIONMESSAGE_H +#define BLACKMISC_INFORMATIONMESSAGE_H + +#include "valueobject.h" +#include +#include + +namespace BlackMisc +{ + namespace Aviation + { + /*! + * Value object encapsulating information message. + * ATIS, METAR, TAF + */ + class CInformationMessage : public BlackMisc::CValueObject + { + public: + /*! + * Type + */ + enum InformationType + { + Unspecified, + ATIS, + METAR, + TAF + }; + + /*! + * Default constructor. + */ + CInformationMessage(CInformationMessage::InformationType type = CInformationMessage::Unspecified) + : m_type(type), m_receivedTimestamp(QDateTime::currentDateTimeUtc()) + {} + + /*! + * \brief Information message of type + * \param type + * \param message + */ + CInformationMessage(InformationType type, const QString &message) + : m_type(type), m_message(message) + {} + + /*! + * \brief Virtual method to return QVariant, used with DBUS QVariant lists + * \return + */ + virtual QVariant toQVariant() const + { + return QVariant::fromValue(*this); + } + + /*! + * \brief Equal operator == + * \param other + * @return + */ + bool operator ==(const CInformationMessage &other) const; + + /*! + * \brief operator != + * \param other + * \return + */ + bool operator !=(const CInformationMessage &other) const; + + /*! + * Get message. + * \return + */ + const QString &getMessage() const { return m_message; } + + /*! + * \brief Is a message available + * \return + */ + bool hasMessage() const { return !m_message.isEmpty(); } + + /*! + * \brief Add message + * \remarks ATIS message come in as parts, this here features some logic, to either append or reset the message + * \param message + */ + void addMessage(const QString &message); + + /*! + * \brief Set message + * \param message + */ + void setMessage(const QString &message) { m_message = message; } + + /*! + * \brief Type as string + * \return + */ + const QString &getTypeAsString() const; + + /*! + * \brief Type + * \return + */ + InformationType getType() const { return this->m_type; } + + /*! + * \brief Timestamp + * \return + */ + const QDateTime &getReceivedTimestamp() const { return this->m_receivedTimestamp; } + + /*! + * \brief Received before n ms + * \return + */ + qint64 timeDiffReceivedMs() const + { + return this->m_receivedTimestamp.msecsTo(QDateTime::currentDateTimeUtc()); + } + + /*! + * \brief Is empty + * \return + */ + bool isEmpty() const { return this->m_message.isEmpty(); } + + /*! + * \brief Value hash + */ + virtual uint getValueHash() const; + + /*! + * \brief Register metadata + */ + static void registerMetadata(); + + protected: + /*! + * \brief Rounded value as string + * \param i18n + * \return + */ + virtual QString convertToQString(bool i18n = false) const; + + /*! + * \brief Stream to DBus << + * \param argument + */ + virtual void marshallToDbus(QDBusArgument &argument) const; + + /*! + * \brief Stream from DBus >> + * \param argument + */ + virtual void unmarshallFromDbus(const QDBusArgument &argument); + + private: + InformationType m_type; + QString m_message; + QDateTime m_receivedTimestamp; + + /*! + * \brief Outdated timestamp? + * \return + */ + bool isOutdated() const; + }; + } // namespace +} // namespace + +Q_DECLARE_METATYPE(BlackMisc::Aviation::CInformationMessage) + +#endif // guard diff --git a/src/blackmisc/blackmisc.h b/src/blackmisc/blackmisc.h index 58a32cab4..bb96e9cf4 100644 --- a/src/blackmisc/blackmisc.h +++ b/src/blackmisc/blackmisc.h @@ -34,6 +34,16 @@ * \brief Classes for physical quantities and units such as length, mass, speed. */ +/*! + * \namespace BlackMisc::Network + * \brief Classes related to the traffic network such as VATSIM user etc. + */ + +/*! + * \namespace BlackMisc::Settings + * \brief Classes related to configuration settings. + */ + /*! * \namespace BlackMisc::Predicates * \brief Functor classes for evaluating predicate calculus expressions. diff --git a/src/blackmisc/blackmiscallvalueclasses.h b/src/blackmisc/blackmiscallvalueclasses.h new file mode 100644 index 000000000..7a9198b28 --- /dev/null +++ b/src/blackmisc/blackmiscallvalueclasses.h @@ -0,0 +1,18 @@ +/* Copyright (C) 2013 VATSIM Community / contributors + * This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +#ifndef BLACKMISC_ALLVALUECLASSES_H +#define BLACKMISC_ALLVALUECLASSES_H + +#include "blackmisc/pqallquantities.h" +#include "blackmisc/avallclasses.h" +#include "blackmisc/geoallclasses.h" +#include "blackmisc/settingsallclasses.h" +#include "blackmisc/valuemap.h" +#include "blackmisc/networkallclasses.h" +#include "blackmisc/statusmessages.h" +#include "blackmisc/statusmessage.h" + +#endif // guard diff --git a/src/blackmisc/blackmiscfreefunctions.cpp b/src/blackmisc/blackmiscfreefunctions.cpp index b04b1a52f..74c211315 100644 --- a/src/blackmisc/blackmiscfreefunctions.cpp +++ b/src/blackmisc/blackmiscfreefunctions.cpp @@ -8,6 +8,8 @@ #include "pqallquantities.h" #include "mathallclasses.h" #include "geoallclasses.h" +#include "networkallclasses.h" +#include "settingsallclasses.h" #include "valuemap.h" /* @@ -39,6 +41,14 @@ void BlackMisc::Aviation::registerMetadata() CTransponder::registerMetadata(); CHeading::registerMetadata(); CTrack::registerMetadata(); + CCallsign::registerMetadata(); + CAtcStation::registerMetadata(); + CInformationMessage::registerMetadata(); + CAtcStationList::registerMetadata(); + CAircraft::registerMetadata(); + CAircraftList::registerMetadata(); + CAircraftSituation::registerMetadata(); + CAircraftIcao::registerMetadata(); } /* @@ -65,6 +75,26 @@ void BlackMisc::Geo::registerMetadata() CLongitude::registerMetadata(); } +/* + * Metadata for Network + */ +void BlackMisc::Network::registerMetadata() +{ + CUser::registerMetadata(); + CServer::registerMetadata(); + CServerList::registerMetadata(); + CTextMessage::registerMetadata(); + CTextMessageList::registerMetadata(); +} + +/* + * Metadata for Settings + */ +void BlackMisc::Settings::registerMetadata() +{ + CSettingsNetwork::registerMetadata(); +} + /* * Metadata for Blackmisc */ @@ -73,10 +103,14 @@ void BlackMisc::registerMetadata() // !! make sure the first id is correctly returned by // !! firstBlackMetaType CValueMap::registerMetadata(); + + // sub namespaces PhysicalQuantities::registerMetadata(); Aviation::registerMetadata(); Math::registerMetadata(); Geo::registerMetadata(); + Network::registerMetadata(); + Settings::registerMetadata(); } /* diff --git a/src/blackmisc/blackmiscfreefunctions.h b/src/blackmisc/blackmiscfreefunctions.h index 0f36b589a..f1b2d87f8 100644 --- a/src/blackmisc/blackmiscfreefunctions.h +++ b/src/blackmisc/blackmiscfreefunctions.h @@ -73,6 +73,22 @@ namespace BlackMisc } // Geo + namespace Network + { + /*! + * \brief Register metadata for network (server, user) + */ + void registerMetadata(); + } + + namespace Settings + { + /*! + * \brief Register metadata for settings + */ + void registerMetadata(); + } + /*! * \brief Register all relevant metadata in BlackMisc */ diff --git a/src/blackmisc/networkallclasses.h b/src/blackmisc/networkallclasses.h new file mode 100644 index 000000000..6ddaf5166 --- /dev/null +++ b/src/blackmisc/networkallclasses.h @@ -0,0 +1,13 @@ +/* Copyright (C) 2013 VATSIM Community / contributors + * This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +#ifndef BLACKMISC_NETWORKALLCLASSES_H +#define BLACKMISC_NETWORKALLCLASSES_H + +#include "blackmisc/nwuser.h" +#include "blackmisc/nwserverlist.h" +#include "blackmisc/nwtextmessagelist.h" + +#endif // guard diff --git a/src/blackmisc/nwserver.cpp b/src/blackmisc/nwserver.cpp new file mode 100644 index 000000000..19935e52c --- /dev/null +++ b/src/blackmisc/nwserver.cpp @@ -0,0 +1,166 @@ +#include "nwserver.h" +#include "blackmisc/blackmiscfreefunctions.h" + +namespace BlackMisc +{ + namespace Network + { + /* + * Convert to string + */ + QString CServer::convertToQString(bool i18n) const + { + QString s(this->m_name); + s.append(" ").append(this->m_description); + s.append(" ").append(this->m_address); + s.append(" ").append(QString::number(this->m_port)); + s.append(" ").append(this->m_user.toQString(i18n)); + return s; + } + + /* + * Marshall to DBus + */ + void CServer::marshallToDbus(QDBusArgument &argument) const + { + argument << this->m_name; + argument << this->m_description; + argument << this->m_address; + argument << this->m_port; + argument << this->m_user; + } + + /* + * Unmarshall from DBus + */ + void CServer::unmarshallFromDbus(const QDBusArgument &argument) + { + argument >> this->m_name; + argument >> this->m_description; + argument >> this->m_address; + argument >> this->m_port; + argument >> this->m_user; + } + + /* + * Valid for login + */ + bool CServer::isValidForLogin() const + { + return this->m_user.hasValidCredentials() && this->m_port > 0 && !this->m_address.isEmpty(); + } + + /* + * Equal? + */ + bool CServer::operator ==(const CServer &other) const + { + if (this == &other) return true; + return this->getValueHash() == other.getValueHash(); + } + + /* + * Unequal? + */ + bool CServer::operator !=(const CServer &other) const + { + return !((*this) == other); + } + + /* + * Hash + */ + uint CServer::getValueHash() const + { + QList hashs; + hashs << qHash(this->m_name); + hashs << qHash(this->m_address); + hashs << qHash(this->m_port); + hashs << qHash(this->m_user); + return BlackMisc::calculateHash(hashs, "CServer"); + } + + /* + * Property by index + */ + QVariant CServer::propertyByIndex(int index) const + { + switch (index) + { + case IndexAddress: + return QVariant::fromValue(this->m_address); + case IndexDescription: + return QVariant::fromValue(this->m_description); + case IndexName: + return QVariant::fromValue(this->m_name); + case IndexPort: + return QVariant::fromValue(this->m_port); + case IndexUserId: + return QVariant::fromValue(this->m_user.getId()); + case IndexUserRealname: + return QVariant::fromValue(this->m_user.getRealname()); + default: + break; + } + + Q_ASSERT_X(false, "CServer", "index unknown"); + QString m = QString("no property, index ").append(QString::number(index)); + return QVariant::fromValue(m); + } + + /* + * Property as string by index + */ + QString CServer::propertyByIndexAsString(int index, bool i18n) const + { + QVariant qv = this->propertyByIndex(index); + return BlackMisc::qVariantToString(qv, i18n); + } + + /* + * Property by index (setter) + */ + void CServer::propertyByIndex(const QVariant &variant, int index) + { + switch (index) + { + case IndexAddress: + this->setAddress(variant.value()); + break; + case IndexPort: + this->setPort(variant.value()); + break; + case IndexDescription: + this->setDescription(variant.value()); + break; + case IndexName: + this->setName(variant.value()); + break; + case IndexUserId: + this->m_user.setId(variant.value()); + break; + case IndexUserPassword: + this->m_user.setPassword(variant.value()); + break; + case IndexUserRealname: + this->m_user.setRealname(variant.value()); + break; + default: + Q_ASSERT_X(false, "CServer", "index unknown"); + break; + } + } + + + + /* + * Register metadata + */ + void CServer::registerMetadata() + { + qRegisterMetaType(); + qDBusRegisterMetaType(); + } + + } // namespace +} // namespace diff --git a/src/blackmisc/nwserver.h b/src/blackmisc/nwserver.h new file mode 100644 index 000000000..c8abb8c13 --- /dev/null +++ b/src/blackmisc/nwserver.h @@ -0,0 +1,208 @@ +/* Copyright (C) 2013 VATSIM Community / authors + * This Source Code Form is subject to the terms of the Mozilla Public + * 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 BLACKMISC_SERVER_H +#define BLACKMISC_SERVER_H +#include "nwuser.h" +#include "valueobject.h" + +namespace BlackMisc +{ + namespace Network + { + /*! + * Value object encapsulating information of a server + */ + class CServer : public BlackMisc::CValueObject + { + public: + /*! + * Default constructor. + */ + CServer() : m_port(-1) {} + + /*! + * Constructor. + * \param name + * \param description + * \param address + * \param port + * \param user + */ + CServer(const QString &name, const QString &description, const QString &address, qint32 port, const CUser &user) + : m_name(name), m_description(description), m_address(address), m_port(port), m_user(user) {} + + /*! + * \brief QVariant, required for DBus QVariant lists + * \return + */ + virtual QVariant toQVariant() const + { + return QVariant::fromValue(*this); + } + + /*! + * Get address. + * \return + */ + const QString &getAddress() const { return m_address; } + + /*! + * \brief Set address + * \param realname + */ + void setAddress(const QString &address) { m_address = address; } + + /*! + * Get user + * \return + */ + const CUser &getUser() const { return m_user; } + + /*! + * \brief Set user + * \param password + */ + void setUser(const CUser &user) { m_user = user; } + + /*! + * Get name + * \return + */ + const QString &getName() const { return m_name; } + + /*! + * \brief Set name + * \param name + */ + void setName(const QString &name) { m_name = name; } + + /*! + * Get description + * \return + */ + const QString &getDescription() const { return m_description; } + + /*! + * \brief Set description + * \param description + */ + void setDescription(const QString &description) { m_description = description; } + + /*! + * Get port + * \return + */ + qint32 getPort() const { return m_port; } + + /*! + * \brief Set port + * \param port + */ + void setPort(qint32 port) { m_port = port; } + + /*! + * \brief Is valid for login + * \return + */ + bool isValidForLogin() const; + + /*! + * \brief Equal operator == + * \param other + * \return + */ + bool operator ==(const CServer &other) const; + + /*! + * \brief Unequal operator == + * \param other + * \return + */ + bool operator !=(const CServer &other) const; + + /*! + * \brief Value hash + */ + virtual uint getValueHash() const; + + /*! + * \brief Register metadata + */ + static void registerMetadata(); + + /*! + * \brief Properties by index + */ + enum ColumnIndex + { + IndexName = 0, + IndexDescription, + IndexAddress, + IndexPort, + IndexUserId, + IndexUserRealname, + IndexUserPassword + }; + + /*! + * \brief Property by index + * \param index + * \return + */ + QVariant propertyByIndex(int index) const; + + /*! + * \brief Property by index as string + * \param index + * \param i18n + * \return + */ + QString propertyByIndexAsString(int index, bool i18n) const; + + /*! + * \brief Property by index (setter) + * \param variant + * \param index + */ + void propertyByIndex(const QVariant &variant, int index); + + protected: + /*! + * \brief Rounded value as string + * \param i18n + * \return + */ + virtual QString convertToQString(bool i18n = false) const; + + /*! + * \brief Stream to DBus << + * \param argument + */ + virtual void marshallToDbus(QDBusArgument &argument) const; + + /*! + * \brief Stream from DBus >> + * \param argument + */ + virtual void unmarshallFromDbus(const QDBusArgument &argument); + + private: + QString m_name; + QString m_description; + QString m_address; + qint32 m_port; + CUser m_user; + }; + } // namespace +} // namespace + +Q_DECLARE_METATYPE(BlackMisc::Network::CServer) + +#endif // guard diff --git a/src/blackmisc/nwserverlist.cpp b/src/blackmisc/nwserverlist.cpp new file mode 100644 index 000000000..a47d77c58 --- /dev/null +++ b/src/blackmisc/nwserverlist.cpp @@ -0,0 +1,38 @@ +/* Copyright (C) 2013 VATSIM Community / authors + * This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +#include "nwserverlist.h" + +namespace BlackMisc +{ + namespace Network + { + /* + * Empty constructor + */ + CServerList::CServerList() { } + + /* + * Construct from base class object + */ + CServerList::CServerList(const CSequence &other) : + CSequence(other) + { } + + /* + * Register metadata + */ + void CServerList::registerMetadata() + { + qRegisterMetaType>(); + qDBusRegisterMetaType>(); + qRegisterMetaType>(); + qDBusRegisterMetaType>(); + qRegisterMetaType(); + qDBusRegisterMetaType(); + } + + } // namespace +} // namespace diff --git a/src/blackmisc/nwserverlist.h b/src/blackmisc/nwserverlist.h new file mode 100644 index 000000000..7666bb73e --- /dev/null +++ b/src/blackmisc/nwserverlist.h @@ -0,0 +1,64 @@ +/* Copyright (C) 2013 VATSIM Community / authors + * This Source Code Form is subject to the terms of the Mozilla Public + * 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 BLACKMISC_SERVERLIST_H +#define BLACKMISC_SERVERLIST_H + +#include "nwserver.h" +#include "collection.h" +#include "sequence.h" +#include +#include +#include + +namespace BlackMisc +{ + namespace Network + { + /*! + * Value object encapsulating a list of servers. + */ + class CServerList : public CSequence + { + public: + /*! + * \brief Empty constructor. + */ + CServerList(); + + /*! + * \brief Construct from a base class object. + * \param other + */ + CServerList(const CSequence &other); + + /*! + * \brief QVariant, required for DBus QVariant lists + * \return + */ + virtual QVariant toQVariant() const + { + return QVariant::fromValue(*this); + } + + /*! + * \brief Register metadata + */ + static void registerMetadata(); + + }; + + } //namespace +} // namespace + +Q_DECLARE_METATYPE(BlackMisc::Network::CServerList) +Q_DECLARE_METATYPE(BlackMisc::CCollection) +Q_DECLARE_METATYPE(BlackMisc::CSequence) + +#endif //guard diff --git a/src/blackmisc/nwtextmessage.cpp b/src/blackmisc/nwtextmessage.cpp new file mode 100644 index 000000000..c1624b14b --- /dev/null +++ b/src/blackmisc/nwtextmessage.cpp @@ -0,0 +1,178 @@ +#include "nwtextmessage.h" +#include "blackmisc/blackmiscfreefunctions.h" +#include "blackmisc/pqconstants.h" +#include "blackmisc/aviocomsystem.h" + +namespace BlackMisc +{ + namespace Network + { + /* + * Convert to string + */ + QString CTextMessage::convertToQString(bool i18n) const + { + QString s(this->m_message); + if (this->isPrivateMessage()) + { + s.append(" ").append(this->m_fromCallsign.toQString(i18n)); + s.append(" ").append(this->m_toCallsign.toQString(i18n)); + } + else + { + s.append(" ").append(this->m_frequency.toQString(i18n)); + } + return s; + } + + /* + * Marshall to DBus + */ + void CTextMessage::marshallToDbus(QDBusArgument &argument) const + { + argument << this->m_fromCallsign; + argument << this->m_toCallsign; + argument << this->m_message; + argument << this->m_frequency; + } + + /* + * Unmarshall from DBus + */ + void CTextMessage::unmarshallFromDbus(const QDBusArgument &argument) + { + argument >> this->m_fromCallsign; + argument >> this->m_toCallsign; + argument >> this->m_message; + argument >> this->m_frequency; + } + + /* + * Private message? + */ + bool CTextMessage::isPrivateMessage() const + { + return !this->m_fromCallsign.isEmpty() && !this->m_toCallsign.isEmpty(); + } + + /* + * Sent to frequency? + */ + bool CTextMessage::isSendToFrequency(const PhysicalQuantities::CFrequency &frequency) const + { + if (!this->isRadioMessage()) return false; + return this->m_frequency == frequency; + } + + /* + * Sent to UNICOM? + */ + bool CTextMessage::isSendToUnicom() const + { + return this->isSendToFrequency(BlackMisc::PhysicalQuantities::CPhysicalQuantitiesConstants::FrequencyUnicom()); + } + + /* + * Valid receiver? + */ + bool CTextMessage::hasValidReceiver() const + { + if (!this->m_toCallsign.isEmpty()) return true; + return BlackMisc::Aviation::CComSystem::isValidCivilAviationFrequency(this->m_frequency); + } + + /* + * Radio message? + */ + bool CTextMessage::isRadioMessage() const + { + return (BlackMisc::Aviation::CComSystem::isValidCivilAviationFrequency(this->m_frequency)); + } + + /* + * Formatted string + */ + QString CTextMessage::asString(bool withFrom, bool withTo, const QString separator) const + { + QString s; + if (withFrom) + { + if (!this->m_fromCallsign.isEmpty()) + s.append(this->m_fromCallsign.getStringAsSet()); + } + + if (withTo) + { + if (!this->m_toCallsign.isEmpty()) + { + if (!s.isEmpty()) s.append(separator); + s.append(this->m_toCallsign.getStringAsSet()); + } + else + { + if (BlackMisc::Aviation::CComSystem::isValidCivilAviationFrequency(this->m_frequency)) + { + if (!s.isEmpty()) s.append(separator); + s.append(this->m_frequency.valueRoundedWithUnit(3, true)); + } + + } + } // to + + if (this->m_message.isEmpty()) return s; + if (!s.isEmpty()) s.append(separator); + s.append(this->m_message); + return s; + } + + /* + * Toggle sender / receiver + */ + void CTextMessage::toggleSenderReceiver() + { + BlackMisc::Aviation::CCallsign csOldFrom(this->getFromCallsign()); + this->setFromCallsign(this->getToCallsign()); + this->setToCallsign(csOldFrom); + } + + /* + * Equal? + */ + bool CTextMessage::operator ==(const CTextMessage &other) const + { + if (this == &other) return true; + return this->getValueHash() == other.getValueHash(); + } + + /* + * Unequal? + */ + bool CTextMessage::operator !=(const CTextMessage &other) const + { + return !((*this) == other); + } + + /* + * Hash + */ + uint CTextMessage::getValueHash() const + { + QList hashs; + hashs << qHash(this->m_fromCallsign); + hashs << qHash(this->m_toCallsign); + hashs << qHash(this->m_frequency); + hashs << qHash(this->m_message); + return BlackMisc::calculateHash(hashs, "CTextMessage"); + } + + /* + * Register metadata + */ + void CTextMessage::registerMetadata() + { + qRegisterMetaType(); + qDBusRegisterMetaType(); + } + + } // namespace +} // namespace diff --git a/src/blackmisc/nwtextmessage.h b/src/blackmisc/nwtextmessage.h new file mode 100644 index 000000000..c07a20aee --- /dev/null +++ b/src/blackmisc/nwtextmessage.h @@ -0,0 +1,217 @@ +/* Copyright (C) 2013 VATSIM Community / authors + * This Source Code Form is subject to the terms of the Mozilla Public + * 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 BLACKMISC_TEXTMESSAGE_H +#define BLACKMISC_TEXTMESSAGE_H + +#include "pqfrequency.h" +#include "avcallsign.h" +#include "valueobject.h" + +namespace BlackMisc +{ + namespace Network + { + /*! + * Value object encapsulating information of a textserver + */ + class CTextMessage : public BlackMisc::CValueObject + { + public: + /*! + * Default constructor. + */ + CTextMessage() : m_frequency(-1.0, BlackMisc::PhysicalQuantities::CFrequencyUnit::MHz()) {} + + /*! + * Constructor, radio message + * \param message + * \param frequency + * \param fromCallsign + */ + CTextMessage(const QString &message, const BlackMisc::PhysicalQuantities::CFrequency &frequency, const BlackMisc::Aviation::CCallsign &fromCallsign = BlackMisc::Aviation::CCallsign()) + : m_message(message), m_fromCallsign(fromCallsign), m_frequency(frequency) + { + this->m_frequency.switchUnit(BlackMisc::PhysicalQuantities::CFrequencyUnit::MHz()); + } + + /*! + * Constructor, private message + * \param message + * \param fromCallsign + * \param toCallsign + */ + CTextMessage(const QString &message, const BlackMisc::Aviation::CCallsign &fromCallsign, const BlackMisc::Aviation::CCallsign &toCallsign = BlackMisc::Aviation::CCallsign()) + : m_message(message), m_fromCallsign(fromCallsign), m_toCallsign(toCallsign), m_frequency(-1.0, BlackMisc::PhysicalQuantities::CFrequencyUnit::MHz()) {} + + /*! + * \brief QVariant, required for DBus QVariant lists + * \return + */ + virtual QVariant toQVariant() const + { + return QVariant::fromValue(*this); + } + + /*! + * Get callsign (from) + * \return + */ + const BlackMisc::Aviation::CCallsign &getFromCallsign() const { return m_fromCallsign; } + + /*! + * Set callsign (from) + * \param + */ + void setFromCallsign(const BlackMisc::Aviation::CCallsign &callsign) { m_fromCallsign = callsign; } + + /*! + * Get callsign (to) + * \return + */ + const BlackMisc::Aviation::CCallsign &getToCallsign() const { return m_toCallsign; } + + /*! + * Set callsign (to) + * \param + */ + void setToCallsign(const BlackMisc::Aviation::CCallsign &callsign) { m_toCallsign = callsign; } + + /* + * Send to frequency? + * \param frequency + * \return + */ + bool isSendToFrequency(const BlackMisc::PhysicalQuantities::CFrequency &frequency) const; + + /*! + * Send to UNICOM? + * \return + */ + bool isSendToUnicom() const; + + /*! + * \brief Valid receviver? + * \return + */ + bool hasValidReceiver() const; + + /*! + * Get message + * \return + */ + const QString &getMessage() const { return m_message; } + + /*! + * Empty message + * \return + */ + bool isEmpty() const { return m_message.isEmpty(); } + + /*! + * Set message + * \param + */ + void setMessage(const QString &message) { m_message = message.trimmed(); } + + /*! + * Get frequency + * \return + */ + const BlackMisc::PhysicalQuantities::CFrequency &getFrequency() const { return m_frequency; } + + /*! + * Set frequency + * \param + */ + void setFrequency(const BlackMisc::PhysicalQuantities::CFrequency &frequency) { m_frequency = frequency; } + + /*! + * \brief Is private message? + * \return + */ + bool isPrivateMessage() const; + + /*! + * \brief Is radio message? + * \return + */ + bool isRadioMessage() const; + + /*! + * Whole message as formatted string. + * Used to display message in a console window. + * \param withFrom + * \param withTo + * \param separator + * \return + */ + QString asString(bool withFrom, bool withTo, const QString separator = ", ") const; + + /*! + * Toggle sender receiver, can be used to ping my own message + */ + void toggleSenderReceiver(); + + /*! + * \brief Equal operator == + * \param other + * @return + */ + bool operator ==(const CTextMessage &other) const; + + /*! + * \brief Unequal operator == + * \param other + * @return + */ + bool operator !=(const CTextMessage &other) const; + + /*! + * \brief Value hash + */ + virtual uint getValueHash() const; + + /*! + * \brief Register metadata + */ + static void registerMetadata(); + + protected: + /*! + * \brief Rounded value as string + * \param i18n + * \return + */ + virtual QString convertToQString(bool i18n = false) const; + + /*! + * \brief Stream to DBus << + * \param argument + */ + virtual void marshallToDbus(QDBusArgument &argument) const; + + /*! + * \brief Stream from DBus >> + * \param argument + */ + virtual void unmarshallFromDbus(const QDBusArgument &argument); + + private: + QString m_message; + BlackMisc::Aviation::CCallsign m_fromCallsign; + BlackMisc::Aviation::CCallsign m_toCallsign; + BlackMisc::PhysicalQuantities::CFrequency m_frequency; + }; + } // namespace +} // namespace + +Q_DECLARE_METATYPE(BlackMisc::Network::CTextMessage) + +#endif // guard diff --git a/src/blackmisc/nwtextmessagelist.cpp b/src/blackmisc/nwtextmessagelist.cpp new file mode 100644 index 000000000..480d04e87 --- /dev/null +++ b/src/blackmisc/nwtextmessagelist.cpp @@ -0,0 +1,152 @@ +/* Copyright (C) 2013 VATSIM Community / authors + * This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +#include "nwtextmessagelist.h" +#include "predicates.h" + +using namespace BlackMisc::PhysicalQuantities; +using namespace BlackMisc::Aviation; + +namespace BlackMisc +{ + namespace Network + { + /* + * Empty constructor + */ + CTextMessageList::CTextMessageList() { } + + /* + * Single private message constructor + */ + CTextMessageList::CTextMessageList(const QString &message, const CCallsign &toCallsign) + { + CTextMessage pm(message, toCallsign); + this->push_back(pm); + } + + /* + * Single private message + */ + CTextMessageList::CTextMessageList(const QString &message, const CCallsign &fromCallsign, const CCallsign &toCallsign) + { + CTextMessage pm(message, fromCallsign, toCallsign); + this->push_back(pm); + } + + /* + * Single radio message + */ + CTextMessageList::CTextMessageList(const QString &message, const CFrequency &frequency, const CCallsign &fromCallsign) + { + CTextMessage pm(message, frequency, fromCallsign); + this->push_back(pm); + } + + /* + * Single text message + */ + CTextMessageList::CTextMessageList(const CTextMessage &message) + { + this->push_back(message); + } + + /* + * Radio messages + */ + CTextMessageList::CTextMessageList(const QString &message, const QList &frequencies, const BlackMisc::Aviation::CCallsign &fromCallsign) + { + if (frequencies.isEmpty()) return; + foreach(CFrequency frequency, frequencies) + { + CTextMessage pm(message, frequency, fromCallsign); + this->push_back(pm); + } + } + + /* + * Construct from base class object + */ + CTextMessageList::CTextMessageList(const CSequence &other) : + CSequence(other) + { } + + /* + * Private messages + */ + CTextMessageList CTextMessageList::getPrivateMessages() const + { + return this->findBy(&CTextMessage::isPrivateMessage, true); + } + + /* + * Private messages? + */ + bool CTextMessageList::containsPrivateMessages() const + { + return this->contains(&CTextMessage::isPrivateMessage, true); + } + + /* + * Radio messages + */ + CTextMessageList CTextMessageList::getRadioMessages() const + { + return this->findBy(&CTextMessage::isRadioMessage, true); + } + + /* + * Radio messages? + */ + bool CTextMessageList::containsRadioMessages() const + { + return this->contains(&CTextMessage::isRadioMessage, true); + } + + /* + * Register metadata + */ + void CTextMessageList::registerMetadata() + { + qRegisterMetaType>(); + qDBusRegisterMetaType>(); + qRegisterMetaType>(); + qDBusRegisterMetaType>(); + qRegisterMetaType(); + qDBusRegisterMetaType(); + } + + /* + * Find by callsign + */ + CTextMessageList CTextMessageList::findByToCallsign(const CCallsign &callsign) const + { + return CTextMessageList(this->findBy(&CTextMessage::getToCallsign, callsign)); + } + + /* + * Find by frequency + */ + CTextMessageList CTextMessageList::findByFrequency(const CFrequency &frequency) const + { + return CTextMessageList(this->findBy(&CTextMessage::getFrequency, frequency)); + } + + /* + * Toggle all senders / receivers + */ + void CTextMessageList::toggleSenderReceivers() + { + if (this->isEmpty()) return; + for (int i = 0; i < this->size(); i++) + { + CTextMessage tm = (*this)[i]; + tm.toggleSenderReceiver(); + (*this)[i] = tm; + } + } + + } // namespace +} // namespace diff --git a/src/blackmisc/nwtextmessagelist.h b/src/blackmisc/nwtextmessagelist.h new file mode 100644 index 000000000..e93e74e95 --- /dev/null +++ b/src/blackmisc/nwtextmessagelist.h @@ -0,0 +1,142 @@ +/* Copyright (C) 2013 VATSIM Community / authors + * This Source Code Form is subject to the terms of the Mozilla Public + * 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 BLACKMISC_TEXTMESSAGELIST_H +#define BLACKMISC_TEXTMESSAGELIST_H + +#include "nwtextmessage.h" +#include "collection.h" +#include "sequence.h" +#include +#include +#include + +namespace BlackMisc +{ + namespace Network + { + /*! + * Value object encapsulating a list of text messages + */ + class CTextMessageList : public CSequence + { + public: + /*! + * \brief Empty constructor. + */ + CTextMessageList(); + + /*! + * \brief Constructor, single private message + * \param message + * \param frequency + */ + CTextMessageList(const QString &message, const BlackMisc::Aviation::CCallsign &toCallsign); + + /*! + * \brief Constructor, single private message + * \param message + * \param fromCallsign + * \param toCallsign + */ + CTextMessageList(const QString &message, const BlackMisc::Aviation::CCallsign &fromCallsign, const BlackMisc::Aviation::CCallsign &toCallsign); + + /*! + * \brief Constructor, single radio message + * \param message + * \param frequency + */ + CTextMessageList(const QString &message, const BlackMisc::PhysicalQuantities::CFrequency &frequency, const BlackMisc::Aviation::CCallsign &fromCallsign = BlackMisc::Aviation::CCallsign()); + + /*! + * \brief Constructor, single message + * \param message + */ + CTextMessageList(const CTextMessage &message); + + /*! + * \brief Constructor, multi-frequency radio messages + * \param message + * \param frequencies + */ + CTextMessageList(const QString &message, const QList &frequencies, const BlackMisc::Aviation::CCallsign &fromCallsign = BlackMisc::Aviation::CCallsign()); + + /*! + * \brief Construct from a base class object. + * \param other + */ + CTextMessageList(const CSequence &other); + + /*! + * \brief QVariant, required for DBus QVariant lists + * \return + */ + virtual QVariant toQVariant() const + { + return QVariant::fromValue(*this); + } + + /*! + * \brief Private messages + * \return + */ + CTextMessageList getPrivateMessages() const; + + /*! + * \brief Contains private messages? + * \return + */ + bool containsPrivateMessages() const; + + /*! + * \brief Public messages + * \return + */ + CTextMessageList getRadioMessages() const; + + /*! + * \brief Contains radio messages? + * \return + */ + bool containsRadioMessages() const; + + /*! + * \brief Find 0..n stations by callsign + * \param callsign + * \return + */ + CTextMessageList findByToCallsign(const BlackMisc::Aviation::CCallsign &callsign) const; + + /*! + * \brief Find by frequency + * \param frequency + * \return + */ + CTextMessageList findByFrequency(const BlackMisc::PhysicalQuantities::CFrequency &frequency) const; + + /*! + * \brief Toggle all sender receivers + */ + void toggleSenderReceivers(); + + /*! + * \brief Register metadata + */ + static void registerMetadata(); + + }; + + } //namespace +} // namespace + +Q_DECLARE_METATYPE(BlackMisc::Network::CTextMessageList) +Q_DECLARE_METATYPE(BlackMisc::CCollection) +Q_DECLARE_METATYPE(BlackMisc::CSequence) + +#endif //guard diff --git a/src/blackmisc/nwuser.cpp b/src/blackmisc/nwuser.cpp new file mode 100644 index 000000000..fe5eb2fae --- /dev/null +++ b/src/blackmisc/nwuser.cpp @@ -0,0 +1,108 @@ +#include "nwuser.h" +#include "blackmisc/blackmiscfreefunctions.h" + +namespace BlackMisc +{ + namespace Network + { + /* + * Convert to string + */ + QString CUser::convertToQString(bool /** i18n **/) const + { + if (this->m_realname.isEmpty()) return "Unknown??"; + QString s = this->m_realname; + if (this->m_id >= 0) + { + s = s.append(" (").append(this->m_id).append(')'); + } + return s; + } + + /* + * Marshall to DBus + */ + void CUser::marshallToDbus(QDBusArgument &argument) const + { + argument << this->m_id; + argument << this->m_realname; + argument << this->m_email; + argument << this->m_password; + } + + /* + * Unmarshall from DBus + */ + void CUser::unmarshallFromDbus(const QDBusArgument &argument) + { + argument >> this->m_id; + argument >> this->m_realname; + argument >> this->m_email; + argument >> this->m_password; + } + + /* + * Equal? + */ + bool CUser::operator ==(const CUser &other) const + { + if (this == &other) return true; + return (this->m_id == other.m_id && + this->m_realname == other.m_realname && + this->m_email == other.m_email); + } + + /* + * Exchange data + */ + void CUser::syncronizeData(CUser &otherUser) + { + if (otherUser == (*this)) return; + + if (this->hasValidRealname()) + otherUser.setRealname(this->getRealname()); + else if (otherUser.hasValidRealname()) + this->setRealname(otherUser.getRealname()); + + if (this->hasValidId()) + otherUser.setId(this->getId()); + else if (otherUser.hasValidId()) + this->setId(otherUser.getId()); + + if (this->hasValidEmail()) + otherUser.setEmail(this->getEmail()); + else if (otherUser.hasValidEmail()) + this->setEmail(otherUser.getEmail()); + } + + /* + * Unequal? + */ + bool CUser::operator !=(const CUser &other) const + { + return !((*this) == other); + } + + /* + * Hash + */ + uint CUser::getValueHash() const + { + QList hashs; + hashs << qHash(this->m_id); + hashs << qHash(this->m_realname); + hashs << qHash(this->m_email); + return BlackMisc::calculateHash(hashs, "CUser"); + } + + /* + * Register metadata + */ + void CUser::registerMetadata() + { + qRegisterMetaType(); + qDBusRegisterMetaType(); + } + + } // namespace +} // namespace diff --git a/src/blackmisc/nwuser.h b/src/blackmisc/nwuser.h new file mode 100644 index 000000000..7c6fbc625 --- /dev/null +++ b/src/blackmisc/nwuser.h @@ -0,0 +1,186 @@ +/* Copyright (C) 2013 VATSIM Community / authors + * This Source Code Form is subject to the terms of the Mozilla Public + * 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 BLACKMISC_USER_H +#define BLACKMISC_USER_H +#include "valueobject.h" + +namespace BlackMisc +{ + namespace Network + { + /*! + * Value object encapsulating information of a user. + */ + class CUser : public BlackMisc::CValueObject + { + public: + /*! + * Default constructor. + */ + CUser() {} + + /*! + * Constructor. + */ + CUser(const QString &id, const QString &realname, const QString &email = "", const QString &password = "") + : m_id(id), m_realname(realname), m_email(email), m_password(password) + {} + + /*! + * \brief QVariant, required for DBus QVariant lists + * \return + */ + virtual QVariant toQVariant() const + { + return QVariant::fromValue(*this); + } + + /*! + * Get full name. + * \return + */ + QString getRealname() const { return m_realname; } + + /*! + * \brief setRealname + * \param realname + */ + void setRealname(const QString &realname) { m_realname = realname.trimmed(); } + + /*! + * Get password + * \return + */ + QString getPassword() const { return m_password; } + + /*! + * Set password + * \param + */ + void setPassword(const QString &pw) { m_password = pw.trimmed(); } + + /*! + * \brief Valid user object? + * \return + */ + bool isValid() const { return !this->m_realname.isEmpty() && !this->m_id.isEmpty(); } + + /*! + * \brief Valid credentials? + * \return + */ + bool hasValidCredentials() const { return this->isValid() && !this->m_password.isEmpty(); } + + /*! + * \brief Valid real name? + * \return + */ + bool hasValidRealname() const { return !this->m_realname.isEmpty(); } + + /*! + * \brief Valid id? + * \return + */ + bool hasValidId() const { return !this->m_id.isEmpty(); } + + /*! + * Get email. + * \return + */ + QString getEmail() const { return m_email; } + + /*! + * Set email. + * \param + */ + void setEmail(const QString &email) { m_email = email.trimmed(); } + + /*! + * Get id. + * \return + */ + QString getId() const { return m_id; } + + /*! + * \brief Valid email? + * \return + */ + bool hasValidEmail() const { return !this->m_email.isEmpty(); } + + /*! + * \brief Set id + * \param realname + */ + void setId(const QString &id) { m_id = id.trimmed(); } + + /*! + * \brief Equal operator == + * \param other + * @return + */ + bool operator ==(const CUser &other) const; + + /*! + * \brief Unequal operator == + * \param other + * @return + */ + bool operator !=(const CUser &other) const; + + /*! + * \brief Value hash + */ + virtual uint getValueHash() const; + + /*! + * \brief Register metadata + */ + static void registerMetadata(); + + /*! + * This another user exchange missing data + * This user has priority and overrides first + * \param otherUser + */ + void syncronizeData(CUser &otherUser); + + protected: + /*! + * \brief Rounded value as string + * \param i18n + * \return + */ + virtual QString convertToQString(bool i18n = false) const; + + /*! + * \brief Stream to DBus << + * \param argument + */ + virtual void marshallToDbus(QDBusArgument &argument) const; + + /*! + * \brief Stream from DBus >> + * \param argument + */ + virtual void unmarshallFromDbus(const QDBusArgument &argument); + + private: + QString m_id; + QString m_realname; + QString m_email; + QString m_password; + }; + } // namespace +} // namespace + +Q_DECLARE_METATYPE(BlackMisc::Network::CUser) + + +#endif // guard diff --git a/src/blackmisc/setnetwork.cpp b/src/blackmisc/setnetwork.cpp new file mode 100644 index 000000000..8e9df6f1a --- /dev/null +++ b/src/blackmisc/setnetwork.cpp @@ -0,0 +1,128 @@ +#include "setnetwork.h" +#include "blackmisc/blackmiscfreefunctions.h" +#include "blackmisc/statusmessages.h" +#include "blackmisc/settingutilities.h" + +using namespace BlackMisc::Network; + +namespace BlackMisc +{ + namespace Settings + { + /* + * Constructor + */ + CSettingsNetwork::CSettingsNetwork() + { + // settings + } + + bool CSettingsNetwork::setCurrentNetworkServer(const CServer ¤tServer) + { + if (this->m_trafficNetworkServerCurrent == currentServer) return false; + m_trafficNetworkServerCurrent = currentServer; + return true; + } + + /* + * Convert to string + */ + QString CSettingsNetwork::convertToQString(bool i18n) const + { + QString s("Traffic servers:"); + s.append(" ").append(this->m_trafficNetworkServers.toQString(i18n)); + return s; + } + + /* + * Marshall to DBus + */ + void CSettingsNetwork::marshallToDbus(QDBusArgument &argument) const + { + argument << this->m_trafficNetworkServerCurrent; + argument << this->m_trafficNetworkServers; + } + + /* + * Unmarshall from DBus + */ + void CSettingsNetwork::unmarshallFromDbus(const QDBusArgument &argument) + { + argument >> this->m_trafficNetworkServerCurrent; + argument >> this->m_trafficNetworkServers; + } + + /* + * Equal? + */ + bool CSettingsNetwork::operator ==(const CSettingsNetwork &other) const + { + if (this == &other) return true; + return this->getValueHash() == other.getValueHash(); + } + + /* + * Unequal? + */ + bool CSettingsNetwork::operator !=(const CSettingsNetwork &other) const + { + return !((*this) == other); + } + + /* + * Hash + */ + uint CSettingsNetwork::getValueHash() const + { + QList hashs; + hashs << qHash(this->m_trafficNetworkServers); + return BlackMisc::calculateHash(hashs, "CSettingsNetwork"); + } + + /* + * Register metadata + */ + void CSettingsNetwork::registerMetadata() + { + qRegisterMetaType(); + qDBusRegisterMetaType(); + } + + /* + * Value + */ + BlackMisc::CStatusMessages CSettingsNetwork::value(const QString &path, const QString &command, const QVariant &value, bool &changedFlag) + { + // TODO: This needs to be refactored to a smarter way to delegate commands + changedFlag = false; + CStatusMessages msgs; + if (path == CSettingsNetwork::PathTrafficServer()) + { + const CServer server = value.value(); + if (command == CSettingsNetwork::CmdSetCurrentServer()) + { + changedFlag = this->setCurrentNetworkServer(server); + if (changedFlag) + { + // make sure the server is correct int the list too + this->m_trafficNetworkServers.replaceOrAdd(&CServer::getName, server.getName(), server); + } + } + else if (command == CSettingUtilities::CmdUpdate()) + { + this->m_trafficNetworkServers.replaceOrAdd(&CServer::getName, server.getName(), server); + changedFlag = true; + } + else if (command == CSettingUtilities::CmdRemove()) + { + changedFlag = this->m_trafficNetworkServers.contains(&CServer::getName, server.getName()); + this->m_trafficNetworkServers.removeIf(&CServer::getName, server.getName()); + } + msgs.append(CStatusMessage::getInfoMessage("set current server")); + return msgs; + } + return CSettingUtilities::wrongPathMessages(path); + } + + } // namespace +} // namespace diff --git a/src/blackmisc/setnetwork.h b/src/blackmisc/setnetwork.h new file mode 100644 index 000000000..1bd0bc4a2 --- /dev/null +++ b/src/blackmisc/setnetwork.h @@ -0,0 +1,157 @@ +/* Copyright (C) 2013 VATSIM Community / authors + * This Source Code Form is subject to the terms of the Mozilla Public + * 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 BLACKMISC_SETTINGS_SERVER_H +#define BLACKMISC_SETTINGS_SERVER_H + +#include "nwserverlist.h" +#include "valueobject.h" +#include "statusmessages.h" +#include "settingutilities.h" + + +namespace BlackMisc +{ + namespace Settings + { + /*! + * Value object encapsulating information of a server + */ + class CSettingsNetwork : public BlackMisc::CValueObject + { + public: + /*! + * Default constructor. + */ + CSettingsNetwork(); + + /*! + * Destructor. + */ + virtual ~CSettingsNetwork() {} + + /*! + * \brief Update + * \return + */ + static const QString &CmdSetCurrentServer() + { + static const QString cmd("currenttrafficserver"); + return cmd; + } + + /*! + * \brief Path + * \return + */ + static const QString &PathTrafficServer() + { + static const QString cmd("trafficserver"); + return cmd; + } + + /*! + * \brief QVariant, required for DBus QVariant lists + * \return + */ + virtual QVariant toQVariant() const + { + return QVariant::fromValue(*this); + } + + /*! + * Traffic network server objects + * \return + */ + BlackMisc::Network::CServerList getTrafficNetworkServers() const { return m_trafficNetworkServers; } + + /*! + * Selected traffic network server + * \return + */ + BlackMisc::Network::CServer getCurrentNetworkServer() const { return m_trafficNetworkServerCurrent; } + + /*! + * Selected traffic network server + * \param currentServer + * \return + */ + bool setCurrentNetworkServer(const BlackMisc::Network::CServer ¤tServer); + + /*! + * Traffic network server objects + * \return + */ + void addTrafficNetworkServer(const BlackMisc::Network::CServer &server) { m_trafficNetworkServers.push_back(server); } + + /*! + * \brief Equal operator == + * \param other + * @return + */ + bool operator ==(const CSettingsNetwork &other) const; + + /*! + * \brief Unequal operator == + * \param other + * @return + */ + bool operator !=(const CSettingsNetwork &other) const; + + /*! + * \brief Value + * \param path + * \param command + * \param value + * \param changedFlag + * \return + */ + virtual BlackMisc::CStatusMessages value(const QString &path, const QString &command, const QVariant &value, bool &changedFlag); + + /*! + * \brief Value hash + */ + virtual uint getValueHash() const; + + /*! + * \brief Register metadata + */ + static void registerMetadata(); + + protected: + /*! + * \brief Rounded value as string + * \param i18n + * \return + */ + virtual QString convertToQString(bool i18n = false) const; + + /*! + * \brief Stream to DBus << + * \param argument + */ + virtual void marshallToDbus(QDBusArgument &argument) const; + + /*! + * \brief Stream from DBus >> + * \param argument + */ + virtual void unmarshallFromDbus(const QDBusArgument &argument); + + private: + BlackMisc::Network::CServerList m_trafficNetworkServers; + BlackMisc::Network::CServer m_trafficNetworkServerCurrent; + }; + + } // namespace +} // namespace + +Q_DECLARE_METATYPE(BlackMisc::Settings::CSettingsNetwork) + +#endif // guard diff --git a/src/blackmisc/settingsallclasses.h b/src/blackmisc/settingsallclasses.h new file mode 100644 index 000000000..629f14e66 --- /dev/null +++ b/src/blackmisc/settingsallclasses.h @@ -0,0 +1,11 @@ +/* Copyright (C) 2013 VATSIM Community / contributors + * This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +#ifndef BLACKMISC_SETTINGSALLCLASSES_H +#define BLACKMISC_SETTINGSALLCLASSES_H + +#include "blackmisc/setnetwork.h" + +#endif // guard diff --git a/src/blackmisc/settingutilities.cpp b/src/blackmisc/settingutilities.cpp new file mode 100644 index 000000000..79d850ff2 --- /dev/null +++ b/src/blackmisc/settingutilities.cpp @@ -0,0 +1,60 @@ +#include "settingutilities.h" + +namespace BlackMisc +{ + namespace Settings + { + /* + * Wrong path name message + */ + BlackMisc::CStatusMessage CSettingUtilities::wrongPathMessage(const QString &path) + { + QString msg = "wrong path"; + if (!path.isEmpty()) + { + msg.append(": ").append(path); + } + BlackMisc::CStatusMessage rp(BlackMisc::CStatusMessage::TypeValidation, + BlackMisc::CStatusMessage::SeverityError, msg); + return rp; + } + + /* + * Wrong path name messages + */ + CStatusMessages CSettingUtilities::wrongPathMessages(const QString &path) + { + BlackMisc::CStatusMessages rps; + rps.append(CSettingUtilities::wrongPathMessage(path)); + return rps; + } + + /* + * leading path + */ + QString CSettingUtilities::removeLeadingPath(const QString &path) + { + int sl = path.indexOf('/'); + Q_ASSERT(sl >= 0); + Q_ASSERT(path.length() > sl + 2); + return path.mid(sl + 1); + } + + /*! + * \brief Append paths + * \param part1 + * \param part2 + * \param part3 + * \return + */ + QString CSettingUtilities::appendPaths(const QString &part1, const QString &part2, const QString &part3) + { + QString p(part1); + if (part2.isEmpty()) return p; + p.append('/').append(part2); + if (part3.isEmpty()) return p; + p.append('/').append(part3); + return p; + } + } +} diff --git a/src/blackmisc/settingutilities.h b/src/blackmisc/settingutilities.h new file mode 100644 index 000000000..791e382e5 --- /dev/null +++ b/src/blackmisc/settingutilities.h @@ -0,0 +1,90 @@ +#ifndef BLACKMISC_SETTINGUTILITIES_H +#define BLACKMISC_SETTINGUTILITIES_H + +#include "blackmisc/statusmessages.h" + +namespace BlackMisc +{ + namespace Settings + { + class CSettingUtilities + { + private: + CSettingUtilities() {} + + public: + + /*! + * \brief Validate + * \return + */ + static const QString &CmdValidate() + { + static const QString cmd("validate"); + return cmd; + } + + /*! + * \brief Update + * \return + */ + static const QString &CmdUpdate() + { + static const QString cmd("update"); + return cmd; + } + + /*! + * \brief Remove + * \return + */ + static const QString &CmdRemove() + { + static const QString cmd("remove"); + return cmd; + } + + /*! + * \brief Add + * \return + */ + static const QString &CmdAdd() + { + static const QString cmd("add"); + return cmd; + } + + /*! + * \brief Wrong path message + * \param path + * \return + */ + static BlackMisc::CStatusMessage wrongPathMessage(const QString &path = ""); + + /*! + * \brief Wrong path messages + * \param path + * \return + */ + static BlackMisc::CStatusMessages wrongPathMessages(const QString &path = ""); + + /*! + * \brief Remove leading path + * \param path + * \return + */ + static QString removeLeadingPath(const QString &path); + + /*! + * \brief Append paths + * \param part1 + * \param part2 + * \param part3 + * \return + */ + static QString appendPaths(const QString &part1, const QString &part2, const QString &part3 = ""); + + }; + } // namespace +} // namespace +#endif // guard diff --git a/src/blackmisc/statusmessage.cpp b/src/blackmisc/statusmessage.cpp index 4eb1825fb..ab83fa580 100644 --- a/src/blackmisc/statusmessage.cpp +++ b/src/blackmisc/statusmessage.cpp @@ -8,7 +8,7 @@ namespace BlackMisc /* * Constructor */ - CStatusMessage::CStatusMessage(StatusType type, StatusSeverity severity, const QString message) + CStatusMessage::CStatusMessage(StatusType type, StatusSeverity severity, const QString &message) : m_type(type), m_severity(severity), m_message(message), m_timestamp(QDateTime::currentDateTimeUtc()) { // void diff --git a/src/blackmisc/statusmessage.h b/src/blackmisc/statusmessage.h index a96b703ec..82bda8508 100644 --- a/src/blackmisc/statusmessage.h +++ b/src/blackmisc/statusmessage.h @@ -90,7 +90,7 @@ namespace BlackMisc * \brief As QVariant * \return */ - QVariant asQVariant() const + QVariant toQVariant() const { return QVariant::fromValue(*this); } diff --git a/src/blackmisc/statusmessages.h b/src/blackmisc/statusmessages.h index d418768b2..f9c98e7e1 100644 --- a/src/blackmisc/statusmessages.h +++ b/src/blackmisc/statusmessages.h @@ -90,7 +90,7 @@ namespace BlackMisc * \brief As QVariant * \return */ - virtual QVariant asQVariant() const + virtual QVariant toQVariant() const { return QVariant::fromValue(*this); }