Initial commit

This commit is contained in:
torsten committed 2026-08-13 18:33:10 +02:00
commit b7d90b9afe
16245 files changed
+3396666

No files matched your search

+343
View File
@@ -0,0 +1,343 @@
/**
* @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)