1 | /* |
2 | * SPDX-FileCopyrightText: 2007-2009 Petri Damstén <damu@iki.fi> |
3 | * SPDX-FileCopyrightText: 2014 John Layt <jlayt@kde.org> |
4 | * |
5 | * SPDX-License-Identifier: LGPL-2.0-or-later |
6 | */ |
7 | |
8 | #include "value.h" |
9 | #include "converter.h" |
10 | |
11 | #include <QVariant> |
12 | #include <qmath.h> |
13 | |
14 | namespace KUnitConversion |
15 | { |
16 | class ValuePrivate : public QSharedData |
17 | { |
18 | public: |
19 | ValuePrivate() |
20 | : m_number(0) |
21 | { |
22 | } |
23 | |
24 | ValuePrivate(qreal number, UnitId unitId = InvalidUnit) |
25 | : m_number(number) |
26 | { |
27 | m_unit = m_converter.unit(unitId); |
28 | } |
29 | |
30 | ValuePrivate(qreal number, const Unit &unit) |
31 | : m_number(number) |
32 | , m_unit(unit) |
33 | { |
34 | } |
35 | |
36 | ValuePrivate(qreal number, const QString &unitString) |
37 | : m_number(number) |
38 | { |
39 | m_unit = m_converter.unit(unitString); |
40 | } |
41 | |
42 | ValuePrivate(const ValuePrivate &other) |
43 | : QSharedData(other) |
44 | , m_number(other.m_number) |
45 | , m_unit(other.m_unit) |
46 | { |
47 | } |
48 | |
49 | virtual ~ValuePrivate() |
50 | { |
51 | } |
52 | |
53 | ValuePrivate &operator=(const ValuePrivate &other) |
54 | { |
55 | m_number = other.m_number; |
56 | m_unit = other.m_unit; |
57 | return *this; |
58 | } |
59 | |
60 | ValuePrivate *clone() |
61 | { |
62 | return new ValuePrivate(*this); |
63 | } |
64 | |
65 | bool operator==(const ValuePrivate &other) const |
66 | { |
67 | return (m_number == other.m_number && m_unit == other.m_unit); |
68 | } |
69 | |
70 | bool operator!=(const ValuePrivate &other) const |
71 | { |
72 | return !(*this == other); |
73 | } |
74 | |
75 | qreal m_number; |
76 | Unit m_unit; |
77 | Converter m_converter; |
78 | }; |
79 | |
80 | Value::Value() |
81 | : d(nullptr) |
82 | { |
83 | } |
84 | |
85 | Value::Value(const Value &other) |
86 | : d(other.d) |
87 | { |
88 | } |
89 | |
90 | Value::Value(qreal number, const Unit &unit) |
91 | : d(new ValuePrivate(number, unit)) |
92 | { |
93 | } |
94 | |
95 | Value::Value(qreal number, const QString &unitString) |
96 | : d(new ValuePrivate(number, unitString)) |
97 | { |
98 | } |
99 | |
100 | Value::Value(qreal number, UnitId unitId) |
101 | : d(new ValuePrivate(number, unitId)) |
102 | { |
103 | } |
104 | |
105 | Value::Value(const QVariant &number, const QString &unitString) |
106 | : d(new ValuePrivate(number.toReal(), unitString)) |
107 | { |
108 | } |
109 | |
110 | Value::~Value() |
111 | { |
112 | } |
113 | |
114 | Value &Value::operator=(const Value &other) |
115 | { |
116 | d = other.d; |
117 | return *this; |
118 | } |
119 | |
120 | bool Value::operator==(const Value &other) const |
121 | { |
122 | if (d && other.d) { |
123 | return (*d == *other.d); |
124 | } else { |
125 | return (d == other.d); |
126 | } |
127 | } |
128 | |
129 | bool Value::operator!=(const Value &other) const |
130 | { |
131 | if (d && other.d) { |
132 | return (*d != *other.d); |
133 | } else { |
134 | return (d != other.d); |
135 | } |
136 | } |
137 | |
138 | bool Value::isNull() const |
139 | { |
140 | return !d; |
141 | } |
142 | |
143 | bool Value::isValid() const |
144 | { |
145 | return (d && d->m_unit.isValid() && !qIsNaN(d: d->m_number)); |
146 | } |
147 | |
148 | qreal Value::number() const |
149 | { |
150 | if (d) { |
151 | return d->m_number; |
152 | } |
153 | return 0; |
154 | } |
155 | |
156 | Unit Value::unit() const |
157 | { |
158 | if (d) { |
159 | return d->m_unit; |
160 | } |
161 | return Unit(); |
162 | } |
163 | |
164 | QString Value::toString(int fieldWidth, char format, int precision, const QChar &fillChar) const |
165 | { |
166 | if (isValid()) { |
167 | return d->m_unit.toString(value: d->m_number, fieldWidth, format, precision, fillChar); |
168 | } |
169 | return QString(); |
170 | } |
171 | |
172 | QString Value::toSymbolString(int fieldWidth, char format, int precision, const QChar &fillChar) const |
173 | { |
174 | if (isValid()) { |
175 | return d->m_unit.toSymbolString(value: d->m_number, fieldWidth, format, precision, fillChar); |
176 | } |
177 | return QString(); |
178 | } |
179 | |
180 | Value &Value::round(uint decimals) |
181 | { |
182 | if (!isValid()) { |
183 | return *this; |
184 | } |
185 | |
186 | uint div = qPow(x: 10, y: decimals); |
187 | qreal add = 0.5 / (qreal)div; |
188 | |
189 | d->m_number = (int)((d->m_number + add) * div) / (qreal)div; |
190 | return *this; |
191 | } |
192 | |
193 | Value Value::convertTo(const Unit &unit) const |
194 | { |
195 | if (d) { |
196 | return d->m_converter.convert(value: *this, toUnit: unit); |
197 | } |
198 | return Value(); |
199 | } |
200 | |
201 | Value Value::convertTo(UnitId unitId) const |
202 | { |
203 | if (d) { |
204 | return d->m_converter.convert(value: *this, toUnit: unitId); |
205 | } |
206 | return Value(); |
207 | } |
208 | |
209 | Value Value::convertTo(const QString &unitString) const |
210 | { |
211 | if (d) { |
212 | return d->m_converter.convert(value: *this, toUnit: unitString); |
213 | } |
214 | return Value(); |
215 | } |
216 | |
217 | } |
218 | |