Files
qt5-legatus-legacy/Lts/Plugins/AdvancedSymbology/Gui/SymbolProxy/asb_flm_subscriber.cpp
T
2026-08-13 18:33:10 +02:00

748 lines
26 KiB
C++
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* @RDE_HEADER@
* Subscribe to file management service
* $Id$
* $HeadURL$
* $Author$
*
* Created by Norbert Thoden, NLE, 2019-04-15
*/
#include "asb_flm_subscriber.h"
#include <LtsUtilsCore/dds_vector.h>
#include <NGLLogger/NGLLoggerBootstrap.h>
#include <Symbology/symbol_dictionary.h>
#include <Symbology/sidc_codec.h>
#include "flm_symbol_proxy.h"
#include <Plugins/FileManagement/flm_data_plugin_interface.h>
#include <Plugins/OperatorManagement/opm_data_plugin_interface.h>
// Qt
#include <QPointer>
#include <QSet>
#include <QSvgRenderer>
#include <QImage>
#include <QPainter>
#include <QJsonDocument>
#include <QJsonObject>
#include <QDomDocument>
#include <QTimer>
namespace AdvancedSymbology
{
uint qHash(SymbologyType type)
{
return static_cast<uint>(type);
}
struct FileContentStruct
{
enum SymbolType { UnsupportedSymbol, EtsSymbol, XmlSymbol };
enum ReplyState { Undefined, Requested, RequestFailure, ReplyReceived, ReplySuccess, ReplyFailure };
QString name;
SymbolType type{UnsupportedSymbol};
QString operatorName;
int64_t lastModified{0};
QStringList usrTags;
QColor colorTobeReplaced;
struct Monitoring
{
qint64 requestTime{-1}; // sec
int retryCnt{0};
ReplyState replyState{Undefined};
int replyContentSize{-1};
};
mutable Monitoring monitoring;
};
qint64 getRequestTime()
{
return time(nullptr);
}
QString toString(FileContentStruct::ReplyState rs)
{
switch (rs)
{
case FileContentStruct::Undefined:
return QStringLiteral("Undefined");
case FileContentStruct::Requested:
return QStringLiteral("Requested");
case FileContentStruct::RequestFailure:
return QStringLiteral("RequestFailure");
case FileContentStruct::ReplyReceived:
return QStringLiteral("ReplyReceived");
case FileContentStruct::ReplySuccess:
return QStringLiteral("ReplySuccess");
case FileContentStruct::ReplyFailure:
return QStringLiteral("ReplyFailure");
}
return QStringLiteral("UnknownReplyState");
}
//------------------------------------------------------------------------------
struct FlmSubscriber::Private
{
QHash<int32_t, FileContentStruct> m_fileContentMap; // fileContentId -> name
QTimer *m_reFetchTimer{nullptr};
FlmSymbolProxy m_symbolProxy;
QSet<SymbologyType> m_symbolDictionaryToUpdate;
std::shared_ptr<FileManagement::Interface::Dtc> m_flmDtc;
std::shared_ptr<FileManagement::Interface::Ftc> m_flmFtc;
std::shared_ptr<OperatorManagement::Interface::Dtc> m_opmDtc;
static long m_counter;
};
long FlmSubscriber::Private::m_counter = 0;
FlmSubscriber::FlmSubscriber(const std::shared_ptr<FileManagement::Interface::Dtc> &flmDtc,
const std::shared_ptr<FileManagement::Interface::Ftc> &flmFtc,
const std::shared_ptr<OperatorManagement::Interface::Dtc> &opmDtc)
: m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("AdvSymbology.FlmSubscriber"))
, d(new Private())
{
INFO_LOG(m_logger) << LOGFUNCTION << " m_counter =" << ++d->m_counter;
d->m_flmDtc = flmDtc;
d->m_flmFtc = flmFtc;
d->m_opmDtc = opmDtc;
d->m_reFetchTimer = new QTimer(this);
d->m_reFetchTimer->setInterval(10000);
connect(d->m_reFetchTimer, &QTimer::timeout,
this, &FlmSubscriber::checkForReFetching);
// To enable QueuedConnection:
qRegisterMetaType<FileManagement::FileContent>("FileManagement::FileContent");
qRegisterMetaType<DataModification>("DataModification");
}
FlmSubscriber::~FlmSubscriber()
{
INFO_LOG(m_logger) << LOGFUNCTION << " m_counter =" << d->m_counter--;
if (d->m_reFetchTimer)
d->m_reFetchTimer->stop();
delete d;
}
bool FlmSubscriber::createFlmSymbolProxy(int type_placeholder)
{
Q_UNUSED(type_placeholder);
if (!d->m_flmDtc || !d->m_flmFtc)
return false;
d->m_flmDtc->enableFileContent();
d->m_flmFtc->enableGetFileContentData();
//
// 1 connect changed signals:
//
// avoid multiple connect
connect(d->m_flmDtc.get(), &FileManagement::Interface::Dtc::fileContentChanged,
this, &FlmSubscriber::onFileContentChanged, Qt::ConnectionType(Qt::QueuedConnection | Qt::UniqueConnection));
//
// 2. retrieve FileContent
//
const auto cb = [this](const FileManagement::FileContent & data) -> void
{
updateFileContentMap(data);
};
if (!d->m_flmDtc->fileContents(cb))
ERROR_LOG(m_logger) << LOGFUNCTION << " Error performing fileContents";
INFO_LOG(m_logger) << LOGFUNCTION << " m_fileContentMap.size()=" << d->m_fileContentMap.size() ;
//
// now we have all FileContentIds: -> retrieve contentDATA (svg data)
//
for (auto it = d->m_fileContentMap.cbegin(); it != d->m_fileContentMap.cend(); ++it)
{
const int fileContentId = it.key();
FileManagement::GetFileContentDataRequest request(fileContentId);
const FileContentStruct &fcsRef = it.value(); // monitoring is mutable
#ifdef LTS_DEBUG
//#define SKIP_SOME_TO_TEST_REFETCHING
#ifdef SKIP_SOME_TO_TEST_REFETCHING
if (fileContentId>=98)
request.fileContentId(-1);
#endif // SKIP_SOME_TO_TEST_REFETCHING
#endif // LTS_DEBUG
if (d->m_flmFtc->getFileContentDataRequest(request, this))
{
fcsRef.monitoring.requestTime = getRequestTime();
fcsRef.monitoring.replyState = FileContentStruct::Requested;
} else {
fcsRef.monitoring.replyState = FileContentStruct::RequestFailure;
ERROR_LOG(m_logger) << "Error requesting FileContentData, fileContentId=" << fileContentId;
}
} // while
//
// start reFetchTimer using rand to avoid heavy load at server side:
//
const int randomOffset = rand() % 10 + 5; // 5 .. 15
QTimer::singleShot(randomOffset, this , [this]()
{
DEBUG_LOG(m_logger) << "start ReFetchingTimer";
d->m_reFetchTimer->start(); // -> checkForReFetching
});
return true;
}
void FlmSubscriber::onGetFileContentDataReply(const FileManagement::GetFileContentDataReply &reply)
{
const int32_t fileContentId = reply.id();
TRACE_LOG(m_logger) << LOGFUNCTION << " START, " << fileContentId;
if (!d->m_fileContentMap.contains(fileContentId))
{
ERROR_LOG(m_logger) << LOGFUNCTION << " fileContentId unknown, fileContentId=" << fileContentId;
return;
}
const FileContentStruct &fcData = d->m_fileContentMap[fileContentId];
fcData.monitoring.replyState = FileContentStruct::ReplyReceived;
const QString &name = fcData.name;
const QString &operatorName = fcData.operatorName;
const qint64 lastModified = fcData.lastModified;
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " fileContentId=" << fileContentId
<< " name=" << name
<< " operatorName=" << operatorName
<< " lastModified=" << lastModified
<< " #bytes =" << reply.content().size();
fcData.monitoring.replyContentSize = reply.content().size(); // update ReplayState
switch (fcData.type)
{
case FileContentStruct::SymbolType::EtsSymbol:
{
QImage image;
if (!svgToImage(QByteArray::fromRawData(reinterpret_cast<const char*>(&reply.content().at(0)), reply.content().size()), image))
{
ERROR_LOG(m_logger) << LOGFUNCTION << " svgToImage failed, fileContentId=" << fileContentId;
fcData.monitoring.replyState = FileContentStruct::ReplyFailure; // update ReplayState
return;
}
// now we have metaData (fileContentId, name) and data (content/svg)
// transfer to symbolProxy:
FlmSymbolProxy::SymbolData symbolData(name, image, fcData.colorTobeReplaced);
symbolData.setUsrTags(fcData.usrTags);
// store:
d->m_symbolProxy.setSymbol(fileContentId, symbolData);
fcData.monitoring.replyState = FileContentStruct::ReplySuccess; // update ReplayState
break;
}
case FileContentStruct::SymbolType::XmlSymbol:
{
FlmSymbolProxy::SymbolData symbolData(name, operatorName, lastModified, LtsUtils::toQByteArray(reply.content()));
if (symbolData.isXmlSymbol())
{
symbolData.setUsrTags(fcData.usrTags);
// store it
d->m_symbolProxy.setSymbol(fileContentId, symbolData);
fcData.monitoring.replyState = FileContentStruct::ReplySuccess; // update ReplayState
}
else
{
ERROR_LOG(m_logger) << LOGFUNCTION << " xmlSymbolContent is empty, fileContentId=" << fileContentId;
fcData.monitoring.replyState = FileContentStruct::ReplyFailure; // update ReplayState
}
break;
}
case FileContentStruct::SymbolType::UnsupportedSymbol:
{
ERROR_LOG(m_logger) << LOGFUNCTION << " unsupported symbol found, fileContentId=" << fileContentId;
fcData.monitoring.replyState = FileContentStruct::ReplyFailure; // update ReplayState
break;
}
} // switch
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
bool FlmSubscriber::svgToImage(const QByteArray &svgByteArray, QImage &imageOut)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
// load QByteArray
QSvgRenderer svgRenderer;
if (!svgRenderer.load(svgByteArray))
{
ERROR_LOG(m_logger) << LOGFUNCTION << " svgRenderer.load failed";
return false;
}
// prepare Image:
int size = 200; // pixel
imageOut = QImage(size, size, QImage::Format_ARGB32);
imageOut.fill(Qt::transparent);
// render
QPainter painter(&imageOut);
svgRenderer.render(&painter);
painter.end();
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
QString FlmSubscriber::operatorName(int operatorId)
{
if (d->m_opmDtc)
return QString::fromStdString(d->m_opmDtc->user(operatorId).name());
return QStringLiteral("unknown user<%1>").arg(operatorId);
}
void FlmSubscriber::checkForReFetching()
{
// use own logging channel:
LOGGER_T logger = NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("AdvSymbology.FlmSubscriber.ReFetch");
DEBUG_LOG(logger) << "********** checkForReFetching START, size=" << d->m_fileContentMap.size();
int i{0};
int unfinished{0};
int reFetchCounter{0};
static int s_reFetchCounter = 0;
const qint64 curTime = time(nullptr);
for (auto it = d->m_fileContentMap.cbegin(); it != d->m_fileContentMap.cend(); ++it)
{
const FileContentStruct &fcs = it.value();
qint64 ageSec = curTime - fcs.monitoring.requestTime;
DEBUG_LOG(logger) << "***** dump i=" << ++i
<< ", fileContentId=" << it.key()
<< ", retryCnt=" << fcs.monitoring.retryCnt
<< ", ageSec = " << ageSec
<< ", replyState=" << toString(fcs.monitoring.replyState)
<< ", replyContentSize=" << fcs.monitoring.replyContentSize
<< ", name='" << fcs.name << "'"
;
if (fcs.monitoring.replyState != FileContentStruct::ReplySuccess)
{
++unfinished;
if ((ageSec > 30) && (fcs.monitoring.retryCnt < 3))
{
// retry / reFetch
const int32_t fileContentId = it.key();
INFO_LOG(logger) << "***** reFetch *** :"
<< " ageSec = " << ageSec
<< ", fileContentId=" << fileContentId
<< ", replyState=" << toString(fcs.monitoring.replyState)
<< ", replyContentSize=" << fcs.monitoring.replyContentSize
<< ", name='" << fcs.name << "'"
;
FileManagement::GetFileContentDataRequest request(fileContentId);
if (!d->m_flmFtc->getFileContentDataRequest(request, this)) // -> onGetFileContentDataReply -> ... -> setSymbol
ERROR_LOG(logger) << LOGFUNCTION << "Error reading FileContentData, fileContentId=" << fileContentId;
fcs.monitoring.replyState = FileContentStruct::Requested;
fcs.monitoring.requestTime = getRequestTime();
++fcs.monitoring.retryCnt;
// Server-Restart: Topic is removed and therefore the fcs is also removed from container -> retryCnt is fine
++reFetchCounter;
++s_reFetchCounter;
}
}
}
INFO_LOG(logger) << "***** checkForReFetching END"
<< ", size=" << d->m_fileContentMap.size()
<< ", unfinished=" << unfinished
<< ", reFetchCounter=" << reFetchCounter
<< ", s_reFetchCounter=" << s_reFetchCounter;
}
void FlmSubscriber::onFileContentChanged(const FileManagement::FileContent &data, DataModification modType)
{
TRACE_LOG(m_logger) << LOGFUNCTION
<< " data.id=" << data.id()
<< " data.fileStatus=" << data.fileStatus().underlying()
<< " modType=" << modType
<< " data.name='" << data.name().c_str() << "'";
if (!d->m_flmFtc)
return;
if (data.isDeleted())
return;
// check fileType
if (data.fileType().underlying() != FileManagement::FileType::OperatorDefinedSymbol)
return;
// check fileStatus in relation with modType:
// (if modified to FileStatus::Deleted process as DataModification::eRemoved)
if (data.fileStatus().underlying() == FileManagement::FileStatus::Deleted)
{
switch (modType)
{
case DataModification::eAdded:
return;
case DataModification::eModified:
modType = DataModification::eRemoved;
break;
case DataModification::eRemoved:
// empty
break;
} // switch
}
//
// no check against ExerciseId, because we assume that all symbols are 'global'
//
const int32_t fileContentId = data.id();
switch (modType)
{
case DataModification::eAdded:
case DataModification::eModified:
{
// since it´s caused by an update/changed signal,
// we have to update our own map, (to let onGetFileContentDataReply work)
updateFileContentMap(data);
FileManagement::GetFileContentDataRequest request(fileContentId);
if (!d->m_flmFtc->getFileContentDataRequest(request, this)) // -> onGetFileContentDataReply -> ... -> setSymbol
ERROR_LOG(m_logger) << LOGFUNCTION << "Error reading FileContentData, fileContentId=" << fileContentId;
break;
}
case DataModification::eRemoved:
{
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " modType=" << modType
<< " fileContentId=" << fileContentId
<< " fileContentName=" << data.name();
// update own container:
d->m_fileContentMap.remove(fileContentId);
// remove:
if (!d->m_symbolProxy.removeSymbol(fileContentId))
ERROR_LOG(m_logger) << LOGFUNCTION << " removeSymbol failed"
<< " fileContentId=" << fileContentId
<< " fileContentName='" << data.name() << "'"
<< " contains=" << d->m_fileContentMap.contains(fileContentId);
break;
}
} // switch
} // void FlmSubscriber::onFileContentChanged(const FileManagement::FileContent &data, DataModification modType)
void FlmSubscriber::updateFileContentMap(const FileManagement::FileContent &data)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " d->m_fileContentMap.size()=" << d->m_fileContentMap.size()
<< " fileContentId=" << data.id()
<< " data.isDeleted()=" <<data.isDeleted()
<< " data.fileStatus().underlying()=" << data.fileStatus().underlying()
<< " data.name='" <<QString::fromStdString(data.name()) << "'";
if (data.isDeleted())
return;
if (data.fileStatus().underlying() == FileManagement::FileStatus::Deleted)
return;
if (data.fileType() != FileManagement::FileType::OperatorDefinedSymbol)
return;
// check exerciseId in future ???
const int32_t fileContentId = data.id();
FileContentStruct fcData;
fcData.name = QString::fromStdString(data.name());
fcData.type = FileContentStruct::SymbolType::UnsupportedSymbol;
fcData.operatorName = operatorName(data.operatorId());
fcData.lastModified = data.lastModified();
fcData.usrTags << QStringLiteral("file-id=%1").arg(fileContentId);
fcData.usrTags << QStringLiteral("exercise-id=%1").arg(data.exerciseId().is_set() ? data.exerciseId().get() : -1);
fcData.usrTags << fcData.operatorName;
// optional properties (containing 'imageFormat', 'partyColor')
if (data.properties().size() != 0)
{
const QByteArray attributesJson(QByteArray::fromRawData(data.properties().c_str(), data.properties().size()));
QJsonParseError parseError;
QJsonDocument jDoc(QJsonDocument::fromJson(attributesJson, &parseError));
if (parseError.error == QJsonParseError::NoError)
{
const QJsonObject &obj = jDoc.object();
const QLatin1String imageFormatKey("imageFormat");
if (obj.contains(imageFormatKey))
{
const QString &imageFormatValue = obj[imageFormatKey].toString();
if (QLatin1String("xml") == imageFormatValue)
fcData.type = FileContentStruct::SymbolType::XmlSymbol;
if (QLatin1String("ets") == imageFormatValue)
fcData.type = FileContentStruct::SymbolType::EtsSymbol;
}
else
fcData.type = FileContentStruct::SymbolType::EtsSymbol;
if (FileContentStruct::SymbolType::EtsSymbol == fcData.type)
{
// partyColor
const QLatin1String partyColorStr("partyColor");
if (obj.contains(partyColorStr))
{
QJsonObject partyColor = obj[partyColorStr].toObject();
if (partyColor.size() == 3) // r, g, b
{
// update map:
fcData.colorTobeReplaced.setRgb(
partyColor[QLatin1String("r")].toInt(),
partyColor[QLatin1String("g")].toInt(),
partyColor[QLatin1String("b")].toInt());
} // if (partyColor.size() == 3)
} // if (obj.contains(partyColorStr))
} // if (FileContentStruct::SymbolType::EtsSymbol == fcRef.type)
} else {
ERROR_LOG(m_logger) << LOGFUNCTION
<< " QJsonParseError->errorString: '" << parseError.errorString() << "'"
<< ", offset: " << parseError.offset;
} // if (parseError.error == QJsonParseError::NoError)
} // if (data.attributes().is_set())
d->m_fileContentMap[fileContentId] = fcData;
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< " d->m_fileContentMap.size()=" << d->m_fileContentMap.size()
<< " fileContentId=" << data.id()
<< " data.isDeleted()=" <<data.isDeleted()
<< " data.fileStatus().underlying()=" << data.fileStatus().underlying()
<< " data.name='" <<QString::fromStdString(data.name()) << "'";
} // void FlmSubscriber::updateFileContentMap(const FileManagement::FileContent &data)
void FlmSubscriber::onLocalSymbolProxyEtsSymbolAdded(qint32 fileContentId,
const QString &name,
const QImage &image,
const QColor &colorToBeReplaced,
const QStringList &usrTags)
{
Q_UNUSED(fileContentId);
for (const SymbologyType symbologyType : qAsConst(d->m_symbolDictionaryToUpdate))
{
AdvancedSymbology::SymbolDictionary &dict =
AdvancedSymbology::SymbolDictionary::dictionary(symbologyType);
this->setEtsSymbolToDict(dict, fileContentId, name, image, colorToBeReplaced, usrTags);
}
}
void FlmSubscriber::onLocalSymbolProxyEtsSymbolRemoved(qint32 fileContentId, const QString &name)
{
for (const SymbologyType &symbologyType : qAsConst(d->m_symbolDictionaryToUpdate))
{
AdvancedSymbology::SymbolDictionary &dict =
AdvancedSymbology::SymbolDictionary::dictionary(symbologyType);
INFO_LOG(m_logger) << LOGFUNCTION << " dict.removeEtsSymbol:"
<< " symbologyType='" << (int)symbologyType << "'"
<< ", name='" << name << "'"
<< ", fileContentId=" << fileContentId;
dict.removeEtsSymbol(fileContentId);
dict.removeEtsSymbol(name);
}
}
void FlmSubscriber::onLocalSymbolProxyXmlSymbolAdded(qint32 fileContentId,
const QString &operatorName,
qint64 lastModified,
const QString &name,
const QString &xmlContent,
const QStringList &usrTags)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " fileContentId=" << fileContentId
<< " name='" << name << "'";
if (!xmlContent.isEmpty())
{
for (const SymbologyType &symbologyType : qAsConst(d->m_symbolDictionaryToUpdate))
{
AdvancedSymbology::SymbolDictionary &dict =
AdvancedSymbology::SymbolDictionary::dictionary(symbologyType);
if (!this->setXmlSymbolToDict(dict, fileContentId, operatorName, lastModified, name, xmlContent, usrTags))
ERROR_LOG(m_logger) << LOGFUNCTION << " dict.setXmlSymbolToDict failed"
<< ", symbologyType='" << (int)symbologyType << "'"
<< ", name='" << name << "'";
}
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< " fileContentId=" << fileContentId
<< " name='" << name << "'";
}
void FlmSubscriber::onLocalSymbolProxyXmlSymbolRemoved(qint32 fileContentId)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " fileContentId=" << fileContentId;
for (const SymbologyType &symbologyType : qAsConst(d->m_symbolDictionaryToUpdate))
{
AdvancedSymbology::SymbolDictionary &dict =
AdvancedSymbology::SymbolDictionary::dictionary(symbologyType);
DEBUG_LOG(m_logger) << LOGFUNCTION << " dict.removeXmlSymbol:"
<< " symbologyType='" << symbologyType << "'"
<< ", fileContentId=" << fileContentId;
const QString &skey = QString::number(fileContentId);
const QString &sidc = SidcCodec::encodeCivilXml(skey);
dict.removeXmlSymbol(sidc);
dict.removeXmlSymbol(fileContentId);
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END" << " fileContentId=" << fileContentId;
}
//
// Proxy
//
bool FlmSubscriber::connectFlmSymbolProxy(int type_placeholder, SymbologyType symbologyType)
{
Q_UNUSED(type_placeholder);
TRACE_LOG(m_logger) << LOGFUNCTION << " m_fileContentMap.size()=" << d->m_fileContentMap.size() ;
d->m_symbolDictionaryToUpdate.insert(symbologyType);
// ETS
// connect to some signals like added, modified, removed:
connect(&d->m_symbolProxy, &FlmSymbolProxy::etsSymbolAdded,
this, &FlmSubscriber::onLocalSymbolProxyEtsSymbolAdded, Qt::QueuedConnection);
connect(&d->m_symbolProxy, &FlmSymbolProxy::etsSymbolRemoved,
this, &FlmSubscriber::onLocalSymbolProxyEtsSymbolRemoved, Qt::QueuedConnection);
// XML
// connect to some signals like added, modified, removed:
connect(&d->m_symbolProxy, &FlmSymbolProxy::xmlSymbolAdded,
this, &FlmSubscriber::onLocalSymbolProxyXmlSymbolAdded, Qt::QueuedConnection);
connect(&d->m_symbolProxy, &FlmSymbolProxy::xmlSymbolRemoved,
this, &FlmSubscriber::onLocalSymbolProxyXmlSymbolRemoved, Qt::QueuedConnection);
// continue?
if (d->m_symbolProxy.isEmpty())
return true;
AdvancedSymbology::SymbolDictionary &dict =
AdvancedSymbology::SymbolDictionary::dictionary(symbologyType);
// Don´t use QSignalBlocker here!!!
dict.blockSignals(true); // to make sure that set{Ets,Xml}SymbolToDict will NOT emit huge number of 'symbolAdded'
for (auto mapIt = d->m_symbolProxy.getMap().begin(); mapIt != d->m_symbolProxy.getMap().end(); ++mapIt)
{
const int fileContentId = mapIt.key();
const FlmSymbolProxy::SymbolData &symData = mapIt.value();
if (symData.isXmlSymbol())
setXmlSymbolToDict(dict, fileContentId, symData.operatorName(), symData.lastModified(), symData.name(), symData.xmlContent(), symData.usrTags());
else
setEtsSymbolToDict(dict, fileContentId, symData.name(), symData.image(), symData.colorToBeReplaced(), symData.usrTags());
}
dict.blockSignals(false);
return true;
}
bool FlmSubscriber::setEtsSymbolToDict(SymbolDictionary &dict,
qint32 fileContentId,
const QString &name,
const QImage &image,
const QColor &colorToBeReplaced,
const QStringList &usrTags)
{
// -> ETS_%1
SymbolProperties symProps;
symProps.setKey(name);
symProps.setSidc(SidcCodec::encodeCivilEts(name));
symProps.setName(name);
// symProps.setCategory(); // maybe?
symProps.setSymbolClass(QLatin1String("3")); // 18.10.2016, N.Thoden: 3 == PointSymbol (mil2525d.stylx - QuartzRelease)
symProps.setGeometryType(GeometryType::Point); // ETS-Symbols are always Points
symProps.setTags(QStringList() << name << usrTags);
symProps.setColorToBeReplaced(colorToBeReplaced);
if (!dict.setEtsSymbol(fileContentId, symProps.sidc(), symProps, image))
{
ERROR_LOG(m_logger) << LOGFUNCTION << " dict.insertExtraSymbol failed"
<< ", fileContentId=" << fileContentId << ", name='" << name << "'";
return false;
}
else
INFO_LOG(m_logger) << LOGFUNCTION << " dict.insertExtraSymbol done"
<< ", fileContentId=" << fileContentId << ", name='" << name << "'";
return true;
}
bool FlmSubscriber::setXmlSymbolToDict(SymbolDictionary &dict,
qint32 fileContentId,
const QString &operatorName,
qint64 lastModified,
const QString &name,
const QString &xmlContent,
const QStringList &usrTags)
{
SymbolProperties symProps;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* ToDo add more search infos to symProps
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
symProps.setTags(QStringList() << name << usrTags);
bool success = dict.setXmlSymbol(fileContentId, name, operatorName, lastModified, xmlContent, symProps);
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " setXmlSymbol failed:"
<< ", file-id=" << fileContentId
<< ", filenameid='" << name << "'";
return success;
}
} // namespace AdvancedSymbology