280 lines
7.5 KiB
C++
Executable File
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
|
|
|