-
Notifications
You must be signed in to change notification settings - Fork 0
/
qt_helpers.hpp
172 lines (150 loc) · 4.92 KB
/
qt_helpers.hpp
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
#ifndef QT_HELPERS_HPP_
#define QT_HELPERS_HPP_
#include <stdexcept>
#include <ostream>
#include <QString>
#include <QChar>
#include <QMetaObject>
#include <QHostAddress>
#include <QDataStream>
#include <QMetaType>
#include <QMetaEnum>
#define ENUM_QDATASTREAM_OPS_DECL(CLASS, ENUM) \
QDataStream& operator << (QDataStream&, CLASS::ENUM const&); \
QDataStream& operator >> (QDataStream&, CLASS::ENUM&);
#define ENUM_QDATASTREAM_OPS_IMPL(CLASS, ENUM) \
QDataStream& operator << (QDataStream& os, CLASS::ENUM const& v) \
{ \
auto const& mo = CLASS::staticMetaObject; \
return os << mo.enumerator (mo.indexOfEnumerator (#ENUM)).valueToKey (static_cast<int> (v)); \
} \
\
QDataStream& operator >> (QDataStream& is, CLASS::ENUM& v) \
{ \
char * buffer; \
is >> buffer; \
bool ok {false}; \
auto const& mo = CLASS::staticMetaObject; \
auto const& me = mo.enumerator (mo.indexOfEnumerator (#ENUM)); \
if (buffer) \
{ \
v = static_cast<CLASS::ENUM> (me.keyToValue (buffer, &ok)); \
delete [] buffer; \
} \
if (!ok) \
{ \
v = static_cast<CLASS::ENUM> (me.value (0)); \
} \
return is; \
}
#define ENUM_CONVERSION_OPS_DECL(CLASS, ENUM) \
QString enum_to_qstring (CLASS::ENUM const&);
#define ENUM_CONVERSION_OPS_IMPL(CLASS, ENUM) \
QString enum_to_qstring (CLASS::ENUM const& m) \
{ \
auto const& mo = CLASS::staticMetaObject; \
return QString {mo.enumerator (mo.indexOfEnumerator (#ENUM)).valueToKey (static_cast<int> (m))}; \
}
#if QT_VERSION >= QT_VERSION_CHECK (5, 15, 0)
Qt::SplitBehaviorFlags const SkipEmptyParts = Qt::SkipEmptyParts;
#else
QString::SplitBehavior const SkipEmptyParts = QString::SkipEmptyParts;
#endif
inline
std::ostream& operator << (std::ostream& os, QByteArray const& b)
{
return os << b.constData ();
}
inline
std::ostream& operator << (std::ostream& os, QString const& s)
{
return os << s.toStdString ();
}
inline
void throw_qstring (QString const& qs)
{
throw std::runtime_error {qs.toLocal8Bit ().constData ()};
}
QString font_as_stylesheet (QFont const&);
// do what is necessary to change a dynamic property and trigger any
// conditional style sheet updates
void update_dynamic_property (QWidget *, char const * property, QVariant const& value);
// round a QDateTime instance to an integral interval of milliseconds
QDateTime qt_round_date_time_to (QDateTime dt, int milliseconds);
// truncate a QDateTime to an integral interval of milliseconds
QDateTime qt_truncate_date_time_to (QDateTime dt, int milliseconds);
template <class T>
class VPtr
{
public:
static T * asPtr (QVariant v)
{
return reinterpret_cast<T *> (v.value<void *> ());
}
static QVariant asQVariant(T * ptr)
{
return QVariant::fromValue (reinterpret_cast<void *> (ptr));
}
};
#if QT_VERSION < QT_VERSION_CHECK (5, 14, 0)
// The Qt devs "fixed" this in 5.14 to specialize to use their own
// qHash(), it doesn't fix the problem we were addressing as qHash()
// returns a uint so is still a poorly distributed 32-bit value on
// 64-bit platforms, but we can't specialize ourselves as Qt already
// has - sigh.
namespace std
{
// std::hash<> specialization for QString based on the dbj2
// algorithm http://www.cse.yorku.ca/~oz/hash.html because qHash()
// is poor on 64-bit platforms due to being a 32-bit hash value
template<>
struct hash<QString>
{
std::size_t operator () (QString const& s) const noexcept
{
std::size_t hash {5381};
for (int i = 0; i < s.size (); ++i)
{
hash = ((hash << 5) + hash) + ((s.at (i).row () << 8) | s.at (i).cell ());
}
return hash;
}
};
}
#endif
inline
bool is_broadcast_address (QHostAddress const& host_addr)
{
#if QT_VERSION >= QT_VERSION_CHECK (5, 11, 0)
return host_addr.isBroadcast ();
#else
bool ok;
return host_addr.toIPv4Address (&ok) == 0xffffffffu && ok;
#endif
}
inline
bool is_multicast_address (QHostAddress const& host_addr)
{
#if QT_VERSION >= QT_VERSION_CHECK (5, 6, 0)
return host_addr.isMulticast ();
#else
bool ok;
return (((host_addr.toIPv4Address (&ok) & 0xf0000000u) == 0xe0000000u) && ok)
|| host_addr.toIPv6Address ()[0] == 0xff;
#endif
}
inline
bool is_MAC_ambiguous_multicast_address (QHostAddress const& host_addr)
{
// sub-ranges 224.128.0.0/24, 225.0.0.0/24, 225.128.0.0/24,
// 226.0.0.0/24, 226.128.0.0/24, ..., 239.0.0.0/24, 239.128.0.0/24
// are not supported as they are inefficient due to ambiguous
// mappings to Ethernet MAC addresses. 224.0.0.0/24 alone is allowed
// from these ranges
bool ok;
auto ipv4 = host_addr.toIPv4Address (&ok);
return ok && !((ipv4 & 0xffffff00u) == 0xe0000000) && (ipv4 & 0xf07fff00) == 0xe0000000;
}
// Register some useful Qt types with QMetaType
Q_DECLARE_METATYPE (QHostAddress);
#endif