Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
@@ -0,0 +1,394 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Interface-Implementation of EsriDictionaryProcessor
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
// Own
|
||||
#include "esri_dictionary_processor.h"
|
||||
|
||||
#include "symbol_dictionary.h" // Interface (enums)
|
||||
#include <Common/situation_map_logging.h>
|
||||
|
||||
|
||||
// ESRI
|
||||
#include <arcgis/TaskWatcher.h>
|
||||
#include <arcgis/Symbol.h>
|
||||
#include <arcgis/SymbolStyleSearchParameters.h>
|
||||
#include <arcgis/SymbolStyleSearchResultListModel.h>
|
||||
#include <arcgis/SymbolStyleSearchResult.h>
|
||||
|
||||
|
||||
// Qt
|
||||
#include <QtConcurrent>
|
||||
#include <QFuture>
|
||||
|
||||
#define CREATE_ESRI_SYMBOL_ON_DEMAND // save time on startup
|
||||
// REGG-3483 - EsriDictionaryProcessor::syncTableWithinMainThread verzögert Applikations-Start um mehrere Sekunden
|
||||
|
||||
QImage AdvancedSymbology::scaleImage(const QImage &image, int sizeL)
|
||||
{
|
||||
if (sizeL == 100)
|
||||
return image;
|
||||
double factor = sizeL / 100.0;
|
||||
const QSize &newSize = image.size() * factor;
|
||||
return image.scaled(newSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
}
|
||||
|
||||
|
||||
namespace AdvancedSymbology
|
||||
{
|
||||
|
||||
EsriDictionaryProcessor::EsriDictionaryProcessor(SymbologyType symbologyType)
|
||||
: m_logger(getLogger("EsriDictionaryProcessor")),
|
||||
m_baseSymbolCodeToSymbolPropertyTable(symbologyType, SidcCodec::SidcType::Base)
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " ThreadId=" << QThread::currentThreadId();
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
||||
}
|
||||
|
||||
EsriDictionaryProcessor::~EsriDictionaryProcessor()
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
||||
this->cancel();
|
||||
this->waitForFinished();
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
||||
}
|
||||
|
||||
void EsriDictionaryProcessor::cancel()
|
||||
{
|
||||
NOTICE_LOG(m_logger) << LOGFUNCTION << " canceling ...";
|
||||
m_baseSymbolCodeToSymbolPropertyTableWatcher.cancel(); // Job 1
|
||||
m_modifierTableWatcher.cancel(); // Job 2
|
||||
// Job n
|
||||
NOTICE_LOG(m_logger) << LOGFUNCTION << " canceling ... done";
|
||||
}
|
||||
|
||||
void EsriDictionaryProcessor::waitForFinished()
|
||||
{
|
||||
NOTICE_LOG(m_logger) << LOGFUNCTION << " waitForFinished ...";
|
||||
m_baseSymbolCodeToSymbolPropertyTableWatcher.waitForFinished(); // Job 1
|
||||
m_modifierTableWatcher.waitForFinished(); // Job 2
|
||||
// Job n
|
||||
NOTICE_LOG(m_logger) << LOGFUNCTION << " waitForFinished ... done";
|
||||
}
|
||||
|
||||
void EsriDictionaryProcessor::init(Esri::ArcGISRuntime::DictionarySymbolStyle *loaded_esri_dictionary)
|
||||
{
|
||||
m_esri_dictionary = loaded_esri_dictionary;
|
||||
}
|
||||
|
||||
void EsriDictionaryProcessor::prepare()
|
||||
{
|
||||
searchSymbols();
|
||||
}
|
||||
|
||||
void EsriDictionaryProcessor::searchSymbols()
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
||||
|
||||
//
|
||||
// search for all results (and store them in member):
|
||||
//
|
||||
|
||||
connect(m_esri_dictionary, &Esri::ArcGISRuntime::DictionarySymbolStyle::searchSymbolsCompleted,
|
||||
this, &EsriDictionaryProcessor::onSearchSymbolsCompletedPropertyTable, Qt::UniqueConnection);
|
||||
|
||||
Esri::ArcGISRuntime::SymbolStyleSearchParameters sssp;
|
||||
|
||||
Esri::ArcGISRuntime::TaskWatcher tw = m_esri_dictionary->searchSymbols(sssp);
|
||||
if (tw.isValid())
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << " TaskWatcher valid: ssTaskId=" << tw.taskId().toString();
|
||||
else
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << " TaskWatcher invalid" << " ThreadId=" << QThread::currentThreadId();
|
||||
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
||||
|
||||
}
|
||||
|
||||
void EsriDictionaryProcessor::startBaseSymbolCodeToPropertyTable()
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
||||
|
||||
// A-sync:
|
||||
// (slot is a pure virtual method)
|
||||
m_baseSymbolCodeToSymbolPropertyTableWatcher = QtConcurrent::run(this, &EsriDictionaryProcessor::processBaseSymbolCodeToPropertyTable);
|
||||
|
||||
|
||||
// Sync: // processBaseSymbolCodeToPropertyTable();
|
||||
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
||||
}
|
||||
|
||||
void EsriDictionaryProcessor::startModifierTable()
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
||||
|
||||
// A-sync:
|
||||
// (slot is a pure virtual method)
|
||||
m_modifierTableWatcher = QtConcurrent::run(this, &EsriDictionaryProcessor::processModifierTable);
|
||||
|
||||
// Sync: // processModifierTable();
|
||||
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
||||
}
|
||||
|
||||
QStringList EsriDictionaryProcessor::symbolModifierKeys() const
|
||||
{
|
||||
return m_modifierTable.keys();
|
||||
} // QStringList EsriDictionaryProcessor::symbolModifierKeys() const
|
||||
|
||||
|
||||
bool EsriDictionaryProcessor::symbolModifierData(const QString &key, ModifierData &data) const
|
||||
{
|
||||
if (!m_modifierTable.contains(key)) return false;
|
||||
data = m_modifierTable[key];
|
||||
return true;
|
||||
} // bool EsriDictionaryProcessor::symbolModifierData(const QString & key, SymbolDictionary::ModifierData & data) const
|
||||
|
||||
|
||||
QVector<ModifierData> EsriDictionaryProcessor::symbolModifierList(SidcDefinitions::SymbolSet symbolSet, unsigned int modifierSector) const
|
||||
{
|
||||
// check modifierSector, must be 1 or 2
|
||||
|
||||
if ((modifierSector < 1) || (modifierSector > 2))
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << " Illegal modifierSector \"" << modifierSector << "\". Must be 1 or 2.";
|
||||
return QVector<ModifierData>();
|
||||
}
|
||||
|
||||
|
||||
QVector<ModifierData> resultList;
|
||||
resultList.reserve(m_modifierTable.size());
|
||||
|
||||
QMapIterator<QString, ModifierData> hIt(m_modifierTable);
|
||||
while (hIt.hasNext())
|
||||
{
|
||||
hIt.next();
|
||||
if ((hIt.value().m_symbolSet == symbolSet) && (hIt.value().m_modifierSector == modifierSector))
|
||||
resultList << hIt.value();
|
||||
}
|
||||
return resultList;
|
||||
} // QVector<SymbolDictionary::ModifierData> EsriDictionaryProcessor::symbolModifierList(const QString & baseSymbolCode, unsigned int modifierSector) const
|
||||
|
||||
|
||||
|
||||
bool EsriDictionaryProcessor::allJobsDone() const
|
||||
{
|
||||
return
|
||||
m_baseSymbolCodeToSymbolPropertyTableFilled && // Job 1
|
||||
m_modifierTableFilled; // Job 2
|
||||
// Job n
|
||||
}
|
||||
|
||||
void EsriDictionaryProcessor::onSearchSymbolsCompletedPropertyTable(QUuid, Esri::ArcGISRuntime::SymbolStyleSearchResultListModel *searchResults)
|
||||
{
|
||||
// ssTaskId can be ignored during initializing phase:
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
||||
|
||||
// save:
|
||||
m_searchResultList = searchResults->searchResults();
|
||||
// m_searchResultList << searchResults->searchResults().first(); // speed up for valgrind
|
||||
|
||||
// cleanup:
|
||||
searchResults->deleteLater();
|
||||
|
||||
// disconnect:
|
||||
disconnect(m_esri_dictionary, &Esri::ArcGISRuntime::DictionarySymbolStyle::searchSymbolsCompleted,
|
||||
this, &EsriDictionaryProcessor::onSearchSymbolsCompletedPropertyTable);
|
||||
|
||||
// method 'symbol' has to be called (created) within mainThread:
|
||||
syncTableWithinMainThread();
|
||||
|
||||
|
||||
//
|
||||
// trigger single jobs:
|
||||
//
|
||||
startBaseSymbolCodeToPropertyTable(); // Job 1
|
||||
startModifierTable(); // Job 2
|
||||
// Job n
|
||||
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " END, m_searchResultList.size()=" << m_searchResultList.size();
|
||||
}
|
||||
|
||||
void EsriDictionaryProcessor::onEsriSymbolSwatchCompleted(const QUuid &csTaskId, const QImage &image)
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
|
||||
<< " csTaskId= '" << csTaskId << "'"
|
||||
<< " image.isNull= '" << image.isNull() << "'"
|
||||
<< " image.colorTable().size()= '" << image.colorTable().size() << "'"
|
||||
<< " ThreadId=" << QThread::currentThreadId();
|
||||
|
||||
auto it = m_symbolPropertyImage2symbolResult.find(csTaskId);
|
||||
if (it == m_symbolPropertyImage2symbolResult.end())
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << " no taskIdMapping"
|
||||
<< " csTaskId= '" << csTaskId << "'";
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << " SymbolResult found..." << " csTaskId= '" << csTaskId << "'";
|
||||
QSharedPointer<SymbolResult> symResult = it.value().toStrongRef();
|
||||
if (symResult)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << " SymbolResult found and still valid..."
|
||||
<< " csTaskId= '" << csTaskId << "'";
|
||||
|
||||
const SymbolDataToRender &symDataToRender = symResult->symbolDataToRender();
|
||||
|
||||
// save in 'cache':
|
||||
const QString &originalKey = symDataToRender.spiOriginalKey;
|
||||
const int sizeL = symDataToRender.spiSizeL;
|
||||
auto itCache = m_originalKeyToEsriSymbol.find(originalKey);
|
||||
if (itCache == m_originalKeyToEsriSymbol.end())
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << " save to cache, not found, " << " originalKey= '" << originalKey << "'"
|
||||
<< " csTaskId= '" << csTaskId << "'";
|
||||
}
|
||||
else
|
||||
itCache.value().swatchImage = image;
|
||||
|
||||
// return value
|
||||
SymbolImage symImage;
|
||||
|
||||
const QImage &scaledImg = scaleImage(image, sizeL);
|
||||
|
||||
if (scaledImg.isNull())
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION
|
||||
<< " image.isNull() = " << image.isNull()
|
||||
<< " scaledImg.isNull() = " << scaledImg.isNull()
|
||||
<< " sizeL=" << sizeL;
|
||||
}
|
||||
|
||||
symImage.setImage(scaledImg);
|
||||
symImage.setValid(true);
|
||||
symResult->setSymbolImage(symImage);
|
||||
symResult->fireResultReady(); // ToDo: maybe async!?!?
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
INFO_LOG(m_logger) << LOGFUNCTION << " SymbolResult has already been deleted"
|
||||
<< " csTaskId= '" << csTaskId << "'";
|
||||
}
|
||||
|
||||
// cleanup
|
||||
m_symbolPropertyImage2symbolResult.erase(it);
|
||||
}
|
||||
|
||||
void EsriDictionaryProcessor::checkIfAllAreDone()
|
||||
{
|
||||
if (allJobsDone())
|
||||
emit allIsDone();
|
||||
}
|
||||
|
||||
void EsriDictionaryProcessor::syncTableWithinMainThread()
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
||||
|
||||
// for ALL searchResuls (for valid baseSymbolCodes, for modifierTable...)
|
||||
for (const Esri::ArcGISRuntime::SymbolStyleSearchResult &resultItem : qAsConst(m_searchResultList))
|
||||
{
|
||||
const QString &originalKey = resultItem.key();
|
||||
|
||||
// store esriSymbol for rendering issues:
|
||||
EsriSymbol eSym;
|
||||
#ifdef CREATE_ESRI_SYMBOL_ON_DEMAND
|
||||
eSym.m_sssResult =resultItem;
|
||||
#else
|
||||
QObject *parent = this;
|
||||
eSym.esriSymbol = resultItem.symbol(parent); // resultItem.symbol() has to be called from mainThread???
|
||||
#endif // CREATE_ESRI_SYMBOL_ON_DEMAND
|
||||
m_originalKeyToEsriSymbol[originalKey] = eSym;
|
||||
}
|
||||
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " END, m_originalKeyToEsriSymbol.size=" << m_originalKeyToEsriSymbol.size();
|
||||
}
|
||||
|
||||
bool EsriDictionaryProcessor::symbolPropertyImageContains(const QString &originalKey) const
|
||||
{
|
||||
return m_originalKeyToEsriSymbol.contains(originalKey);
|
||||
}
|
||||
|
||||
QSharedPointer<SymbolResult> EsriDictionaryProcessor::symbolPropertyImage(QSharedPointer<SymbolResult> symResult, const QString &originalKey) const
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
||||
|
||||
auto it = m_originalKeyToEsriSymbol.find(originalKey);
|
||||
if (it == m_originalKeyToEsriSymbol.end())
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << " not found, " << " originalKey= '" << originalKey << "'";
|
||||
return symResult;
|
||||
}
|
||||
|
||||
const EsriSymbol &eSym = it.value();
|
||||
|
||||
if (eSym.swatchImage.isNull())
|
||||
{
|
||||
#ifdef CREATE_ESRI_SYMBOL_ON_DEMAND
|
||||
if (!eSym.esriSymbol)
|
||||
{
|
||||
QObject *parent = const_cast<EsriDictionaryProcessor *>(this); // cast const away
|
||||
eSym.esriSymbol = eSym.m_sssResult.symbol(parent); // resultItem.symbol() has to be called from mainThread???
|
||||
}
|
||||
#endif // CREATE_ESRI_SYMBOL_ON_DEMAND
|
||||
|
||||
connect(eSym.esriSymbol, &Esri::ArcGISRuntime::Symbol::createSwatchCompleted,
|
||||
this, &EsriDictionaryProcessor::onEsriSymbolSwatchCompleted, Qt::UniqueConnection);
|
||||
|
||||
#ifdef USE_ARCADE_SYMBOLOGY
|
||||
Esri::ArcGISRuntime::TaskWatcher tw;
|
||||
auto it = m_baseSymbolCodeToSymbolPropertyTable.find(originalKey);
|
||||
if (it != m_baseSymbolCodeToSymbolPropertyTable.end() && (it->geometryType() == GeometryType::Polygon) )
|
||||
// area/Polygon -> request rectangle, otherwise quadratic swatch:
|
||||
tw = eSym.esriSymbol->createSwatch(CREATE_SWATCH_PARAMETER.m_width, CREATE_SWATCH_PARAMETER.m_height, CREATE_SWATCH_PARAMETER.m_screenScale);
|
||||
else
|
||||
tw = eSym.esriSymbol->createSwatch(CREATE_SWATCH_PARAMETER.m_height, CREATE_SWATCH_PARAMETER.m_height, CREATE_SWATCH_PARAMETER.m_screenScale);
|
||||
|
||||
#else
|
||||
Esri::ArcGISRuntime::TaskWatcher tw = eSym.esriSymbol->createSwatch(CREATE_SWATCH_SCREEN_SCALE);
|
||||
#endif // USE_ARCADE_SYMBOLOGY
|
||||
QUuid csTaskId;
|
||||
if (tw.isValid())
|
||||
{
|
||||
csTaskId = tw.taskId();
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << " csTaskWatcher valid: csTaskId=" << csTaskId;
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << " csTaskWatcher invalid"
|
||||
<< " ThreadId=" << QThread::currentThreadId();
|
||||
}
|
||||
|
||||
if (! csTaskId.isNull())
|
||||
m_symbolPropertyImage2symbolResult[csTaskId] = symResult.toWeakRef();
|
||||
else
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << " csTaskWatcher invalid";
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// use from 'cache':
|
||||
SymbolImage symImage;
|
||||
|
||||
const SymbolDataToRender &symDataToRender = symResult->symbolDataToRender();
|
||||
int sizeL = symDataToRender.sizeL;
|
||||
|
||||
const QImage &scaledImg = scaleImage(eSym.swatchImage, sizeL);
|
||||
|
||||
symImage.setImage(scaledImg);
|
||||
symImage.setValid(true);
|
||||
symResult->setSymbolImage(symImage);
|
||||
symResult->fireResultReady(); // ToDo: maybe async!?!?
|
||||
}
|
||||
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
||||
return symResult;
|
||||
}
|
||||
|
||||
} // namespace AdvancedSymbology
|
||||
|
||||
Reference in new issue
Block a user