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