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 }