/** * @RDE_HEADER@ * Class SymbolResult * $Id$ * $HeadURL$ * $Author$ */ #pragma once // Own #include "advanced_symbology_export.h" #include "symbol_dictionary_types.h" #include #include "result_watcher.h" // Qt #include #include #include #include #include #include #include // 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; friend class SymbolResultWatcher; void setSymbolDataToRender(const SymbolDataToRender &symDataToRender); void setTaskId(const QUuid &uuid); void setFuture(const QFuture &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 { Q_OBJECT using BaseClass = ResultWatcher; public: explicit SymbolResultWatcher(QObject *parent = nullptr); ~SymbolResultWatcher() = default; QSharedPointer symbolResult() const; void setSymbolResult(const QSharedPointer &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); /** * @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(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); QSharedPointer symbolResult() const; private slots: void onResultReady(); signals: void resultReady(); protected: virtual void onResultReadyImpl() = 0; AdvancedSymbology::SymbolResultWatcher m_watcher; }; template 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 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(""); tooltip += QStringLiteral("
"); tooltip += QStringLiteral("").arg(QString::fromLatin1(data.toBase64())); tooltip += QStringLiteral("
"); tooltip += QStringLiteral("
"); tooltip += symResult->symbolDataToRender().sidc; tooltip += QStringLiteral("
"); tooltip += QStringLiteral("
"); tooltip += QStringLiteral(""); 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 &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)