Port SymbologyImpl Esri processors to the ArcGIS 300 QFuture async API
TaskWatcher (searchSymbols/fetchSymbol/createSwatch + completion signals) -> QFuture (searchSymbolsAsync/fetchSymbolAsync/createSwatchAsync + QFutureWatcher finished/result getter); flat arcgis/ includes; arcgisversion.h shim (external SDK). advancedSymbology now builds+links vs 300 (0 errors); SymbologyXML CTest 6/6, 0 assertion failures. Migration-only vs legacy; one documented forced delta: 300 has no spec-only DictionarySymbolStyle. Summary: MIGRATION_SUMMARY_ARCGIS300_SYMBOLOGY.md.
This commit is contained in:
13 files changed
+512
-157
No files matched your search
+93
-40
@@ -18,8 +18,9 @@
|
||||
|
||||
|
||||
// arcgis
|
||||
#include <TaskWatcher.h>
|
||||
#include <DictionarySymbolStyle.h>
|
||||
#include <MapTypes.h> // Esri::ArcGISRuntime::LoadStatus (300: enum class; Loadable.h only forward-declares it)
|
||||
#include <Error.h> // Esri::ArcGISRuntime::Error (complete type; 300 dropped Error::code())
|
||||
|
||||
|
||||
// Qt
|
||||
@@ -31,6 +32,9 @@
|
||||
#include <utility>
|
||||
#include <QMimeData>
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtCore/QFuture>
|
||||
#include <QtCore/QFutureWatcher>
|
||||
#include <QtGui/QImage>
|
||||
|
||||
|
||||
namespace AdvancedSymbology
|
||||
@@ -159,7 +163,7 @@ QString BaseSymbolItem::symbolSet()
|
||||
{
|
||||
if (m_symbolSet.isEmpty())
|
||||
{
|
||||
SidcDefinitions::SymbolSet symbolSet = SidcDefinitions::castToSymbolSet(m_symbolProperties.originalKey().left(2).toUInt() // Qt6: leftRef removed);
|
||||
SidcDefinitions::SymbolSet symbolSet = SidcDefinitions::castToSymbolSet(m_symbolProperties.originalKey().left(2).toUInt()); // Qt6: leftRef(2) removed
|
||||
m_symbolSet = QString(QStringLiteral("%1 - ")).arg(static_cast<int>(symbolSet)) + AdvancedSymbology::SidcDefinitions::toString(symbolSet);
|
||||
}
|
||||
return m_symbolSet;
|
||||
@@ -167,7 +171,7 @@ QString BaseSymbolItem::symbolSet()
|
||||
|
||||
int BaseSymbolItem::symbolSetAsInt()
|
||||
{
|
||||
return static_cast<int>(SidcDefinitions::castToSymbolSet(m_symbolProperties.originalKey().left(2).toUInt() // Qt6: leftRef removed));
|
||||
return static_cast<int>(SidcDefinitions::castToSymbolSet(m_symbolProperties.originalKey().left(2).toUInt())); // Qt6: leftRef(2) removed
|
||||
}
|
||||
|
||||
|
||||
@@ -222,23 +226,32 @@ QImage BaseSymbolItem::getSearchSwatch()
|
||||
// qCritical() << " SEARCH: id=" << m_id << " create swatch now";
|
||||
// qCritical() << " SEARCH: id=" << m_esriSearch.m_esriSymbol->toJson();
|
||||
|
||||
connect(m_esriSearch.m_esriSymbol, &Esri::ArcGISRuntime::Symbol::createSwatchCompleted,
|
||||
this, &BaseSymbolItem::onEsriSearchSymbolSwatchCompleted, Qt::UniqueConnection);
|
||||
|
||||
const Esri::ArcGISRuntime::TaskWatcher &tw = m_esriSearch.m_esriSymbol->createSwatch(SWATCH_SIZE, SWATCH_SIZE, 1);
|
||||
if (tw.isValid())
|
||||
m_esriSearch.m_esriTaskUuid = tw.taskId();
|
||||
// ArcGIS 300: no TaskWatcher / createSwatchCompleted — createSwatchAsync() returns a
|
||||
// QFuture<QImage>; a per-request QFutureWatcher delivers the QImage on the main thread.
|
||||
const QFuture<QImage> fut = m_esriSearch.m_esriSymbol->createSwatchAsync(SWATCH_SIZE, SWATCH_SIZE, 1);
|
||||
if (fut.isValid())
|
||||
{
|
||||
m_esriSearch.m_esriTaskUuid = QUuid::createUuid(); // in-flight guard (was the 100.x task id)
|
||||
QFutureWatcher<QImage> *watcher = new QFutureWatcher<QImage>(this);
|
||||
watcher->setFuture(fut);
|
||||
// 300/Qt6: the 'result' signal is name-collision-ambiguous with the result() getter (QOverload
|
||||
// can't disambiguate); connect to the unambiguous finished() signal and read the value via the
|
||||
// result() getter (the future is finished when finished() fires).
|
||||
connect(watcher, &QFutureWatcher<QImage>::finished, watcher,
|
||||
[this, watcher] {
|
||||
onEsriSearchSymbolSwatchCompleted(watcher->result());
|
||||
watcher->deleteLater();
|
||||
});
|
||||
}
|
||||
else
|
||||
qCritical() << " SEARCH: id=" << m_id << " taskId invalid";
|
||||
qCritical() << " SEARCH: id=" << m_id << " createSwatchAsync future invalid";
|
||||
}
|
||||
return m_esriSearch.m_esriSwatch;
|
||||
}
|
||||
|
||||
void BaseSymbolItem::onEsriSearchSymbolSwatchCompleted(const QUuid &taskId, const QImage &image)
|
||||
void BaseSymbolItem::onEsriSearchSymbolSwatchCompleted(const QImage &image)
|
||||
{
|
||||
if (m_esriSearch.m_esriTaskUuid != taskId)
|
||||
return;
|
||||
|
||||
// ArcGIS 300: the dedicated QFutureWatcher makes the (removed) taskId stale-check unnecessary.
|
||||
m_esriSearch.m_esriSwatch = image;
|
||||
|
||||
emit dataChanged(m_id);
|
||||
@@ -251,9 +264,6 @@ QImage BaseSymbolItem::getFetchSwatch() const
|
||||
|
||||
if (m_esriFetch.m_esriSwatch.isNull() && m_esriFetch.m_esriFetchTaskIdUuid.isNull())
|
||||
{
|
||||
connect(m_esriDictionary, &Esri::ArcGISRuntime::DictionarySymbolStyle::fetchSymbolCompleted,
|
||||
this, &BaseSymbolItem::onEsriFetchCompleted, Qt::UniqueConnection);
|
||||
|
||||
// from key8 to sidc (20 digits)
|
||||
const QString &key8 = m_symbolProperties.key().left(8);
|
||||
|
||||
@@ -272,39 +282,57 @@ QImage BaseSymbolItem::getFetchSwatch() const
|
||||
const QVariantMap keys({{QStringLiteral("sidc"), m_esriFetch.m_sidc}, // SidcCodec::decodeRawSidc ; set sidc of symbol in case of MIL2525
|
||||
{QStringLiteral("sic"), m_esriFetch.m_sidc}}); // SidcCodec::decodeRawSidc , set sidc of symbol in case of APP6
|
||||
|
||||
const Esri::ArcGISRuntime::TaskWatcher &tw = m_esriDictionary->fetchSymbol(keys);
|
||||
if (tw.isValid())
|
||||
m_esriFetch.m_esriFetchTaskIdUuid = tw.taskId();
|
||||
// ArcGIS 300: no TaskWatcher / fetchSymbolCompleted — fetchSymbolAsync() returns a
|
||||
// QFuture<Symbol*>; a per-request QFutureWatcher delivers the Symbol* on the main thread.
|
||||
const QFuture<Esri::ArcGISRuntime::Symbol *> fut = m_esriDictionary->fetchSymbolAsync(keys);
|
||||
if (fut.isValid())
|
||||
{
|
||||
m_esriFetch.m_esriFetchTaskIdUuid = QUuid::createUuid(); // in-flight guard (was the 100.x task id)
|
||||
|
||||
BaseSymbolItem *const self = const_cast<BaseSymbolItem *>(this); // this method is const
|
||||
QFutureWatcher<Esri::ArcGISRuntime::Symbol *> *watcher = new QFutureWatcher<Esri::ArcGISRuntime::Symbol *>(self);
|
||||
watcher->setFuture(fut);
|
||||
// 300/Qt6: connect to finished() and read the Symbol* via the result() getter (see above).
|
||||
connect(watcher, &QFutureWatcher<Esri::ArcGISRuntime::Symbol *>::finished, watcher,
|
||||
[self, watcher] {
|
||||
self->onEsriFetchCompleted(watcher->result());
|
||||
watcher->deleteLater();
|
||||
});
|
||||
}
|
||||
else
|
||||
qCritical() << " FETCH: id=" << m_id << " m_esriFetchTaskIdUuid invalid";
|
||||
qCritical() << " FETCH: id=" << m_id << " fetchSymbolAsync future invalid";
|
||||
}
|
||||
return m_esriFetch.m_esriSwatch;
|
||||
}
|
||||
|
||||
void BaseSymbolItem::onEsriFetchCompleted(const QUuid &taskId, Esri::ArcGISRuntime::Symbol *symbol)
|
||||
void BaseSymbolItem::onEsriFetchCompleted(Esri::ArcGISRuntime::Symbol *symbol)
|
||||
{
|
||||
if (m_esriFetch.m_esriFetchTaskIdUuid != taskId)
|
||||
return;
|
||||
// ArcGIS 300: the dedicated QFutureWatcher makes the (removed) taskId stale-check unnecessary.
|
||||
|
||||
// save intermediate result:
|
||||
m_esriFetch.m_esriSymbol = symbol;
|
||||
|
||||
// start creating swatch of fetched symbol:
|
||||
connect(m_esriFetch.m_esriSymbol, &Esri::ArcGISRuntime::Symbol::createSwatchCompleted,
|
||||
this, &BaseSymbolItem::onEsriFetchSymbolSwatchCompleted, Qt::UniqueConnection);
|
||||
|
||||
const Esri::ArcGISRuntime::TaskWatcher &tw = m_esriFetch.m_esriSymbol->createSwatch(SWATCH_SIZE, SWATCH_SIZE, 1);
|
||||
if (tw.isValid())
|
||||
m_esriFetch.m_esriSwatchTaskUuid = tw.taskId();
|
||||
// start creating swatch of fetched symbol (createSwatchAsync -> QFuture<QImage>):
|
||||
const QFuture<QImage> fut = m_esriFetch.m_esriSymbol->createSwatchAsync(SWATCH_SIZE, SWATCH_SIZE, 1);
|
||||
if (fut.isValid())
|
||||
{
|
||||
m_esriFetch.m_esriSwatchTaskUuid = QUuid::createUuid(); // in-flight guard (was the 100.x task id)
|
||||
QFutureWatcher<QImage> *watcher = new QFutureWatcher<QImage>(this);
|
||||
watcher->setFuture(fut);
|
||||
// 300/Qt6: connect to finished() and read the QImage via the result() getter (see above).
|
||||
connect(watcher, &QFutureWatcher<QImage>::finished, watcher,
|
||||
[this, watcher] {
|
||||
onEsriFetchSymbolSwatchCompleted(watcher->result());
|
||||
watcher->deleteLater();
|
||||
});
|
||||
}
|
||||
else
|
||||
qCritical() << " FETCH: id=" << m_id << " taskId invalid";
|
||||
qCritical() << " FETCH: id=" << m_id << " createSwatchAsync future invalid";
|
||||
}
|
||||
|
||||
void BaseSymbolItem::onEsriFetchSymbolSwatchCompleted(const QUuid &taskId, const QImage &image)
|
||||
void BaseSymbolItem::onEsriFetchSymbolSwatchCompleted(const QImage &image)
|
||||
{
|
||||
if (m_esriFetch.m_esriSwatchTaskUuid != taskId)
|
||||
return;
|
||||
|
||||
// ArcGIS 300: the dedicated QFutureWatcher makes the (removed) taskId stale-check unnecessary.
|
||||
m_esriFetch.m_esriSwatch = image;
|
||||
|
||||
// qCritical() << " FETCH: id=" << m_id << " image " << image.size();
|
||||
@@ -426,7 +454,7 @@ void BaseSymbolModel::onLoadStatusChanged(Esri::ArcGISRuntime::LoadStatus loadSt
|
||||
void BaseSymbolModel::onErrorDictionary(const Esri::ArcGISRuntime::Error &error)
|
||||
{
|
||||
FATAL_LOG(m_logger) << LOGFUNCTION << " ---EsriError--- occured: "
|
||||
<< " code=" << error.code()
|
||||
<< " code=" << error.arcGISServerErrorCode().value_or(-1) // 300: Error::code() removed
|
||||
<< ", domain=" << static_cast<int>(error.domain())
|
||||
<< ", extendedErrorType=" << static_cast<int>(error.extendedErrorType())
|
||||
<< ", message='" << error.message() << "'"
|
||||
@@ -456,13 +484,15 @@ void BaseSymbolModel::initModel(SymbolDictionary *symbolDictionary,
|
||||
|
||||
// spend time to create (expensive) Esri::ArcGISRuntime::Symbol?
|
||||
#ifdef LTS_DEBUG
|
||||
Esri::ArcGISRuntime::Symbol *esriSymbol = nullptr;
|
||||
Esri::ArcGISRuntime::Symbol *esriSymbol = nullptr; // 300: filled asynchronously (see below)
|
||||
const bool showAll = QGuiApplication::keyboardModifiers().testFlag(Qt::KeyboardModifier::ControlModifier);
|
||||
if (showAll)
|
||||
esriSymbol = searchResult.symbol(this); // symbol() has to be called from mainThread, is expensive / time consuming
|
||||
// 300: symbol() (const, sync, mainThread) is gone; fetchSymbolAsync() is non-const + async.
|
||||
// When showAll, the Symbol is fetched after the item exists and attached via
|
||||
// setEsriSearchSymbol() when the future completes.
|
||||
#else
|
||||
// release mode: save time, won´t be visible
|
||||
Esri::ArcGISRuntime::Symbol *esriSymbol = nullptr;
|
||||
const bool showAll = false;
|
||||
#endif // LTS_DEBUG
|
||||
|
||||
|
||||
@@ -470,6 +500,29 @@ void BaseSymbolModel::initModel(SymbolDictionary *symbolDictionary,
|
||||
|
||||
bsi->setSymbolDictionary(symbolDictionary);
|
||||
|
||||
#ifdef LTS_DEBUG
|
||||
// 300: fetch the Symbol asynchronously and attach it to the item when the future completes.
|
||||
// fetchSymbolAsync() is non-const; copy the (const) search result to call it.
|
||||
if (showAll)
|
||||
{
|
||||
Esri::ArcGISRuntime::SymbolStyleSearchResult sr(searchResult);
|
||||
QFuture<Esri::ArcGISRuntime::Symbol *> fut = sr.fetchSymbolAsync(this);
|
||||
if (fut.isValid())
|
||||
{
|
||||
QFutureWatcher<Esri::ArcGISRuntime::Symbol *> *watcher = new QFutureWatcher<Esri::ArcGISRuntime::Symbol *>(this);
|
||||
watcher->setFuture(fut);
|
||||
// 300/Qt6: connect to finished() and read the Symbol* via the result() getter (see above).
|
||||
connect(watcher, &QFutureWatcher<Esri::ArcGISRuntime::Symbol *>::finished, watcher,
|
||||
[bsi, watcher] {
|
||||
Esri::ArcGISRuntime::Symbol *symbol = watcher->result();
|
||||
if (symbol)
|
||||
bsi->setEsriSearchSymbol(symbol);
|
||||
watcher->deleteLater();
|
||||
});
|
||||
}
|
||||
}
|
||||
#endif // LTS_DEBUG
|
||||
|
||||
bsi->m_symbolProperties.setTags(searchResult.tags());
|
||||
bsi->m_symbolProperties.setName(searchResult.name());
|
||||
bsi->m_symbolProperties.setSymbolClass(searchResult.symbolClass());
|
||||
|
||||
Reference in new issue
Block a user