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 }