summaryrefslogtreecommitdiffhomepage
path: root/options/value-traits.hpp
blob: 31b6b5341aee7d01bab30ce050231833ce4cf490 (plain)
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#pragma once

#include "slider.hpp"
#include "export.hpp"

#include <QString>

#include <cmath>
#include <cinttypes>
#include <type_traits>

namespace options::detail {

template<typename t, typename Enable = void>
struct value_traits;

template<typename t, typename u = t, typename Enable = void>
struct default_value_traits
{
    using stored_type = std::decay_t<u>;
    using value_type = std::decay_t<t>;

    using self = value_traits<t>;

    static value_type value_with_default(const value_type& val, const value_type&)
    {
        return val;
    }

    static value_type value_from_storage(const stored_type& x)
    {
        return static_cast<value_type>(x);
    }

    static stored_type storage_from_value(const value_type& val)
    {
        return static_cast<stored_type>(val);
    }

    static value_type value_from_qvariant(const QVariant& x)
    {
        return self::value_from_storage(self::storage_from_qvariant(x));
    }

    static QVariant qvariant_from_value(const value_type& val)
    {
        return self::qvariant_from_storage(self::storage_from_value(val));
    }

    static constexpr inline
    value_type pass_value(const value_type& x)
    {
        if constexpr(std::is_same_v<value_type, stored_type>)
            return x;
        else
            return self::value_from_storage(self::storage_from_value(x));
    }

    static stored_type storage_from_qvariant(const QVariant& x)
    {
        // XXX TODO
        return x.value<stored_type>();
    }

    static QVariant qvariant_from_storage(const stored_type& val)
    {
        // XXX TODO
        return QVariant::fromValue<stored_type>(val);
    }

    static bool is_equal(const value_type& x, const value_type& y)
    {
        return x == y;
    }
};

template<typename t, typename Enable>
struct value_traits : default_value_traits<t> {};

template<>
struct value_traits<double> : default_value_traits<double>
{
    static bool is_equal(value_type x, value_type y)
    {
        if (x == y)
            return true;
        else
        {
            using I = std::int64_t;
            constexpr int K = 1000;

            value_type x_, y_;

            return I(std::round(std::modf(x, &x_) * K)) == I(std::round(std::modf(y, &y_) * K)) &&
                   I(std::round(x_)) == I(std::round(y_));
        }
    }
};

template<> struct value_traits<bool> : default_value_traits<bool, int>
{
    static stored_type storage_from_qvariant(const QVariant& x)
    {
        if (x.type() == QVariant::String)
            return x.toBool();
        else
            return !!x.toInt();
    }

    static QVariant qvariant_from_storage(const stored_type& val)
    {
        return QVariant::fromValue<int>(!!val);
    }

    static value_type value_from_storage(const stored_type& x)
    {
        return !!x;
    }
};

template<> struct value_traits<float> : value_traits<float, double>
{
    static constexpr inline value_type pass_value(const value_type& x) { return x; }
};

template<>
struct value_traits<slider_value> : default_value_traits<slider_value>
{
    static slider_value value_with_default(const slider_value& val, const slider_value& def)
    {
        return { val.cur(), def.min(), def.max() };
    }

    static bool is_equal(const slider_value& x, const slider_value& y)
    {
        using tr = value_traits<double>;
        return tr::is_equal(x.cur(), y.cur());
    }
};

// Qt uses int a lot in slots so use it for all enums
template<typename t>
struct value_traits<t, std::enable_if_t<std::is_enum_v<t>>> : default_value_traits<t, int> {};

} // ns options::detail