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

344 lines
9.3 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@
* Class SymbolResult
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include "advanced_symbology_export.h"
#include "symbol_dictionary_types.h"
#include <SymbologyImpl/advanced_symbology_logging.h>
#include "result_watcher.h"
// Qt
#include <QObject>
#include <QImage>
#include <QLabel>
#include <QFuture>
#include <QSize>
#include <QBuffer>
#include <QElapsedTimer>
// forward
class QUuid;
class QComboBox;
//----------------------------------------------------------------------------
namespace AdvancedSymbology
{
/**
* @brief The SymbolResult class mainly contains a GeometryType and a SymbolImage.
* It´s based on the future pattern. So the real result can only be retrieved if
* the asynchron operation has finished (and the result is ready).
* To standardize this you should use a propper watcher: SymbolResultWatcher.
*
* \sa \ref secResultWatcherExample
*/
class ADVANCED_SYMBOLOGY_EXPORT SymbolResult : public QObject
{
Q_OBJECT
/*! \name Construction, Destruction */
//@{
public:
/**
* @brief Constructor / Destructor.
*/
explicit SymbolResult();
virtual ~SymbolResult();
//@}
/*! \name Data regarding requested */
//@{
/**
* @brief symbolDataToRender What was requested?
* @return Requested data
*/
const SymbolDataToRender &symbolDataToRender() const;
//@}
/*! \name Data regarding processing*/
//@{
/**
* @brief taskId internal taskId
* @return internal taskId
*/
const QUuid &taskId() const;
/*! \name Data regarding result*/
//@{
/**
* @brief Get geometryType of request
* @return Geometry type
*/
GeometryType geometryType() const;
/**
* @brief Get symbol image
* @return symbol image
*/
SymbolImage symbolImage() const;
//@}
bool isResultReady() const;
Q_SIGNALS:
/// This signal is for internal usage only. Use SymbolResultWatcher!
void resultReadyInternal();
protected:
friend class SymbolDictionaryImpl;
friend class EsriDictionaryProcessor;
friend class BaseSymbolModel;
void fireResultReady();
friend class ResultWatcher<SymbolResult>;
friend class SymbolResultWatcher;
void setSymbolDataToRender(const SymbolDataToRender &symDataToRender);
void setTaskId(const QUuid &uuid);
void setFuture(const QFuture<QImage> &future);
void setGeometryType(GeometryType geometryType);
void setSymbolImage(const SymbolImage &symbolImage);
protected Q_SLOTS:
void onFinished();
private:
class Private;
/**
* The private d->pointer to not break BC when changing internals of this class
*/
Private *d = nullptr;
LOGGER_T m_logger; ///< Interface of the Logging-Facility
};
//------------------------------------------------------------------------------
/**
* @brief The SymbolResultWatcher class can watch one SymbolResult using setSymbolResult.
* If the background operation has finished, the signal resultReady is emitted exactly one time.
*
* \sa \ref secResultWatcherExample
*/
class ADVANCED_SYMBOLOGY_EXPORT SymbolResultWatcher : public ResultWatcher<SymbolResult>
{
Q_OBJECT
using BaseClass = ResultWatcher<SymbolResult>;
public:
explicit SymbolResultWatcher(QObject *parent = nullptr);
~SymbolResultWatcher() = default;
QSharedPointer<SymbolResult> symbolResult() const;
void setSymbolResult(const QSharedPointer<SymbolResult> &symbolResult);
QElapsedTimer *m_et { nullptr };
protected:
LOGGER_T m_logger; ///< Interface of the Logging-Facility
};
//------------------------------------------------------------------------------
// for convenience (ComboxBox)
//------------------------------------------------------------------------------
/**
* @brief The SymbolResultWatcherComboxBox class can be used to combine a comboBox
* and an infinite number of item containing an icon.
*
* Here is an example:
*
* \code
* AdvancedSymbology::SymbolResultWatcherComboxBox *srwCb;
foreach(auto sidc, sidcs)
{
// SymbolResultWatcherComboxBox is stored as userData at every item.
// The lifetime is limited to the lifetime of the comboBox since it`s the parent.
d->m_cbRubSidc->addItem(sidc, QVariant::fromValue(srwCb = new AdvancedSymbology::SymbolResultWatcherComboxBox(d->m_cbRubSidc)) );
srwCb->setSymbolResult(dict.fetchSymbol(sidc));
}
* \endcode
*/
class ADVANCED_SYMBOLOGY_EXPORT SymbolResultWatcherComboxBox : public QObject
{
Q_OBJECT
public:
explicit SymbolResultWatcherComboxBox(QComboBox *comboBox, int role = Qt::UserRole);
void setSymbolResult(const QSharedPointer<SymbolResult> &symbolResult);
/**
* @brief enableToolTip of each entry
* @param on
*/
void enableToolTip(bool on = true) { m_enableToolTip = on; }
bool isToolTipEnabled() { return m_enableToolTip; }
private slots:
void onResultReady();
private:
QComboBox *m_comboBox{nullptr};
AdvancedSymbology::SymbolResultWatcher m_watcher;
int m_role{Qt::UserRole};
bool m_enableToolTip{true};
};
//------------------------------------------------------------------------------
// for convenience (QWidget)
//------------------------------------------------------------------------------
/**
* @brief The SymbolResultWatcherQWidgetBase class can be used with a QWidget,
* most of the time a LtsWidgets::LtsDragIcon.
* Required is a method 'setIcon(const QPixmap &pixmap)'
*
* Here is an example:
*
* \code
LtsWidgets::LtsDragIcon *dummyIcon = new LtsWidgets::LtsDragIcon(this);
AdvancedSymbology::SymbolResultWatcherQWidgetBase *dummyIconSibling =
new AdvancedSymbology::SymbolResultWatcherQWidget<LtsWidgets::LtsDragIcon>(dummyIcon);
AdvancedSymbology::SymbolDictionary &dict = d->m_mapImpl->symbolDictionary();
dummyIconSibling->setSymbolResult(dict.fetchSymbol(SidcCodec::encodeComplete(SymbologyType::MIL2525D,"10042500001401040000")));
* \endcode
* This sibling define the lifetime.
*/
class ADVANCED_SYMBOLOGY_EXPORT SymbolResultWatcherQWidgetBase : public QObject
{
Q_OBJECT
using BaseClass = QObject;
public:
explicit SymbolResultWatcherQWidgetBase(QObject *widget);
void setSymbolResult(const QSharedPointer<SymbolResult> &symbolResult);
QSharedPointer<AdvancedSymbology::SymbolResult> symbolResult() const;
private slots:
void onResultReady();
signals:
void resultReady();
protected:
virtual void onResultReadyImpl() = 0;
AdvancedSymbology::SymbolResultWatcher m_watcher;
};
template <typename PARENT_TYPE>
class SymbolResultWatcherQWidget : public SymbolResultWatcherQWidgetBase
{
using BaseClass = SymbolResultWatcherQWidgetBase;
public:
explicit SymbolResultWatcherQWidget(PARENT_TYPE *parentWidget, const QSize &size = QSize())
: BaseClass(parentWidget)
, m_size(size)
, m_parentWidget(parentWidget)
{}
private:
void onResultReadyImpl() override
{
if (!m_parentWidget)
return;
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_parentWidget->devicePixelRatioF();
QImage imgCopy;
if (m_size.isValid())
imgCopy = symImage.image().scaled(m_size * dpr, Qt::KeepAspectRatio, Qt::SmoothTransformation);
else
imgCopy = symImage.image();
imgCopy.setDevicePixelRatio(dpr);
m_parentWidget->setIcon(QPixmap::fromImage(std::move(imgCopy)));
{
QString tooltip;
QByteArray data;
QBuffer buffer(&data);
// XML-Symbol with scale = 4 will produce huge images. Limit the size:
symImage.image().scaled(QSize(300, 300), Qt::KeepAspectRatio, Qt::SmoothTransformation).save(&buffer, "PNG", 100);
tooltip = QStringLiteral("<html>");
tooltip += QStringLiteral("<center>");
tooltip += QStringLiteral("<img src='data:image/png;base64,%1'>").arg(QString::fromLatin1(data.toBase64()));
tooltip += QStringLiteral("</center>");
tooltip += QStringLiteral("<center>");
tooltip += symResult->symbolDataToRender().sidc;
tooltip += QStringLiteral("</center>");
tooltip += QStringLiteral("<hr>");
tooltip += QStringLiteral("</html>");
m_parentWidget->setToolTip(tooltip);
}
}
QSize m_size;
PARENT_TYPE *m_parentWidget;
};
//------------------------------------------------------------------------------
// for convenience (QLabel)
//------------------------------------------------------------------------------
/**
* @brief The SymbolResultWatcherLabel class can be used to combine a QLabel
* Here is an example:
*
* \code
* QLabel *label = new QLabel(this);
* AdvancedSymbology::SymbolResultWatcherLabel *symbolLabelWatcher(label);
*
*
*
* \endcode
*/
class ADVANCED_SYMBOLOGY_EXPORT SymbolResultWatcherLabel : public QObject
{
Q_OBJECT
public:
explicit SymbolResultWatcherLabel(QLabel *label, const QSize &size = QSize(45, 45));
void setSymbolResult(const QSharedPointer<AdvancedSymbology::SymbolResult> &symbolResult);
private slots:
void onResultReady();
private:
QSize m_size;
QLabel *m_label{nullptr};
AdvancedSymbology::SymbolResultWatcher m_watcher;
};
} // namespace AdvancedSymbology
Q_DECLARE_METATYPE_TEMPLATE_1ARG(AdvancedSymbology::ResultWatcher)