diff options
Diffstat (limited to 'options/value.hpp')
| -rw-r--r-- | options/value.hpp | 167 | 
1 files changed, 167 insertions, 0 deletions
| diff --git a/options/value.hpp b/options/value.hpp new file mode 100644 index 00000000..4d8d69f8 --- /dev/null +++ b/options/value.hpp @@ -0,0 +1,167 @@ +#pragma once + +#include "bundle.hpp" +#include "slider.hpp" +#include <type_traits> +#include <QString> +#include <QPointF> +#include <QList> + +#define OPENTRACK_DEFINE_SLOT(t) void setValue(t datum) { store(datum); } +#define OPENTRACK_DEFINE_SIGNAL(t) void valueChanged(t) +namespace options { + +namespace detail { +template<typename t> struct value_type_traits { using type = t;}; +template<> struct value_type_traits<QString> { using type = const QString&; }; +template<> struct value_type_traits<slider_value> { using type = const slider_value&; }; +template<typename u> struct value_type_traits<QList<u>> +{ +    using type = const QList<typename std::remove_const<typename std::remove_reference<u>::type>::type>&; +}; +template<typename t> using value_type_t = typename value_type_traits<t>::type; +} + +class OPENTRACK_OPTIONS_EXPORT base_value : public QObject +{ +    Q_OBJECT +public: +    QString name() const { return self_name; } +    base_value(bundle b, const QString& name) : b(b), self_name(name) {} +signals: +    OPENTRACK_DEFINE_SIGNAL(double); +    OPENTRACK_DEFINE_SIGNAL(float); +    OPENTRACK_DEFINE_SIGNAL(int); +    OPENTRACK_DEFINE_SIGNAL(bool); +    OPENTRACK_DEFINE_SIGNAL(const QString&); +    OPENTRACK_DEFINE_SIGNAL(const slider_value&); +    OPENTRACK_DEFINE_SIGNAL(const QPointF&); + +    OPENTRACK_DEFINE_SIGNAL(const QList<double>&); +    OPENTRACK_DEFINE_SIGNAL(const QList<float>&); +    OPENTRACK_DEFINE_SIGNAL(const QList<int>&); +    OPENTRACK_DEFINE_SIGNAL(const QList<bool>&); +    OPENTRACK_DEFINE_SIGNAL(const QList<QString>&); +    OPENTRACK_DEFINE_SIGNAL(const QList<slider_value>&); +    OPENTRACK_DEFINE_SIGNAL(const QList<QPointF>&); +protected: +    bundle b; +    QString self_name; + +    template<typename t> +    void store(const t& datum) +    { +        b->store_kv(self_name, QVariant::fromValue(datum)); +        emit valueChanged(static_cast<detail::value_type_t<t>>(datum)); +    } + +    void store(float datum) +    { +        store(double(datum)); +    } + +public slots: +    OPENTRACK_DEFINE_SLOT(double) +    OPENTRACK_DEFINE_SLOT(int) +    OPENTRACK_DEFINE_SLOT(bool) +    OPENTRACK_DEFINE_SLOT(const QString&) +    OPENTRACK_DEFINE_SLOT(const slider_value&) +    OPENTRACK_DEFINE_SLOT(const QPointF&) + +    OPENTRACK_DEFINE_SLOT(const QList<double>&) +    OPENTRACK_DEFINE_SLOT(const QList<float>&) +    OPENTRACK_DEFINE_SLOT(const QList<int>&) +    OPENTRACK_DEFINE_SLOT(const QList<bool>&) +    OPENTRACK_DEFINE_SLOT(const QList<QString>&) +    OPENTRACK_DEFINE_SLOT(const QList<slider_value>&) +    OPENTRACK_DEFINE_SLOT(const QList<QPointF>&) +    public slots: +        virtual void reload() = 0; +}; + +namespace detail { +template<typename t> +struct value_get_traits +{ +    static inline t get(const t& val, const t&) +    { +        return val; +    } +}; + +template<> +struct value_get_traits<slider_value> +{ +    using t = slider_value; +    static inline t get(const t& val, const t& def) +    { +        return t(val.cur(), def.min(), def.max()); +    } +}; + +template<typename t, typename Enable = void> +struct value_element_type +{ +    using type = typename std::remove_reference<typename std::remove_cv<t>::type>::type; +}; + +// Qt uses int a lot in slots so use it for all enums +template<typename t> +struct value_element_type<t, typename std::enable_if<std::is_enum<t>::value>::type> +{ +    using type = int; +}; + +template<typename t> using value_element_type_t = typename value_element_type<t>::type; + +} + +template<typename t> +class value final : public base_value +{ +public: +    using element_type = detail::value_element_type_t<t>; + +    t operator=(const t& datum) +    { +        store(static_cast<element_type>(datum)); +        return datum; +    } + +    static constexpr const Qt::ConnectionType DIRECT_CONNTYPE = Qt::AutoConnection; +    static constexpr const Qt::ConnectionType SAFE_CONNTYPE = Qt::QueuedConnection; + +    value(bundle b, const QString& name, t def) : base_value(b, name), def(def) +    { +        QObject::connect(b.get(), SIGNAL(reloading()), +                         this, SLOT(reload()), +                         DIRECT_CONNTYPE); +        if (!b->contains(name) || b->get<QVariant>(name).type() == QVariant::Invalid) +            *this = def; +    } + +    value(bundle b, const char* name, t def) : value(b, QString(name), def) +    { +    } + +    t get() const +    { +        t val = b->contains(self_name) +                ? static_cast<t>(b->get<element_type>(self_name)) +                : def; +        return detail::value_get_traits<t>::get(val, def); +    } + +    operator t() const { return get(); } + +    void reload() override +    { +        *this = static_cast<t>(*this); +    } + +private: +    t def; +}; + + +} | 
