/** * @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 #include // arcgis #include #include // Qt #include #include #include #include #include #include #include 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 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(symbolDictionary); m_esriDictionary = const_cast(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(symbolSet)) + AdvancedSymbology::SidcDefinitions::toString(symbolSet); } return m_symbolSet; } int BaseSymbolItem::symbolSetAsInt() { return static_cast(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("
"); const QString paragraphEnd = QStringLiteral("
"); const QString separator = QStringLiteral("
"); tooltip = QStringLiteral(""); tooltip += paragraphBegin; tooltip += QStringLiteral("").arg(QString::fromLatin1(data.toBase64())); tooltip += paragraphEnd; // + QStringLiteral("
"); tooltip += paragraphBegin; tooltip += symProp.name(); tooltip += paragraphEnd; tooltip += paragraphBegin; tooltip += baseSymbolCode(); tooltip += paragraphEnd; tooltip += QStringLiteral("
"); // tooltip += separator; tooltip += paragraphBegin + geometryTypeToDisplayString(symProp.geometryType()) + paragraphEnd; tooltip += QStringLiteral("
"); tooltip += paragraphBegin + symProp.tags().join(separator) + paragraphEnd; tooltip += QStringLiteral(""); 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> m_findBaseSymbol2symbolResult; QTimer *m_finishInitializationTimer = nullptr; // For proxyModel QSet m_usedOperator; QMap m_usedSymbolSet; QSet m_usedSymbolClass; QSet m_usedXmlSymbolScale; QSet m_usedGeometryTypes; QSet m_usedCategory; QSet 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(symbolDictionary); d->m_esriDictionary = const_cast(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(error.domain()) << ", extendedErrorType=" << static_cast(error.extendedErrorType()) << ", message='" << error.message() << "'" << ", additionalMessage='" << error.additionalMessage() << "'"; } void BaseSymbolModel::initModel(SymbolDictionary *symbolDictionary, const QList &searchResultList, const SidcCodec::SidcHashTable &baseSymbolCodeToSymbolPropertyTable) { clear(); int itemCounter = 0; QVector 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 > : 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 &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(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 BaseSymbolProxyModel::validBaseSymbolCodes() const { return m_validBaseSymbolCodes; } void BaseSymbolProxyModel::setValidBaseSymbolCodes(const QSet &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 &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 &left = m_sourceModel->m_vecData.at(source_left.row()); const QSharedPointer &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