mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-05-04 00:45:46 +08:00
refs #321 Methods to read/write aircraft config packets from/to network
This commit is contained in:
committed by
Klaus Basan
parent
a3e13db2ae
commit
466a9a24ef
@@ -259,6 +259,12 @@ namespace BlackCore
|
|||||||
const QString &aircraftDesignator, const QString &combinedType, const QString &modelString) = 0;
|
const QString &aircraftDesignator, const QString &combinedType, const QString &modelString) = 0;
|
||||||
//! @}
|
//! @}
|
||||||
|
|
||||||
|
//! Broadcast an incremental aircraft config
|
||||||
|
virtual void broadcastAircraftConfig(const QJsonObject &config) = 0;
|
||||||
|
|
||||||
|
//! Query callsign for its current full aircraft config
|
||||||
|
virtual void sendAircraftConfigQuery(const BlackMisc::Aviation::CCallsign &callsign) = 0;
|
||||||
|
|
||||||
//! @}
|
//! @}
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
//! \name ATC slots
|
//! \name ATC slots
|
||||||
@@ -499,6 +505,9 @@ namespace BlackCore
|
|||||||
void fsipirCustomPacketReceived(const BlackMisc::Aviation::CCallsign &callsign, const QString &airlineDesignator,
|
void fsipirCustomPacketReceived(const BlackMisc::Aviation::CCallsign &callsign, const QString &airlineDesignator,
|
||||||
const QString &aircraftDesignator, const QString &combinedType, const QString &modelString);
|
const QString &aircraftDesignator, const QString &combinedType, const QString &modelString);
|
||||||
|
|
||||||
|
//! We received a aircraft config packet
|
||||||
|
void aircraftConfigPacketReceived(const BlackMisc::Aviation::CCallsign &callsign, const QJsonObject &incremental, bool isFull);
|
||||||
|
|
||||||
//! @}
|
//! @}
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
//! \name Weather signals
|
//! \name Weather signals
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include "network_vatlib.h"
|
#include "network_vatlib.h"
|
||||||
#include "blackmisc/project.h"
|
#include "blackmisc/project.h"
|
||||||
#include "blackmisc/logmessage.h"
|
#include "blackmisc/logmessage.h"
|
||||||
|
#include <QJsonDocument>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
@@ -37,7 +38,8 @@ namespace BlackCore
|
|||||||
: INetwork(parent), COwnAircraftProviderSupport(ownAircraft),
|
: INetwork(parent), COwnAircraftProviderSupport(ownAircraft),
|
||||||
m_loginMode(LoginNormal),
|
m_loginMode(LoginNormal),
|
||||||
m_status(vatStatusIdle),
|
m_status(vatStatusIdle),
|
||||||
m_fsdTextCodec(QTextCodec::codecForName("latin1"))
|
m_fsdTextCodec(QTextCodec::codecForName("latin1")),
|
||||||
|
m_tokenBucket(10, CTime(5, CTimeUnit::s()), 1)
|
||||||
{
|
{
|
||||||
connect(this, &CNetworkVatlib::terminate, this, &INetwork::terminateConnection, Qt::QueuedConnection);
|
connect(this, &CNetworkVatlib::terminate, this, &INetwork::terminateConnection, Qt::QueuedConnection);
|
||||||
connect(this, &INetwork::customPacketReceived, this, &CNetworkVatlib::customPacketDispatcher);
|
connect(this, &INetwork::customPacketReceived, this, &CNetworkVatlib::customPacketDispatcher);
|
||||||
@@ -50,6 +52,9 @@ namespace BlackCore
|
|||||||
connect(&m_processingTimer, SIGNAL(timeout()), this, SLOT(process()));
|
connect(&m_processingTimer, SIGNAL(timeout()), this, SLOT(process()));
|
||||||
connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(update()));
|
connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(update()));
|
||||||
m_processingTimer.start(c_processingIntervalMsec);
|
m_processingTimer.start(c_processingIntervalMsec);
|
||||||
|
|
||||||
|
this->connect(&this->m_scheduledConfigUpdate, &QTimer::timeout, this, &CNetworkVatlib::sendIncrementalAircraftConfig);
|
||||||
|
m_scheduledConfigUpdate.setSingleShot(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CNetworkVatlib::initializeSession()
|
void CNetworkVatlib::initializeSession()
|
||||||
@@ -90,6 +95,7 @@ namespace BlackCore
|
|||||||
Vat_SetAircraftInfoRequestHandler(m_net.data(), onPilotInfoRequestReceived, this);
|
Vat_SetAircraftInfoRequestHandler(m_net.data(), onPilotInfoRequestReceived, this);
|
||||||
Vat_SetAircraftInfoHandler(m_net.data(), onPilotInfoReceived, this);
|
Vat_SetAircraftInfoHandler(m_net.data(), onPilotInfoReceived, this);
|
||||||
Vat_SetCustomPilotPacketHandler(m_net.data(), onCustomPacketReceived, this);
|
Vat_SetCustomPilotPacketHandler(m_net.data(), onCustomPacketReceived, this);
|
||||||
|
Vat_SetAircraftConfigHandler(m_net.data(), onAircraftConfigReceived, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
CNetworkVatlib::~CNetworkVatlib()
|
CNetworkVatlib::~CNetworkVatlib()
|
||||||
@@ -100,6 +106,7 @@ namespace BlackCore
|
|||||||
void CNetworkVatlib::process()
|
void CNetworkVatlib::process()
|
||||||
{
|
{
|
||||||
if (!m_net) { return; }
|
if (!m_net) { return; }
|
||||||
|
sendIncrementalAircraftConfig();
|
||||||
Vat_ExecuteNetworkTasks(m_net.data());
|
Vat_ExecuteNetworkTasks(m_net.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,6 +235,25 @@ namespace BlackCore
|
|||||||
return qstrList;
|
return qstrList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString CNetworkVatlib::convertToUnicodeEscaped(const QString &str)
|
||||||
|
{
|
||||||
|
QString escaped;
|
||||||
|
for (const auto &ch : str)
|
||||||
|
{
|
||||||
|
ushort code = ch.unicode();
|
||||||
|
if (code < 0x80)
|
||||||
|
{
|
||||||
|
escaped += ch;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
escaped += "\\u";
|
||||||
|
escaped += QString::number(code, 16).rightJustified(4, '0');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return escaped;
|
||||||
|
}
|
||||||
|
|
||||||
/********************************** * * * * * * * * * * * * * * * * * * * ************************************/
|
/********************************** * * * * * * * * * * * * * * * * * * * ************************************/
|
||||||
/********************************** INetwork slots ************************************/
|
/********************************** INetwork slots ************************************/
|
||||||
/********************************** * * * * * * * * * * * * * * * * * * * ************************************/
|
/********************************** * * * * * * * * * * * * * * * * * * * ************************************/
|
||||||
@@ -454,6 +480,19 @@ namespace BlackCore
|
|||||||
Vat_SendInformation(m_net.data(), vatInfoQueryTypeName, toFSD(callsign), toFSD(m_server.getUser().getRealName()));
|
Vat_SendInformation(m_net.data(), vatInfoQueryTypeName, toFSD(callsign), toFSD(m_server.getUser().getRealName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CNetworkVatlib::replyToConfigQuery(const CCallsign &callsign)
|
||||||
|
{
|
||||||
|
QJsonObject currentConfig = ownAircraft().getParts().toJson();
|
||||||
|
// Fixme: Use QJsonObject with std::initializer_list once 5.4 is baseline
|
||||||
|
currentConfig.insert("is_full_data", true);
|
||||||
|
QJsonObject packet;
|
||||||
|
packet.insert("config", currentConfig);
|
||||||
|
QJsonDocument doc(packet);
|
||||||
|
QString data { doc.toJson(QJsonDocument::Compact) };
|
||||||
|
data = convertToUnicodeEscaped(data);
|
||||||
|
Vat_SendAircraftConfig(m_net.data(), toFSD(callsign), toFSD(data));
|
||||||
|
}
|
||||||
|
|
||||||
void CNetworkVatlib::sendIcaoCodesQuery(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");
|
Q_ASSERT_X(isConnected(), "CNetworkVatlib", "Can't send to server when disconnected");
|
||||||
@@ -470,6 +509,32 @@ namespace BlackCore
|
|||||||
Vat_SendModernPlaneInfo(m_net.data(), toFSD(callsign), &aircraftInfo);
|
Vat_SendModernPlaneInfo(m_net.data(), toFSD(callsign), &aircraftInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CNetworkVatlib::sendIncrementalAircraftConfig()
|
||||||
|
{
|
||||||
|
if (!isConnected()) return;
|
||||||
|
|
||||||
|
CAircraftParts currentParts = ownAircraft().getParts();
|
||||||
|
|
||||||
|
// If it hasn't changed, return
|
||||||
|
if (m_sentAircraftConfig == currentParts) return;
|
||||||
|
|
||||||
|
if (!m_tokenBucket.tryConsume())
|
||||||
|
{
|
||||||
|
// If timer is not yet active, start it
|
||||||
|
if (!m_scheduledConfigUpdate.isActive()) m_scheduledConfigUpdate.start(1000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method could have been triggered by another change in aircraft config
|
||||||
|
// so a previous update might still be scheduled. Stop it.
|
||||||
|
if (m_scheduledConfigUpdate.isActive()) m_scheduledConfigUpdate.stop();
|
||||||
|
QJsonObject previousConfig = m_sentAircraftConfig.toJson();
|
||||||
|
QJsonObject currentConfig = currentParts.toJson();
|
||||||
|
QJsonObject incrementalConfig = getIncrementalObject(previousConfig, currentConfig);
|
||||||
|
broadcastAircraftConfig(incrementalConfig);
|
||||||
|
m_sentAircraftConfig = currentParts;
|
||||||
|
}
|
||||||
|
|
||||||
void CNetworkVatlib::sendPing(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");
|
Q_ASSERT_X(isConnected(), "CNetworkVatlib", "Can't send to server when disconnected");
|
||||||
@@ -502,6 +567,24 @@ namespace BlackCore
|
|||||||
sendCustomPacket(callsign, "FSIPIR", data);
|
sendCustomPacket(callsign, "FSIPIR", data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CNetworkVatlib::broadcastAircraftConfig(const QJsonObject &config)
|
||||||
|
{
|
||||||
|
// Fixme: Use QJsonObject with std::initializer_list once 5.4 is baseline
|
||||||
|
QJsonObject packet;
|
||||||
|
packet.insert("config", config);
|
||||||
|
QJsonDocument doc(packet);
|
||||||
|
QString data { doc.toJson(QJsonDocument::Compact) };
|
||||||
|
data = convertToUnicodeEscaped(data);
|
||||||
|
Vat_SendAircraftConfigBroadcast(m_net.data(), toFSD(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CNetworkVatlib::sendAircraftConfigQuery(const CCallsign &callsign)
|
||||||
|
{
|
||||||
|
QJsonDocument doc(JsonPackets::aircraftConfigRequest());
|
||||||
|
QString data { doc.toJson(QJsonDocument::Compact) };
|
||||||
|
Vat_SendAircraftConfig(m_net.data(), toFSD(callsign), toFSD(data));
|
||||||
|
}
|
||||||
|
|
||||||
/********************************** * * * * * * * * * * * * * * * * * * * ************************************/
|
/********************************** * * * * * * * * * * * * * * * * * * * ************************************/
|
||||||
/********************************** shimlib callbacks ************************************/
|
/********************************** shimlib callbacks ************************************/
|
||||||
/********************************** * * * * * * * * * * * * * * * * * * * ************************************/
|
/********************************** * * * * * * * * * * * * * * * * * * * ************************************/
|
||||||
@@ -597,6 +680,30 @@ namespace BlackCore
|
|||||||
emit cbvar_cast(cbvar)->aircraftPositionUpdate(callsign, situation, transponder);
|
emit cbvar_cast(cbvar)->aircraftPositionUpdate(callsign, situation, transponder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CNetworkVatlib::onAircraftConfigReceived(VatSessionID, const char *callsign, const char *aircraftConfig, void *cbvar)
|
||||||
|
{
|
||||||
|
QByteArray json = cbvar_cast(cbvar)->fromFSD(aircraftConfig).toUtf8();
|
||||||
|
QJsonParseError parserError;
|
||||||
|
QJsonDocument doc = QJsonDocument::fromJson(json, &parserError);
|
||||||
|
|
||||||
|
if (parserError.error != QJsonParseError::NoError)
|
||||||
|
CLogMessage(static_cast<CNetworkVatlib*>(nullptr)).warning("Failed to parse aircraft config packet: %1") << parserError.errorString();
|
||||||
|
|
||||||
|
QJsonObject packet = doc.object();
|
||||||
|
|
||||||
|
if (packet == JsonPackets::aircraftConfigRequest() )
|
||||||
|
{
|
||||||
|
cbvar_cast(cbvar)->replyToConfigQuery(cbvar_cast(cbvar)->fromFSD(callsign));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject config = doc.object().value("config").toObject();
|
||||||
|
if (config.empty()) return;
|
||||||
|
|
||||||
|
bool isFull = config.take("is_full_data").toBool(false);
|
||||||
|
emit cbvar_cast(cbvar)->aircraftConfigPacketReceived(cbvar_cast(cbvar)->fromFSD(callsign), config, isFull);
|
||||||
|
}
|
||||||
|
|
||||||
void CNetworkVatlib::onInterimPilotPositionUpdate(VatSessionID, const char * /** callsign **/, const VatPilotPosition * /** position **/, void * /** cbvar **/)
|
void CNetworkVatlib::onInterimPilotPositionUpdate(VatSessionID, const char * /** callsign **/, const VatPilotPosition * /** position **/, void * /** cbvar **/)
|
||||||
{
|
{
|
||||||
//TODO
|
//TODO
|
||||||
@@ -839,4 +946,12 @@ namespace BlackCore
|
|||||||
CLogMessage(static_cast<CNetworkVatlib *>(nullptr)).error(message);
|
CLogMessage(static_cast<CNetworkVatlib *>(nullptr)).error(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QJsonObject CNetworkVatlib::JsonPackets::aircraftConfigRequest()
|
||||||
|
{
|
||||||
|
// Fixme: Use static QJsonObject with std::initializer_list once 5.4 is baseline
|
||||||
|
QJsonObject request;
|
||||||
|
request.insert("request", "full");
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
#include "network.h"
|
#include "network.h"
|
||||||
#include "blackmisc/simulation/simdirectaccessownaircraft.h"
|
#include "blackmisc/simulation/simdirectaccessownaircraft.h"
|
||||||
|
#include "token_bucket.h"
|
||||||
#include <vatlib/vatlib2.h>
|
#include <vatlib/vatlib2.h>
|
||||||
#include <QScopedPointer>
|
#include <QScopedPointer>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
@@ -61,6 +62,13 @@ namespace BlackCore
|
|||||||
virtual void sendFsipirCustomPacket(const BlackMisc::Aviation::CCallsign &callsign, const QString &airlineDesignator,
|
virtual void sendFsipirCustomPacket(const BlackMisc::Aviation::CCallsign &callsign, const QString &airlineDesignator,
|
||||||
const QString &aircraftDesignator, const QString &combinedType, const QString &modelString) override;
|
const QString &aircraftDesignator, const QString &combinedType, const QString &modelString) override;
|
||||||
|
|
||||||
|
//! \copydoc INetwork::broadcastAircraftConfig
|
||||||
|
virtual void broadcastAircraftConfig(const QJsonObject &config) override;
|
||||||
|
|
||||||
|
//! \copydoc INetwork::sendAircraftConfigQuery
|
||||||
|
virtual void sendAircraftConfigQuery(const BlackMisc::Aviation::CCallsign &callsign) override;
|
||||||
|
|
||||||
|
|
||||||
// Text message slots
|
// Text message slots
|
||||||
virtual void sendTextMessages(const BlackMisc::Network::CTextMessageList &messages) override;
|
virtual void sendTextMessages(const BlackMisc::Network::CTextMessageList &messages) override;
|
||||||
|
|
||||||
@@ -83,7 +91,9 @@ namespace BlackCore
|
|||||||
private slots:
|
private slots:
|
||||||
void replyToFrequencyQuery(const BlackMisc::Aviation::CCallsign &callsign);
|
void replyToFrequencyQuery(const BlackMisc::Aviation::CCallsign &callsign);
|
||||||
void replyToNameQuery(const BlackMisc::Aviation::CCallsign &callsign);
|
void replyToNameQuery(const BlackMisc::Aviation::CCallsign &callsign);
|
||||||
|
void replyToConfigQuery(const BlackMisc::Aviation::CCallsign &callsign);
|
||||||
void sendAircraftInfo(const BlackMisc::Aviation::CCallsign &callsign);
|
void sendAircraftInfo(const BlackMisc::Aviation::CCallsign &callsign);
|
||||||
|
void sendIncrementalAircraftConfig();
|
||||||
|
|
||||||
private: //shimlib callbacks
|
private: //shimlib callbacks
|
||||||
static void onConnectionStatusChanged(VatSessionID, VatConnectionStatus oldStatus, VatConnectionStatus newStatus, void *cbvar);
|
static void onConnectionStatusChanged(VatSessionID, VatConnectionStatus oldStatus, VatConnectionStatus newStatus, void *cbvar);
|
||||||
@@ -110,6 +120,7 @@ namespace BlackCore
|
|||||||
static void onPilotInfoRequestReceived(VatSessionID, const char *callsign, void *cbvar);
|
static void onPilotInfoRequestReceived(VatSessionID, const char *callsign, void *cbvar);
|
||||||
static void onPilotInfoReceived(VatSessionID, const char *callsign, const VatAircraftInfo *aircraftInfo, void *cbvar);
|
static void onPilotInfoReceived(VatSessionID, const char *callsign, const VatAircraftInfo *aircraftInfo, void *cbvar);
|
||||||
static void onPilotPositionUpdate(VatSessionID, const char *callsign, const VatPilotPosition *position, void *cbvar);
|
static void onPilotPositionUpdate(VatSessionID, const char *callsign, const VatPilotPosition *position, void *cbvar);
|
||||||
|
static void onAircraftConfigReceived(VatSessionID, const char *callsign, const char *aircraftConfig, void *cbvar);
|
||||||
static void onCustomPacketReceived(VatSessionID, const char *callsign, const char *packetId, const char **data, int dataSize, void *cbvar);
|
static void onCustomPacketReceived(VatSessionID, const char *callsign, const char *packetId, const char **data, int dataSize, void *cbvar);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -122,8 +133,14 @@ namespace BlackCore
|
|||||||
void initializeSession();
|
void initializeSession();
|
||||||
void changeConnectionStatus(VatConnectionStatus newStatus);
|
void changeConnectionStatus(VatConnectionStatus newStatus);
|
||||||
bool isDisconnected() const { return m_status != vatStatusConnecting && m_status != vatStatusConnected; }
|
bool isDisconnected() const { return m_status != vatStatusConnecting && m_status != vatStatusConnected; }
|
||||||
|
QString convertToUnicodeEscaped(const QString &str);
|
||||||
static void networkErrorHandler(const char *message);
|
static void networkErrorHandler(const char *message);
|
||||||
|
|
||||||
|
struct JsonPackets
|
||||||
|
{
|
||||||
|
static QJsonObject aircraftConfigRequest();
|
||||||
|
};
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void process();
|
void process();
|
||||||
void update();
|
void update();
|
||||||
@@ -154,6 +171,11 @@ namespace BlackCore
|
|||||||
static int const c_updateIntervalMsec = 5000;
|
static int const c_updateIntervalMsec = 5000;
|
||||||
static int const c_logoffTimeoutSec = 5;
|
static int const c_logoffTimeoutSec = 5;
|
||||||
QTextCodec *m_fsdTextCodec;
|
QTextCodec *m_fsdTextCodec;
|
||||||
|
|
||||||
|
BlackMisc::Aviation::CAircraftParts m_sentAircraftConfig;
|
||||||
|
QTimer m_scheduledConfigUpdate;
|
||||||
|
CTokenBucket m_tokenBucket;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} //namespace BlackCore
|
} //namespace BlackCore
|
||||||
|
|||||||
@@ -372,3 +372,42 @@ bool BlackMisc::Audio::startWindowsMixer()
|
|||||||
QStringList parameterlist;
|
QStringList parameterlist;
|
||||||
return QProcess::startDetached("SndVol.exe", parameterlist);
|
return QProcess::startDetached("SndVol.exe", parameterlist);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QJsonObject BlackMisc::getIncrementalObject(const QJsonObject &previousObject, const QJsonObject ¤tObject)
|
||||||
|
{
|
||||||
|
QJsonObject incrementalObject = currentObject;
|
||||||
|
for (const auto &key : previousObject.keys())
|
||||||
|
{
|
||||||
|
if (previousObject.value(key).isObject())
|
||||||
|
{
|
||||||
|
auto child = getIncrementalObject(previousObject.value(key).toObject(), currentObject.value(key).toObject());
|
||||||
|
if (child.isEmpty()) incrementalObject.remove(key);
|
||||||
|
else incrementalObject.insert(key, child);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (currentObject.value(key) == previousObject.value(key))
|
||||||
|
incrementalObject.remove(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return incrementalObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject BlackMisc::applyIncrementalObject(const QJsonObject &previousObject, const QJsonObject &incrementalObject)
|
||||||
|
{
|
||||||
|
QJsonObject currentObject = previousObject;
|
||||||
|
for(const auto &key : incrementalObject.keys())
|
||||||
|
{
|
||||||
|
// If it is not an object, just insert the value
|
||||||
|
if (!incrementalObject.value(key).isObject())
|
||||||
|
{
|
||||||
|
currentObject.insert(key,incrementalObject.value(key));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto child = applyIncrementalObject(currentObject.value(key).toObject(), incrementalObject.value(key).toObject());
|
||||||
|
currentObject.insert(key, child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return currentObject;
|
||||||
|
}
|
||||||
|
|||||||
@@ -184,6 +184,14 @@ namespace BlackMisc
|
|||||||
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
|
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! Creates an incremental json object from two existing objects
|
||||||
|
QJsonObject getIncrementalObject(const QJsonObject &previousObject, const QJsonObject ¤tObject);
|
||||||
|
|
||||||
|
//! Merges an incremental json object into an existing one
|
||||||
|
QJsonObject applyIncrementalObject(const QJsonObject &previousObject, const QJsonObject &incrementalObject);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // BlackMisc
|
} // BlackMisc
|
||||||
|
|
||||||
#endif // guard
|
#endif // guard
|
||||||
|
|||||||
Reference in New Issue
Block a user