1 /************************************************************************
2 *
3 * Copyright 2010 - 2012 Jakob Leben (jakob.leben@gmail.com)
4 *
5 * This file is part of SuperCollider Qt GUI.
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 ************************************************************************/
21
22 #pragma once
23
24 #include "widgets/QcTreeWidget.h"
25 #include "widgets/QcMenu.h"
26 #include "image.h"
27
28 #include <PyrSlot.h>
29 #include <PyrKernel.h>
30
31 #include <QDebug>
32 #include <QChar>
33 #include <QString>
34 #include <QPoint>
35 #include <QPointF>
36 #include <QSize>
37 #include <QSizeF>
38 #include <QRect>
39 #include <QRectF>
40 #include <QColor>
41 #include <QFont>
42 #include <QPalette>
43 #include <QWidget>
44 #include <QLayout>
45 #include <QVector>
46 #include <QUrl>
47 #include <QVariantList>
48
49 class QObjectProxy;
50
51 namespace QtCollider {
52
53 template <typename T, typename EnabledT = void> struct TypeCodec {};
54
55 // Forwarding from QtCollider namespace to TypeCodec
56
read(PyrSlot * slot)57 template <typename T> inline T read(PyrSlot* slot) { return TypeCodec<T>::read(slot); }
58
write(PyrSlot * slot,const T & val)59 template <typename T> inline void write(PyrSlot* slot, const T& val) { return TypeCodec<T>::write(slot, val); }
60
61 // Lazy conversion, allows automatic codec deduction
62
63 struct DecodableSlot {
64 PyrSlot* _slot;
DecodableSlotQtCollider::DecodableSlot65 DecodableSlot(PyrSlot* slot): _slot(slot) {}
operator TQtCollider::DecodableSlot66 template <typename T> operator T() { return TypeCodec<T>::safeRead(_slot); }
67 };
68
get(PyrSlot * slot)69 inline DecodableSlot get(PyrSlot* slot) { return DecodableSlot(slot); }
70
get(PyrSlot * slot)71 template <typename T> inline T get(PyrSlot* slot) { return TypeCodec<T>::safeRead(slot); }
72
set(PyrSlot * slot,const T & val)73 template <typename T> inline void set(PyrSlot* slot, const T& val) {
74 // write is always type-safe
75 TypeCodec<T>::write(slot, val);
76 }
77
setObjectList(PyrSlot * slot,int size,IteratorT iter,IteratorT end)78 template <typename IteratorT> static void setObjectList(PyrSlot* slot, int size, IteratorT iter, IteratorT end) {
79 typedef typename IteratorT::value_type ValueT;
80 VMGlobals* g = gMainVMGlobals;
81
82 PyrObject* array = newPyrArray(g->gc, size, 0, true);
83 SetObject(slot, array);
84
85 PyrSlot* s = array->slots;
86 for (; iter != end; ++iter) {
87 if (size > 0) {
88 TypeCodec<ValueT>::write(s, *iter);
89 ++array->size;
90 ++s;
91 --size;
92 }
93 }
94 }
95
96
97 // TypeCodecs
98
99 template <> struct TypeCodec<bool> {
readQtCollider::TypeCodec100 static bool read(PyrSlot* slot) { return IsTrue(slot); }
101
safeReadQtCollider::TypeCodec102 static bool safeRead(PyrSlot* slot) { return read(slot); }
103
writeQtCollider::TypeCodec104 static void write(PyrSlot* slot, const bool val) {
105 if (val)
106 SetTrue(slot);
107 else
108 SetFalse(slot);
109 }
110 };
111
112 template <> struct TypeCodec<int> {
readQtCollider::TypeCodec113 static int read(PyrSlot* slot) { return slotRawInt(slot); }
114
safeReadQtCollider::TypeCodec115 static int safeRead(PyrSlot* slot) {
116 int val;
117 if (slotIntVal(slot, &val))
118 return 0;
119 return val;
120 }
121
writeQtCollider::TypeCodec122 static void write(PyrSlot* slot, const int val) { SetInt(slot, val); }
123 };
124
125 template <> struct TypeCodec<float> {
readQtCollider::TypeCodec126 static float read(PyrSlot* slot) { return slotRawFloat(slot); }
127
safeReadQtCollider::TypeCodec128 static float safeRead(PyrSlot* slot) {
129 float val;
130 if (slotFloatVal(slot, &val))
131 return 0.f;
132 return val;
133 }
134
writeQtCollider::TypeCodec135 static void write(PyrSlot* slot, const float val) { SetFloat(slot, val); }
136 };
137
138 template <> struct TypeCodec<double> {
readQtCollider::TypeCodec139 static double read(PyrSlot* slot) {
140 double d;
141 slotVal(slot, &d);
142 return d;
143 }
144
safeReadQtCollider::TypeCodec145 static double safeRead(PyrSlot* slot) {
146 double val;
147 if (slotDoubleVal(slot, &val))
148 return 0.0;
149 return val;
150 }
151
writeQtCollider::TypeCodec152 static void write(PyrSlot* slot, const double val) {
153 // NOTE: the signature actually reads SetFloat(PyrSlot*, double):
154 SetFloat(slot, val);
155 }
156 };
157
158 template <> struct TypeCodec<QChar> {
readQtCollider::TypeCodec159 static QChar read(PyrSlot* slot) { return QChar(slotRawChar(slot)); }
160
safeReadQtCollider::TypeCodec161 static QChar safeRead(PyrSlot* slot) {
162 if (GetTag(slot) == tagChar)
163 return QChar(slotRawChar(slot));
164 else
165 return QChar();
166 }
167
writeQtCollider::TypeCodec168 static void write(PyrSlot* slot, const QChar& val) {
169 // FIXME: Should add support for unicode in PyrSlot!
170 SetChar(slot, val.toLatin1());
171 }
172 };
173
174 template <> struct TypeCodec<QString> {
175 static QString read(PyrSlot* slot);
176
safeReadQtCollider::TypeCodec177 static QString safeRead(PyrSlot* slot) { return read(slot); }
178
179 static void write(PyrSlot* slot, const QString& val);
180 };
181
182 template <> struct TypeCodec<QUrl> {
183 static QUrl read(PyrSlot* slot);
184
safeReadQtCollider::TypeCodec185 static QUrl safeRead(PyrSlot* slot) { return read(slot); }
186
187 static void write(PyrSlot* slot, const QUrl& val);
188 };
189
190 template <> struct TypeCodec<QPointF> {
191 static QPointF read(PyrSlot* slot);
192
193 static QPointF safeRead(PyrSlot* slot);
194
195 static void write(PyrSlot* slot, const QPointF& pt);
196 };
197
198 template <> struct TypeCodec<QPoint> {
readQtCollider::TypeCodec199 static QPoint read(PyrSlot* slot) { return TypeCodec<QPointF>::read(slot).toPoint(); }
200
safeReadQtCollider::TypeCodec201 static QPoint safeRead(PyrSlot* slot) { return TypeCodec<QPointF>::safeRead(slot).toPoint(); }
202
writeQtCollider::TypeCodec203 static void write(PyrSlot* slot, const QPoint& pt) { TypeCodec<QPointF>::write(slot, pt); }
204 };
205
206 template <> struct TypeCodec<QRectF> {
207 static QRectF read(PyrSlot* slot);
208
209 static QRectF safeRead(PyrSlot* slot);
210
211 static void write(PyrSlot* slot, const QRectF& r);
212 };
213
214 template <> struct TypeCodec<QRect> {
readQtCollider::TypeCodec215 static QRect read(PyrSlot* slot) { return TypeCodec<QRectF>::read(slot).toRect(); }
216
safeReadQtCollider::TypeCodec217 static QRect safeRead(PyrSlot* slot) { return TypeCodec<QRectF>::safeRead(slot).toRect(); }
218
writeQtCollider::TypeCodec219 static void write(PyrSlot* slot, const QRect& rect) { TypeCodec<QRectF>::write(slot, rect); }
220 };
221
222 template <> struct TypeCodec<QSizeF> {
223 static QSizeF read(PyrSlot* slot);
224
225 static QSizeF safeRead(PyrSlot* slot);
226
227 static void write(PyrSlot* slot, const QSizeF& sz);
228 };
229
230 template <> struct TypeCodec<QSize> {
readQtCollider::TypeCodec231 static QSize read(PyrSlot* slot) { return TypeCodec<QSizeF>::read(slot).toSize(); }
232
safeReadQtCollider::TypeCodec233 static QSize safeRead(PyrSlot* slot) { return TypeCodec<QSizeF>::safeRead(slot).toSize(); }
234
writeQtCollider::TypeCodec235 static void write(PyrSlot* slot, const QSize& size) { TypeCodec<QSizeF>::write(slot, size); }
236 };
237
238 template <> struct TypeCodec<QColor> {
239 static QColor read(PyrSlot* slot);
240
safeReadQtCollider::TypeCodec241 static QColor safeRead(PyrSlot* slot) {
242 if (IsObj(slot))
243 return read(slot);
244 return QColor();
245 }
246
247 static void write(PyrSlot* slot, const QColor&);
248 };
249
250 template <> struct TypeCodec<QFont> {
251 static QFont read(PyrSlot* slot);
252
253 static QFont safeRead(PyrSlot* slot);
254
writeQtCollider::TypeCodec255 static void write(PyrSlot* slot, const QFont&) {
256 qWarning("WARNING: QtCollider: writing QFont to PyrSlot not supported.");
257 }
258 };
259
260 template <> struct TypeCodec<QPalette> {
261 static QPalette read(PyrSlot* slot);
262
263 static QPalette safeRead(PyrSlot* slot);
264
265 static void write(PyrSlot* slot, const QPalette&);
266 };
267
268 template <> struct TypeCodec<QObjectProxy*> {
readQtCollider::TypeCodec269 static QObjectProxy* read(PyrSlot* slot) {
270 PyrSlot* proxySlot = slotRawObject(slot)->slots;
271 if (IsPtr(proxySlot))
272 return (QObjectProxy*)slotRawPtr(proxySlot);
273 else
274 return 0;
275 }
276
277 static QObjectProxy* safeRead(PyrSlot* slot);
278
writeQtCollider::TypeCodec279 static void write(PyrSlot*, QObjectProxy*) {
280 qWarning("WARNING: QtCollider: writing QObjectProxy* to PyrSlot not supported.");
281 }
282 };
283
284 template <> struct TypeCodec<QObject*> {
readQtCollider::TypeCodec285 static QObject* read(PyrSlot*) {
286 qWarning("WARNING: QtCollider: reading QObject* from PyrSlot not supported.");
287 return 0;
288 }
289
290 static void write(PyrSlot*, QObject*);
291 };
292
293
294 #define TYPE_IS_QOBJECT(type) std::is_convertible<QObjectT, QObject*>::value
295 template <> struct TypeCodec<PyrObject*> {
readQtCollider::TypeCodec296 static PyrObject* read(PyrSlot*) {
297 qWarning("WARNING: TypeCodec<PyrObject*>::read(PyrSlot*) = NO-OP");
298 return 0;
299 }
300
writeQtCollider::TypeCodec301 static void write(PyrSlot* slot, PyrObject* object) { SetObject(slot, object); }
302 };
303
304 template <> struct TypeCodec<QcTreeWidget::ItemPtr> {
305 static QcTreeWidget::ItemPtr read(PyrSlot* slot);
306
307 static void write(PyrSlot* slot, const QcTreeWidget::ItemPtr&);
308 };
309
310 template <> struct TypeCodec<SharedImage> {
311 static SharedImage read(PyrSlot* slot);
312 static SharedImage safeRead(PyrSlot* slot);
313 static void write(PyrSlot* slot, SharedImage image);
314 };
315
316 template <> struct TypeCodec<QVector<int>> {
317 static QVector<int> read(PyrSlot* slot);
318
319 static void write(PyrSlot* slot, const QVector<int>&);
320 };
321
322 template <> struct TypeCodec<QVector<double>> {
323 static QVector<double> read(PyrSlot* slot);
324
325 static void write(PyrSlot* slot, const QVector<double>&);
326 };
327
328 template <typename ContainedT> struct TypeCodec<QVector<ContainedT>> {
readQtCollider::TypeCodec329 static QVector<ContainedT> read(PyrSlot* slot) {
330 qWarning("WARNING: TypeCodec<PyrObject*>::read(PyrSlot*) = NO-OP");
331 return QVector<ContainedT>();
332 }
333
writeQtCollider::TypeCodec334 static void write(PyrSlot* slot, const QVector<ContainedT>& vec) {
335 setObjectList(slot, vec.size(), vec.begin(), vec.end());
336 }
337 };
338
339 template <typename ContainedT> struct TypeCodec<QList<ContainedT>> {
readQtCollider::TypeCodec340 static QList<ContainedT> read(PyrSlot* slot) {
341 qWarning("WARNING: TypeCodec<PyrObject*>::read(PyrSlot*) = NO-OP");
342 return QList<ContainedT>();
343 }
344
writeQtCollider::TypeCodec345 static void write(PyrSlot* slot, const QList<ContainedT>& vec) {
346 setObjectList(slot, vec.size(), vec.begin(), vec.end());
347 }
348 };
349
350 template <> struct TypeCodec<QVariantList> {
351 static QVariantList read(PyrSlot* slot);
352
safeReadQtCollider::TypeCodec353 static QVariantList safeRead(PyrSlot* slot) { return read(slot); }
354
355 static void write(PyrSlot* slot, const QVariantList&);
356 };
357
358 template <typename QObjectT> struct TypeCodec<QObjectT, void> {
readQtCollider::TypeCodec359 static QObjectT read(PyrSlot* slot) { return safeRead(slot); }
360
safeReadQtCollider::TypeCodec361 static QObjectT safeRead(PyrSlot* slot) {
362 auto proxy = TypeCodec<QObjectProxy*>::safeRead(slot);
363
364 if (proxy) {
365 auto action = qobject_cast<QObjectT>(proxy->object());
366 return action;
367 } else {
368 return 0;
369 }
370 }
371
writeQtCollider::TypeCodec372 static void write(PyrSlot* slot, QObjectT object) {
373 auto qobject = qobject_cast<QObject*>(object);
374 TypeCodec<QObject*>::write(slot, qobject);
375 }
376 };
377
378 } // namespace QtCollider
379