mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-03-30 20:15:35 +08:00
@@ -27,7 +27,7 @@ namespace BlackCore
|
||||
{
|
||||
|
||||
// 1. Init by "network driver"
|
||||
this->m_network = new CNetworkVatlib(CNetworkVatlib::LoginNormal, this);
|
||||
this->m_network = new CNetworkVatlib(this);
|
||||
|
||||
// 2. Init own aircraft
|
||||
this->initOwnAircraft();
|
||||
@@ -42,15 +42,15 @@ namespace BlackCore
|
||||
// 4. connect signals and slots
|
||||
this->connect(this->m_network, &INetwork::connectionStatusChanged, this, &CContextNetwork::psFsdConnectionStatusChanged);
|
||||
this->connect(this->m_network, &INetwork::atcPositionUpdate, this, &CContextNetwork::psFsdAtcPositionUpdate);
|
||||
this->connect(this->m_network, &INetwork::atisQueryReplyReceived, this, &CContextNetwork::psFsdAtisQueryReceived);
|
||||
this->connect(this->m_network, &INetwork::atisQueryVoiceRoomReplyReceived, this, &CContextNetwork::psFsdAtisVoiceRoomQueryReceived);
|
||||
this->connect(this->m_network, &INetwork::atisQueryLogoffTimeReplyReceived, this, &CContextNetwork::psFsdAtisLogoffTimeQueryReceived);
|
||||
this->connect(this->m_network, &INetwork::metarReceived, this, &CContextNetwork::psFsdMetarReceived);
|
||||
this->connect(this->m_network, &INetwork::nameQueryReplyReceived, this, &CContextNetwork::psFsdNameQueryReplyReceived);
|
||||
this->connect(this->m_network, &INetwork::aircraftInfoReceived, this, &CContextNetwork::psFsdAircraftInfoReceived);
|
||||
this->connect(this->m_network, &INetwork::atisReplyReceived, this, &CContextNetwork::psFsdAtisQueryReceived);
|
||||
this->connect(this->m_network, &INetwork::atisVoiceRoomReplyReceived, this, &CContextNetwork::psFsdAtisVoiceRoomQueryReceived);
|
||||
this->connect(this->m_network, &INetwork::atisLogoffTimeReplyReceived, this, &CContextNetwork::psFsdAtisLogoffTimeQueryReceived);
|
||||
this->connect(this->m_network, &INetwork::metarReplyReceived, this, &CContextNetwork::psFsdMetarReceived);
|
||||
this->connect(this->m_network, &INetwork::realNameReplyReceived, this, &CContextNetwork::psFsdRealNameReplyReceived);
|
||||
this->connect(this->m_network, &INetwork::icaoCodesReplyReceived, this, &CContextNetwork::psFsdIcaoCodesReceived);
|
||||
this->connect(this->m_network, &INetwork::pilotDisconnected, this, &CContextNetwork::psFsdPilotDisconnected);
|
||||
this->connect(this->m_network, &INetwork::aircraftPositionUpdate, this, &CContextNetwork::psFsdAircraftUpdateReceived);
|
||||
this->connect(this->m_network, &INetwork::frequencyQueryReplyReceived, this, &CContextNetwork::psFsdFrequencyReceived);
|
||||
this->connect(this->m_network, &INetwork::frequencyReplyReceived, this, &CContextNetwork::psFsdFrequencyReceived);
|
||||
this->connect(this->m_network, &INetwork::textMessagesReceived, this, &CContextNetwork::psFsdTextMessageReceived);
|
||||
this->connect(this->m_network, &INetwork::statusMessage, this, &CContextNetwork::statusMessage);
|
||||
}
|
||||
@@ -107,8 +107,10 @@ namespace BlackCore
|
||||
}
|
||||
else
|
||||
{
|
||||
this->m_ownAircraft.setPilot(currentServer.getUser());
|
||||
this->m_network->setServer(currentServer);
|
||||
this->m_ownAircraft.setPilot(currentServer.getUser()); // still needed?
|
||||
this->m_network->presetServer(currentServer);
|
||||
this->m_network->presetCallsign(this->m_ownAircraft.getCallsign());
|
||||
this->m_network->presetIcaoCodes(this->m_ownAircraft.getIcaoInfo());
|
||||
this->m_network->setOwnAircraft(this->m_ownAircraft);
|
||||
this->m_network->initiateConnection();
|
||||
QString msg = "Connection pending ";
|
||||
@@ -259,7 +261,7 @@ namespace BlackCore
|
||||
/*
|
||||
* Name query
|
||||
*/
|
||||
void CContextNetwork::psFsdNameQueryReplyReceived(const CCallsign &callsign, const QString &realname)
|
||||
void CContextNetwork::psFsdRealNameReplyReceived(const CCallsign &callsign, const QString &realname)
|
||||
{
|
||||
// this->log(Q_FUNC_INFO, callsign.toQString(), realname);
|
||||
if (realname.isEmpty()) return;
|
||||
|
||||
@@ -271,12 +271,12 @@ namespace BlackCore
|
||||
/*!
|
||||
* \brief Realname recevied
|
||||
*/
|
||||
void psFsdNameQueryReplyReceived(const BlackMisc::Aviation::CCallsign &callsign, const QString &realname);
|
||||
void psFsdRealNameReplyReceived(const BlackMisc::Aviation::CCallsign &callsign, const QString &realname);
|
||||
|
||||
/*!
|
||||
* \brief Plane info received
|
||||
* \brief Plane ICAO codes received
|
||||
*/
|
||||
void psFsdAircraftInfoReceived(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Aviation::CAircraftIcao &icaoData);
|
||||
void psFsdIcaoCodesReceived(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Aviation::CAircraftIcao &icaoData);
|
||||
|
||||
/*!
|
||||
* \brief Aircraft position update received
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace BlackCore
|
||||
/*
|
||||
* Aircraft info received
|
||||
*/
|
||||
void CContextNetwork::psFsdAircraftInfoReceived(const CCallsign &callsign, const CAircraftIcao &icaoData)
|
||||
void CContextNetwork::psFsdIcaoCodesReceived(const CCallsign &callsign, const CAircraftIcao &icaoData)
|
||||
{
|
||||
// this->log(Q_FUNC_INFO, callsign.toQString(), icaoData.toQString());
|
||||
CAircraftList aircraftsWithCallsign = this->m_aircraftsInRange.findByCallsign(callsign);
|
||||
@@ -32,7 +32,7 @@ namespace BlackCore
|
||||
aircraft.calculcateDistanceToPlane(this->m_ownAircraft.getPosition());
|
||||
this->m_aircraftsInRange.push_back(aircraft);
|
||||
emit this->m_network->sendFrequencyQuery(callsign);
|
||||
emit this->m_network->sendNameQuery(callsign);
|
||||
emit this->m_network->sendRealNameQuery(callsign);
|
||||
emit this->changedAircraftsInRange();
|
||||
}
|
||||
else
|
||||
@@ -61,8 +61,8 @@ namespace BlackCore
|
||||
aircraft.calculcateDistanceToPlane(this->m_ownAircraft.getPosition());
|
||||
this->m_aircraftsInRange.push_back(aircraft);
|
||||
emit this->m_network->sendFrequencyQuery(callsign);
|
||||
emit this->m_network->sendNameQuery(callsign);
|
||||
emit this->m_network->requestAircraftInfo(callsign);
|
||||
emit this->m_network->sendRealNameQuery(callsign);
|
||||
emit this->m_network->sendIcaoCodesQuery(callsign);
|
||||
emit this->changedAircraftsInRange();
|
||||
}
|
||||
else
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace BlackCore
|
||||
if (metar.isEmpty() || metar.timeDiffReceivedMs() > 10 * 1000)
|
||||
{
|
||||
// outdated, or not in cache at all
|
||||
this->m_network->requestMetar(airportIcaoCode.trimmed().toUpper());
|
||||
this->m_network->sendMetarQuery(airportIcaoCode.trimmed().toUpper());
|
||||
|
||||
// with this little trick we try to make an asynchronous signal / slot
|
||||
// based approach a synchronous return value
|
||||
@@ -183,7 +183,7 @@ namespace BlackCore
|
||||
this->m_atcStationsOnline.push_back(station);
|
||||
emit this->changedAtcStationsOnline();
|
||||
emit this->m_network->sendAtisQuery(callsign); // request ATIS
|
||||
emit this->m_network->sendNameQuery(callsign);
|
||||
emit this->m_network->sendRealNameQuery(callsign);
|
||||
emit this->m_network->sendServerQuery(callsign);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -31,6 +31,16 @@ namespace BlackCore
|
||||
/*!
|
||||
* Interface for a connection to a multi-user flight simulation and ATC network.
|
||||
*
|
||||
* The connection can be in one of three essential states: disconnected, connecting, and
|
||||
* connected. (There is a fourth state, disconnected due to error, which is a substate of
|
||||
* disconnected.) Some slots may only be called when connected, and some may only be called
|
||||
* when disconnected; there is a naming convention to highlight this fact using prefixes:
|
||||
* "preset" slots are only callable when disconnected, "send" slots are only callable when
|
||||
* connected, and "set" slots are callable in any state.
|
||||
*
|
||||
* Slots with the word "query" in their names are handled asynchronously, with one or more
|
||||
* "reply" signals being sent in response to each invokation of a query slot.
|
||||
*
|
||||
* \warning If an INetwork signal is connected to a slot, and that slot emits a signal
|
||||
* which is connected to an INetwork slot, then at least one of those connections
|
||||
* must be a Qt::QueuedConnection.
|
||||
@@ -42,14 +52,19 @@ namespace BlackCore
|
||||
|
||||
protected:
|
||||
/*!
|
||||
* \brief Constructor
|
||||
* \param parent
|
||||
* Constructor
|
||||
*/
|
||||
INetwork(QObject *parent = nullptr) : QObject(parent) {}
|
||||
|
||||
public:
|
||||
/*!
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~INetwork() {}
|
||||
|
||||
/*!
|
||||
* Flags for capabilities bitfield.
|
||||
*/
|
||||
enum
|
||||
{
|
||||
AcceptsAtisResponses = 1 << 0,
|
||||
@@ -57,14 +72,30 @@ namespace BlackCore
|
||||
SupportsModelDescriptions = 1 << 2
|
||||
};
|
||||
|
||||
enum ConnectionStatus
|
||||
/*!
|
||||
* Login modes
|
||||
*/
|
||||
enum LoginMode
|
||||
{
|
||||
Disconnected = 0,
|
||||
DisconnectedError,
|
||||
Connecting,
|
||||
Connected
|
||||
LoginNormal = 0, //!< Normal login
|
||||
LoginAsObserver, //!< Login as observer
|
||||
LoginStealth //!< Login stealth mode
|
||||
};
|
||||
|
||||
/*!
|
||||
* Status of the connection.
|
||||
*/
|
||||
enum ConnectionStatus
|
||||
{
|
||||
Disconnected = 0, //!< Not connected
|
||||
DisconnectedError, //!< Disconnected due to socket error
|
||||
Connecting, //!< Connection initiated but not established
|
||||
Connected //!< Connection established
|
||||
};
|
||||
|
||||
/*!
|
||||
* Convert a ConnectionStatus to a string.
|
||||
*/
|
||||
static QString connectionStatusToString(ConnectionStatus status)
|
||||
{
|
||||
int index = staticMetaObject.indexOfEnumerator("ConnectionStatus");
|
||||
@@ -72,79 +103,340 @@ namespace BlackCore
|
||||
return metaEnum.valueToKey(status);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Returns true if the given ConnectionStatus represents an error state.
|
||||
*/
|
||||
static bool isErrorStatus(ConnectionStatus status)
|
||||
{
|
||||
return status == DisconnectedError;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Returns true if the current ConnectionStatus is a connected state.
|
||||
*/
|
||||
virtual bool isConnected() const = 0;
|
||||
|
||||
public slots:
|
||||
// Network
|
||||
virtual void setServer(const BlackMisc::Network::CServer &server) = 0;
|
||||
virtual void setCallsign(const BlackMisc::Aviation::CCallsign &callsign) = 0;
|
||||
virtual void setRealName(const QString &name) = 0;
|
||||
virtual void initiateConnection() = 0;
|
||||
virtual void terminateConnection() = 0;
|
||||
virtual void ping(const BlackMisc::Aviation::CCallsign &callsign) = 0;
|
||||
////////////////////////////////////////////////////////////////
|
||||
//! \name Network slots
|
||||
//! @{
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual void sendNameQuery(const BlackMisc::Aviation::CCallsign &callsign) = 0;
|
||||
/*!
|
||||
* Set the server which will be connected to.
|
||||
* \pre Network must be disconnected when calling this function.
|
||||
*/
|
||||
virtual void presetServer(const BlackMisc::Network::CServer &server) = 0;
|
||||
|
||||
/*!
|
||||
* Set our own callsign before connecting.
|
||||
* \pre Network must be disconnected when calling this function.
|
||||
*/
|
||||
virtual void presetCallsign(const BlackMisc::Aviation::CCallsign &callsign) = 0;
|
||||
|
||||
/*!
|
||||
* Set our own aircraft ICAO codes before connecting.
|
||||
* \pre Network must be disconnected when calling this function.
|
||||
*/
|
||||
virtual void presetIcaoCodes(const BlackMisc::Aviation::CAircraftIcao &icao) = 0;
|
||||
|
||||
/*!
|
||||
* Select a login mode before connecting.
|
||||
* \pre Network must be disconnected when calling this function.
|
||||
*/
|
||||
virtual void presetLoginMode(LoginMode mode) = 0;
|
||||
|
||||
/*!
|
||||
* Initiate a connection to the network server.
|
||||
* \pre Network must be disconnected when calling this function.
|
||||
* \post Connection status changes from Disconnected to either Connecting or DisconnectedError.
|
||||
*/
|
||||
virtual void initiateConnection() = 0;
|
||||
|
||||
/*!
|
||||
* Ask the connection to the network server to terminate itself.
|
||||
* \pre It is not legal to call this function when already disconnected.
|
||||
* \post Connection status changes to Disconnected, but maybe not immediately.
|
||||
*/
|
||||
virtual void terminateConnection() = 0;
|
||||
|
||||
/*!
|
||||
* Send a ping message to a user with a specific callsign.
|
||||
* \pre Network must be connected when calling this function.
|
||||
* \sa pongReceived
|
||||
*/
|
||||
virtual void sendPing(const BlackMisc::Aviation::CCallsign &callsign) = 0;
|
||||
|
||||
/*!
|
||||
* Send a message querying the real name of the user with a specific callsign.
|
||||
* \pre Network must be connected when calling this function.
|
||||
* \sa realNameReplyReceived
|
||||
*/
|
||||
virtual void sendRealNameQuery(const BlackMisc::Aviation::CCallsign &callsign) = 0;
|
||||
|
||||
/*!
|
||||
* Send a message querying our own IP address as reported by the server.
|
||||
* \pre Network must be connected when calling this function.
|
||||
* \sa ipReplyReceived
|
||||
*/
|
||||
virtual void sendIpQuery() = 0;
|
||||
|
||||
/*!
|
||||
* Send a message querying which server the user with a specific callsign is connected to.
|
||||
* \pre Network must be connected when calling this function.
|
||||
* \sa serverReplyReceived
|
||||
*/
|
||||
virtual void sendServerQuery(const BlackMisc::Aviation::CCallsign &callsign) = 0;
|
||||
|
||||
// Text messages
|
||||
virtual void sendTextMessages(const BlackMisc::Network::CTextMessageList &textMessages) = 0;
|
||||
/*!
|
||||
* Send one or more text messages.
|
||||
* \pre Network must be connected when calling this function.
|
||||
*/
|
||||
virtual void sendTextMessages(const BlackMisc::Network::CTextMessageList &messages) = 0;
|
||||
|
||||
// ATC
|
||||
//! @}
|
||||
////////////////////////////////////////////////////////////////
|
||||
//! \name ATC slots
|
||||
//! @{
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
/*!
|
||||
* Send a message querying whether or not the user with a specific callsign is an ATC station.
|
||||
* \pre Network must be connected when calling this function.
|
||||
* \sa atcReplyReceived
|
||||
*/
|
||||
virtual void sendAtcQuery(const BlackMisc::Aviation::CCallsign &callsign) = 0;
|
||||
|
||||
/*!
|
||||
* Send a message querying the ATIS for the ATC station with a specific callsign.
|
||||
* \pre Network must be connected when calling this function.
|
||||
* \sa atisReplyReceived
|
||||
* \sa atisVoiceRoomReplyReceived
|
||||
* \sa atisLogoffTimeReplyReceived
|
||||
*/
|
||||
virtual void sendAtisQuery(const BlackMisc::Aviation::CCallsign &callsign) = 0;
|
||||
|
||||
// Aircraft
|
||||
// TODO virtual void sendFlightPlan(...) = 0;
|
||||
|
||||
//! @}
|
||||
////////////////////////////////////////////////////////////////
|
||||
//! \name Aircraft slots
|
||||
//! @{
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
/*!
|
||||
* Send a message querying the capabilities of the client software of the user with a specific callsign.
|
||||
* \pre Network must be connected when calling this function.
|
||||
* \sa capabilitiesReplyReceived
|
||||
*/
|
||||
virtual void sendCapabilitiesQuery(const BlackMisc::Aviation::CCallsign &callsign) = 0;
|
||||
virtual void requestAircraftInfo(const BlackMisc::Aviation::CCallsign &callsign) = 0;
|
||||
|
||||
/*!
|
||||
* Send a message querying the ICAO codes of the aircraft of the user with a specific callsign.
|
||||
* \pre Network must be connected when calling this function.
|
||||
* \sa icaoCodesReplyReceived
|
||||
*/
|
||||
virtual void sendIcaoCodesQuery(const BlackMisc::Aviation::CCallsign &callsign) = 0;
|
||||
|
||||
/*!
|
||||
* Send a message querying the COM frequency of the user with a specific callsign.
|
||||
* \pre Network must be connected when calling this function.
|
||||
* \sa frequencyReplyReceived
|
||||
*/
|
||||
virtual void sendFrequencyQuery(const BlackMisc::Aviation::CCallsign &callsign) = 0;
|
||||
|
||||
/*!
|
||||
* Set our own aircraft data.
|
||||
* \param aircraft Only the situation and avionics parts are used. Callsign, user, and ICAO code parts are ignored.
|
||||
*/
|
||||
virtual void setOwnAircraft(const BlackMisc::Aviation::CAircraft &aircraft) = 0;
|
||||
|
||||
/*!
|
||||
* Set the position and altitude of our own aircraft.
|
||||
*/
|
||||
virtual void setOwnAircraftPosition(const BlackMisc::Geo::CCoordinateGeodetic &position, const BlackMisc::Aviation::CAltitude &altitude) = 0;
|
||||
|
||||
/*!
|
||||
* Set the position, altitude, orientation, and miscellaneous state of our own aircraft.
|
||||
*/
|
||||
virtual void setOwnAircraftSituation(const BlackMisc::Aviation::CAircraftSituation &situation) = 0;
|
||||
|
||||
/*!
|
||||
* Set the COM frequencies and transponder code and mode of our own aircraft.
|
||||
*/
|
||||
virtual void setOwnAircraftAvionics(const BlackMisc::Aviation::CComSystem &com1, const BlackMisc::Aviation::CComSystem &com2,
|
||||
const BlackMisc::Aviation::CTransponder &transponder) = 0;
|
||||
|
||||
// Weather / flight plan
|
||||
virtual void requestMetar(const QString &airportICAO) = 0;
|
||||
virtual void requestWeatherData(const QString &airportICAO) = 0;
|
||||
// TODO virtual void sendFlightPlan(...) = 0;
|
||||
//! @}
|
||||
////////////////////////////////////////////////////////////////
|
||||
//! \name Weather slots
|
||||
//! @{
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
/*!
|
||||
* Send a message querying the METAR for the airport with a specific ICAO code.
|
||||
* \pre Network must be connected when calling this function.
|
||||
* \sa metarReplyReceived
|
||||
*/
|
||||
virtual void sendMetarQuery(const QString &airportICAO) = 0;
|
||||
|
||||
/*!
|
||||
* Send a message querying the weather data for the airport with a specific ICAO code.
|
||||
* \pre Network must be connected when calling this function.
|
||||
* \sa temperatureDataReplyReceived
|
||||
* \sa windDataReplyReceived
|
||||
* \sa cloudDataReplyReceived
|
||||
*/
|
||||
virtual void sendWeatherDataQuery(const QString &airportICAO) = 0;
|
||||
|
||||
signals:
|
||||
// ATC
|
||||
//! @}
|
||||
////////////////////////////////////////////////////////////////
|
||||
//! \name ATC signals
|
||||
//! @{
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
/*!
|
||||
* We received a notification of the state of an ATC station on the network.
|
||||
*/
|
||||
void atcPositionUpdate(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::PhysicalQuantities::CFrequency &freq,
|
||||
const BlackMisc::Geo::CCoordinateGeodetic &pos, const BlackMisc::PhysicalQuantities::CLength &range);
|
||||
void atcDisconnected(const BlackMisc::Aviation::CCallsign &callsign);
|
||||
void atcQueryReplyReceived(const BlackMisc::Aviation::CCallsign &callsign, bool isATC);
|
||||
void atisQueryReplyReceived(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Aviation::CInformationMessage &atis);
|
||||
void atisQueryVoiceRoomReplyReceived(const BlackMisc::Aviation::CCallsign &callsign, const QString &url);
|
||||
void atisQueryLogoffTimeReplyReceived(const BlackMisc::Aviation::CCallsign &callsign, const QString &zuluTime);
|
||||
void metarReceived(const QString &data);
|
||||
|
||||
// Aircraft
|
||||
/*!
|
||||
* We received a notification that an ATC station has disconnected from the network.
|
||||
*/
|
||||
void atcDisconnected(const BlackMisc::Aviation::CCallsign &callsign);
|
||||
|
||||
/*!
|
||||
* We received a reply to one of our queries.
|
||||
* \sa sendAtcQuery
|
||||
*/
|
||||
void atcReplyReceived(const BlackMisc::Aviation::CCallsign &callsign, bool isATC);
|
||||
|
||||
/*!
|
||||
* We received a reply to one of our ATIS queries.
|
||||
* \sa sendAtisQuery
|
||||
*/
|
||||
void atisReplyReceived(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Aviation::CInformationMessage &atis);
|
||||
|
||||
/*!
|
||||
* We received a reply to one of our ATIS queries, containing the controller's voice room URL.
|
||||
* \sa sendAtisQuery
|
||||
*/
|
||||
void atisVoiceRoomReplyReceived(const BlackMisc::Aviation::CCallsign &callsign, const QString &url);
|
||||
|
||||
/*!
|
||||
* We received a reply to one of our ATIS queries, containing the controller's planned logoff time.
|
||||
* \sa sendAtisQuery
|
||||
*/
|
||||
void atisLogoffTimeReplyReceived(const BlackMisc::Aviation::CCallsign &callsign, const QString &zuluTime);
|
||||
|
||||
/*!
|
||||
* We received a reply to one of our METAR queries.
|
||||
* \sa sendMetarQuery
|
||||
*/
|
||||
void metarReplyReceived(const QString &data);
|
||||
|
||||
//! @}
|
||||
////////////////////////////////////////////////////////////////
|
||||
//! \name Aircraft signals
|
||||
//! @{
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
/*!
|
||||
* We received a notification that a pilot has disconnected from the network.
|
||||
*/
|
||||
void pilotDisconnected(const BlackMisc::Aviation::CCallsign &callsign);
|
||||
void aircraftInfoReceived(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Aviation::CAircraftIcao &icao);
|
||||
|
||||
/*!
|
||||
* We received a reply to one of our queries.
|
||||
* \sa sendIcaoCodesQuery
|
||||
*/
|
||||
void icaoCodesReplyReceived(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Aviation::CAircraftIcao &icao);
|
||||
|
||||
/*!
|
||||
* We received a notification of the state of another aircraft on the network.
|
||||
*/
|
||||
void aircraftPositionUpdate(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Aviation::CAircraftSituation &situation,
|
||||
const BlackMisc::Aviation::CTransponder &transponder);
|
||||
|
||||
/*!
|
||||
* We received a reply to one of our queries.
|
||||
* \sa sendFrequencyQuery
|
||||
*/
|
||||
void frequencyReplyReceived(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::PhysicalQuantities::CFrequency &freq);
|
||||
|
||||
// TODO void aircraftInterimPositionUpdate(...);
|
||||
void frequencyQueryReplyReceived(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::PhysicalQuantities::CFrequency &freq);
|
||||
|
||||
// Connection / Network in general
|
||||
//! @}
|
||||
////////////////////////////////////////////////////////////////
|
||||
//! \name Network signals
|
||||
//! @{
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
/*!
|
||||
* We sent a message about the status of the network connection, for the attention of the user.
|
||||
*/
|
||||
void statusMessage(const BlackMisc::CStatusMessage &message);
|
||||
void kicked(const QString &msg);
|
||||
void connectionStatusChanged(ConnectionStatus oldStatus, ConnectionStatus newStatus);
|
||||
void pong(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::PhysicalQuantities::CTime &elapsedTime);
|
||||
void capabilitiesQueryReplyReceived(const BlackMisc::Aviation::CCallsign &callsign, quint32 flags);
|
||||
void ipQueryReplyReceived(const QString &ip);
|
||||
void serverQueryReplyReceived(const BlackMisc::Aviation::CCallsign &callsign, const QString &hostname);
|
||||
void nameQueryReplyReceived(const BlackMisc::Aviation::CCallsign &callsign, const QString &realname);
|
||||
|
||||
// Text messages
|
||||
/*!
|
||||
* We were kicked from the network. (A connectionStatusChanged signal will also be sent.)
|
||||
*/
|
||||
void kicked(const QString &msg);
|
||||
|
||||
/*!
|
||||
* The status of our connection has changed.
|
||||
*/
|
||||
void connectionStatusChanged(ConnectionStatus oldStatus, ConnectionStatus newStatus);
|
||||
|
||||
/*!
|
||||
* We received a reply to one of our pings.
|
||||
* \sa sendPing
|
||||
*/
|
||||
void pongReceived(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::PhysicalQuantities::CTime &elapsedTime);
|
||||
|
||||
/*!
|
||||
* We received a reply to one of our queries.
|
||||
* \param flags A combination of capabilities flags.
|
||||
* \sa sendCapabilitiesQuery
|
||||
*/
|
||||
void capabilitiesReplyReceived(const BlackMisc::Aviation::CCallsign &callsign, quint32 flags);
|
||||
|
||||
/*!
|
||||
* We received a reply to one of our queries.
|
||||
* \param ip Our IP address, as seen by the server.
|
||||
* \sa sendIpQuery
|
||||
*/
|
||||
void ipReplyReceived(const QString &ip);
|
||||
|
||||
/*!
|
||||
* We received a reply to one of our queries.
|
||||
* \sa sendServerQuery
|
||||
*/
|
||||
void serverReplyReceived(const BlackMisc::Aviation::CCallsign &callsign, const QString &hostname);
|
||||
|
||||
/*!
|
||||
* We received a reply to one of our queries.
|
||||
* \sa sendRealNameQuery
|
||||
*/
|
||||
void realNameReplyReceived(const BlackMisc::Aviation::CCallsign &callsign, const QString &realname);
|
||||
|
||||
/*!
|
||||
* We received one or more text messages from another user.
|
||||
*/
|
||||
void textMessagesReceived(const BlackMisc::Network::CTextMessageList &messages);
|
||||
|
||||
// Weather
|
||||
// TODO void temperatureDataReceived(...);
|
||||
// TODO void windDataReceived(...);
|
||||
// TODO void cloudDataReceived(...);
|
||||
//! @}
|
||||
////////////////////////////////////////////////////////////////
|
||||
//! \name Weather signals
|
||||
//! @{
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
// TODO void temperatureDataReplyReceived(...);
|
||||
// TODO void windDataReplyReceived(...);
|
||||
// TODO void cloudDataReplyReceived(...);
|
||||
|
||||
//! @}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -28,19 +28,29 @@ namespace BlackCore
|
||||
|
||||
void exceptionDispatcher(const char *caller);
|
||||
|
||||
CNetworkVatlib::CNetworkVatlib(CNetworkVatlib::LoginMode loginMode, QObject *parent)
|
||||
CNetworkVatlib::CNetworkVatlib(QObject *parent)
|
||||
: INetwork(parent),
|
||||
m_net(Cvatlib_Network::Create()),
|
||||
m_loginMode(loginMode),
|
||||
m_loginMode(LoginNormal),
|
||||
m_status(Cvatlib_Network::connStatus_Idle),
|
||||
m_fsdTextCodec(QTextCodec::codecForName("latin1"))
|
||||
{
|
||||
connect(this, &CNetworkVatlib::terminate, this, &INetwork::terminateConnection, Qt::QueuedConnection);
|
||||
|
||||
Q_ASSERT_X(m_fsdTextCodec, "CNetworkVatlib", "Missing default wire text encoding");
|
||||
//TODO reinit m_fsdTextCodec from WireTextEncoding config setting if present
|
||||
|
||||
connect(&m_processingTimer, SIGNAL(timeout()), this, SLOT(process()));
|
||||
connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(update()));
|
||||
m_processingTimer.start(c_processingIntervalMsec);
|
||||
}
|
||||
|
||||
void CNetworkVatlib::initializeSession()
|
||||
{
|
||||
Q_ASSERT_X(isDisconnected(), "CNetworkVatlib", "attempted to reinitialize session while still connected");
|
||||
|
||||
try
|
||||
{
|
||||
connect(this, SIGNAL(terminate()), this, SLOT(terminateConnection()), Qt::QueuedConnection);
|
||||
|
||||
Q_ASSERT_X(m_fsdTextCodec, "CNetworkVatlib", "Missing default wire text encoding");
|
||||
//TODO reinit m_fsdTextCodec from WireTextEncoding config setting if present
|
||||
m_net.reset(Cvatlib_Network::Create());
|
||||
|
||||
QString capabilities;
|
||||
capabilities += m_net->capability_AtcInfo;
|
||||
@@ -49,7 +59,7 @@ namespace BlackCore
|
||||
capabilities += "=1:";
|
||||
capabilities += m_net->capability_ModelDesc;
|
||||
capabilities += "=1";
|
||||
if (loginMode == LoginStealth)
|
||||
if (m_loginMode == LoginStealth)
|
||||
{
|
||||
capabilities += "STEALTH"; // TODO m_net->capability_Stealth
|
||||
capabilities += "=1";
|
||||
@@ -79,21 +89,19 @@ namespace BlackCore
|
||||
m_net->InstallOnCloudDataReceivedEvent(onCloudDataReceived, this);
|
||||
m_net->InstallOnPilotInfoRequestReceivedEvent(onPilotInfoRequestReceived, this);
|
||||
m_net->InstallOnPilotInfoReceivedEvent(onPilotInfoReceived, this);
|
||||
|
||||
connect(&m_processingTimer, SIGNAL(timeout()), this, SLOT(process()));
|
||||
connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(update()));
|
||||
m_processingTimer.start(c_processingIntervalMsec);
|
||||
}
|
||||
catch (...) { exceptionDispatcher(Q_FUNC_INFO); }
|
||||
}
|
||||
|
||||
CNetworkVatlib::~CNetworkVatlib()
|
||||
{
|
||||
if (!m_net) { return; }
|
||||
|
||||
try
|
||||
{
|
||||
if (m_net->IsNetworkConnected())
|
||||
if (m_net->IsValid() && m_net->IsNetworkConnected())
|
||||
{
|
||||
m_net->LogoffAndDisconnect(0);
|
||||
m_net->LogoffAndDisconnect(0); // emits a connectionStatusChanged signal
|
||||
}
|
||||
}
|
||||
catch (...) { exceptionDispatcher(Q_FUNC_INFO); }
|
||||
@@ -106,6 +114,8 @@ namespace BlackCore
|
||||
|
||||
void CNetworkVatlib::process()
|
||||
{
|
||||
if (!m_net) { return; }
|
||||
|
||||
try
|
||||
{
|
||||
if (m_net->IsValid() && m_net->IsSessionExists())
|
||||
@@ -118,6 +128,8 @@ namespace BlackCore
|
||||
|
||||
void CNetworkVatlib::update()
|
||||
{
|
||||
if (!m_net) { return; }
|
||||
|
||||
try
|
||||
{
|
||||
if (m_net->IsValid() && m_net->IsSessionExists() && isConnected())
|
||||
@@ -161,6 +173,34 @@ namespace BlackCore
|
||||
catch (...) { exceptionDispatcher(Q_FUNC_INFO); }
|
||||
}
|
||||
|
||||
INetwork::ConnectionStatus convertConnectionStatus(Cvatlib_Network::connStatus status)
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case Cvatlib_Network::connStatus_Idle: return INetwork::Disconnected;
|
||||
case Cvatlib_Network::connStatus_Connecting: return INetwork::Connecting;
|
||||
case Cvatlib_Network::connStatus_Connected: return INetwork::Connected;
|
||||
case Cvatlib_Network::connStatus_Disconnected: return INetwork::Disconnected;
|
||||
case Cvatlib_Network::connStatus_Error: return INetwork::DisconnectedError;
|
||||
}
|
||||
qFatal("unrecognised connection status");
|
||||
return INetwork::DisconnectedError;
|
||||
}
|
||||
|
||||
void CNetworkVatlib::changeConnectionStatus(Cvatlib_Network::connStatus status)
|
||||
{
|
||||
if (m_status != status)
|
||||
{
|
||||
qSwap(m_status, status);
|
||||
emit connectionStatusChanged(convertConnectionStatus(status), convertConnectionStatus(m_status));
|
||||
|
||||
if (isDisconnected())
|
||||
{
|
||||
m_updateTimer.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QByteArray CNetworkVatlib::toFSD(QString qstr) const
|
||||
{
|
||||
return m_fsdTextCodec->fromUnicode(qstr);
|
||||
@@ -176,11 +216,6 @@ namespace BlackCore
|
||||
return m_fsdTextCodec->toUnicode(cstr);
|
||||
}
|
||||
|
||||
bool CNetworkVatlib::isConnected() const
|
||||
{
|
||||
return m_status == Cvatlib_Network::connStatus_Connected;
|
||||
}
|
||||
|
||||
void exceptionDispatcher(const char *caller)
|
||||
{
|
||||
try
|
||||
@@ -210,26 +245,30 @@ namespace BlackCore
|
||||
/********************************** INetwork slots ************************************/
|
||||
/********************************** * * * * * * * * * * * * * * * * * * * ************************************/
|
||||
|
||||
void CNetworkVatlib::setServer(const CServer &server)
|
||||
void CNetworkVatlib::presetServer(const CServer &server)
|
||||
{
|
||||
Q_ASSERT_X(isDisconnected(), "CNetworkVatlib", "Can't change server details while still connected");
|
||||
this->m_server = server;
|
||||
m_server = server;
|
||||
}
|
||||
|
||||
void CNetworkVatlib::setCallsign(const BlackMisc::Aviation::CCallsign &callsign)
|
||||
void CNetworkVatlib::presetCallsign(const BlackMisc::Aviation::CCallsign &callsign)
|
||||
{
|
||||
Q_ASSERT_X(isDisconnected(), "CNetworkVatlib", "Can't change callsign while still connected");
|
||||
|
||||
m_ownAircraft.setCallsign(callsign);
|
||||
m_callsign = callsign;
|
||||
}
|
||||
|
||||
void CNetworkVatlib::setRealName(const QString &name)
|
||||
void CNetworkVatlib::presetIcaoCodes(const BlackMisc::Aviation::CAircraftIcao &icao)
|
||||
{
|
||||
Q_ASSERT_X(isDisconnected(), "CNetworkVatlib", "Can't change name while still connected");
|
||||
Q_ASSERT_X(isDisconnected(), "CNetworkVatlib", "Can't change ICAO codes while still connected");
|
||||
m_icaoCodes = icao;
|
||||
}
|
||||
|
||||
auto pilot = m_ownAircraft.getPilot();
|
||||
pilot.setRealName(name);
|
||||
m_ownAircraft.setPilot(pilot);
|
||||
void CNetworkVatlib::presetLoginMode(LoginMode mode)
|
||||
{
|
||||
Q_ASSERT_X(isDisconnected(), "CNetworkVatlib", "Can't change login mode while still connected");
|
||||
m_loginMode = mode;
|
||||
|
||||
m_net.reset(nullptr);
|
||||
}
|
||||
|
||||
void CNetworkVatlib::initiateConnection()
|
||||
@@ -238,12 +277,17 @@ namespace BlackCore
|
||||
|
||||
try
|
||||
{
|
||||
m_status = Cvatlib_Network::connStatus_Connecting; // paranoia
|
||||
if (!m_net)
|
||||
{
|
||||
initializeSession();
|
||||
}
|
||||
|
||||
changeConnectionStatus(Cvatlib_Network::connStatus_Connecting); // paranoia
|
||||
|
||||
QByteArray callsign = toFSD(m_loginMode == LoginAsObserver ?
|
||||
m_ownAircraft.getCallsign().getAsObserverCallsignString() :
|
||||
m_ownAircraft.getCallsign().asString());
|
||||
QByteArray name = toFSD(m_ownAircraft.getPilot().getRealName());
|
||||
m_callsign.getAsObserverCallsignString() :
|
||||
m_callsign.asString());
|
||||
QByteArray name = toFSD(m_server.getUser().getRealName());
|
||||
|
||||
if (this->m_loginMode == LoginAsObserver)
|
||||
{
|
||||
@@ -270,15 +314,22 @@ namespace BlackCore
|
||||
toFSD(m_server.getUser().getPassword()),
|
||||
info);
|
||||
}
|
||||
m_net->ConnectAndLogon();
|
||||
if (! m_updateTimer.isActive())
|
||||
|
||||
if (m_net->ConnectAndLogon())
|
||||
{
|
||||
m_updateTimer.start(c_updateIntervalMsec);
|
||||
if (! m_updateTimer.isActive())
|
||||
{
|
||||
m_updateTimer.start(c_updateIntervalMsec);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
changeConnectionStatus(Cvatlib_Network::connStatus_Error);
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
m_status = Cvatlib_Network::connStatus_Idle;
|
||||
changeConnectionStatus(Cvatlib_Network::connStatus_Error);
|
||||
exceptionDispatcher(Q_FUNC_INFO);
|
||||
}
|
||||
}
|
||||
@@ -288,7 +339,11 @@ namespace BlackCore
|
||||
try
|
||||
{
|
||||
m_updateTimer.stop();
|
||||
m_net->LogoffAndDisconnect(c_logoffTimeoutSec);
|
||||
|
||||
if (m_net && m_net->IsValid() && m_net->IsNetworkConnected())
|
||||
{
|
||||
m_net->LogoffAndDisconnect(c_logoffTimeoutSec);
|
||||
}
|
||||
}
|
||||
catch (...) { exceptionDispatcher(Q_FUNC_INFO); }
|
||||
}
|
||||
@@ -319,6 +374,8 @@ namespace BlackCore
|
||||
|
||||
void CNetworkVatlib::sendTextMessages(const BlackMisc::Network::CTextMessageList &messages)
|
||||
{
|
||||
Q_ASSERT_X(isConnected(), "CNetworkVatlib", "Can't send to server when disconnected");
|
||||
|
||||
if (messages.isEmpty()) return;
|
||||
try
|
||||
{
|
||||
@@ -345,6 +402,8 @@ namespace BlackCore
|
||||
|
||||
void CNetworkVatlib::sendIpQuery()
|
||||
{
|
||||
Q_ASSERT_X(isConnected(), "CNetworkVatlib", "Can't send to server when disconnected");
|
||||
|
||||
try
|
||||
{
|
||||
m_net->SendInfoQuery(Cvatlib_Network::infoQuery_IP, "SERVER");
|
||||
@@ -354,6 +413,8 @@ namespace BlackCore
|
||||
|
||||
void CNetworkVatlib::sendFrequencyQuery(const BlackMisc::Aviation::CCallsign &callsign)
|
||||
{
|
||||
Q_ASSERT_X(isConnected(), "CNetworkVatlib", "Can't send to server when disconnected");
|
||||
|
||||
try
|
||||
{
|
||||
m_net->SendInfoQuery(Cvatlib_Network::infoQuery_Freq, toFSD(callsign));
|
||||
@@ -363,6 +424,8 @@ namespace BlackCore
|
||||
|
||||
void CNetworkVatlib::sendServerQuery(const BlackMisc::Aviation::CCallsign &callsign)
|
||||
{
|
||||
Q_ASSERT_X(isConnected(), "CNetworkVatlib", "Can't send to server when disconnected");
|
||||
|
||||
try
|
||||
{
|
||||
m_net->SendInfoQuery(Cvatlib_Network::infoQuery_Server, toFSD(callsign));
|
||||
@@ -372,6 +435,8 @@ namespace BlackCore
|
||||
|
||||
void CNetworkVatlib::sendAtcQuery(const BlackMisc::Aviation::CCallsign &callsign)
|
||||
{
|
||||
Q_ASSERT_X(isConnected(), "CNetworkVatlib", "Can't send to server when disconnected");
|
||||
|
||||
try
|
||||
{
|
||||
m_net->SendInfoQuery(Cvatlib_Network::infoQuery_ATC, toFSD(callsign));
|
||||
@@ -381,6 +446,8 @@ namespace BlackCore
|
||||
|
||||
void CNetworkVatlib::sendAtisQuery(const BlackMisc::Aviation::CCallsign &callsign)
|
||||
{
|
||||
Q_ASSERT_X(isConnected(), "CNetworkVatlib", "Can't send to server when disconnected");
|
||||
|
||||
try
|
||||
{
|
||||
m_net->SendInfoQuery(Cvatlib_Network::infoQuery_ATIS, toFSD(callsign));
|
||||
@@ -388,8 +455,10 @@ namespace BlackCore
|
||||
catch (...) { exceptionDispatcher(Q_FUNC_INFO); }
|
||||
}
|
||||
|
||||
void CNetworkVatlib::sendNameQuery(const BlackMisc::Aviation::CCallsign &callsign)
|
||||
void CNetworkVatlib::sendRealNameQuery(const BlackMisc::Aviation::CCallsign &callsign)
|
||||
{
|
||||
Q_ASSERT_X(isConnected(), "CNetworkVatlib", "Can't send to server when disconnected");
|
||||
|
||||
try
|
||||
{
|
||||
m_net->SendInfoQuery(Cvatlib_Network::infoQuery_Name, toFSD(callsign));
|
||||
@@ -399,6 +468,8 @@ namespace BlackCore
|
||||
|
||||
void CNetworkVatlib::sendCapabilitiesQuery(const BlackMisc::Aviation::CCallsign &callsign)
|
||||
{
|
||||
Q_ASSERT_X(isConnected(), "CNetworkVatlib", "Can't send to server when disconnected");
|
||||
|
||||
try
|
||||
{
|
||||
m_net->SendInfoQuery(Cvatlib_Network::infoQuery_Capabilities, toFSD(callsign));
|
||||
@@ -406,7 +477,7 @@ namespace BlackCore
|
||||
catch (...) { exceptionDispatcher(Q_FUNC_INFO); }
|
||||
}
|
||||
|
||||
void CNetworkVatlib::replyToFrequencyQuery(const BlackMisc::Aviation::CCallsign &callsign)
|
||||
void CNetworkVatlib::replyToFrequencyQuery(const BlackMisc::Aviation::CCallsign &callsign) // private
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -416,7 +487,7 @@ namespace BlackCore
|
||||
catch (...) { exceptionDispatcher(Q_FUNC_INFO); }
|
||||
}
|
||||
|
||||
void CNetworkVatlib::replyToNameQuery(const BlackMisc::Aviation::CCallsign &callsign)
|
||||
void CNetworkVatlib::replyToNameQuery(const BlackMisc::Aviation::CCallsign &callsign) // private
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -425,8 +496,10 @@ namespace BlackCore
|
||||
catch (...) { exceptionDispatcher(Q_FUNC_INFO); }
|
||||
}
|
||||
|
||||
void CNetworkVatlib::requestAircraftInfo(const BlackMisc::Aviation::CCallsign &callsign)
|
||||
void CNetworkVatlib::sendIcaoCodesQuery(const BlackMisc::Aviation::CCallsign &callsign)
|
||||
{
|
||||
Q_ASSERT_X(isConnected(), "CNetworkVatlib", "Can't send to server when disconnected");
|
||||
|
||||
try
|
||||
{
|
||||
m_net->RequestPlaneInfo(toFSD(callsign));
|
||||
@@ -434,25 +507,25 @@ namespace BlackCore
|
||||
catch (...) { exceptionDispatcher(Q_FUNC_INFO); }
|
||||
}
|
||||
|
||||
void CNetworkVatlib::sendAircraftInfo(const BlackMisc::Aviation::CCallsign &callsign)
|
||||
void CNetworkVatlib::sendAircraftInfo(const BlackMisc::Aviation::CCallsign &callsign) // private
|
||||
{
|
||||
try
|
||||
{
|
||||
const QByteArray acTypeICAObytes = toFSD(m_ownAircraft.getIcaoInfo().getDesignator());
|
||||
const QByteArray airlineICAObytes = toFSD(m_ownAircraft.getIcaoInfo().getAirline());
|
||||
const QByteArray liverybytes = toFSD(m_ownAircraft.getIcaoInfo().getLivery());
|
||||
const QByteArray acTypeICAObytes = toFSD(m_icaoCodes.getDesignator());
|
||||
const QByteArray airlineICAObytes = toFSD(m_icaoCodes.getAirline());
|
||||
const QByteArray liverybytes = toFSD(m_icaoCodes.getLivery());
|
||||
std::vector<const char *> keysValues;
|
||||
if (!m_ownAircraft.getIcaoInfo().getDesignator().isEmpty())
|
||||
if (!m_icaoCodes.getDesignator().isEmpty())
|
||||
{
|
||||
keysValues.push_back(m_net->acinfo_Equipment);
|
||||
keysValues.push_back(acTypeICAObytes);
|
||||
}
|
||||
if (m_ownAircraft.getIcaoInfo().hasAirline())
|
||||
if (m_icaoCodes.hasAirline())
|
||||
{
|
||||
keysValues.push_back(m_net->acinfo_Airline);
|
||||
keysValues.push_back(airlineICAObytes);
|
||||
}
|
||||
if (m_ownAircraft.getIcaoInfo().hasLivery())
|
||||
if (m_icaoCodes.hasLivery())
|
||||
{
|
||||
keysValues.push_back(m_net->acinfo_Livery);
|
||||
keysValues.push_back(liverybytes);
|
||||
@@ -463,8 +536,10 @@ namespace BlackCore
|
||||
catch (...) { exceptionDispatcher(Q_FUNC_INFO); }
|
||||
}
|
||||
|
||||
void CNetworkVatlib::ping(const BlackMisc::Aviation::CCallsign &callsign)
|
||||
void CNetworkVatlib::sendPing(const BlackMisc::Aviation::CCallsign &callsign)
|
||||
{
|
||||
Q_ASSERT_X(isConnected(), "CNetworkVatlib", "Can't send to server when disconnected");
|
||||
|
||||
try
|
||||
{
|
||||
m_net->PingUser(toFSD(callsign));
|
||||
@@ -472,8 +547,10 @@ namespace BlackCore
|
||||
catch (...) { exceptionDispatcher(Q_FUNC_INFO); }
|
||||
}
|
||||
|
||||
void CNetworkVatlib::requestMetar(const QString &airportICAO)
|
||||
void CNetworkVatlib::sendMetarQuery(const QString &airportICAO)
|
||||
{
|
||||
Q_ASSERT_X(isConnected(), "CNetworkVatlib", "Can't send to server when disconnected");
|
||||
|
||||
try
|
||||
{
|
||||
m_net->RequestMetar(toFSD(airportICAO));
|
||||
@@ -481,8 +558,10 @@ namespace BlackCore
|
||||
catch (...) { exceptionDispatcher(Q_FUNC_INFO); }
|
||||
}
|
||||
|
||||
void CNetworkVatlib::requestWeatherData(const QString &airportICAO)
|
||||
void CNetworkVatlib::sendWeatherDataQuery(const QString &airportICAO)
|
||||
{
|
||||
Q_ASSERT_X(isConnected(), "CNetworkVatlib", "Can't send to server when disconnected");
|
||||
|
||||
try
|
||||
{
|
||||
m_net->RequestWeatherData(toFSD(airportICAO));
|
||||
@@ -499,24 +578,9 @@ namespace BlackCore
|
||||
return static_cast<CNetworkVatlib *>(cbvar);
|
||||
}
|
||||
|
||||
CNetworkVatlib::ConnectionStatus convertConnectionStatus(Cvatlib_Network::connStatus status)
|
||||
void CNetworkVatlib::onConnectionStatusChanged(Cvatlib_Network *, Cvatlib_Network::connStatus, Cvatlib_Network::connStatus newStatus, void *cbvar)
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case Cvatlib_Network::connStatus_Idle: return CNetworkVatlib::Disconnected;
|
||||
case Cvatlib_Network::connStatus_Connecting: return CNetworkVatlib::Connecting;
|
||||
case Cvatlib_Network::connStatus_Connected: return CNetworkVatlib::Connected;
|
||||
case Cvatlib_Network::connStatus_Disconnected: return CNetworkVatlib::Disconnected;
|
||||
case Cvatlib_Network::connStatus_Error: return CNetworkVatlib::DisconnectedError;
|
||||
}
|
||||
qFatal("unrecognised connection status");
|
||||
return CNetworkVatlib::DisconnectedError;
|
||||
}
|
||||
|
||||
void CNetworkVatlib::onConnectionStatusChanged(Cvatlib_Network *, Cvatlib_Network::connStatus oldStatus, Cvatlib_Network::connStatus newStatus, void *cbvar)
|
||||
{
|
||||
cbvar_cast(cbvar)->m_status = newStatus;
|
||||
emit cbvar_cast(cbvar)->connectionStatusChanged(convertConnectionStatus(oldStatus), convertConnectionStatus(newStatus));
|
||||
cbvar_cast(cbvar)->changeConnectionStatus(newStatus);
|
||||
}
|
||||
|
||||
void CNetworkVatlib::onTextMessageReceived(Cvatlib_Network *, const char *from, const char *to, const char *msg, void *cbvar)
|
||||
@@ -596,16 +660,17 @@ namespace BlackCore
|
||||
void CNetworkVatlib::onKicked(Cvatlib_Network *, const char *reason, void *cbvar)
|
||||
{
|
||||
emit cbvar_cast(cbvar)->kicked(cbvar_cast(cbvar)->fromFSD(reason));
|
||||
emit cbvar_cast(cbvar)->terminate();
|
||||
}
|
||||
|
||||
void CNetworkVatlib::onPong(Cvatlib_Network *, const char *callsign, INT elapsedTime, void *cbvar)
|
||||
{
|
||||
emit cbvar_cast(cbvar)->pong(cbvar_cast(cbvar)->fromFSD(callsign), CTime(elapsedTime, CTimeUnit::s()));
|
||||
emit cbvar_cast(cbvar)->pongReceived(cbvar_cast(cbvar)->fromFSD(callsign), CTime(elapsedTime, CTimeUnit::s()));
|
||||
}
|
||||
|
||||
void CNetworkVatlib::onMetarReceived(Cvatlib_Network *, const char *data, void *cbvar)
|
||||
{
|
||||
emit cbvar_cast(cbvar)->metarReceived(cbvar_cast(cbvar)->fromFSD(data));
|
||||
emit cbvar_cast(cbvar)->metarReplyReceived(cbvar_cast(cbvar)->fromFSD(data));
|
||||
}
|
||||
|
||||
void CNetworkVatlib::onInfoQueryRequestReceived(Cvatlib_Network *, const char *callsignString, Cvatlib_Network::infoQuery type, const char *, void *cbvar)
|
||||
@@ -630,11 +695,11 @@ namespace BlackCore
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case Cvatlib_Network::infoQuery_Freq: emit cbvar_cast(cbvar)->frequencyQueryReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), CFrequency(cbvar_cast(cbvar)->fromFSD(data).toFloat(), CFrequencyUnit::MHz())); break;
|
||||
case Cvatlib_Network::infoQuery_Server: emit cbvar_cast(cbvar)->serverQueryReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), cbvar_cast(cbvar)->fromFSD(data)); break;
|
||||
case Cvatlib_Network::infoQuery_ATC: emit cbvar_cast(cbvar)->atcQueryReplyReceived(cbvar_cast(cbvar)->fromFSD(data2), *data == 'Y'); break;
|
||||
case Cvatlib_Network::infoQuery_Name: emit cbvar_cast(cbvar)->nameQueryReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), cbvar_cast(cbvar)->fromFSD(data)); break;
|
||||
case Cvatlib_Network::infoQuery_IP: emit cbvar_cast(cbvar)->ipQueryReplyReceived(cbvar_cast(cbvar)->fromFSD(data)); break;
|
||||
case Cvatlib_Network::infoQuery_Freq: emit cbvar_cast(cbvar)->frequencyReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), CFrequency(cbvar_cast(cbvar)->fromFSD(data).toFloat(), CFrequencyUnit::MHz())); break;
|
||||
case Cvatlib_Network::infoQuery_Server: emit cbvar_cast(cbvar)->serverReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), cbvar_cast(cbvar)->fromFSD(data)); break;
|
||||
case Cvatlib_Network::infoQuery_ATC: emit cbvar_cast(cbvar)->atcReplyReceived(cbvar_cast(cbvar)->fromFSD(data2), *data == 'Y'); break;
|
||||
case Cvatlib_Network::infoQuery_Name: emit cbvar_cast(cbvar)->realNameReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), cbvar_cast(cbvar)->fromFSD(data)); break;
|
||||
case Cvatlib_Network::infoQuery_IP: emit cbvar_cast(cbvar)->ipReplyReceived(cbvar_cast(cbvar)->fromFSD(data)); break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -653,7 +718,7 @@ namespace BlackCore
|
||||
}
|
||||
keysValues += 2;
|
||||
}
|
||||
emit cbvar_cast(cbvar)->capabilitiesQueryReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), flags);
|
||||
emit cbvar_cast(cbvar)->capabilitiesReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), flags);
|
||||
}
|
||||
|
||||
void CNetworkVatlib::onAtisReplyReceived(Cvatlib_Network *, const char *callsign, Cvatlib_Network::atisLineType lineType, const char *data, void *cbvar)
|
||||
@@ -662,17 +727,17 @@ namespace BlackCore
|
||||
|
||||
if (lineType == Cvatlib_Network::atisLineType_VoiceRoom)
|
||||
{
|
||||
emit cbvar_cast(cbvar)->atisQueryVoiceRoomReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), cbvar_cast(cbvar)->fromFSD(data));
|
||||
emit cbvar_cast(cbvar)->atisVoiceRoomReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), cbvar_cast(cbvar)->fromFSD(data));
|
||||
}
|
||||
if (lineType == Cvatlib_Network::atisLineType_ZuluLogoff)
|
||||
{
|
||||
emit cbvar_cast(cbvar)->atisQueryLogoffTimeReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), cbvar_cast(cbvar)->fromFSD(data));
|
||||
emit cbvar_cast(cbvar)->atisLogoffTimeReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), cbvar_cast(cbvar)->fromFSD(data));
|
||||
}
|
||||
|
||||
if (lineType == Cvatlib_Network::atisLineType_LineCount)
|
||||
{
|
||||
atis.setType(CInformationMessage::ATIS);
|
||||
emit cbvar_cast(cbvar)->atisQueryReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), atis);
|
||||
emit cbvar_cast(cbvar)->atisReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), atis);
|
||||
cbvar_cast(cbvar)->m_atisParts.remove(cbvar_cast(cbvar)->fromFSD(callsign));
|
||||
}
|
||||
else
|
||||
@@ -734,7 +799,7 @@ namespace BlackCore
|
||||
|
||||
terminate:
|
||||
emit cbvar_cast(cbvar)->statusMessage(BlackMisc::CStatusMessage(BlackMisc::CStatusMessage::TypeTrafficNetwork, BlackMisc::CStatusMessage::SeverityError, msg));
|
||||
emit cbvar_cast(cbvar)->terminate();
|
||||
emit cbvar_cast(cbvar)->terminate(); // private, will be handled during the next pass of the Qt event loop
|
||||
}
|
||||
|
||||
void CNetworkVatlib::onWindDataReceived(Cvatlib_Network *, Cvatlib_Network::WindLayer /** layers **/[4], void * /** cbvar **/)
|
||||
@@ -769,7 +834,7 @@ namespace BlackCore
|
||||
else if (key == net->acinfo_Livery) { icao.setLivery(*keysValues); }
|
||||
keysValues++;
|
||||
}
|
||||
emit cbvar_cast(cbvar)->aircraftInfoReceived(cbvar_cast(cbvar)->fromFSD(callsign), icao);
|
||||
emit cbvar_cast(cbvar)->icaoCodesReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), icao);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -27,40 +27,36 @@ namespace BlackCore
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum LoginMode
|
||||
{
|
||||
LoginNormal = 0,
|
||||
LoginAsObserver,
|
||||
LoginStealth
|
||||
};
|
||||
|
||||
CNetworkVatlib(LoginMode loginMode = LoginNormal, QObject *parent = nullptr);
|
||||
CNetworkVatlib(QObject *parent = nullptr);
|
||||
virtual ~CNetworkVatlib();
|
||||
|
||||
bool isConnected() const;
|
||||
bool isConnected() const { return m_status == Cvatlib_Network::connStatus_Connected; }
|
||||
|
||||
public: // INetwork slots overrides
|
||||
|
||||
// Network
|
||||
virtual void setServer(const BlackMisc::Network::CServer &server);
|
||||
virtual void setCallsign(const BlackMisc::Aviation::CCallsign &callsign);
|
||||
virtual void setRealName(const QString &name);
|
||||
virtual void presetServer(const BlackMisc::Network::CServer &server);
|
||||
virtual void presetCallsign(const BlackMisc::Aviation::CCallsign &callsign);
|
||||
virtual void presetIcaoCodes(const BlackMisc::Aviation::CAircraftIcao &icao);
|
||||
virtual void presetLoginMode(LoginMode mode);
|
||||
virtual void initiateConnection();
|
||||
virtual void terminateConnection();
|
||||
virtual void sendPing(const BlackMisc::Aviation::CCallsign &callsign);
|
||||
|
||||
virtual void sendRealNameQuery(const BlackMisc::Aviation::CCallsign &callsign);
|
||||
virtual void sendIpQuery();
|
||||
virtual void sendServerQuery(const BlackMisc::Aviation::CCallsign &callsign);
|
||||
virtual void sendNameQuery(const BlackMisc::Aviation::CCallsign &callsign);
|
||||
virtual void sendCapabilitiesQuery(const BlackMisc::Aviation::CCallsign &callsign);
|
||||
virtual void ping(const BlackMisc::Aviation::CCallsign &callsign);
|
||||
|
||||
// Weather
|
||||
virtual void requestWeatherData(const QString &airportICAO);
|
||||
|
||||
// Text messages
|
||||
virtual void sendTextMessages(const BlackMisc::Network::CTextMessageList &messages);
|
||||
|
||||
// ATC
|
||||
virtual void sendAtcQuery(const BlackMisc::Aviation::CCallsign &callsign);
|
||||
virtual void sendAtisQuery(const BlackMisc::Aviation::CCallsign &callsign);
|
||||
|
||||
// Aircraft
|
||||
virtual void requestAircraftInfo(const BlackMisc::Aviation::CCallsign &callsign);
|
||||
virtual void sendCapabilitiesQuery(const BlackMisc::Aviation::CCallsign &callsign);
|
||||
virtual void sendIcaoCodesQuery(const BlackMisc::Aviation::CCallsign &callsign);
|
||||
virtual void sendFrequencyQuery(const BlackMisc::Aviation::CCallsign &callsign);
|
||||
virtual void setOwnAircraft(const BlackMisc::Aviation::CAircraft &aircraft);
|
||||
virtual void setOwnAircraftPosition(const BlackMisc::Geo::CCoordinateGeodetic &position, const BlackMisc::Aviation::CAltitude &altitude);
|
||||
@@ -68,10 +64,9 @@ namespace BlackCore
|
||||
virtual void setOwnAircraftAvionics(const BlackMisc::Aviation::CComSystem &com1, const BlackMisc::Aviation::CComSystem &com2,
|
||||
const BlackMisc::Aviation::CTransponder &xpdr);
|
||||
|
||||
// ATC
|
||||
virtual void sendAtcQuery(const BlackMisc::Aviation::CCallsign &callsign);
|
||||
virtual void sendAtisQuery(const BlackMisc::Aviation::CCallsign &callsign);
|
||||
virtual void requestMetar(const QString &airportICAO);
|
||||
// Weather
|
||||
virtual void sendMetarQuery(const QString &airportICAO);
|
||||
virtual void sendWeatherDataQuery(const QString &airportICAO);
|
||||
|
||||
private slots:
|
||||
void replyToFrequencyQuery(const BlackMisc::Aviation::CCallsign &callsign);
|
||||
@@ -105,6 +100,8 @@ namespace BlackCore
|
||||
QByteArray toFSD(QString qstr) const;
|
||||
QByteArray toFSD(const BlackMisc::Aviation::CCallsign &callsign) const;
|
||||
QString fromFSD(const char *cstr) const;
|
||||
void initializeSession();
|
||||
void changeConnectionStatus(Cvatlib_Network::connStatus newStatus);
|
||||
bool isDisconnected() const { return m_status != Cvatlib_Network::connStatus_Connecting && m_status != Cvatlib_Network::connStatus_Connected; }
|
||||
|
||||
private slots:
|
||||
@@ -127,7 +124,9 @@ namespace BlackCore
|
||||
LoginMode m_loginMode;
|
||||
Cvatlib_Network::connStatus m_status;
|
||||
BlackMisc::Network::CServer m_server;
|
||||
BlackMisc::Aviation::CAircraft m_ownAircraft;
|
||||
BlackMisc::Aviation::CCallsign m_callsign;
|
||||
BlackMisc::Aviation::CAircraftIcao m_icaoCodes;
|
||||
BlackMisc::Aviation::CAircraft m_ownAircraft; // not using callsign, user, or icao parts of this member because they can't be changed when connected
|
||||
QMap<BlackMisc::Aviation::CCallsign, BlackMisc::Aviation::CInformationMessage> m_atisParts;
|
||||
|
||||
QTimer m_processingTimer;
|
||||
|
||||
@@ -52,27 +52,21 @@ namespace BlackMisc
|
||||
|
||||
/*!
|
||||
* \brief Copy constructor.
|
||||
* \param other
|
||||
*/
|
||||
CCollection(const CCollection &other) : m_pimpl(other.pimpl() ? other.pimpl()->clone() : nullptr) {}
|
||||
|
||||
/*!
|
||||
* \brief Move constructor.
|
||||
* \param other
|
||||
*/
|
||||
CCollection(CCollection &&other) : m_pimpl(other.m_pimpl.take()) {}
|
||||
|
||||
/*!
|
||||
* \brief Copy assignment.
|
||||
* \param other
|
||||
* \return
|
||||
*/
|
||||
CCollection &operator =(const CCollection &other) { m_pimpl.reset(other.pimpl() ? other.pimpl()->clone() : nullptr); return *this; }
|
||||
|
||||
/*!
|
||||
* \brief Move assignment.
|
||||
* \param other
|
||||
* \return
|
||||
*/
|
||||
CCollection &operator =(CCollection && other) { m_pimpl.reset(other.m_pimpl.take()); return *this; }
|
||||
|
||||
@@ -80,7 +74,6 @@ namespace BlackMisc
|
||||
* \brief Create a new collection with a specific implementation type.
|
||||
* \tparam C Becomes the collection's implementation type.
|
||||
* \param c Initial value for the collection; default is empty, but it could contain elements if desired. The value is copied.
|
||||
* \return
|
||||
*/
|
||||
template <class C> static CCollection fromImpl(C c = C()) { return CCollection(new Pimpl<C>(std::move(c))); }
|
||||
|
||||
@@ -92,68 +85,57 @@ namespace BlackMisc
|
||||
|
||||
/*!
|
||||
* \brief Like changeImpl, but uses the implementation type of another collection.
|
||||
* \param other
|
||||
* \pre The other collection must be initialized.
|
||||
*/
|
||||
void useImplOf(const CCollection &other) { PimplPtr p = other.pimpl()->cloneEmpty(); for (auto i = cbegin(); i != cend(); ++i) p->insert(*i); m_pimpl.reset(p.take()); }
|
||||
|
||||
/*!
|
||||
* \brief Returns iterator at the beginning of the collection.
|
||||
* \return
|
||||
*/
|
||||
iterator begin() { return pimpl() ? pimpl()->begin() : iterator(); }
|
||||
|
||||
/*!
|
||||
* \brief Returns iterator at the beginning of the collection.
|
||||
* \return
|
||||
*/
|
||||
const_iterator begin() const { return pimpl() ? pimpl()->begin() : const_iterator(); }
|
||||
|
||||
/*!
|
||||
* \brief Returns iterator at the beginning of the collection.
|
||||
* \return
|
||||
*/
|
||||
const_iterator cbegin() const { return pimpl() ? pimpl()->cbegin() : const_iterator(); }
|
||||
|
||||
/*!
|
||||
* \brief Returns iterator one past the end of the collection.
|
||||
* \return
|
||||
*/
|
||||
iterator end() { return pimpl() ? pimpl()->end() : iterator(); }
|
||||
|
||||
/*!
|
||||
* \brief Returns iterator one past the end of the collection.
|
||||
* \return
|
||||
*/
|
||||
const_iterator end() const { return pimpl() ? pimpl()->end() : const_iterator(); }
|
||||
|
||||
/*!
|
||||
* \brief Returns iterator one past the end of the collection.
|
||||
* \return
|
||||
*/
|
||||
const_iterator cend() const { return pimpl() ? pimpl()->cend() : const_iterator(); }
|
||||
|
||||
/*!
|
||||
* \brief Swap this collection with another.
|
||||
* \param other
|
||||
*/
|
||||
void swap(CCollection &other) { m_pimpl.swap(other.m_pimpl); }
|
||||
|
||||
/*!
|
||||
* \brief Returns number of elements in the collection.
|
||||
* \return
|
||||
*/
|
||||
size_type size() const { return pimpl() ? pimpl()->size() : 0; }
|
||||
|
||||
/*!
|
||||
* \brief Returns true if the collection is empty.
|
||||
* \return
|
||||
*/
|
||||
bool empty() const { return pimpl() ? pimpl()->empty() : true; }
|
||||
|
||||
/*!
|
||||
* \brief Synonym for empty.
|
||||
* \return
|
||||
*/
|
||||
bool isEmpty() const { return empty(); }
|
||||
|
||||
@@ -164,7 +146,6 @@ namespace BlackMisc
|
||||
|
||||
/*!
|
||||
* \brief Inserts an element into the collection.
|
||||
* \param value
|
||||
* \return An iterator to the position where value was inserted.
|
||||
* \pre The collection must be initialized.
|
||||
*/
|
||||
@@ -172,7 +153,6 @@ namespace BlackMisc
|
||||
|
||||
/*!
|
||||
* \brief Synonym for insert.
|
||||
* \param value
|
||||
* \return An iterator to the position where value was inserted.
|
||||
* \pre The collection must be initialized.
|
||||
*/
|
||||
@@ -180,7 +160,6 @@ namespace BlackMisc
|
||||
|
||||
/*!
|
||||
* \brief Remove the element pointed to by the given iterator.
|
||||
* \param pos
|
||||
* \return An iterator to the position of the next element after the one removed.
|
||||
* \pre The collection must be initialized.
|
||||
*/
|
||||
@@ -188,8 +167,6 @@ namespace BlackMisc
|
||||
|
||||
/*!
|
||||
* \brief Remove the range of elements between two iterators.
|
||||
* \param it1
|
||||
* \param it2
|
||||
* \return An iterator to the position of the next element after the one removed.
|
||||
* \pre The sequence must be initialized.
|
||||
*/
|
||||
@@ -197,16 +174,12 @@ namespace BlackMisc
|
||||
|
||||
/*!
|
||||
* \brief Test for equality.
|
||||
* \param other
|
||||
* \return
|
||||
* \todo Improve inefficient implementation.
|
||||
*/
|
||||
bool operator ==(const CCollection &other) const { return (empty() && other.empty()) ? true : (size() != other.size() ? false : *pimpl() == *other.pimpl()); }
|
||||
|
||||
/*!
|
||||
* \brief Test for inequality.
|
||||
* \param other
|
||||
* \return
|
||||
* \todo Improve inefficient implementation.
|
||||
*/
|
||||
bool operator !=(const CCollection &other) const { return !(*this == other); }
|
||||
|
||||
@@ -29,14 +29,12 @@ namespace BlackMisc
|
||||
public:
|
||||
/*!
|
||||
* \brief Return a copy containing only those elements for which a given predicate returns true.
|
||||
* \param p
|
||||
* \return
|
||||
*/
|
||||
template <class Predicate>
|
||||
C<T> findBy(Predicate p) const
|
||||
{
|
||||
C<T> result = derived();
|
||||
result.erase(std::remove_if(result.begin(), result.end(), [ = ](const T & value) { return !p(value); }), result.end());
|
||||
result.erase(std::remove_if(result.begin(), result.end(), [ = ](const T &value) { return !p(value); }), result.end());
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -44,7 +42,6 @@ namespace BlackMisc
|
||||
* \brief Return a copy containing only those elements matching a particular key/value pair.
|
||||
* \param key1 A pointer to a member function of T.
|
||||
* \param value1 Will be compared to the return value of key1.
|
||||
* \return
|
||||
*/
|
||||
template <class K1, class V1>
|
||||
C<T> findBy(K1 key1, V1 value1) const
|
||||
@@ -58,7 +55,6 @@ namespace BlackMisc
|
||||
* \param value1 Will be compared to the return value of key1.
|
||||
* \param key2 A pointer to a member function of T.
|
||||
* \param value2 Will be compared to the return value of key2.
|
||||
* \return
|
||||
*/
|
||||
template <class K1, class V1, class K2, class V2>
|
||||
C<T> findBy(K1 key1, V1 value1, K2 key2, V2 value2) const
|
||||
@@ -74,7 +70,6 @@ namespace BlackMisc
|
||||
* \param value2 Will be compared to the return value of key2.
|
||||
* \param key3 A pointer to a member function of T.
|
||||
* \param value3 Will be compared to the return value of key3.
|
||||
* \return
|
||||
*/
|
||||
template <class K1, class V1, class K2, class V2, class K3, class V3>
|
||||
C<T> findBy(K1 key1, V1 value1, K2 key2, V2 value2, K3 key3, V3 value3) const
|
||||
@@ -84,12 +79,19 @@ namespace BlackMisc
|
||||
|
||||
/*!
|
||||
* \brief Return a copy containing only those elements matching a given value map.
|
||||
* \param valueMap
|
||||
* \return
|
||||
*/
|
||||
C<T> findBy(const CValueMap &valueMap) const
|
||||
{
|
||||
return findBy([ & ](const T & value) { return value == valueMap; });
|
||||
return findBy([ & ](const T &value) { return value == valueMap; });
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Return true if there is an element for which a given predicate returns true
|
||||
*/
|
||||
template <class Predicate>
|
||||
bool contains(Predicate p) const
|
||||
{
|
||||
return std::any_of(derived().begin(), derived().end(), p);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -99,25 +101,13 @@ namespace BlackMisc
|
||||
*/
|
||||
bool contains(const T &object) const
|
||||
{
|
||||
return std::binary_search(derived().begin(), derived().end(), object);
|
||||
return std::find(derived().begin(), derived().end(), object) != derived().end();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Return true if there is an element for which a given predicate returns true
|
||||
* \param p
|
||||
* \return
|
||||
*/
|
||||
template <class Predicate>
|
||||
bool contains(Predicate p) const
|
||||
{
|
||||
return std::any_of(derived().begin(), derived().end(), p);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Return true if there is an element matching a particular key/value pair.
|
||||
* \brief Return a copy containing only those elements matching a particular key/value pair.
|
||||
* \param key1 A pointer to a member function of T.
|
||||
* \param value1 Will be compared to the return value of key1.
|
||||
* \return
|
||||
*/
|
||||
template <class K1, class V1>
|
||||
bool contains(K1 key1, V1 value1) const
|
||||
@@ -125,36 +115,6 @@ namespace BlackMisc
|
||||
return contains(BlackMisc::Predicates::MemberEqual<T>(key1, value1));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Remove given object
|
||||
* \param object remove this object from in container
|
||||
*/
|
||||
void remove(const T &object)
|
||||
{
|
||||
std::remove(derived().begin(), derived().end(), object);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Remove elements for which a given predicate returns true.
|
||||
* \param p
|
||||
*/
|
||||
template <class Predicate>
|
||||
void removeIf(Predicate p)
|
||||
{
|
||||
std::remove_if(derived().begin(), derived().end(), p);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Remove elements matching a particular key/value pair.
|
||||
* \param key1 A pointer to a member function of T.
|
||||
* \param value1 Will be compared to the return value of key1.
|
||||
*/
|
||||
template <class K1, class V1>
|
||||
void removeIf(K1 key1, V1 value1)
|
||||
{
|
||||
removeIf(BlackMisc::Predicates::MemberEqual<T>(key1, value1));
|
||||
}
|
||||
|
||||
public: // CValueObject overrides
|
||||
/*!
|
||||
* \copydoc CValueObject::toQVariant()
|
||||
@@ -174,7 +134,7 @@ namespace BlackMisc
|
||||
{
|
||||
QString str;
|
||||
// qualifying stringify with this-> to workaround bug in GCC 4.7.2 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56402
|
||||
std::for_each(derived().begin(), derived().end(), [ & ](const T & value) { str += (str.isEmpty() ? "{" : ",") + this->stringify(value, i18n); });
|
||||
std::for_each(derived().begin(), derived().end(), [ & ](const T &value) { str += (str.isEmpty() ? "{" : ",") + this->stringify(value, i18n); });
|
||||
if (str.isEmpty()) { str = "{"; }
|
||||
return str += "}";
|
||||
}
|
||||
@@ -212,7 +172,7 @@ namespace BlackMisc
|
||||
virtual void marshallToDbus(QDBusArgument &argument) const
|
||||
{
|
||||
argument.beginArray(qMetaTypeId<T>());
|
||||
std::for_each(derived().begin(), derived().end(), [ & ](const T & value) { argument << value; });
|
||||
std::for_each(derived().begin(), derived().end(), [ & ](const T &value) { argument << value; });
|
||||
argument.endArray();
|
||||
}
|
||||
|
||||
|
||||
@@ -46,27 +46,21 @@ namespace BlackMisc
|
||||
|
||||
/*!
|
||||
* \brief Copy constructor.
|
||||
* \param other
|
||||
*/
|
||||
ConstForwardIterator(const ConstForwardIterator &other) : m_pimpl(other.pimpl() ? other.pimpl()->clone() : nullptr) {}
|
||||
|
||||
/*!
|
||||
* \brief Move constructor.
|
||||
* \param other
|
||||
*/
|
||||
ConstForwardIterator(ConstForwardIterator &&other) : m_pimpl(other.m_pimpl.take()) {}
|
||||
|
||||
/*!
|
||||
* \brief Copy assignment.
|
||||
* \param other
|
||||
* \return
|
||||
*/
|
||||
ConstForwardIterator &operator =(const ConstForwardIterator &other) { m_pimpl.reset(other.pimpl() ? other.pimpl()->clone() : nullptr); return *this; }
|
||||
|
||||
/*!
|
||||
* \brief Move assignment.
|
||||
* \param other
|
||||
* \return
|
||||
*/
|
||||
ConstForwardIterator &operator =(ConstForwardIterator &&other) { m_pimpl.reset(other.m_pimpl.take()); return *this; }
|
||||
|
||||
@@ -74,20 +68,17 @@ namespace BlackMisc
|
||||
* \brief Create a new iterator with a specific implementation type.
|
||||
* \tparam C Becomes the iterator's implementation type.
|
||||
* \param c Initial value for the iterator. The value is copied.
|
||||
* \return
|
||||
*/
|
||||
template <class I> static ConstForwardIterator fromImpl(I i) { return ConstForwardIterator(new Pimpl<I>(std::move(i))); }
|
||||
|
||||
/*!
|
||||
* \brief Returns a reference to the object pointed to.
|
||||
* \return
|
||||
* \pre The iterator must be initialized and valid.
|
||||
*/
|
||||
const_reference operator *() const { Q_ASSERT(m_pimpl); return **pimpl(); }
|
||||
|
||||
/*!
|
||||
* \brief Arrow operator provides access to members of the object pointed to.
|
||||
* \return
|
||||
* \pre The iterator must be initialized and valid.
|
||||
*/
|
||||
const_pointer operator ->() const { Q_ASSERT(m_pimpl); return &**pimpl(); }
|
||||
@@ -108,7 +99,6 @@ namespace BlackMisc
|
||||
|
||||
/*!
|
||||
* \brief Advance the iterator by a certain amount.
|
||||
* \param n
|
||||
* \return Reference to the iterator at the new position.
|
||||
* \pre The iterator must be initialized and valid.
|
||||
*/
|
||||
@@ -116,7 +106,6 @@ namespace BlackMisc
|
||||
|
||||
/*!
|
||||
* \brief Advance the iterator by a certain amount.
|
||||
* \param n
|
||||
* \return Copy of the iterator in its new position.
|
||||
* \pre The iterator must be initialized and valid.
|
||||
*/
|
||||
@@ -124,23 +113,18 @@ namespace BlackMisc
|
||||
|
||||
/*!
|
||||
* \brief Test for equality.
|
||||
* \param other
|
||||
* \return
|
||||
* \pre Both iterators must originate from the same collection, and not mix begin/end with cbegin/cend.
|
||||
*/
|
||||
bool operator ==(const ConstForwardIterator &other) const { return (pimpl() && other.pimpl()) ? *pimpl() == *other.pimpl() : pimpl() == other.pimpl(); }
|
||||
|
||||
/*!
|
||||
* \brief Test for inequality.
|
||||
* \param other
|
||||
* \return
|
||||
* \pre Both iterators must originate from the same collection, and not mix begin/end with cbegin/cend.
|
||||
*/
|
||||
bool operator !=(const ConstForwardIterator &other) const { return !(*this == other); }
|
||||
|
||||
/*!
|
||||
* \brief Return opaque pointer to underlying implementation iterator object.
|
||||
* \return
|
||||
* \pre The iterator must have been initialized.
|
||||
* \todo Returning by void* is rotten, but GCC gives a very cryptic error if I make it a function template with a cast inside.
|
||||
*/
|
||||
@@ -210,27 +194,21 @@ namespace BlackMisc
|
||||
|
||||
/*!
|
||||
* \brief Copy constructor.
|
||||
* \param other
|
||||
*/
|
||||
ConstBidirectionalIterator(const ConstBidirectionalIterator &other) : m_pimpl(other.pimpl() ? other.pimpl()->clone() : nullptr) {}
|
||||
|
||||
/*!
|
||||
* \brief Move constructor.
|
||||
* \param other
|
||||
*/
|
||||
ConstBidirectionalIterator(ConstBidirectionalIterator &&other) : m_pimpl(other.m_pimpl.take()) {}
|
||||
|
||||
/*!
|
||||
* \brief Copy assignment.
|
||||
* \param other
|
||||
* \return
|
||||
*/
|
||||
ConstBidirectionalIterator &operator =(const ConstBidirectionalIterator &other) { m_pimpl.reset(other.pimpl() ? other.pimpl()->clone() : nullptr); return *this; }
|
||||
|
||||
/*!
|
||||
* \brief Move assignment.
|
||||
* \param other
|
||||
* \return
|
||||
*/
|
||||
ConstBidirectionalIterator &operator =(ConstBidirectionalIterator &&other) { m_pimpl.reset(other.m_pimpl.take()); return *this; }
|
||||
|
||||
@@ -238,20 +216,17 @@ namespace BlackMisc
|
||||
* \brief Create a new iterator with a specific implementation type.
|
||||
* \tparam C Becomes the iterator's implementation type.
|
||||
* \param c Initial value for the iterator. The value is copied.
|
||||
* \return
|
||||
*/
|
||||
template <class I> static ConstBidirectionalIterator fromImpl(I i) { return ConstBidirectionalIterator(new Pimpl<I>(std::move(i))); }
|
||||
|
||||
/*!
|
||||
* \brief Returns a reference to the object pointed to.
|
||||
* \return
|
||||
* \pre The iterator must be initialized and valid.
|
||||
*/
|
||||
const_reference operator *() const { Q_ASSERT(m_pimpl); return **pimpl(); }
|
||||
|
||||
/*!
|
||||
* \brief Arrow operator provides access to members of the object pointed to.
|
||||
* \return
|
||||
* \pre The iterator must be initialized and valid.
|
||||
*/
|
||||
const_pointer operator ->() const { Q_ASSERT(m_pimpl); return &**pimpl(); }
|
||||
@@ -286,7 +261,6 @@ namespace BlackMisc
|
||||
|
||||
/*!
|
||||
* \brief Advance the iterator by a certain amount.
|
||||
* \param n
|
||||
* \return Reference to the iterator at the new position.
|
||||
* \pre The iterator must be initialized and valid.
|
||||
*/
|
||||
@@ -294,7 +268,6 @@ namespace BlackMisc
|
||||
|
||||
/*!
|
||||
* \brief Advance the iterator by a certain amount.
|
||||
* \param n
|
||||
* \return Copy of the iterator in its new position.
|
||||
* \pre The iterator must be initialized and valid.
|
||||
*/
|
||||
@@ -302,7 +275,6 @@ namespace BlackMisc
|
||||
|
||||
/*!
|
||||
* \brief Backtrack the iterator by a certain amount.
|
||||
* \param n
|
||||
* \return Reference to the iterator at the new position.
|
||||
* \pre The iterator must be initialized and valid.
|
||||
*/
|
||||
@@ -310,7 +282,6 @@ namespace BlackMisc
|
||||
|
||||
/*!
|
||||
* \brief Backtrack the iterator by a certain amount.
|
||||
* \param n
|
||||
* \return Copy of the iterator in its new position.
|
||||
* \pre The iterator must be initialized and valid.
|
||||
*/
|
||||
@@ -318,39 +289,30 @@ namespace BlackMisc
|
||||
|
||||
/*!
|
||||
* \brief Return the distance between two iterators.
|
||||
* \param other
|
||||
* \return
|
||||
* \pre Both iterators must originate from the same collection, and not mix begin/end with cbegin/cend.
|
||||
*/
|
||||
difference_type operator -(const ConstBidirectionalIterator &other) const { Q_ASSERT(m_pimpl && other.m_pimpl); return *pimpl() - *other.pimpl(); }
|
||||
|
||||
/*!
|
||||
* \brief Test for equality.
|
||||
* \param other
|
||||
* \return
|
||||
* \pre Both iterators must originate from the same collection, and not mix begin/end with cbegin/cend.
|
||||
*/
|
||||
bool operator ==(const ConstBidirectionalIterator &other) const { return (pimpl() && other.pimpl()) ? *pimpl() == *other.pimpl() : pimpl() == other.pimpl(); }
|
||||
|
||||
/*!
|
||||
* \brief Test for inequality.
|
||||
* \param other
|
||||
* \return
|
||||
* \pre Both iterators must originate from the same collection, and not mix begin/end with cbegin/cend.
|
||||
*/
|
||||
bool operator !=(const ConstBidirectionalIterator &other) const { return !(*this == other); }
|
||||
|
||||
/*!
|
||||
* \brief For sorting.
|
||||
* \param other
|
||||
* \return
|
||||
* \pre Both iterators must originate from the same collection, and not mix begin/end with cbegin/cend.
|
||||
*/
|
||||
bool operator <(const ConstBidirectionalIterator &other) const { Q_ASSERT(m_pimpl && other.m_pimpl); return *pimpl() < *other.pimpl(); }
|
||||
|
||||
/*!
|
||||
* \brief Return opaque pointer to underlying implementation iterator object.
|
||||
* \return
|
||||
* \pre The iterator must have been initialized.
|
||||
* \todo Returning by void* is rotten, but GCC gives a very cryptic error if I make it a function template with a cast inside.
|
||||
*/
|
||||
@@ -428,27 +390,21 @@ namespace BlackMisc
|
||||
|
||||
/*!
|
||||
* \brief Copy constructor.
|
||||
* \param other
|
||||
*/
|
||||
BidirectionalIterator(const BidirectionalIterator &other) : m_pimpl(other.pimpl() ? other.pimpl()->clone() : nullptr) {}
|
||||
|
||||
/*!
|
||||
* \brief Move constructor.
|
||||
* \param other
|
||||
*/
|
||||
BidirectionalIterator(BidirectionalIterator &&other) : m_pimpl(other.m_pimpl.take()) {}
|
||||
|
||||
/*!
|
||||
* \brief Copy assignment.
|
||||
* \param other
|
||||
* \return
|
||||
*/
|
||||
BidirectionalIterator &operator =(const BidirectionalIterator &other) { m_pimpl.reset(other.pimpl() ? other.pimpl()->clone() : nullptr); return *this; }
|
||||
|
||||
/*!
|
||||
* \brief Move assignment.
|
||||
* \param other
|
||||
* \return
|
||||
*/
|
||||
BidirectionalIterator &operator =(BidirectionalIterator &&other) { m_pimpl.reset(other.m_pimpl.take()); return *this; }
|
||||
|
||||
@@ -456,34 +412,29 @@ namespace BlackMisc
|
||||
* \brief Create a new iterator with a specific implementation type.
|
||||
* \tparam C Becomes the iterator's implementation type.
|
||||
* \param c Initial value for the iterator. The value is copied.
|
||||
* \return
|
||||
*/
|
||||
template <class I> static BidirectionalIterator fromImpl(I i) { return BidirectionalIterator(new Pimpl<I>(std::move(i))); }
|
||||
|
||||
/*!
|
||||
* \brief Returns a reference to the object pointed to.
|
||||
* \return
|
||||
* \pre The iterator must be initialized and valid.
|
||||
*/
|
||||
const_reference operator *() const { Q_ASSERT(m_pimpl); return **pimpl(); }
|
||||
|
||||
/*!
|
||||
* \brief Returns a reference to the object pointed to.
|
||||
* \return
|
||||
* \pre The iterator must be initialized and valid.
|
||||
*/
|
||||
reference operator *() { Q_ASSERT(m_pimpl); return **pimpl(); }
|
||||
|
||||
/*!
|
||||
* \brief Arrow operator provides access to members of the object pointed to.
|
||||
* \return
|
||||
* \pre The iterator must be initialized and valid.
|
||||
*/
|
||||
const_pointer operator ->() const { Q_ASSERT(m_pimpl); return &**pimpl(); }
|
||||
|
||||
/*!
|
||||
* \brief Arrow operator provides access to members of the object pointed to.
|
||||
* \return
|
||||
* \pre The iterator must be initialized and valid.
|
||||
*/
|
||||
pointer operator ->() { Q_ASSERT(m_pimpl); return &**pimpl(); }
|
||||
@@ -518,7 +469,6 @@ namespace BlackMisc
|
||||
|
||||
/*!
|
||||
* \brief Advance the iterator by a certain amount.
|
||||
* \param n
|
||||
* \return Reference to the iterator at the new position.
|
||||
* \pre The iterator must be initialized and valid.
|
||||
*/
|
||||
@@ -526,7 +476,6 @@ namespace BlackMisc
|
||||
|
||||
/*!
|
||||
* \brief Advance the iterator by a certain amount.
|
||||
* \param n
|
||||
* \return Copy of the iterator in its new position.
|
||||
* \pre The iterator must be initialized and valid.
|
||||
*/
|
||||
@@ -534,7 +483,6 @@ namespace BlackMisc
|
||||
|
||||
/*!
|
||||
* \brief Backtrack the iterator by a certain amount.
|
||||
* \param n
|
||||
* \return Reference to the iterator at the new position.
|
||||
* \pre The iterator must be initialized and valid.
|
||||
*/
|
||||
@@ -542,7 +490,6 @@ namespace BlackMisc
|
||||
|
||||
/*!
|
||||
* \brief Backtrack the iterator by a certain amount.
|
||||
* \param n
|
||||
* \return Copy of the iterator in its new position.
|
||||
* \pre The iterator must be initialized and valid.
|
||||
*/
|
||||
@@ -550,39 +497,30 @@ namespace BlackMisc
|
||||
|
||||
/*!
|
||||
* \brief Return the distance between two iterators.
|
||||
* \param other
|
||||
* \return
|
||||
* \pre Both iterators must originate from the same collection, and not mix begin/end with cbegin/cend.
|
||||
*/
|
||||
difference_type operator -(const BidirectionalIterator &other) const { Q_ASSERT(m_pimpl && other.m_pimpl); return *pimpl() - *other.pimpl(); }
|
||||
|
||||
/*!
|
||||
* \brief Test for equality.
|
||||
* \param other
|
||||
* \return
|
||||
* \pre Both iterators must originate from the same collection, and not mix begin/end with cbegin/cend.
|
||||
*/
|
||||
bool operator ==(const BidirectionalIterator &other) const { return (pimpl() && other.pimpl()) ? *pimpl() == *other.pimpl() : pimpl() == other.pimpl(); }
|
||||
|
||||
/*!
|
||||
* \brief Test for inequality.
|
||||
* \param other
|
||||
* \return
|
||||
* \pre Both iterators must originate from the same collection, and not mix begin/end with cbegin/cend.
|
||||
*/
|
||||
bool operator !=(const BidirectionalIterator &other) const { return !(*this == other); }
|
||||
|
||||
/*!
|
||||
* \brief For sorting.
|
||||
* \param other
|
||||
* \return
|
||||
* \pre Both iterators must originate from the same collection, and not mix begin/end with cbegin/cend.
|
||||
*/
|
||||
bool operator <(const BidirectionalIterator &other) const { Q_ASSERT(m_pimpl && other.m_pimpl); return *pimpl() < *other.pimpl(); }
|
||||
|
||||
/*!
|
||||
* \brief Return opaque pointer to underlying implementation iterator object.
|
||||
* \return
|
||||
* \pre The iterator must have been initialized.
|
||||
* \todo Returning by void* is rotten, but GCC gives a very cryptic error if I make it a function template with a cast inside.
|
||||
*/
|
||||
|
||||
@@ -52,27 +52,21 @@ namespace BlackMisc
|
||||
|
||||
/*!
|
||||
* \brief Copy constructor.
|
||||
* \param other
|
||||
*/
|
||||
CSequence(const CSequence &other) : m_pimpl(other.pimpl() ? other.pimpl()->clone() : nullptr) {}
|
||||
|
||||
/*!
|
||||
* \brief Move constructor.
|
||||
* \param other
|
||||
*/
|
||||
CSequence(CSequence &&other) : m_pimpl(other.m_pimpl.take()) {}
|
||||
|
||||
/*!
|
||||
* \brief Copy assignment.
|
||||
* \param other
|
||||
* \return
|
||||
*/
|
||||
CSequence &operator =(const CSequence &other) { m_pimpl.reset(other.pimpl() ? other.pimpl()->clone() : nullptr); return *this; }
|
||||
|
||||
/*!
|
||||
* \brief Move assignment.
|
||||
* \param other
|
||||
* \return
|
||||
*/
|
||||
CSequence &operator =(CSequence &&other) { m_pimpl.reset(other.m_pimpl.take()); return *this; }
|
||||
|
||||
@@ -80,7 +74,6 @@ namespace BlackMisc
|
||||
* \brief Create a new sequence with a specific implementation type.
|
||||
* \tparam C Becomes the sequence's implementation type.
|
||||
* \param c Initial value for the sequence; default is empty, but it could contain elements if desired. The value is copied.
|
||||
* \return
|
||||
*/
|
||||
template <class C> static CSequence fromImpl(C c = C()) { return CSequence(new Pimpl<C>(std::move(c))); }
|
||||
|
||||
@@ -92,112 +85,93 @@ namespace BlackMisc
|
||||
|
||||
/*!
|
||||
* \brief Like changeImpl, but uses the implementation type of another sequence.
|
||||
* \param other
|
||||
* \pre The other sequence must be initialized.
|
||||
*/
|
||||
void useImplOf(const CSequence &other) { PimplPtr p = other.pimpl()->cloneEmpty(); for (auto i = cbegin(); i != cend(); ++i) p->push_back(*i); m_pimpl.reset(p.take()); }
|
||||
|
||||
/*!
|
||||
* \brief Returns iterator at the beginning of the sequence.
|
||||
* \return
|
||||
*/
|
||||
iterator begin() { return pimpl() ? pimpl()->begin() : iterator(); }
|
||||
|
||||
/*!
|
||||
* \brief Returns iterator at the beginning of the sequence.
|
||||
* \return
|
||||
*/
|
||||
const_iterator begin() const { return pimpl() ? pimpl()->begin() : const_iterator(); }
|
||||
|
||||
/*!
|
||||
* \brief Returns iterator at the beginning of the sequence.
|
||||
* \return
|
||||
*/
|
||||
const_iterator cbegin() const { return pimpl() ? pimpl()->cbegin() : const_iterator(); }
|
||||
|
||||
/*!
|
||||
* \brief Returns iterator one past the end of the sequence.
|
||||
* \return
|
||||
*/
|
||||
iterator end() { return pimpl() ? pimpl()->end() : iterator(); }
|
||||
|
||||
/*!
|
||||
* \brief Returns iterator one past the end of the sequence.
|
||||
* \return
|
||||
*/
|
||||
const_iterator end() const { return pimpl() ? pimpl()->end() : const_iterator(); }
|
||||
|
||||
/*!
|
||||
* \brief Returns iterator one past the end of the sequence.
|
||||
* \return
|
||||
*/
|
||||
const_iterator cend() const { return pimpl() ? pimpl()->cend() : const_iterator(); }
|
||||
|
||||
/*!
|
||||
* \brief Swap this sequence with another.
|
||||
* \param other
|
||||
*/
|
||||
void swap(CSequence &other) { m_pimpl.swap(other.m_pimpl); }
|
||||
|
||||
/*!
|
||||
* \brief Access an element by its index.
|
||||
* \param index
|
||||
* \return
|
||||
* \pre The sequence must be initialized and the index in bounds.
|
||||
*/
|
||||
reference operator [](size_type index) { Q_ASSERT(pimpl()); return pimpl()->operator [](index); }
|
||||
|
||||
/*!
|
||||
* \brief Access an element by its index.
|
||||
* \param index
|
||||
* \return
|
||||
* \pre The sequence must be initialized and the index in bounds.
|
||||
*/
|
||||
const_reference operator [](size_type index) const { Q_ASSERT(pimpl()); return pimpl()->operator [](index); }
|
||||
|
||||
/*!
|
||||
* \brief Access the first element.
|
||||
* \return
|
||||
* \pre The sequence must not be empty.
|
||||
*/
|
||||
reference front() { Q_ASSERT(!empty()); return pimpl()->front(); }
|
||||
|
||||
/*!
|
||||
* \brief Access the first element.
|
||||
* \return
|
||||
* \pre The sequence must not be empty.
|
||||
*/
|
||||
const_reference front() const { Q_ASSERT(!empty()); return pimpl()->front(); }
|
||||
|
||||
/*!
|
||||
* \brief Access the last element.
|
||||
* \return
|
||||
* \pre The sequence must not be empty.
|
||||
*/
|
||||
reference back() { Q_ASSERT(!empty()); return pimpl()->back(); }
|
||||
|
||||
/*!
|
||||
* \brief Access the last element.
|
||||
* \return
|
||||
* \pre The sequence must not be empty.
|
||||
*/
|
||||
const_reference back() const { Q_ASSERT(!empty()); return pimpl()->back(); }
|
||||
|
||||
/*!
|
||||
* \brief Returns number of elements in the sequence.
|
||||
* \return
|
||||
*/
|
||||
size_type size() const { return pimpl() ? pimpl()->size() : 0; }
|
||||
|
||||
/*!
|
||||
* \brief Returns true if the sequence is empty.
|
||||
* \return
|
||||
*/
|
||||
bool empty() const { return pimpl() ? pimpl()->empty() : true; }
|
||||
|
||||
/*!
|
||||
* \brief Synonym for empty.
|
||||
* \return
|
||||
*/
|
||||
bool isEmpty() const { return empty(); }
|
||||
|
||||
@@ -208,8 +182,6 @@ namespace BlackMisc
|
||||
|
||||
/*!
|
||||
* \brief Inserts an element into the sequence.
|
||||
* \param before
|
||||
* \param value
|
||||
* \return An iterator to the position where value was inserted.
|
||||
* \pre The sequence must be initialized.
|
||||
*/
|
||||
@@ -217,14 +189,12 @@ namespace BlackMisc
|
||||
|
||||
/*!
|
||||
* \brief Appends an element at the end of the sequence.
|
||||
* \param value
|
||||
* \pre The sequence must be initialized.
|
||||
*/
|
||||
void push_back(const T &value) { Q_ASSERT(pimpl()); pimpl()->push_back(value); }
|
||||
|
||||
/*!
|
||||
* \brief Synonym for push_back.
|
||||
* \param value
|
||||
* \pre The sequence must be initialized.
|
||||
*/
|
||||
void insert(const T &value) { push_back(value); }
|
||||
@@ -237,7 +207,6 @@ namespace BlackMisc
|
||||
|
||||
/*!
|
||||
* \brief Remove the element pointed to by the given iterator.
|
||||
* \param pos
|
||||
* \return An iterator to the position of the next element after the one removed.
|
||||
* \pre The sequence must be initialized.
|
||||
*/
|
||||
@@ -245,8 +214,6 @@ namespace BlackMisc
|
||||
|
||||
/*!
|
||||
* \brief Remove the range of elements between two iterators.
|
||||
* \param it1
|
||||
* \param it2
|
||||
* \return An iterator to the position of the next element after the one removed.
|
||||
* \pre The sequence must be initialized.
|
||||
*/
|
||||
@@ -254,8 +221,6 @@ namespace BlackMisc
|
||||
|
||||
/*!
|
||||
* \brief Modify by applying a value map to each element for which a given predicate returns true.
|
||||
* \param p
|
||||
* \param newValues
|
||||
*/
|
||||
template <class Predicate>
|
||||
void applyIf(Predicate p, const CValueMap &newValues)
|
||||
@@ -267,7 +232,6 @@ namespace BlackMisc
|
||||
* \brief Modify by applying a value map to each element matching a particular key/value pair.
|
||||
* \param key1 A pointer to a member function of T.
|
||||
* \param value1 Will be compared to the return value of key1.
|
||||
* \param newValues
|
||||
*/
|
||||
template <class K1, class V1>
|
||||
void applyIf(K1 key1, V1 value1, const CValueMap &newValues)
|
||||
@@ -277,18 +241,50 @@ namespace BlackMisc
|
||||
|
||||
/*!
|
||||
* \brief Modify by applying a value map to each element matching a given value map.
|
||||
* \param pattern
|
||||
* \param newValues
|
||||
*/
|
||||
void applyIf(const CValueMap &pattern, const CValueMap &newValues)
|
||||
{
|
||||
applyIf([ & ](const T &value) { return value == pattern; }, newValues);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Remove elements for which a given predicate returns true.
|
||||
*/
|
||||
template <class Predicate>
|
||||
void removeIf(Predicate p)
|
||||
{
|
||||
std::remove_if(begin(), end(), p);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Remove elements matching a particular key/value pair.
|
||||
* \param key1 A pointer to a member function of T.
|
||||
* \param value1 Will be compared to the return value of key1.
|
||||
*/
|
||||
template <class K1, class V1>
|
||||
void removeIf(K1 key1, V1 value1)
|
||||
{
|
||||
removeIf(BlackMisc::Predicates::MemberEqual<T>(key1, value1));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Remove the given object, if it is contained.
|
||||
*/
|
||||
void remove(const T &object)
|
||||
{
|
||||
std::remove(begin(), end(), object);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Replace elements matching the given element with a replacement.
|
||||
*/
|
||||
void replace(const T &original, const T &replacement)
|
||||
{
|
||||
std::replace(begin(), end(), original, replacement);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Replace elements for which a given predicate returns true.
|
||||
* \param p
|
||||
* \param replacement
|
||||
*/
|
||||
template <class Predicate>
|
||||
void replaceIf(Predicate p, const T &replacement)
|
||||
@@ -300,7 +296,6 @@ namespace BlackMisc
|
||||
* \brief Replace elements matching a particular key/value pair.
|
||||
* \param key1 A pointer to a member function of T.
|
||||
* \param value1 Will be compared to the return value of key1.
|
||||
* \param replacement
|
||||
*/
|
||||
template <class K1, class V1>
|
||||
void replaceIf(K1 key1, V1 value1, const T &replacement)
|
||||
@@ -310,8 +305,6 @@ namespace BlackMisc
|
||||
|
||||
/*!
|
||||
* \brief Replace elements for which a given predicate returns true. If there is no match, push the new element on the end.
|
||||
* \param p
|
||||
* \param replacement
|
||||
*/
|
||||
template <class Predicate>
|
||||
void replaceOrAdd(Predicate p, const T &replacement)
|
||||
@@ -320,11 +313,19 @@ namespace BlackMisc
|
||||
else { push_back(replacement); }
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Replace elements matching the given element. If there is no match, push the new element on the end.
|
||||
*/
|
||||
void replaceOrAdd(const T &original, const T &replacement)
|
||||
{
|
||||
if (this->contains(original)) { replace(original, replacement); }
|
||||
else { push_back(replacement); }
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Replace elements matching a particular key/value pair. If there is no match, push the new element on the end.
|
||||
* \param key1 A pointer to a member function of T.
|
||||
* \param value1 Will be compared to the return value of key1.
|
||||
* \param replacement
|
||||
*/
|
||||
template <class K1, class V1>
|
||||
void replaceOrAdd(K1 key1, V1 value1, const T &replacement)
|
||||
@@ -335,7 +336,6 @@ namespace BlackMisc
|
||||
|
||||
/*!
|
||||
* \brief In-place sort by a given comparator predicate.
|
||||
* \param p
|
||||
*/
|
||||
template <class Predicate> void sort(Predicate p)
|
||||
{
|
||||
@@ -374,8 +374,6 @@ namespace BlackMisc
|
||||
|
||||
/*!
|
||||
* \brief Return a copy sorted by a given comparator predicate.
|
||||
* \param p
|
||||
* \return
|
||||
*/
|
||||
template <class Predicate>
|
||||
CSequence sorted(Predicate p) const
|
||||
@@ -388,7 +386,6 @@ namespace BlackMisc
|
||||
/*!
|
||||
* \brief Return a copy sorted by a particular key.
|
||||
* \param key1 A pointer to a member function of T.
|
||||
* \return
|
||||
*/
|
||||
template <class K1>
|
||||
CSequence sortedBy(K1 key1) const
|
||||
@@ -400,7 +397,6 @@ namespace BlackMisc
|
||||
* \brief Return a copy sorted by some particular keys.
|
||||
* \param key1 A pointer to a member function of T.
|
||||
* \param key2 A pointer to a member function of T.
|
||||
* \return
|
||||
*/
|
||||
template <class K1, class K2>
|
||||
CSequence sortedBy(K1 key1, K2 key2) const
|
||||
@@ -413,7 +409,6 @@ namespace BlackMisc
|
||||
* \param key1 A pointer to a member function of T.
|
||||
* \param key2 A pointer to a member function of T.
|
||||
* \param key3 A pointer to a member function of T.
|
||||
* \return
|
||||
*/
|
||||
template <class K1, class K2, class K3>
|
||||
CSequence sortedBy(K1 key1, K2 key2, K3 key3) const
|
||||
@@ -423,16 +418,12 @@ namespace BlackMisc
|
||||
|
||||
/*!
|
||||
* \brief Test for equality.
|
||||
* \param other
|
||||
* \return
|
||||
* \todo Improve inefficient implementation.
|
||||
*/
|
||||
bool operator ==(const CSequence &other) const { return (empty() && other.empty()) ? true : (size() != other.size() ? false : *pimpl() == *other.pimpl()); }
|
||||
|
||||
/*!
|
||||
* \brief Test for inequality.
|
||||
* \param other
|
||||
* \return
|
||||
* \todo Improve inefficient implementation.
|
||||
*/
|
||||
bool operator !=(const CSequence &other) const { return !(*this == other); }
|
||||
|
||||
Reference in New Issue
Block a user