/* Copyright (c) 2015-2016, Stanislaw Halik * Permission to use, copy, modify, and/or distribute this * software for any purpose with or without fee is hereby granted, * provided that the above copyright notice and this permission * notice appear in all copies. */ #pragma once #include "export.hpp" #include "bundle.hpp" #include "slider.hpp" #include "base-value.hpp" #include "value-traits.hpp" #include "compat/macros.hpp" #include #include #include namespace options::detail { template struct dereference_wrapper final { cc_forceinline constexpr t const* operator->() const { return &x; } cc_forceinline constexpr t* operator->() { return &x; } t x; constexpr explicit cc_forceinline dereference_wrapper(t&& x) : x(x) {} }; } // ns options::detail namespace options { template class value final : public value_ { const t def; using traits = detail::value_traits; using stored_type = typename traits::stored_type; static bool is_equal(const QVariant& val1, const QVariant& val2) { return val1.value() == val2.value(); } cc_noinline t get() const { if (self_name.isEmpty()) return def; QVariant variant = b->get(self_name); if (!b->contains(self_name) || variant.type() == QVariant::Invalid) return def; const stored_type x { variant.value() }; return traits::from_value(traits::from_storage(x), def); } friend class detail::connector; void bundle_value_changed() const override { if (!self_name.isEmpty()) emit valueChanged(traits::to_storage(get())); } void store_variant(const QVariant& value) override { if (self_name.isEmpty()) return; if (value.type() == qMetaTypeId()) b->store_kv(self_name, value); else operator=(traits::value_from_variant(value)); } public: cc_noinline value& operator=(const t& datum) { if (self_name.isEmpty()) return *this; if (datum != get()) b->store_kv(self_name, QVariant::fromValue(traits::to_storage(datum))); return *this; } static constexpr inline Qt::ConnectionType DIRECT_CONNTYPE = Qt::DirectConnection; static constexpr inline Qt::ConnectionType SAFE_CONNTYPE = Qt::QueuedConnection; cc_noinline value(bundle b, const QString& name, t def) : value_(b, name, &is_equal, std::type_index(typeid(stored_type))), def(def) { if (!self_name.isEmpty()) QObject::connect(b.get(), &detail::bundle::reloading, this, &value_::reload, DIRECT_CONNTYPE); } cc_noinline t default_value() const { return def; } cc_noinline void set_to_default() override { *this = def; } operator t() const { return get(); } // NOLINT template(std::declval()))> explicit cc_forceinline operator u() const { return to(); } auto operator->() const { return detail::dereference_wrapper{get()}; } cc_noinline void reload() override { #if 0 if (!self_name.isEmpty()) store(traits::to_storage(get())); #endif } cc_forceinline t operator()() const { return get(); } cc_forceinline t operator*() const { return get(); } template u to() const { return static_cast(get()); } }; // some linker problems #if !defined OTR_INST_VALUE # define OTR_INST_VALUE OTR_TEMPLATE_IMPORT #endif OTR_INST_VALUE(value); OTR_INST_VALUE(value); OTR_INST_VALUE(value); OTR_INST_VALUE(value); OTR_INST_VALUE(value); OTR_INST_VALUE(value); OTR_INST_VALUE(value); OTR_INST_VALUE(value); OTR_INST_VALUE(value>); OTR_INST_VALUE(value>); OTR_INST_VALUE(value>); OTR_INST_VALUE(value>); OTR_INST_VALUE(value>); OTR_INST_VALUE(value>); OTR_INST_VALUE(value>); OTR_INST_VALUE(value>); } // ns options