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

280 lines
7.5 KiB
C++
Executable File

/**
* @RDE_HEADER@
* Class SymbolResult
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "symbol_result.h"
// Qt
#include <QUuid>
#include <QComboBox>
#include <QFutureWatcher>
#include <QTimer>
namespace AdvancedSymbology
{
class SymbolResult::Private
{
public:
Private() = default;
~Private() = default;
// Input data:
SymbolDataToRender m_symDataToRender;
// process data:
QUuid m_taskIdFindSymbol; // of esriDict::findSymbol
QFutureWatcher<QImage> 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<QImage> &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<SymbolResult> SymbolResultWatcher::symbolResult() const
{
return BaseClass::result();
}
void SymbolResultWatcher::setSymbolResult(const QSharedPointer<SymbolResult> &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<AdvancedSymbology::SymbolResult> &symbolResult)
{
m_watcher.setSymbolResult(symbolResult);
}
void SymbolResultWatcherComboxBox::onResultReady()
{
QSharedPointer<AdvancedSymbology::SymbolResult> 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("<html>"));
// without a temporary file:
QByteArray baData;
QBuffer buffer(&baData);
img.save(&buffer, "PNG", 100);
tooltip.append(QStringLiteral("<center><img src='data:image/png;base64,%1'></center>").arg(QString::fromLatin1(baData.toBase64()))); // how can i center the image?
tooltip.append(QStringLiteral("</html>"));
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<AdvancedSymbology::SymbolResult> &symbolResult)
{
m_watcher.setSymbolResult(symbolResult);
}
QSharedPointer<SymbolResult> 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<AdvancedSymbology::SymbolResult> &symbolResult)
{
m_watcher.setSymbolResult(symbolResult);
}
void SymbolResultWatcherLabel::onResultReady()
{
QSharedPointer<AdvancedSymbology::SymbolResult> 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