EHM DAL 0.2.5
Data abstraction layer for Eastside Hockey Manager
Loading...
Searching...
No Matches
data_type.h
1#pragma once
2
3// Application headers
4#include "include/database/database_version.h"
5
6// Qt headers
7#include <QDataStream>
8#include <QLocale>
9#include <QVariant>
10#include <type_traits>
11
12namespace ehm_dal::data_types {
13template<class T>
14concept Number = std::is_integral<T>::value || std::is_floating_point<T>::value;
15
19template<Number T>
21{
22public:
23 DataType(const T value = 0);
24 // NOTE making DataType virtual in any manner results in vtable corruption
25 //virtual ~DataType() = default;
26
27 template<Number T_CustomType>
28 void readCustomType(QDataStream &in);
29 template<Number T_CustomType>
30 void writeCustomType(QDataStream &out);
31
32 // File i/o (for compatibility with container classes)
33 bool read(QDataStream &in, ehm_dal::database::DatabaseVersion &version);
34 bool write(QDataStream &out, ehm_dal::database::DatabaseVersion &version);
35
36 // Get data
41 QVariant data(const qint32 role = Qt::DisplayRole) const;
45 inline T value() const { return value_; }
46
47 // Get data - decimals
48 // TODO <float> results in inaccurate decimal values (see e.g. Continent::RegionalStrength)
53 QVariant accurateDecimal(const qint32 role = Qt::DisplayRole) const;
58 QVariant roundedDecimal(const qint32 role = Qt::DisplayRole) const;
62 double toDouble() const;
66 float toFloat() const;
67
68 // Operator overloading: Comparators
69 inline auto operator<=>(const DataType &rhs) const { return value() <=> rhs.value(); }
70 inline bool operator==(const DataType &rhs) const { return value() == rhs.value(); }
71 inline auto operator<=>(const qint32 &rhs) const { return value() <=> rhs; }
72 inline bool operator==(const qint32 &rhs) const { return value() == rhs; }
73 inline bool operator==(const bool &rhs) const { return static_cast<bool>(value()) == rhs; }
74
75 // Set data
76 Q_DECL_DEPRECATED void set(const QVariant &value, const qint32 role = Qt::EditRole);
77 // BUG making setData() a virtual function appears to corrupt the vtable
83 void setData(const QVariant &value, const qint32 role = Qt::EditRole);
88 inline void setValue(const T value) { value_ = value; }
89
90private:
91 T value_;
92
93 // File i/o
94 friend QDataStream &operator>>(QDataStream &in, DataType<T> &data)
95 {
96 in.readRawData(reinterpret_cast<char *>(&data.value_), sizeof(T));
97 return in;
98 }
99 friend QDataStream &operator<<(QDataStream &out, const DataType<T> &data)
100 {
101 out.writeRawData(reinterpret_cast<const char *>(&data.value_), sizeof(T));
102 return out;
103 }
104};
105
106/* ================== */
107/* Data Type */
108/* ================== */
109
110template<Number T>
111DataType<T>::DataType(const T value)
112 : value_(value)
113{}
114
115/* ================== */
116/* File I/O */
117/* ================== */
118
119// --- Read data (for compatibility with container classes which require this method) --- //
120template<Number T>
121inline bool DataType<T>::read(QDataStream &in, database::DatabaseVersion &version)
122{
123 Q_UNUSED(version);
124 in >> *this;
125 return true;
126}
127
128// --- Write data (for compatibility with container classes which require this method) --- //
129template<Number T>
130inline bool DataType<T>::write(QDataStream &out, database::DatabaseVersion &version)
131{
132 Q_UNUSED(version);
133 out << *this;
134 return true;
135}
136
137// --- Read data from a data stream using a custom source type --- //
138template<Number T>
139template<Number T_CustomType>
140inline void DataType<T>::readCustomType(QDataStream &in)
141{
142 T_CustomType buffer;
143 in.readRawData(reinterpret_cast<char *>(&buffer), sizeof(T_CustomType));
144 value_ = static_cast<T>(buffer);
145}
146
147// --- Write data to a data stream using a custom source type --- //
148template<Number T>
149template<Number T_CustomType>
150inline void DataType<T>::writeCustomType(QDataStream &out)
151{
152 T_CustomType buffer{static_cast<T_CustomType>(value_)};
153 out.writeRawData(reinterpret_cast<const char *>(&buffer), sizeof(T_CustomType));
154}
155
156/* ================= */
157/* Get Data */
158/* ================= */
159
160template<Number T>
161QVariant DataType<T>::data(const qint32 role) const
162{
163 switch (role) {
164 case Qt::DisplayRole:
165 case Qt::EditRole:
166 return value_;
167 default:
168 return QVariant();
169 }
170}
171
172/* ============================ */
173/* Get Data - Decimals */
174/* ============================ */
175
176template<Number T>
177QVariant DataType<T>::accurateDecimal(const qint32 role) const
178{
179 if (role == Qt::DisplayRole || role == Qt::EditRole)
180 return QLocale().toString(value_);
181
182 return QVariant();
183}
184
185template<Number T>
186QVariant DataType<T>::roundedDecimal(const qint32 role) const
187{
188 if (role != Qt::DisplayRole && role != Qt::EditRole)
189 return QVariant();
190
191 if constexpr (std::is_floating_point_v<T>)
192 return QLocale().toString(value_, 'g', 8);
193
194 return QString::number(0.0);
195}
196
197template<Number T>
199{
200 return static_cast<double>(value_);
201}
202
203template<Number T>
205{
206 return static_cast<float>(value_);
207}
208
209/* ================= */
210/* Set Data */
211/* ================= */
212
213// TODO deprecate this function in favour of setData()
214template<Number T>
215void DataType<T>::set(const QVariant &value, const qint32 role)
216{
217 setData(value, role);
218}
219
220template<Number T>
221void DataType<T>::setData(const QVariant &value, const qint32 role)
222{
223 if (role != Qt::EditRole)
224 return;
225
226 if constexpr (std::is_floating_point_v<T>)
227 setValue(static_cast<T>(value.toDouble()));
228 else if constexpr (std::is_unsigned_v<T>)
229 setValue(static_cast<T>(value.toUInt()));
230 else
231 setValue(static_cast<T>(value.toInt()));
232}
233
234} // namespace ehm_dal::data_types
The DataType class is a template class for all C++ integral and floating point data types.
Definition: data_type.h:21
double toDouble() const
Returns the value as a double.
Definition: data_type.h:198
QVariant accurateDecimal(const qint32 role=Qt::DisplayRole) const
Returns the decimal value to as many decimal places as possible.
Definition: data_type.h:177
float toFloat() const
Returns the value as a float.
Definition: data_type.h:204
QVariant roundedDecimal(const qint32 role=Qt::DisplayRole) const
Returns the decimal value rounded to 8 decimal places. This is useful when converting a double to a f...
Definition: data_type.h:186
QVariant data(const qint32 role=Qt::DisplayRole) const
Returns the data stored under the given role for the item.
Definition: data_type.h:161
T value() const
Returns the raw value which can otherwise be accessed via QVariant data(const qint32 role).
Definition: data_type.h:45
void setValue(const T value)
Sets the value to value
Definition: data_type.h:88
void setData(const QVariant &value, const qint32 role=Qt::EditRole)
Sets the role data for the item at to value.
Definition: data_type.h:221
The DatabaseVersion class represents the database version number.
Definition: database_version.h:12
Definition: data_type.h:14
namespace ehm_dal::data_types
Definition: attribute.h:6