1 /****************************************************************************
2 **
3 ** DQt - D bindings for the Qt Toolkit
4 **
5 ** GNU Lesser General Public License Usage
6 ** This file may be used under the terms of the GNU Lesser
7 ** General Public License version 3 as published by the Free Software
8 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
9 ** packaging of this file. Please review the following information to
10 ** ensure the GNU Lesser General Public License version 3 requirements
11 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
12 **
13 ****************************************************************************/
14 module qt.core.flags;
15 extern(C++):
16 
17 import qt.config;
18 import qt.core.global;
19 import qt.core.typeinfo;
20 import qt.helpers;
21 version(D_LP64){}else
22     import core.stdc.config;
23 
24 /+ #ifndef QFLAGS_H +/
25 /+ #define QFLAGS_H
26 
27 
28 class QDataStream; +/
29 
30 @Q_PRIMITIVE_TYPE extern(C++, class) struct QFlag
31 {
32 private:
33     int i;
34 public:
35     pragma(inline, true) this(int value)/+ noexcept+/
36     {
37         this.i = value;
38     }
39     pragma(inline, true) auto opCast(T : int)() const/+ noexcept+/ { return i; }
40     pragma(inline, true) int toInt() const/+ noexcept+/ { return i; }
41     alias toInt this;
42 
43 /+ #if !defined(Q_CC_MSVC)
44     // Microsoft Visual Studio has buggy behavior when it comes to
45     // unsigned enums: even if the enum is unsigned, the enum tags are
46     // always signed
47 #  if !defined(__LP64__) && !defined(Q_CLANG_QDOC) +/
48     version(D_LP64){}else
49     {
50         pragma(inline, true) this(cpp_long value)/+ noexcept+/
51         {
52             this.i = cast(int)(value);
53         }
54         pragma(inline, true) this(cpp_ulong value)/+ noexcept+/
55         {
56             this.i = cast(int)(long(value));
57         }
58     }
59 /+ #  endif +/
60     pragma(inline, true) this(uint value)/+ noexcept+/
61     {
62         this.i = int(value);
63     }
64     pragma(inline, true) this(short value)/+ noexcept+/
65     {
66         this.i = int(value);
67     }
68     pragma(inline, true) this(ushort value)/+ noexcept+/
69     {
70         this.i = int(uint(value));
71     }
72     /+pragma(inline, true) auto opCast(T : uint)() const/+ noexcept+/ { return uint(i); }+/
73 /+ #endif +/
74 }
75 /+ Q_DECLARE_TYPEINFO(QFlag, Q_PRIMITIVE_TYPE); +/
76 
77 @Q_PRIMITIVE_TYPE extern(C++, class) struct QIncompatibleFlag
78 {
79 private:
80     int i;
81 public:
82     /+ explicit +/pragma(inline, true) this(int value)/+ noexcept+/
83     {
84         this.i = value;
85     }
86     /+pragma(inline, true) auto opCast(T : int)() const/+ noexcept+/ { return i; }+/
87 }
88 /+ Q_DECLARE_TYPEINFO(QIncompatibleFlag, Q_PRIMITIVE_TYPE);
89 
90 
91 #ifndef Q_NO_TYPESAFE_FLAGS +/
92 
93 extern(C++, class) struct QFlags(Enum)
94 {
95 private:
96     mixin(Q_STATIC_ASSERT_X(q{(Enum.sizeof <= int.sizeof)},
97                           q{"QFlags uses an int as storage, so an enum with underlying " ~
98                           "long long will overflow."}));
99     mixin(Q_STATIC_ASSERT_X(q{is(Enum == enum)}, q{"QFlags is only usable on enumeration types."}));
100 
101 /+ #if QT_DEPRECATED_SINCE(5,15) +/
102     struct Private;
103     alias Zero = int/+ Private::* +/*;
104 /+ #endif +/
105     /+ template <typename E> +/ /+ friend QDataStream &operator>>(QDataStream &, QFlags<E> &); +/
106     /+ template <typename E> +/ /+ friend QDataStream &operator<<(QDataStream &, QFlags<E>); +/
107 public:
108 /+ #if defined(Q_CC_MSVC) || defined(Q_CLANG_QDOC)
109     // see above for MSVC
110     // the definition below is too complex for qdoc
111     typedef int Int;
112 #else +/
113     /+ typename std::conditional<
114                 std::is_unsigned<typename std::underlying_type<Enum>::type>::value,
115                 unsigned int,
116                 signed int
117             >::type +/alias Int = int;
118 /+ #endif +/
119     alias enum_type = Enum;
120     // compiler-generated copy/move ctor/assignment operators are fine!
121 /+ #ifdef Q_CLANG_QDOC
122     inline QFlags(const QFlags &other);
123     inline QFlags &operator=(const QFlags &other);
124 #endif +/
125     /+pragma(inline, true) this()/+ noexcept+/
126     {
127         this.i = 0;
128     }+/
129     pragma(inline, true) this(Enum flags)/+ noexcept+/
130     {
131         this.i = Int(flags);
132     }
133 /+ #if QT_DEPRECATED_SINCE(5,15) +/
134     /+ QT_DEPRECATED_X("Use default constructor instead") +/ pragma(inline, true) this(Zero)/+ noexcept+/
135     {
136         this.i = 0;
137     }
138 /+ #endif +/
139     pragma(inline, true) this(QFlag flag)/+ noexcept+/
140     {
141         this.i = flag;
142     }
143 
144     /+ inline QFlags(std::initializer_list<Enum> flags) noexcept
145         : i(initializer_list_helper(flags.begin(), flags.end())) {} +/
146 
147     pragma(inline, true) ref QFlags opOpAssign(string op)(int mask)/+ noexcept+/ if(op == "&") { i &= mask; return this; }
148     pragma(inline, true) ref QFlags opOpAssign(string op)(uint mask)/+ noexcept+/ if(op == "&") { i &= mask; return this; }
149     pragma(inline, true) ref QFlags opOpAssign(string op)(Enum mask)/+ noexcept+/ if(op == "&") { i &= Int(mask); return this; }
150     pragma(inline, true) ref QFlags opOpAssign(string op)(QFlags other)/+ noexcept+/ if(op == "|") { i |= other.i; return this; }
151     pragma(inline, true) ref QFlags opOpAssign(string op)(Enum other)/+ noexcept+/ if(op == "|") { i |= Int(other); return this; }
152     /+pragma(inline, true) ref QFlags operator ^=(QFlags other)/+ noexcept+/ { i ^= other.i; return this; }+/
153     /+pragma(inline, true) ref QFlags operator ^=(Enum other)/+ noexcept+/ { i ^= Int(other); return this; }+/
154 
155     pragma(inline, true) auto opCast(T : Int)() const/+ noexcept+/ { return i; }
156     pragma(inline, true) Int toInt() const/+ noexcept+/ { return i; }
157     alias toInt this;
158 
159     pragma(inline, true) QFlags opBinary(string op)(QFlags other) const/+ noexcept+/ if(op == "|") { return QFlags(QFlag(i | other.i)); }
160     pragma(inline, true) QFlags opBinary(string op)(Enum other) const/+ noexcept+/ if(op == "|") { return QFlags(QFlag(i | Int(other))); }
161     /+pragma(inline, true) QFlags operator ^(QFlags other) const/+ noexcept+/ { return QFlags(QFlag(i ^ other.i)); }+/
162     /+pragma(inline, true) QFlags operator ^(Enum other) const/+ noexcept+/ { return QFlags(QFlag(i ^ Int(other))); }+/
163     pragma(inline, true) QFlags opBinary(string op)(int mask) const/+ noexcept+/ if(op == "&") { return QFlags(QFlag(i & mask)); }
164     pragma(inline, true) QFlags opBinary(string op)(uint mask) const/+ noexcept+/ if(op == "&") { return QFlags(QFlag(i & mask)); }
165     pragma(inline, true) QFlags opBinary(string op)(Enum other) const/+ noexcept+/ if(op == "&") { return QFlags(QFlag(i & Int(other))); }
166     QFlags opBinary(string op)(QFlags other) const if(op == "&") { return QFlags(QFlag(i & other.i)); }
167     /+pragma(inline, true) QFlags operator ~() const/+ noexcept+/ { return QFlags(QFlag(~i)); }+/
168 
169     /+pragma(inline, true) bool operator !() const/+ noexcept+/ { return !i; }+/
170 
171     pragma(inline, true) bool testFlag(Enum flag) const/+ noexcept+/ { return (i & Int(flag)) == Int(flag) && (Int(flag) != 0 || i == Int(flag) ); }
172     /+ inline QFlags &setFlag(Enum flag, bool on = true) noexcept
173     {
174         return on ? (*this |= flag) : (*this &= ~Int(flag));
175     } +/
176 
177     template opDispatch(string name) if(__traits(hasMember, Enum, name))
178     {
179         enum opDispatch = QFlags(__traits(getMember, Enum, name));
180     }
181 
182     bool opCast(T)() if(is(T == bool))
183     {
184         return i != 0;
185     }
186 
187 private:
188     /+pragma(inline, true) static Int initializer_list_helper(/+ typename std::initializer_list<Enum>::const_iterator +/ initializer_list.const_iterator it,
189                                                                    /+ typename std::initializer_list<Enum>::const_iterator +/ initializer_list.const_iterator end)/+
190         noexcept+/
191     {
192         return (it == end ? Int(0) : (Int(*it) | initializer_list_helper(it + 1, end)));
193     }+/
194 
195     Int i = 0;
196 }
197 
198 /+ #ifndef Q_MOC_RUN
199 #define Q_DECLARE_FLAGS(Flags, Enum)\
200 typedef QFlags<Enum> Flags;
201 #endif
202 
203 #define Q_DECLARE_INCOMPATIBLE_FLAGS(Flags) \
204 Q_DECL_CONSTEXPR inline QIncompatibleFlag operator|(Flags::enum_type f1, int f2) noexcept \
205 { return QIncompatibleFlag(int(f1) | f2); }
206 
207 #define Q_DECLARE_OPERATORS_FOR_FLAGS(Flags) \
208 Q_DECL_CONSTEXPR inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, Flags::enum_type f2) noexcept \
209 { return QFlags<Flags::enum_type>(f1) | f2; } \
210 Q_DECL_CONSTEXPR inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, QFlags<Flags::enum_type> f2) noexcept \
211 { return f2 | f1; } Q_DECLARE_INCOMPATIBLE_FLAGS(Flags) +/
212 
213 
214 /+ #else /* Q_NO_TYPESAFE_FLAGS */
215 
216 #ifndef Q_MOC_RUN
217 #define Q_DECLARE_FLAGS(Flags, Enum)\
218 typedef uint Flags;
219 #endif
220 
221 #define Q_DECLARE_OPERATORS_FOR_FLAGS(Flags)
222 
223 #endif +/ /* Q_NO_TYPESAFE_FLAGS */
224 
225 
226 /+ #endif +/ // QFLAGS_H
227 
228 template flagsFromStaticString(T, string str)
229 {
230     enum flagsFromStaticString = (){
231         T r;
232         static foreach(element; imported!q{std.array}.split(str, "|"))
233         {
234             r |= __traits(getMember, T.enum_type, imported!q{std.array}.split(element, "::")[$-1]);
235         }
236         return r;
237     }();
238 }
239 template enumFromStaticString(T, string str)
240 {
241     enum enumFromStaticString = __traits(getMember, T, imported!q{std.array}.split(str, "::")[$-1]);
242 }