Files
qt5-legatus-legacy/Lts/Viewer/SituationMap/SymbologyImpl/base_symbol_model.cpp
T
2026-08-13 18:33:10 +02:00

1089 lines
35 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@
* (Base) Symbol Model for Esri, XML, ETS Symbols
* $Id$
* $HeadURL$
* $Author$
* Created by Norbert Thoden, NLE, 12.12.2019
*/
// Own
#include "base_symbol_model.h"
#include "symbol_dictionary_impl.h"
#include "sidc_codec.h"
#include "sidc_builder_base.h"
#include <LtsWidgets/lts_column_filter_proxy_model.h>
#include <ngltools/ngltools_dtg.h>
// arcgis
#include <arcgis/TaskWatcher.h>
#include <arcgis/DictionarySymbolStyle.h>
// Qt
#include <QGuiApplication>
#include <QString>
#include <QUuid>
#include <QByteArray>
#include <QBuffer>
#include <QMimeData>
#include <QTimer>
namespace AdvancedSymbology
{
static constexpr int SWATCH_SIZE = 64;
static constexpr int ICON_SIZE_CUSTOM = 50;
QString geometryTypeToDisplayString(GeometryType geomType)
{
switch (geomType)
{
case GeometryType::Point:
return QObject::tr("Point");
case GeometryType::Polyline:
return QObject::tr("Line");
case GeometryType::Polygon:
return QObject::tr("Area");
case GeometryType::Undefined:
return QObject::tr("Undefined");
}
return QObject::tr("Undefined");
}
//------------------------------------------------------------------------------
// ResultWatcherData
//------------------------------------------------------------------------------
void ResultWatcherData::onResultReady()
{
if (!m_symbolResultWatcher)
return;
QSharedPointer<AdvancedSymbology::SymbolResult> symResult = m_symbolResultWatcher->symbolResult();
if (!symResult)
return; // should NEVER happen! (Which object should have triggered the signal???)
m_orgImage = symResult->symbolImage().image();
m_scaledImage = m_orgImage.scaled(ICON_SIZE_CUSTOM, ICON_SIZE_CUSTOM, Qt::KeepAspectRatio, Qt::SmoothTransformation);
// update view:
if (m_baseSymbolItem)
m_baseSymbolItem->emit_dataChanged();
}
//------------------------------------------------------------------------------
// BaseSymbolItem
//------------------------------------------------------------------------------
BaseSymbolItem::BaseSymbolItem(int id, Esri::ArcGISRuntime::Symbol *esriSymbol_Search)
: QObject()
{
m_id = id;
m_esriSearch.m_esriSymbol = esriSymbol_Search;
m_findBaseSymbolRWD = new ResultWatcherData(this);
m_findPreviewRWD = new ResultWatcherData(this);
m_findImageRWD = new ResultWatcherData(this);
}
BaseSymbolItem::BaseSymbolItem(int id, const QString &baseSymbolCode, const QString &operatorName, qint64 lastModified, const SymbologyXML::Symbol &symbol)
: QObject()
, m_id(id)
, m_operatorName(operatorName)
, m_lastModified(lastModified)
{
setXmlSymbol(symbol);
m_baseSymbolCode = baseSymbolCode;
m_findBaseSymbolRWD = new ResultWatcherData(this);
m_findPreviewRWD = new ResultWatcherData(this);
m_findImageRWD = new ResultWatcherData(this);
}
BaseSymbolItem::BaseSymbolItem(int id, const QString &baseSymbolCode, const QImage &image)
: QObject()
, m_id(id)
, m_baseSymbolCode(baseSymbolCode)
{
m_findBaseSymbolRWD = new ResultWatcherData(this);
m_findBaseSymbolRWD->image() = image;
m_findBaseSymbolRWD->originalImage() = image;
}
BaseSymbolItem::~BaseSymbolItem()
{
delete m_findBaseSymbolRWD;
delete m_findPreviewRWD;
delete m_findImageRWD;
delete m_xmlSymbol;
}
void BaseSymbolItem::setSymbolDictionary(SymbolDictionary *symbolDictionary)
{
m_symbolDictionaryImpl = static_cast<SymbolDictionaryImpl *>(symbolDictionary);
m_esriDictionary = const_cast<Esri::ArcGISRuntime::DictionarySymbolStyle *>(m_symbolDictionaryImpl->getEsriSymbolDictionary());
}
void BaseSymbolItem::setEsriSearchSymbol(Esri::ArcGISRuntime::Symbol *esriSymbol_Search)
{
m_esriSearch.m_esriSymbol = esriSymbol_Search;
}
void BaseSymbolItem::setXmlSymbol(const SymbologyXML::Symbol &symbol)
{
delete m_xmlSymbol;
if (!m_xmlSymbol)
m_xmlSymbol = new XmlSymbolStruct;
m_xmlSymbol->m_symbol = symbol;
}
QString BaseSymbolItem::baseSymbolCode()
{
if (m_baseSymbolCode.isEmpty() && m_symbolDictionaryImpl)
m_baseSymbolCode = AdvancedSymbology::SidcCodec::encodeBaseSymbolCode(m_symbolDictionaryImpl->symbologyType(),
m_symbolProperties.originalKey().left(8));
return m_baseSymbolCode;
}
QString BaseSymbolItem::sidc()
{
return AdvancedSymbology::SidcBuilderBase::baseSymbolCodeToSidc(baseSymbolCode());
}
QString BaseSymbolItem::symbolSet()
{
if (m_symbolSet.isEmpty())
{
SidcDefinitions::SymbolSet symbolSet = SidcDefinitions::castToSymbolSet(m_symbolProperties.originalKey().leftRef(2).toUInt());
m_symbolSet = QString(QStringLiteral("%1 - ")).arg(static_cast<int>(symbolSet)) + AdvancedSymbology::SidcDefinitions::toString(symbolSet);
}
return m_symbolSet;
}
int BaseSymbolItem::symbolSetAsInt()
{
return static_cast<int>(SidcDefinitions::castToSymbolSet(m_symbolProperties.originalKey().leftRef(2).toUInt()));
}
QString BaseSymbolItem::getTooltip(const QImage &image)
{
QString tooltip;
const AdvancedSymbology::SymbolProperties &symProp = m_symbolProperties;
QByteArray data;
QBuffer buffer(&data);
image.save(&buffer, "PNG", 100);
const QString paragraphBegin = QStringLiteral("<center>");
const QString paragraphEnd = QStringLiteral("</center>");
const QString separator = QStringLiteral("<br/>");
tooltip = QStringLiteral("<html>");
tooltip += paragraphBegin;
tooltip += QStringLiteral("<img src='data:image/png;base64,%1'>").arg(QString::fromLatin1(data.toBase64()));
tooltip += paragraphEnd; // + QStringLiteral("<hr>");
tooltip += paragraphBegin;
tooltip += symProp.name();
tooltip += paragraphEnd;
tooltip += paragraphBegin;
tooltip += baseSymbolCode();
tooltip += paragraphEnd;
tooltip += QStringLiteral("<hr>");
// tooltip += separator;
tooltip += paragraphBegin + geometryTypeToDisplayString(symProp.geometryType()) + paragraphEnd;
tooltip += QStringLiteral("<hr>");
tooltip += paragraphBegin + symProp.tags().join(separator) + paragraphEnd;
tooltip += QStringLiteral("</html>");
return tooltip;
}
QImage BaseSymbolItem::getSearchSwatch()
{
// if (!m_esriSearch.m_esriSymbol)
// m_esriSearch.m_esriSymbol = m_esriSearch.m_sssResult.symbol(this);
if (m_esriSearch.m_esriSwatch.isNull() && m_esriSearch.m_esriSymbol && m_esriSearch.m_esriTaskUuid.isNull())
{
// ok, create swatch now:
// 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();
else
qCritical() << " SEARCH: id=" << m_id << " taskId invalid";
}
return m_esriSearch.m_esriSwatch;
}
void BaseSymbolItem::onEsriSearchSymbolSwatchCompleted(const QUuid &taskId, const QImage &image)
{
if (m_esriSearch.m_esriTaskUuid != taskId)
return;
m_esriSearch.m_esriSwatch = image;
emit dataChanged(m_id);
}
QImage BaseSymbolItem::getFetchSwatch() const
{
if (!m_symbolDictionaryImpl || !m_symbolDictionaryImpl->getEsriSymbolDictionary())
return m_esriFetch.m_esriSwatch;
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);
// "10011500002102000000"
// 0123456789
m_esriFetch.m_sidc = QString(QStringLiteral("10011500002102000000"));
m_esriFetch.m_sidc.replace(4, 2, key8.left(2)); // SymbolSet
m_esriFetch.m_sidc.replace(10, 6, key8.right(6)); // Entity
// static int s_counter = 0;
// qCritical() << " FETCH: id=" << m_id << " fetch now"
// << " sidc='" << m_esriFetch.m_sidc << "'"
// << " s_counter=" << s_counter++;
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();
else
qCritical() << " FETCH: id=" << m_id << " m_esriFetchTaskIdUuid invalid";
}
return m_esriFetch.m_esriSwatch;
}
void BaseSymbolItem::onEsriFetchCompleted(const QUuid &taskId, Esri::ArcGISRuntime::Symbol *symbol)
{
if (m_esriFetch.m_esriFetchTaskIdUuid != taskId)
return;
// 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();
else
qCritical() << " FETCH: id=" << m_id << " taskId invalid";
}
void BaseSymbolItem::onEsriFetchSymbolSwatchCompleted(const QUuid &taskId, const QImage &image)
{
if (m_esriFetch.m_esriSwatchTaskUuid != taskId)
return;
m_esriFetch.m_esriSwatch = image;
// qCritical() << " FETCH: id=" << m_id << " image " << image.size();
emit dataChanged(m_id);
}
//------------------------------------------------------------------------------
// BaseSymbolModel::Private
//------------------------------------------------------------------------------
struct BaseSymbolModel::Private
{
SymbolDictionaryImpl *m_symbolDictionaryImpl = nullptr;
Esri::ArcGISRuntime::DictionarySymbolStyle *m_esriDictionary = nullptr;
// findBaseSymbol-Uuid -> SymbolResult
mutable QMap<QUuid, QWeakPointer<SymbolResult>> m_findBaseSymbol2symbolResult;
QTimer *m_finishInitializationTimer = nullptr;
// For proxyModel
QSet<QString> m_usedOperator;
QMap<int, QString> m_usedSymbolSet;
QSet<QString> m_usedSymbolClass;
QSet<double> m_usedXmlSymbolScale;
QSet<AdvancedSymbology::GeometryType> m_usedGeometryTypes;
QSet<QString> m_usedCategory;
QSet<QString> m_usedGctStrings;
};
//------------------------------------------------------------------------------
// BaseSymbolModel
//------------------------------------------------------------------------------
BaseSymbolModel::BaseSymbolModel(SymbolDictionary *symbolDictionary)
: BaseClass(
{
tr("Id"),
tr("SearchIcon"), // de: so lassen
tr("FetchIcon"), // de: so lassen
tr("Icon"), // ((SD-findBaseSymbol))
tr("SD-findPreview"),
tr("SD-findImage"),
tr("Org_key"),
tr("Key"),
tr("BaseSymbolCode"), // de: so lassen
tr("Sidc"),
tr("SymbolSet"), // de: Symbolset
tr("Name"),
tr("Operator"), // de: Benutzer
tr("last modified"), // de: letzte Änderung (analog zu flm)
tr("Scale"), // ((XmlSymbolSize)) de: Skalierung (analog zum SymbolEditor)
tr("Category"), // de: so lassen
tr("SymbolClass"), // de: so lassen
tr("Tags"), // de: so lassen
tr("GCTString"), // de: so lassen
tr("GeometryType") // de: Geometrytyp
},
symbolDictionary) // parent
, m_logger(getLogger("BaseSymbolModel"))
, d(new Private())
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
d->m_symbolDictionaryImpl = static_cast<SymbolDictionaryImpl *>(symbolDictionary);
d->m_esriDictionary = const_cast<Esri::ArcGISRuntime::DictionarySymbolStyle *>(d->m_symbolDictionaryImpl->getEsriSymbolDictionary());
//// QString path = QStringLiteral("/usr/share/arcgis/resources/symbols/mil2525d/mil2525d.stylx");
// QString path = QStringLiteral("/usr/share/arcgis/resources/symbols_arcade/mil2525d/mil2525d.stylx");
// d->m_esri_dictionary = Esri::ArcGISRuntime::DictionarySymbolStyle::createFromFile(path, this);
// if (d->m_esri_dictionary)
// {
// connect(d->m_esri_dictionary, &Esri::ArcGISRuntime::DictionarySymbolStyle::loadStatusChanged,
// this, &BaseSymbolModel::onLoadStatusChanged);
// connect(d->m_esri_dictionary, &Esri::ArcGISRuntime::DictionarySymbolStyle::errorOccurred,
// this, &BaseSymbolModel::onErrorDictionary);
// }
// d->m_esri_dictionary->load();
d->m_finishInitializationTimer = new QTimer(this);
d->m_finishInitializationTimer->setSingleShot(true);
d->m_finishInitializationTimer->setInterval(500);
connect(d->m_finishInitializationTimer, &QTimer::timeout,
this, &BaseSymbolModel::onFinishInitalization);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
BaseSymbolModel::~BaseSymbolModel()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
delete d->m_finishInitializationTimer;
delete d;
d = nullptr;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void BaseSymbolModel::onLoadStatusChanged(Esri::ArcGISRuntime::LoadStatus loadStatus)
{
if (loadStatus == Esri::ArcGISRuntime::LoadStatus::Loaded)
{
INFO_LOG(m_logger) << LOGFUNCTION << " ***** m_esri_dictionary " << d->m_esriDictionary
<< " loading done ";
}
}
void BaseSymbolModel::onErrorDictionary(const Esri::ArcGISRuntime::Error &error)
{
FATAL_LOG(m_logger) << LOGFUNCTION << " ---EsriError--- occured: "
<< " code=" << error.code()
<< ", domain=" << static_cast<int>(error.domain())
<< ", extendedErrorType=" << static_cast<int>(error.extendedErrorType())
<< ", message='" << error.message() << "'"
<< ", additionalMessage='" << error.additionalMessage() << "'";
}
void BaseSymbolModel::initModel(SymbolDictionary *symbolDictionary,
const QList<Esri::ArcGISRuntime::SymbolStyleSearchResult> &searchResultList,
const SidcCodec::SidcHashTable<SymbolProperties> &baseSymbolCodeToSymbolPropertyTable)
{
clear();
int itemCounter = 0;
QVector<DATA_T> vecData;
vecData.reserve(searchResultList.size());
for (const Esri::ArcGISRuntime::SymbolStyleSearchResult &searchResult : qAsConst(searchResultList))
{
GeometryType gt = GeometryType::Undefined;
auto it = baseSymbolCodeToSymbolPropertyTable.find(searchResult.key().left(8));
if (it != baseSymbolCodeToSymbolPropertyTable.end())
gt = it->geometryType();
#ifndef LTS_DEBUG
else
continue; /// release mode -> skip entries with GeometryType::Undefined
#endif // LTS_DEBUG
// spend time to create (expensive) Esri::ArcGISRuntime::Symbol?
#ifdef LTS_DEBUG
Esri::ArcGISRuntime::Symbol *esriSymbol = nullptr;
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
#else
// release mode: save time, won´t be visible
Esri::ArcGISRuntime::Symbol *esriSymbol = nullptr;
#endif // LTS_DEBUG
BaseSymbolItem *bsi = new BaseSymbolItem(itemCounter++, esriSymbol);
bsi->setSymbolDictionary(symbolDictionary);
bsi->m_symbolProperties.setTags(searchResult.tags());
bsi->m_symbolProperties.setName(searchResult.name());
bsi->m_symbolProperties.setSymbolClass(searchResult.symbolClass());
bsi->m_symbolProperties.setCategory(searchResult.category());
bsi->m_symbolProperties.setKey(searchResult.key().left(8));
bsi->m_symbolProperties.setOriginalKey(searchResult.key()); // searchResult does not have orgKey
bsi->m_symbolProperties.setGeometryType(gt);
connect(bsi, &BaseSymbolItem::dataChanged,
this, &BaseSymbolModel::onDataChanged);
vecData.append(DATA_T(bsi));
} // for
this->setData(vecData);
triggerFinishInitalization();
}
bool BaseSymbolModel::insertXmlSymbol(int fileId, const QString &operatorName, qint64 lastModified, const SymbologyXML::Symbol &symbol, const SymbolProperties &properties)
{
INFO_LOG(m_logger) << LOGFUNCTION << " START"
<< ", fileId=" << fileId
<< ", operatorName='" << operatorName << "'"
<< ", lastModified=" << lastModified
<< ", symbol.id=" << symbol.id()
<< ", symbol.getName=" << symbol.getName();
if (fileId < 0)
{
FATAL_LOG(m_logger) << " fileId not valid. fileId=" << fileId;
return false;
}
if (!symbol.isValid())
{
FATAL_LOG(m_logger) << " symbol not valid. fileId=" << fileId;
return false;
}
BaseSymbolItem *bsi = new BaseSymbolItem(fileId, SidcCodec::encodeCivilXml(QString::number(fileId)),
operatorName, lastModified, symbol);
bsi->m_symbolProperties = properties;
connect(bsi, &BaseSymbolItem::dataChanged, this, &BaseSymbolModel::onDataChanged);
// insert or update?
const int row = findRowForId(fileId);
if (row >= 0)
setRowData(row, DATA_T(bsi));
else
insertRow(DATA_T(bsi));
triggerFinishInitalization();
return true;
}
bool BaseSymbolModel::removeXmlSymbol(int fileId)
{
if (fileId < 0)
{
FATAL_LOG(m_logger) << " fileId not valid. fileId=" << fileId;
return false;
}
const int row = findRowForId(fileId);
return this->removeRow(row);
}
bool BaseSymbolModel::insertEtsSymbol(int fileId, const QString &sidc, const SymbolProperties &properties, const QImage &image)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START" << ", sidc='" << sidc << "'";
if (sidc.isEmpty())
return false;
BaseSymbolItem *bsi = new BaseSymbolItem(fileId, sidc, image);
bsi->m_symbolProperties = properties;
// not required for ETS:
// connect(bsi, &BaseSymbolItem::dataChanged,
// this, &BaseSymbolModel::onDataChanged);
// insert or update?
const int row = findRowForId(fileId);
if (row >= 0)
setRowData(row, DATA_T(bsi));
else
insertRow(DATA_T(bsi));
triggerFinishInitalization();
return true;
}
bool BaseSymbolModel::removeEtsSymbol(int fileId)
{
return removeXmlSymbol(fileId);
}
void BaseSymbolModel::triggerFinishInitalization()
{
d->m_finishInitializationTimer->start();
}
void BaseSymbolModel::onFinishInitalization()
{
qDebug() << LOGFUNCTION << " START";
connect(this, &BaseSymbolModel::rowsInserted, this, &BaseSymbolModel::onUpdateUsedItemsForComboBox, Qt::QueuedConnection);
connect(this, &BaseSymbolModel::rowsRemoved, this, &BaseSymbolModel::onUpdateUsedItemsForComboBox, Qt::QueuedConnection);
connect(this, &BaseSymbolModel::modelReset, this, &BaseSymbolModel::onUpdateUsedItemsForComboBox, Qt::QueuedConnection);
onUpdateUsedItemsForComboBox();
}
QVariant BaseSymbolModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role == LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole &&
orientation == Qt::Horizontal)
{
if (section == OPERATOR_NAME)
{
LtsWidgets::ComboboxFilterContent cfc;
cfc.sortItems = true;
cfc.data.reserve(d->m_usedOperator.size());
LtsWidgets::ComboboxFilterData cfd;
for (const QString &opName : qAsConst(d->m_usedOperator))
{
cfd.data = opName;
cfd.text = opName;
cfc.data.push_back(cfd);
}
return cfc.toVariant();
}
else if (section == SYMBOL_SET)
{
LtsWidgets::ComboboxFilterContent cfc;
cfc.data.reserve(d->m_usedSymbolSet.size());
LtsWidgets::ComboboxFilterData cfd;
for (const auto &symSet : qAsConst(d->m_usedSymbolSet))
{
cfd.data = symSet;
cfd.text = symSet;
cfc.data.push_back(cfd);
}
return cfc.toVariant();
}
else if (section == SYMBOLCLASS)
{
LtsWidgets::ComboboxFilterContent cfc;
cfc.data.reserve(d->m_usedSymbolClass.size());
LtsWidgets::ComboboxFilterData cfd;
for (const auto &sc : qAsConst(d->m_usedSymbolClass))
{
cfd.data = sc;
cfd.text = sc;
cfc.data.push_back(cfd);
}
return cfc.toVariant();
}
else if (section == XML_SYMBOL_SIZE)
{
LtsWidgets::ComboboxFilterContent cfc;
cfc.sortItems = true;
cfc.data.reserve(d->m_usedXmlSymbolScale.size());
LtsWidgets::ComboboxFilterData cfd;
for (const auto &symScale : qAsConst(d->m_usedXmlSymbolScale))
{
cfd.data = symScale;
cfd.text = QString::number(symScale);
cfc.data.push_back(cfd);
}
return cfc.toVariant();
}
else if (section == GEOMETRYTYPE)
{
LtsWidgets::ComboboxFilterContent cfc;
cfc.data.reserve(d->m_usedGeometryTypes.size());
LtsWidgets::ComboboxFilterData cfd;
for (const AdvancedSymbology::GeometryType &gt : qAsConst(d->m_usedGeometryTypes))
{
cfd.data = (int)gt;
cfd.text = geometryTypeToDisplayString(gt);
cfc.data.push_back(cfd);
}
return cfc.toVariant();
}
else if (section == CATEGORY)
{
LtsWidgets::ComboboxFilterContent cfc;
cfc.sortItems = true;
cfc.data.reserve(d->m_usedCategory.size());
LtsWidgets::ComboboxFilterData cfd;
for (const auto &cat : qAsConst(d->m_usedCategory))
{
cfd.data = cat;
cfd.text = cat;
cfc.data.push_back(cfd);
}
return cfc.toVariant();
}
else if (section == GCTSTRING)
{
LtsWidgets::ComboboxFilterContent cfc;
cfc.sortItems = true;
cfc.data.reserve(d->m_usedGctStrings.size());
LtsWidgets::ComboboxFilterData cfd;
for (const auto &gctStr : qAsConst(d->m_usedGctStrings))
{
cfd.data = gctStr;
cfd.text = gctStr;
cfc.data.push_back(cfd);
}
return cfc.toVariant();
}
}
return BaseClass::headerData(section, orientation, role);
}
QVariant BaseSymbolModel::data(const QModelIndex &index, int role) const
{
if ((role == Qt::SizeHintRole) &&
((index.column() == SEARCH_ICON) ||
(index.column() == FETCH_ICON) ||
(index.column() == FIND_BASE_SYMBOL) ||
(index.column() == FIND_PREVIEW) ||
(index.column() == FIND_IMAGE)
))
return QSize(SWATCH_SIZE, SWATCH_SIZE);
if ((role != Qt::DisplayRole) &&
(role != Qt::DecorationRole) &&
(role != Qt::ToolTipRole) &&
// role != Qt::EditRole // required by QDataWidgetMapper
(role != LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole)
)
return QVariant();
const DATA_T &item = m_vecData.at(index.row());
if (!item)
return QVariant();
const QString &baseSymbolCode = item->baseSymbolCode();
if (role == Qt::DecorationRole)
{
switch (index.column())
{
case SEARCH_ICON:
return item->getSearchSwatch();
case FETCH_ICON:
return item->getFetchSwatch();
case FIND_BASE_SYMBOL:
{
ResultWatcherData *rwd = item->m_findBaseSymbolRWD;
if (rwd)
{
if (rwd->image().isNull())
{
// setup temporaryImage until finished/resultReady:
// store that at rwd to avoid unwanted findImage/findBaseSymbol/...
rwd->image() = AdvancedSymbology::SymbolDictionary::temporaryImage();
rwd->getResultWatcher()->setSymbolResult(d->m_symbolDictionaryImpl->findBaseSymbol(baseSymbolCode));
}
return rwd->image();
}
}
break;
case FIND_PREVIEW:
{
ResultWatcherData *rwd = item->m_findPreviewRWD;
if (rwd)
{
if (rwd->image().isNull())
{
// setup temporaryImage until finished/resultReady:
// store that at rwd to avoid unwanted findImage/findBaseSymbol/...
rwd->image() = AdvancedSymbology::SymbolDictionary::temporaryImage();
rwd->getResultWatcher()->setSymbolResult(d->m_symbolDictionaryImpl->findPreview(SidcBuilderBase::baseSymbolCodeToSidc(baseSymbolCode)));
}
return rwd->image();
}
}
break;
case FIND_IMAGE:
{
ResultWatcherData *rwd = item->m_findImageRWD;
if (rwd)
{
if (rwd->image().isNull())
{
AdvancedSymbology::SymbolDataToRender symDataToRender;
// symDataToRender.sidc = SidcCodec::isCivil(sidc) ? sidc : SidcBuilderBase::baseSymbolCodeToSidc(sidc);
symDataToRender.sidc = SidcBuilderBase::baseSymbolCodeToSidc(baseSymbolCode);
symDataToRender.fillColor = Qt::red;
symDataToRender.fillColorReplace = true;
symDataToRender.injury = Injury::TotalKill;
symDataToRender.injuryColor = Qt::gray;
symDataToRender.injuryColor.setAlphaF(0.2);
symDataToRender.additionalSymbols.insert(AdditionalSymbolType::BiteError);
symDataToRender.additionalSymbols.insert(AdditionalSymbolType::Manipulation);
symDataToRender.additionalSymbols.insert(AdditionalSymbolType::NbcProtection);
symDataToRender.additionalSymbols.insert(AdditionalSymbolType::NoPosition);
// setup temporaryImage until finished/resultReady:
// store that at rwd to avoid unwanted findImage/findBaseSymbol/...
rwd->image() = AdvancedSymbology::SymbolDictionary::temporaryImage(symDataToRender.sizeL);
rwd->getResultWatcher()->setSymbolResult(d->m_symbolDictionaryImpl->findImage(symDataToRender));
}
return rwd->image();
}
}
break;
} // switch
return QVariant(); // otherwise we get into next if statement
} // if (role == Qt::DecorationRole)
if ((role == Qt::DisplayRole) || (role == Qt::EditRole) || (role != LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole))
{
const AdvancedSymbology::SymbolProperties &symbolProperties = item->m_symbolProperties;
switch (index.column())
{
case ID:
return item->m_id;
case ORIGINAL_KEY:
return symbolProperties.originalKey();
case KEY:
return symbolProperties.key();
case BASE_SYMBOL_CODE:
return item->baseSymbolCode();
case SIDC:
return item->sidc();
// return symbolProperties.sidc();
case SYMBOL_SET:
return item->symbolSet();
case NAME:
return symbolProperties.name();
case OPERATOR_NAME:
return item->m_operatorName;
case LAST_MODIFIED:
return DTG::toStringMSec(item->m_lastModified);
case XML_SYMBOL_SIZE:
if (item->m_xmlSymbol)
return item->m_xmlSymbol->m_symbol.getScale();
return QVariant();
case CATEGORY:
return symbolProperties.category();
case SYMBOLCLASS:
return symbolProperties.symbolClass();
case TAGS:
return symbolProperties.tags().join(QLatin1Char(';'));
case GCTSTRING:
return symbolProperties.gctString();
case GEOMETRYTYPE:
return AdvancedSymbology::toString(symbolProperties.geometryType());
} // switch
} // if (role == Qt::DisplayRole)
if (role == Qt::ToolTipRole)
{
switch (index.column())
{
case SEARCH_ICON:
return item->getTooltip(item->getSearchSwatch());
case FETCH_ICON:
return item->getTooltip(item->getFetchSwatch());
case FIND_BASE_SYMBOL:
return item->getTooltip(item->m_findBaseSymbolRWD->originalImage());
case FIND_PREVIEW:
return item->getTooltip(item->m_findPreviewRWD->originalImage());
case FIND_IMAGE:
return item->getTooltip(item->m_findImageRWD->originalImage());
default:
break;
} //switch
return item->getTooltip(item->m_findImageRWD->originalImage());
}
else if (role == LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole)
{
if (index.column() == OPERATOR_NAME)
return item->m_operatorName;
if (index.column() == SYMBOL_SET)
return item->symbolSet();
if (index.column() == CATEGORY)
return item->m_symbolProperties.category();
if (index.column() == SYMBOLCLASS)
return item->m_symbolProperties.symbolClass();
if (index.column() == GCTSTRING)
return item->m_symbolProperties.gctString();
if (index.column() == GEOMETRYTYPE)
return (int)item->m_symbolProperties.geometryType();
if (index.column() == XML_SYMBOL_SIZE)
if (item->m_xmlSymbol)
return item->m_xmlSymbol->m_symbol.getScale();
}
return QVariant();
}
int BaseSymbolModel::findRowForBaseSymbolCode(const QString &baseSymbolCode)
{
int row = -1;
for (int i = 0; i < m_vecData.size(); ++i)
{
const DATA_T &item = m_vecData.at(i);
if (!item)
continue;
if (item->baseSymbolCode() == baseSymbolCode)
row = i;
} // for
return row;
}
void BaseSymbolModel::onDataChanged(int id)
{
// FATAL_LOG(m_logger) << LOGFUNCTION << " START, id=" << id;
// new image -> update view:
int row = findRowForId(id);
emit dataChanged(index(row, 0), index(row, LtsAbstractTableModel::columnCount(QModelIndex()) - 1));
}
void BaseSymbolModel::onUpdateUsedItemsForComboBox()
{
d->m_usedOperator.clear();
d->m_usedSymbolSet.clear();
d->m_usedSymbolClass.clear();
d->m_usedXmlSymbolScale.clear();
d->m_usedGeometryTypes.clear();
d->m_usedCategory.clear();
d->m_usedGctStrings.clear();
for (const QSharedPointer<BaseSymbolItem> &item : qAsConst(m_vecData))
{
if (!item)
continue;
d->m_usedOperator.insert(item->m_operatorName);
d->m_usedSymbolSet.insert(item->symbolSetAsInt(), item->symbolSet());
d->m_usedSymbolClass.insert(item->m_symbolProperties.symbolClass());
if (item->m_xmlSymbol)
d->m_usedXmlSymbolScale.insert(item->m_xmlSymbol->m_symbol.getScale());
d->m_usedGeometryTypes.insert(item->m_symbolProperties.geometryType());
d->m_usedCategory.insert(item->m_symbolProperties.category());
d->m_usedGctStrings.insert(item->m_symbolProperties.gctString());
}
d->m_usedGctStrings.remove(QString());
}
SymbolProperties BaseSymbolModel::symbolProperties(const QString &baseSymbolCode)
{
// bisher aus m_baseSymbolCodeToSymbolPropertyTable beantwortet:
SymbolProperties symbolProperties;
for (const auto &item : qAsConst(m_vecData))
{
if (item->baseSymbolCode() != baseSymbolCode)
continue;
symbolProperties = item->m_symbolProperties;
}
return symbolProperties;
}
//------------------------------------------------------------------------------
// BaseSymbolProxyModel
//------------------------------------------------------------------------------
BaseSymbolProxyModel::BaseSymbolProxyModel(QObject *parent)
: BaseClass(parent)
{
}
void BaseSymbolProxyModel::setSourceModel(QAbstractItemModel *sourceModel)
{
m_sourceModel = qobject_cast<BaseSymbolModel *>(sourceModel);
BaseClass::setSourceModel(sourceModel);
}
bool BaseSymbolProxyModel::filterPoints() const
{
return m_geometrySet.contains(AdvancedSymbology::GeometryType::Point);
}
bool BaseSymbolProxyModel::filterLines() const
{
return m_geometrySet.contains(AdvancedSymbology::GeometryType::Polyline);
}
bool BaseSymbolProxyModel::filterAreas() const
{
return m_geometrySet.contains(AdvancedSymbology::GeometryType::Polygon);
}
QSet<QString> BaseSymbolProxyModel::validBaseSymbolCodes() const
{
return m_validBaseSymbolCodes;
}
void BaseSymbolProxyModel::setValidBaseSymbolCodes(const QSet<QString> &validBaseSymbolCodes)
{
m_validBaseSymbolCodes = validBaseSymbolCodes;
invalidateFilter();
}
void BaseSymbolProxyModel::onFilterPoints(bool on)
{
if (on)
m_geometrySet.insert(AdvancedSymbology::GeometryType::Point);
else
m_geometrySet.remove(AdvancedSymbology::GeometryType::Point);
invalidateFilter();
}
void BaseSymbolProxyModel::onFilterLines(bool on)
{
if (on)
m_geometrySet.insert(AdvancedSymbology::GeometryType::Polyline);
else
m_geometrySet.remove(AdvancedSymbology::GeometryType::Polyline);
invalidateFilter();
}
void BaseSymbolProxyModel::onFilterAreas(bool on)
{
if (on)
m_geometrySet.insert(AdvancedSymbology::GeometryType::Polygon);
else
m_geometrySet.remove(AdvancedSymbology::GeometryType::Polygon);
invalidateFilter();
}
bool BaseSymbolProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
{
if (!m_sourceModel || source_parent.isValid() || source_row < 0 || source_row >= m_sourceModel->rowCount())
return LtsWidgets::LtsColumnFilterProxyModel::filterAcceptsRow(source_row, source_parent);
const QSharedPointer<BaseSymbolItem> &item = m_sourceModel->getRowData(source_row);
if (item)
{
// check geometryType
GeometryType symbolGeometry = item->m_symbolProperties.geometryType();
if (!m_geometrySet.contains(symbolGeometry))
return false;
// check m_validBaseSymbolCodes
if (!m_validBaseSymbolCodes.isEmpty() && !m_validBaseSymbolCodes.contains(item->baseSymbolCode()))
return false;
}
return LtsWidgets::LtsColumnFilterProxyModel::filterAcceptsRow(source_row, source_parent);
}
bool BaseSymbolProxyModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
{
if (!m_sourceModel ||
source_left.column() != source_right.column() ||
source_left.row() < 0 || source_left.row() >= m_sourceModel->m_vecData.size() ||
source_right.row() < 0 || source_right.row() >= m_sourceModel->m_vecData.size()
)
return BaseClass::lessThan(source_left, source_right);
const QSharedPointer<BaseSymbolItem> &left = m_sourceModel->m_vecData.at(source_left.row());
const QSharedPointer<BaseSymbolItem> &right = m_sourceModel->m_vecData.at(source_right.row());
switch (source_left.column())
{
case BaseSymbolModel::Columns::ID:
return left->m_id < right->m_id;
case BaseSymbolModel::Columns::OPERATOR_NAME:
return left->m_operatorName < right->m_operatorName;
case BaseSymbolModel::Columns::LAST_MODIFIED:
return left->m_lastModified < right->m_lastModified;
case BaseSymbolModel::Columns::BASE_SYMBOL_CODE:
return left->baseSymbolCode() < right->baseSymbolCode();
// case BaseSymbolModel::Columns::ORIGINAL_KEY:
// return left->m_symbolProperties.originalKey() < right->m_symbolProperties.originalKey();
// case BaseSymbolModel::Columns::KEY:
// return left->m_symbolProperties.key() < right->m_symbolProperties.key();
// case BaseSymbolModel::Columns::NAME:
// return left->m_symbolProperties.name() < right->m_symbolProperties.name();
// case BaseSymbolModel::Columns::CATEGORY:
// return left->m_symbolProperties.category() < right->m_symbolProperties.category();
// case BaseSymbolModel::Columns::SYMBOLCLASS:
// return left->m_symbolProperties.symbolClass() < right->m_symbolProperties.symbolClass();
case BaseSymbolModel::Columns::XML_SYMBOL_SIZE:
if (left->m_xmlSymbol && right->m_xmlSymbol)
return left->m_xmlSymbol->m_symbol.getScale() > right->m_xmlSymbol->m_symbol.getScale();
} // switch
return BaseClass::lessThan(source_left, source_right);
}
} // namespace AdvancedSymbology