1 module dqml.qmetaobject;
2 
3 import dqml.dothersideinterface;
4 import dqml.qmetatype;
5 import std.string;
6 import core.stdc.stdlib;
7 
8 T* mallocArray(T)(int size) 
9 {
10     if (size == 0)
11         return null;
12     return cast(T*) malloc(T.sizeof * size);
13 }
14 
15 public struct ParameterDefinition
16 {
17     this(string name, QMetaType metaType)
18     {
19         this.name = name;
20         this.metaType = metaType;
21     }
22     
23     string name;
24     QMetaType metaType;
25 }
26 
27 public struct SignalDefinition
28 {
29     this(string name, string[] parametersNames, QMetaType[] parametersTypes)
30     {
31         this.name = name;
32         for (int i = 0; i < parametersNames.length; ++i)
33             parameters ~= ParameterDefinition(parametersNames[i], parametersTypes[i]);
34     }
35 
36     string name;
37     ParameterDefinition[] parameters;
38 }
39 
40 public struct SlotDefinition
41 {
42     this(string name, QMetaType returnType, string[] parametersNames, QMetaType[] parametersTypes)
43     {
44         this.name = name;
45         this.returnType = returnType;
46         for (int i = 0; i < parametersNames.length; ++i)
47             parameters ~= ParameterDefinition(parametersNames[i], parametersTypes[i]);
48     }
49 
50     string name;
51     QMetaType returnType;
52     ParameterDefinition[] parameters;
53 }
54 
55 public struct PropertyDefinition
56 {
57     this(string name, QMetaType type, string readSlot, string writeSlot, string notifySignal)
58     {
59         this.name = name;
60         this.type = type;
61         this.readSlot = readSlot;
62         this.writeSlot = writeSlot;
63         this.notifySignal = notifySignal;
64     }
65 
66     string name;
67     QMetaType type;
68     string readSlot;
69     string writeSlot;
70     string notifySignal;
71 }
72 
73 public class QMetaObject
74 {
75     public this(void* vptr)
76     {
77         this.vptr = vptr;
78     }
79 
80     public this(QMetaObject superClass,
81                 string className,
82                 SignalDefinition[] signalDefinitions,
83                 SlotDefinition[] slotDefinitions,
84                 PropertyDefinition[] propertyDefinitions)
85     {
86         this.signalDefinitions = signalDefinitions;
87         this.slotDefinitions = slotDefinitions;
88         this.propertyDefinitions = propertyDefinitions;
89 
90         auto dosSignalDefinitions = mallocDefinitions(signalDefinitions);
91         scope(exit) freeDefinitions(dosSignalDefinitions);
92         
93         auto dosSlotDefinitions = mallocDefinitions(slotDefinitions);
94         scope(exit) freeDefinitions(dosSlotDefinitions);
95         
96         auto dosPropertyDefinitions = mallocDefinitions(propertyDefinitions);
97         scope(exit) freeDefinitions(dosPropertyDefinitions);
98         
99         this.vptr = dos_qmetaobject_create(superClass.vptr,
100                                            className.toStringz(),
101                                            dosSignalDefinitions,
102                                            dosSlotDefinitions,
103                                            dosPropertyDefinitions);
104     }
105 
106     public ~this()
107     {
108         dos_qmetaobject_delete(this.vptr);
109     }
110 
111     @property SignalDefinition[] signals() { return signalDefinitions; }
112     @property SlotDefinition[] slots() { return slotDefinitions; }
113     @property PropertyDefinition[] properties() { return propertyDefinitions; }
114 
115     public void* voidPointer()
116     {
117         return this.vptr;
118     }
119     
120     private DosSignalDefinitions mallocDefinitions(SignalDefinition[] definitions)
121     {
122         DosSignalDefinitions result;
123         result.count = cast(int)definitions.length;
124         result.definitions = mallocArray!DosSignalDefinition(result.count);
125         
126         for (int i = 0; i < result.count; ++i)
127         {
128             SignalDefinition signalProto = definitions[i];
129             DosSignalDefinition* signalDef = result.definitions + i;
130             signalDef.name = toStringz(signalProto.name);
131             signalDef.parametersCount = cast(int)signalProto.parameters.length;
132             signalDef.parameters = mallocArray!DosParameterDefinition(signalDef.parametersCount);
133             for (int j = 0; j < signalDef.parametersCount; ++j)
134             {
135                 ParameterDefinition parameterProto = signalProto.parameters[j];
136                 DosParameterDefinition* parameterDef = signalDef.parameters + j;
137                 parameterDef.name = toStringz(parameterProto.name);
138                 parameterDef.metaType = parameterProto.metaType;
139             }
140         }
141         
142         return result;
143     }
144     
145     private void freeDefinitions(DosSignalDefinitions definitions) 
146     {
147         for (int i = 0; i < definitions.count; ++i)
148             free((definitions.definitions + i).parameters);
149         free(definitions.definitions);
150     }
151     
152     private DosSlotDefinitions mallocDefinitions(SlotDefinition[] definitions)
153     {
154         DosSlotDefinitions result;
155         result.count = cast(int)definitions.length;
156         result.definitions = mallocArray!DosSlotDefinition(result.count);
157         
158         for (int i = 0; i < result.count; ++i)
159         {
160             SlotDefinition slotProto = definitions[i];
161             DosSlotDefinition* slotDef = result.definitions + i;
162             slotDef.name = toStringz(slotProto.name);
163             slotDef.returnType = slotProto.returnType;
164             slotDef.parametersCount = cast(int)slotProto.parameters.length;
165             slotDef.parameters = mallocArray!DosParameterDefinition(slotDef.parametersCount);
166             for (int j = 0; j < slotDef.parametersCount; ++j)
167             {
168                 ParameterDefinition parameterProto = slotProto.parameters[j];
169                 DosParameterDefinition* parameterDef = slotDef.parameters + j;
170                 parameterDef.name = toStringz(parameterProto.name);
171                 parameterDef.metaType = parameterProto.metaType;
172             }
173         }
174         
175         return result;
176     }
177     
178     private void freeDefinitions(DosSlotDefinitions definitions)
179     {
180         for (int i = 0; i < definitions.count; ++i)
181             free((definitions.definitions + i).parameters);
182         free(definitions.definitions);
183     }
184     
185     private DosPropertyDefinitions mallocDefinitions(PropertyDefinition[] definitions)
186     {
187         DosPropertyDefinitions result;
188         result.count = cast(int)definitions.length;
189         result.definitions = mallocArray!DosPropertyDefinition(result.count);
190         for (int i = 0; i < result.count; ++i)
191         {
192             PropertyDefinition proto = definitions[i];
193             DosPropertyDefinition* def = result.definitions + i;
194             def.name = toStringz(proto.name);
195             def.type = proto.type;
196             def.readSlot = toStringz(proto.readSlot);
197             def.writeSlot = toStringz(proto.writeSlot);
198             def.notifySignal = toStringz(proto.notifySignal);
199         }
200         return result;
201     }
202     
203     private void freeDefinitions(DosPropertyDefinitions definitions)
204     {
205         free(definitions.definitions);
206     }
207 
208     private void* vptr;
209     private PropertyDefinition[] propertyDefinitions;
210     private SignalDefinition[] signalDefinitions;
211     private SlotDefinition[] slotDefinitions;
212 }