/** * @RDE_HEADER@ * Class SymbolResult * $Id$ * $HeadURL$ * $Author$ */ // Own #include "symbol_result.h" // Qt #include #include #include #include namespace AdvancedSymbology { class SymbolResult::Private { public: Private() = default; ~Private() = default; // Input data: SymbolDataToRender m_symDataToRender; // process data: QUuid m_taskIdFindSymbol; // of esriDict::findSymbol QFutureWatcher m_futureWatcher; bool m_isReady = false; // Result data: GeometryType m_geometryType = GeometryType::Undefined; SymbolImage m_symbolImage; // For debugging: static unsigned long m_counter; }; unsigned long SymbolResult::Private::m_counter = 0; SymbolResult::SymbolResult() : QObject() , d(new Private) , m_logger(getLogger("SymbolResult")) { TRACE_LOG(m_logger) << LOGFUNCTION << " START, m_counter=" << d->m_counter; ++Private::m_counter; connect(&d->m_futureWatcher, &QFutureWatcherBase::finished, this, &SymbolResult::onFinished); TRACE_LOG(m_logger) << LOGFUNCTION << " END, m_counter=" << d->m_counter; } SymbolResult::~SymbolResult() { LOGGER_T m_logger = getLogger("SymbolResult"); TRACE_LOG(m_logger) << LOGFUNCTION << " START, m_counter=" << d->m_counter; --Private::m_counter; d->m_futureWatcher.disconnect(this); d->m_futureWatcher.cancel(); d->m_futureWatcher.waitForFinished(); delete d; TRACE_LOG(m_logger) << LOGFUNCTION << " END, m_counter=" << Private::m_counter; } void SymbolResult::onFinished() { TRACE_LOG(m_logger) << LOGFUNCTION << " START"; const QImage &image = d->m_futureWatcher.future().result(); d->m_symbolImage.setImage(image); d->m_symbolImage.setValid(true); fireResultReady(); TRACE_LOG(m_logger) << LOGFUNCTION << " END"; } void SymbolResult::fireResultReady() { TRACE_LOG(m_logger) << LOGFUNCTION << " START"; d->m_isReady = true; // Future can`t manually be set to 'ready' :-( emit resultReadyInternal(); TRACE_LOG(m_logger) << LOGFUNCTION << " END"; } void SymbolResult::setSymbolDataToRender(const SymbolDataToRender &symDataToRender) { d->m_symDataToRender = symDataToRender; } const SymbolDataToRender &SymbolResult::symbolDataToRender() const { return d->m_symDataToRender; } void SymbolResult::setTaskId(const QUuid &uuid) { d->m_taskIdFindSymbol = uuid; } const QUuid &SymbolResult::taskId() const { return d->m_taskIdFindSymbol; } void SymbolResult::setFuture(const QFuture &future) { d->m_isReady = false; d->m_futureWatcher.setFuture(future); } void SymbolResult::setGeometryType(GeometryType geometryType) { d->m_geometryType = geometryType; } GeometryType SymbolResult::geometryType() const { return d->m_geometryType; } void SymbolResult::setSymbolImage(const SymbolImage &symbolImage) { d->m_symbolImage = symbolImage; } SymbolImage SymbolResult::symbolImage() const { return d->m_symbolImage; } bool SymbolResult::isResultReady() const { // Do not or 'd->m_futureWatcher.future().isResultReadyAt(0)' will lead to timing problems // When d->m_futureWatcher.future() is ready, the according slot will set d->m_isReady. return d->m_isReady; } //------------------------------------------------------------------------------ // SymbolResultWatcher //------------------------------------------------------------------------------ SymbolResultWatcher::SymbolResultWatcher(QObject *parent) : BaseClass(parent) , m_logger(getLogger("SymbolResultWatcher")) { TRACE_LOG(m_logger) << LOGFUNCTION << " START"; TRACE_LOG(m_logger) << LOGFUNCTION << " END"; } QSharedPointer SymbolResultWatcher::symbolResult() const { return BaseClass::result(); } void SymbolResultWatcher::setSymbolResult(const QSharedPointer &symbolResult) { BaseClass::setResult(symbolResult); } //------------------------------------------------------------------------------ // SymbolResultWatcherComboxBox //------------------------------------------------------------------------------ SymbolResultWatcherComboxBox::SymbolResultWatcherComboxBox(QComboBox *comboBox, int role) : QObject(comboBox), m_comboBox(comboBox), m_role(role) { connect(&m_watcher, &AdvancedSymbology::SymbolResultWatcher::resultReady, this, &SymbolResultWatcherComboxBox::onResultReady); } void SymbolResultWatcherComboxBox::setSymbolResult(const QSharedPointer &symbolResult) { m_watcher.setSymbolResult(symbolResult); } void SymbolResultWatcherComboxBox::onResultReady() { QSharedPointer symResult = m_watcher.symbolResult(); if (! symResult) return; // should NEVER happen! (Which object should have triggered the signal???) int idx = m_comboBox->findData(QVariant::fromValue(this), m_role); const QImage &img = symResult->symbolImage().image(); m_comboBox->setItemIcon(idx, QPixmap::fromImage(img)); if (m_enableToolTip && !img.isNull()) { QString tooltip(QStringLiteral("")); // without a temporary file: QByteArray baData; QBuffer buffer(&baData); img.save(&buffer, "PNG", 100); tooltip.append(QStringLiteral("
").arg(QString::fromLatin1(baData.toBase64()))); // how can i center the image? tooltip.append(QStringLiteral("")); m_comboBox->setItemData(idx, tooltip, Qt::ToolTipRole); } } //------------------------------------------------------------------------------ // for convenience (QWidget) //------------------------------------------------------------------------------ SymbolResultWatcherQWidgetBase::SymbolResultWatcherQWidgetBase(QObject *widget) : BaseClass(widget) { connect(&m_watcher, &AdvancedSymbology::SymbolResultWatcher::resultReady, this, &SymbolResultWatcherQWidgetBase::onResultReady); } void SymbolResultWatcherQWidgetBase::setSymbolResult(const QSharedPointer &symbolResult) { m_watcher.setSymbolResult(symbolResult); } QSharedPointer SymbolResultWatcherQWidgetBase::symbolResult() const { return m_watcher.symbolResult(); } void SymbolResultWatcherQWidgetBase::onResultReady() { this->onResultReadyImpl(); emit resultReady(); } //------------------------------------------------------------------------------ // SymbolResultWatcherLabel //------------------------------------------------------------------------------ SymbolResultWatcherLabel::SymbolResultWatcherLabel(QLabel *label, const QSize &size) : QObject(label) , m_size(size) , m_label(label) { connect(&m_watcher, &AdvancedSymbology::SymbolResultWatcher::resultReady, this, &SymbolResultWatcherLabel::onResultReady); } void SymbolResultWatcherLabel::setSymbolResult(const QSharedPointer &symbolResult) { m_watcher.setSymbolResult(symbolResult); } void SymbolResultWatcherLabel::onResultReady() { QSharedPointer symResult = m_watcher.symbolResult(); if (!symResult) return; // should NEVER happen! (Which object should have triggered the signal???) const SymbolImage &symImage = symResult->symbolImage(); const auto dpr = m_label->devicePixelRatioF(); QImage image = symImage.image().scaled(m_size * dpr, Qt::KeepAspectRatio, Qt::SmoothTransformation); image.setDevicePixelRatio(dpr); m_label->setPixmap(QPixmap::fromImage(std::move(image))); } } // namespace AdvancedSymbology