1 module dqml.qobject; 2 3 import dqml.global; 4 import std.stdio; 5 import std.format; 6 import std.conv; 7 import std.container; 8 import std.traits; 9 import std.string; 10 import std.algorithm; 11 import dqml.qmetaobject; 12 import dqml.qobjectgenerators; 13 import dqml.dothersideinterface; 14 import dqml.qmetatype; 15 import dqml.qvariant; 16 import core.memory; 17 18 public class QObject 19 { 20 shared static this() 21 { 22 m_staticMetaObject = new QMetaObject(dos_qobject_qmetaobject()); 23 } 24 25 public this() 26 { 27 GC.setAttr(cast(void*)this, GC.BlkAttr.NO_MOVE); 28 setVoidPointer(createVoidPointer(), true); 29 } 30 31 ~this() 32 { 33 if (this.vptrOwned) 34 destroyVoidPointer(this.vptr); 35 } 36 37 public void* voidPointer() 38 { 39 return this.vptr; 40 } 41 42 public void setVoidPointer(void* vptr, bool owned) 43 { 44 this.vptr = vptr; 45 this.vptrOwned = owned; 46 } 47 48 @property public string objectName() 49 { 50 char* array = dos_qobject_objectName(this.vptr); 51 string result = fromStringz(array).dup; 52 dos_chararray_delete(array); 53 return result; 54 } 55 56 public static QMetaObject staticMetaObject() 57 { 58 return m_staticMetaObject; 59 } 60 61 public QMetaObject metaObject() 62 { 63 return staticMetaObject(); 64 } 65 66 protected void* createVoidPointer() 67 { 68 return dos_qobject_create(cast(void*)this, 69 metaObject().voidPointer(), 70 &staticSlotCallback); 71 } 72 73 protected void onSlotCalled(QVariant slotName, QVariant[] parameters) 74 { 75 } 76 77 protected bool connect(QObject sender, 78 string signal, 79 string method, 80 ConnectionType type = ConnectionType.Auto) 81 { 82 return QObject.connect(sender, signal, this, method, type); 83 } 84 85 protected bool disconnect(QObject sender, 86 string signal, 87 string method) 88 { 89 return QObject.disconnect(sender, signal, this, method); 90 } 91 92 protected void emit(T)(string signalName, T t) 93 { 94 emit(signalName, new QVariant(t)); 95 } 96 97 protected void emit(string signalName, QVariant value) 98 { 99 QVariant[] array = [value]; 100 emit(signalName, array); 101 } 102 103 protected void emit(string signalName, QVariant[] arguments = null) 104 { 105 int length = cast(int)arguments.length; 106 void*[] array = null; 107 if (length > 0) { 108 array = new void*[length]; 109 foreach (int i, QVariant v; arguments) 110 array[i] = v.voidPointer(); 111 } 112 dos_qobject_signal_emit(this.vptr, 113 signalName.toStringz(), 114 length, 115 array.ptr); 116 } 117 118 protected extern (C) static void staticSlotCallback(void* qObjectPtr, 119 void* rawSlotName, 120 int numParameters, 121 void** parametersArray) 122 { 123 QVariant[] parameters = new QVariant[numParameters]; 124 for (int i = 0; i < numParameters; ++i) 125 parameters[i] = new QVariant(parametersArray[i], Ownership.Clone); 126 QObject qObject = cast(QObject) qObjectPtr; 127 QVariant slotName = new QVariant(rawSlotName, Ownership.Clone); 128 qObject.onSlotCalled(slotName, parameters); 129 dos_qvariant_assign(parametersArray[0], parameters[0].voidPointer()); 130 } 131 132 protected static bool connect(QObject sender, 133 string signal, 134 QObject receiver, 135 string method, 136 ConnectionType type = ConnectionType.Auto) 137 { 138 return dos_qobject_signal_connect(sender.voidPointer, 139 signal.toStringz, 140 receiver.voidPointer, 141 method.toStringz, 142 type); 143 144 } 145 146 protected static bool disconnect(QObject sender, 147 string signal, 148 QObject receiver, 149 string method) 150 { 151 return dos_qobject_signal_disconnect(sender.voidPointer, 152 signal.toStringz, 153 receiver.voidPointer, 154 method.toStringz); 155 } 156 157 template connect(alias slot) 158 { 159 protected static bool connect(QObject sender, 160 string signalName, 161 QObject receiver, 162 ConnectionType type = ConnectionType.Auto) 163 { 164 return connect(sender, 165 SIGNAL!slot(signalName), 166 receiver, 167 SLOT!slot); 168 } 169 170 protected bool connect(QObject sender, 171 string signalName, 172 ConnectionType type = ConnectionType.Auto) 173 { 174 return connect!slot(sender, signalName, this); 175 } 176 } 177 178 template disconnect(alias slot) 179 { 180 protected static bool disconnect(QObject sender, 181 string signalName, 182 QObject receiver) 183 { 184 return disconnect(sender, 185 SIGNAL!slot(signalName), 186 receiver, 187 SLOT!slot); 188 } 189 190 protected bool disconnect(QObject sender, 191 string signalName) 192 { 193 return disconnect!slot(sender, signalName, this); 194 } 195 } 196 197 private void destroyVoidPointer(void* vptr) 198 { 199 dos_qobject_delete(vptr); 200 } 201 202 protected void* vptr; 203 protected bool vptrOwned; 204 private static QMetaObject m_staticMetaObject; 205 } 206 207 enum FindChildOptions : int 208 { 209 DirectOnly = 0, 210 Recursively 211 } 212 213 enum ConnectionType : int 214 { 215 Auto = 0, 216 Direct, 217 Queued, 218 BlockingQueued, 219 220 Unique = 0x80 221 } 222 223 template SIGNAL(alias slot) 224 { 225 string SIGNAL(string signalName) 226 { 227 return "2" ~ signalName ~ QObjectSignalParameters!slot; 228 } 229 } 230 231 template SLOT(alias slot) 232 { 233 enum string SLOT = "1" ~ __traits(identifier, slot) ~ QObjectSignalParameters!slot; 234 } 235 236 template QObjectSignalParameters(alias slot) 237 { 238 enum string QObjectSignalParameters = (Parameters!slot).stringof.replace("string", "QString"); 239 }