1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
|
// ************************************************************************************************
//
// BornAgain: simulate and fit reflection and scattering
//
//! @file GUI/Model/Descriptor/PolyPtr.h
//! @brief Defines and implements template class PolyPtr.
//!
//! @homepage http://www.bornagainproject.org
//! @license GNU General Public License v3 or higher (see COPYING)
//! @copyright Forschungszentrum Jülich GmbH 2021
//! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
//
// ************************************************************************************************
#ifndef BORNAGAIN_GUI_MODEL_DESCRIPTOR_POLYPTR_H
#define BORNAGAIN_GUI_MODEL_DESCRIPTOR_POLYPTR_H
#include "GUI/Model/Util/UtilXML.h"
class PolyBase {
public:
virtual ~PolyBase() = default;
QString piLabel() const { return m_label; }
QString piTooltip() const { return m_tooltip; }
QStringList menuEntries() const { return m_menu_entries; }
virtual void setCertainIndex(int index) = 0;
virtual int certainIndex() const = 0;
protected:
QString m_label; //!< A label text (short, no trailing colon)
QString m_tooltip; //!< Tooltip text
QStringList m_menu_entries; //!< List of options, usually presented as combo entries
};
//! Holds a polymorphous item. Possible types of the item are specified by a Catalog.
template <typename BaseItem, typename Catalog> class PolyPtrBase : public PolyBase {
public:
void simpleInit(const QString& label, const QString& tooltip,
typename Catalog::Type currentType);
BaseItem* certainItem() const { return m_item.get(); }
void setCertainItem(BaseItem* t) { m_item.reset(t); }
void writeTo(QXmlStreamWriter* w) const;
template <typename... Args> void readFrom(QXmlStreamReader* r, Args... args);
int certainIndex() const override { return m_types.indexOf(Catalog::type(m_item.get())); }
protected:
std::unique_ptr<BaseItem> m_item; //!< Current selection
QVector<typename Catalog::Type> m_types = Catalog::types();
};
//! Holds a polymorphous item that can be created without extra parameters.
template <typename BaseItem, typename Catalog>
class PolyPtr : public PolyPtrBase<BaseItem, Catalog> {
public:
void setCertainIndex(int index) override
{
this->m_item.reset(Catalog::create(this->m_types[index]));
}
};
//! Holds a polymorphous item that can only be created with an extra parameter.
template <typename BaseItem, typename Catalog, typename ContextData>
class PolyPtrWithContext : public PolyPtrBase<BaseItem, Catalog> {
public:
PolyPtrWithContext(const ContextData* contextData)
: m_contextData(contextData)
{
}
void setCertainIndex(int index) override
{
this->m_item.reset(Catalog::create(this->m_types[index], m_contextData));
}
private:
const ContextData* m_contextData;
};
//! Initialize by means of a catalog class and optional creation arguments.
//!
//! The current selection will be initialized with the first type in the catalog types. The optional
//! arguments are the arguments which may be necessary for the creation method in the catalog.
template <typename BaseItem, typename Catalog>
void PolyPtrBase<BaseItem, Catalog>::simpleInit(const QString& label, const QString& tooltip,
typename Catalog::Type currentType)
{
m_label = label;
m_tooltip = tooltip;
m_menu_entries.clear();
for (const auto type : m_types)
m_menu_entries << Catalog::uiInfo(type).menuEntry;
int index = Catalog::types().indexOf(currentType);
setCertainIndex(index);
}
//! Serializes the catalog index of the currently selected type and calls
//! main serialization method of the selected class.
template <typename BaseItem, typename Catalog>
void PolyPtrBase<BaseItem, Catalog>::writeTo(QXmlStreamWriter* w) const
{
const BaseItem* t = m_item.get();
const uint typeIndex = static_cast<uint>(Catalog::type(t));
XML::writeAttribute(w, XML::Attrib::type, typeIndex);
// The next line allows to see the name of item type in XML. May be skipped while reading.
XML::writeAttribute(w, XML::Attrib::kind, Catalog::uiInfo(Catalog::type(t)).menuEntry);
if (t)
t->writeTo(w);
}
//! Deserializes the catalog index of the currently selected type, creates a new
//! object of this type and calls main deserialization method of the selected class.
template <typename BaseItem, typename Catalog>
template <typename... Args>
void PolyPtrBase<BaseItem, Catalog>::readFrom(QXmlStreamReader* r, Args... args)
{
const uint typeIndex = XML::readUInt(r, XML::Attrib::type);
const QString kind = XML::readString(r, XML::Attrib::kind);
const auto type = static_cast<typename Catalog::Type>(typeIndex);
BaseItem* t = Catalog::create(type, args...);
if (t)
t->readFrom(r);
m_item.reset(t);
}
#endif // BORNAGAIN_GUI_MODEL_DESCRIPTOR_POLYPTR_H
|