1 /***************************************************************************
3 * This file is part of the KDE project
4 * copyright (C)2005 by Cyrille Berger (cberger@cberger.net)
5 * copyright (C)2006 by Sebastian Sauer (mail@dipe.org)
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public License
16 * along with this program; see the file COPYING. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 ***************************************************************************/
21 #ifndef KROSS_RUBYVARIANT_H
22 #define KROSS_RUBYVARIANT_H
24 #include "rubyconfig.h"
25 #include <kross/core/metatype.h>
28 #include <QStringList>
43 * The RubyType helper classes used to cast between QVariant
46 * Following QVariant::Type's are implemented;
47 * \li QVariant::Invalid
50 * \li QVariant::Double
52 * \li QVariant::LongLong
53 * \li QVariant::ULongLong
54 * \li QVariant::ByteArray
55 * \li QVariant::String
56 * \li QVariant::StringList
60 * \li QVariant::PointF
67 * \li QVariant::DateTime
71 * Following QVariant::Type's are unimplemented yet (do we need them anyways?);
72 * \li QVariant::BitArray
73 * \li QVariant::Bitmap
76 * \li QVariant::Cursor
80 * \li QVariant::KeySequence
83 * \li QVariant::Locale
84 * \li QVariant::Palette
86 * \li QVariant::Pixmap
87 * \li QVariant::PointArray
88 * \li QVariant::Polygon
89 * \li QVariant::RegExp
90 * \li QVariant::Region
91 * \li QVariant::SizePolicy
92 * \li QVariant::TextFormat
93 * \li QVariant::TextLength
95 template<typename VARIANTTYPE
, typename RBTYPE
= VALUE
>
98 // template-specialisations need to implement following both static
99 // functions to translate between QVariant and Ruby's VALUE values.
101 //inline static RBTYPE toVALUE(const VARIANTTYPE&) { return Py::None(); }
102 //inline static QVARIANTTYPE toVariant(const VARIANTTYPE&) { return QVariant(); }
107 struct RubyType
<QVariant
>
109 static VALUE
toVALUE(const QVariant
& v
);
110 static QVariant
toVariant(VALUE value
);
117 inline static VALUE
toVALUE(int i
) {
120 inline static int toVariant(VALUE value
) {
121 switch( TYPE(value
) ) {
123 return FIX2INT(value
);
125 return rb_big2int(value
);
127 return (int)(RFLOAT(value
)->value
);
131 rb_raise(rb_eTypeError
, "Integer must be a fixed number");
138 struct RubyType
<uint
>
140 inline static VALUE
toVALUE(uint i
) {
143 inline static uint
toVariant(VALUE value
) {
144 switch( TYPE(value
) ) {
146 return FIX2UINT(value
);
148 return rb_big2uint(value
);
150 return (uint
)(RFLOAT(value
)->value
);
154 rb_raise(rb_eTypeError
, "Unsigned integer must be a fixed number");
161 struct RubyType
<double>
163 inline static VALUE
toVALUE(double d
) {
164 return rb_float_new(d
);
166 inline static double toVariant(VALUE value
) {
167 return NUM2DBL(value
);
173 struct RubyType
<bool>
175 inline static VALUE
toVALUE(bool b
) {
176 return b
? Qtrue
: Qfalse
;
178 inline static bool toVariant(VALUE value
) {
179 switch( TYPE(value
) ) {
185 rb_raise(rb_eTypeError
, "Boolean value expected");
194 struct RubyType
<qlonglong
>
196 inline static VALUE
toVALUE(qlonglong l
) {
197 return /*INT2NUM*/ LONG2NUM((long)l
);
199 inline static qlonglong
toVariant(VALUE value
) {
200 return NUM2LONG(value
);
206 struct RubyType
<qulonglong
>
208 inline static VALUE
toVALUE(qulonglong l
) {
209 return UINT2NUM((unsigned long)l
);
211 inline static qulonglong
toVariant(VALUE value
) {
212 return NUM2UINT(value
);
218 struct RubyType
<QByteArray
>
220 inline static VALUE
toVALUE(const QByteArray
& ba
) {
221 return rb_str_new(ba
.constData(), ba
.size());
223 inline static QByteArray
toVariant(VALUE value
) {
224 if( TYPE(value
) != T_STRING
) {
225 rb_raise(rb_eTypeError
, "QByteArray must be a string");
226 //return STR2CSTR( rb_inspect(value) );
227 return QByteArray("");
229 long length
= LONG2NUM( RSTRING(value
)->len
);
231 return QByteArray("");
232 char* ca
= rb_str2cstr(value
, &length
);
233 return QByteArray(ca
, length
);
239 struct RubyType
<QString
>
241 inline static VALUE
toVALUE(const QString
& s
) {
242 return s
.isNull() ? rb_str_new2("") : rb_str_new2(s
.toLatin1().data());
244 inline static QString
toVariant(VALUE value
) {
245 if( TYPE(value
) != T_STRING
) {
246 rb_raise(rb_eTypeError
, "QString must be a string");
249 return STR2CSTR(value
);
255 struct RubyType
<QSize
>
257 inline static VALUE
toVALUE(const QSize
& s
) {
258 VALUE l
= rb_ary_new();
259 rb_ary_push(l
, RubyType
<int>::toVALUE(s
.width()));
260 rb_ary_push(l
, RubyType
<int>::toVALUE(s
.height()));
263 inline static QSize
toVariant(VALUE value
) {
264 if( TYPE(value
) != T_ARRAY
|| RARRAY(value
)->len
!= 2 ) {
265 rb_raise(rb_eTypeError
, "QSize must be an array with 2 elements");
268 return QSize( RubyType
<int>::toVariant( rb_ary_entry(value
,0) ), RubyType
<int>::toVariant( rb_ary_entry(value
,1) ) );
274 struct RubyType
<QSizeF
>
276 inline static VALUE
toVALUE(const QSizeF
& s
) {
277 VALUE l
= rb_ary_new();
278 rb_ary_push(l
, RubyType
<double>::toVALUE(s
.width()));
279 rb_ary_push(l
, RubyType
<double>::toVALUE(s
.height()));
282 inline static QSizeF
toVariant(VALUE value
) {
283 if( TYPE(value
) != T_ARRAY
|| RARRAY(value
)->len
!= 2 ) {
284 rb_raise(rb_eTypeError
, "QSizeF must be an array with 2 elements");
287 return QSizeF( RubyType
<double>::toVariant( rb_ary_entry(value
,0) ), RubyType
<double>::toVariant( rb_ary_entry(value
,1) ) );
294 struct RubyType
<QPoint
>
296 inline static VALUE
toVALUE(const QPoint
& s
) {
297 VALUE l
= rb_ary_new();
298 rb_ary_push(l
, RubyType
<int>::toVALUE(s
.x()));
299 rb_ary_push(l
, RubyType
<int>::toVALUE(s
.y()));
302 inline static QPoint
toVariant(VALUE value
) {
303 if( TYPE(value
) != T_ARRAY
|| RARRAY(value
)->len
!= 2 ) {
304 rb_raise(rb_eTypeError
, "QPoint must be an array with 2 elements");
307 return QPoint( RubyType
<int>::toVariant( rb_ary_entry(value
,0) ), RubyType
<int>::toVariant( rb_ary_entry(value
,1) ) );
313 struct RubyType
<QPointF
>
315 inline static VALUE
toVALUE(const QPointF
& s
) {
316 VALUE l
= rb_ary_new();
317 rb_ary_push(l
, RubyType
<double>::toVALUE(s
.x()));
318 rb_ary_push(l
, RubyType
<double>::toVALUE(s
.y()));
321 inline static QPointF
toVariant(VALUE value
) {
322 if( TYPE(value
) != T_ARRAY
|| RARRAY(value
)->len
!= 2 ) {
323 rb_raise(rb_eTypeError
, "QPointF must be an array with 2 elements");
326 return QPointF( RubyType
<double>::toVariant( rb_ary_entry(value
,0) ), RubyType
<double>::toVariant( rb_ary_entry(value
,1) ) );
332 struct RubyType
<QRect
>
334 inline static VALUE
toVALUE(const QRect
& s
) {
335 VALUE l
= rb_ary_new();
336 rb_ary_push(l
, RubyType
<int>::toVALUE(s
.x()));
337 rb_ary_push(l
, RubyType
<int>::toVALUE(s
.y()));
338 rb_ary_push(l
, RubyType
<int>::toVALUE(s
.width()));
339 rb_ary_push(l
, RubyType
<int>::toVALUE(s
.height()));
342 inline static QRect
toVariant(VALUE value
) {
343 if( TYPE(value
) != T_ARRAY
|| RARRAY(value
)->len
!= 4 ) {
344 rb_raise(rb_eTypeError
, "QRect must be an array with 4 elements");
347 return QRect( RubyType
<int>::toVariant( rb_ary_entry(value
,0) ), RubyType
<int>::toVariant( rb_ary_entry(value
,1) ),
348 RubyType
<int>::toVariant( rb_ary_entry(value
,2) ), RubyType
<int>::toVariant( rb_ary_entry(value
,3) ) );
354 struct RubyType
<QRectF
>
356 inline static VALUE
toVALUE(const QRectF
& s
) {
357 VALUE l
= rb_ary_new();
358 rb_ary_push(l
, RubyType
<double>::toVALUE(s
.x()));
359 rb_ary_push(l
, RubyType
<double>::toVALUE(s
.y()));
360 rb_ary_push(l
, RubyType
<double>::toVALUE(s
.width()));
361 rb_ary_push(l
, RubyType
<double>::toVALUE(s
.height()));
364 inline static QRectF
toVariant(VALUE value
) {
365 if( TYPE(value
) != T_ARRAY
|| RARRAY(value
)->len
!= 4 ) {
366 rb_raise(rb_eTypeError
, "QRectF must be an array with 4 elements");
369 return QRectF( RubyType
<double>::toVariant( rb_ary_entry(value
,0) ), RubyType
<double>::toVariant( rb_ary_entry(value
,1) ),
370 RubyType
<double>::toVariant( rb_ary_entry(value
,2) ), RubyType
<double>::toVariant( rb_ary_entry(value
,3) ) );
376 struct RubyType
<QColor
>
378 inline static VALUE
toVALUE(const QColor
& color
) {
379 return color
.isValid() ? RubyType
<QString
>::toVALUE(color
.name()) : Qnil
;
381 inline static QColor
toVariant(VALUE value
) {
382 return (TYPE(value
) == T_STRING
) ? QColor(RubyType
<QString
>::toVariant(value
)) : QColor();
388 struct RubyType
<QUrl
>
390 inline static VALUE
toVALUE(const QUrl
& url
) {
391 return RubyType
<QString
>::toVALUE( url
.toString() );
393 inline static QUrl
toVariant(VALUE value
) {
394 return QUrl( RubyType
<QString
>::toVariant(value
) );
400 struct RubyType
<QDateTime
>
402 inline static VALUE
toVALUE(const QDateTime
& datetime
) {
403 return RubyType
<QString
>::toVALUE( datetime
.toString(Qt::ISODate
) );
405 inline static QDateTime
toVariant(VALUE value
) {
406 return QDateTime::fromString(RubyType
<QString
>::toVariant(value
), Qt::ISODate
);
412 struct RubyType
<QTime
>
414 inline static VALUE
toVALUE(const QTime
& time
) {
415 return RubyType
<QString
>::toVALUE( time
.toString(Qt::ISODate
) );
417 inline static QTime
toVariant(VALUE value
) {
418 return QTime::fromString(RubyType
<QString
>::toVariant(value
), Qt::ISODate
);
424 struct RubyType
<QDate
>
426 inline static VALUE
toVALUE(const QDate
& date
) {
427 return RubyType
<QString
>::toVALUE( date
.toString(Qt::ISODate
) );
429 inline static QDate
toVariant(VALUE value
) {
430 return QDate::fromString(RubyType
<QString
>::toVariant(value
), Qt::ISODate
);
436 struct RubyType
<QStringList
>
438 inline static VALUE
toVALUE(const QStringList
& list
) {
439 VALUE l
= rb_ary_new();
440 foreach(QString s
, list
)
441 rb_ary_push(l
, RubyType
<QString
>::toVALUE(s
));
444 inline static QStringList
toVariant(VALUE value
) {
445 if( TYPE(value
) != T_ARRAY
) {
446 rb_raise(rb_eTypeError
, "QStringList must be an array");
447 return QStringList();
450 for(int i
= 0; i
< RARRAY(value
)->len
; i
++)
451 l
.append( RubyType
<QString
>::toVariant( rb_ary_entry(value
, i
) ) );
458 struct RubyType
<QVariantList
>
460 inline static VALUE
toVALUE(const QVariantList
& list
) {
461 VALUE l
= rb_ary_new();
462 foreach(QVariant v
, list
)
463 rb_ary_push(l
, RubyType
<QVariant
>::toVALUE(v
));
466 inline static QVariantList
toVariant(VALUE value
) {
467 if( TYPE(value
) != T_ARRAY
) {
468 rb_raise(rb_eTypeError
, "QVariantList must be an array");
469 return QVariantList();
472 for(int i
= 0; i
< RARRAY(value
)->len
; i
++)
473 l
.append( RubyType
<QVariant
>::toVariant( rb_ary_entry(value
, i
) ) );
480 struct RubyType
<QVariantMap
>
482 inline static VALUE
toVALUE(const QVariantMap
& map
) {
483 VALUE h
= rb_hash_new();
484 QMap
<QString
, QVariant
>::ConstIterator
it(map
.constBegin()), end(map
.end());
485 for(; it
!= end
; ++it
)
486 rb_hash_aset(h
, RubyType
<QString
>::toVALUE(it
.key()), RubyType
<QVariant
>::toVALUE(it
.value()) );
489 inline static int convertHash(VALUE key
, VALUE value
, VALUE vmap
) {
491 Data_Get_Struct(vmap
, QVariantMap
, map
);
493 map
->insert(STR2CSTR(key
), RubyType
<QVariant
>::toVariant(value
));
496 inline static QVariantMap
toVariant(VALUE value
) {
497 if( TYPE(value
) != T_HASH
) {
498 rb_raise(rb_eTypeError
, "QVariantMap must be a hash");
499 return QVariantMap();
502 VALUE vmap
= Data_Wrap_Struct(rb_cObject
, 0,0, &map
);
503 rb_hash_foreach(value
, (int (*)(...))convertHash
, vmap
);
509 * The RubyMetaTypeFactory helper class us used as factory within
510 * \a RubyExtension to translate an argument into a \a MetaType
511 * needed for QGenericArgument's data pointer.
513 class RubyMetaTypeFactory
516 static MetaType
* create(const char* typeName
, int typeId
, int metaTypeId
, VALUE value
= Qnil
);
520 template<typename VARIANTTYPE
>
521 class RubyMetaTypeVariant
: public MetaTypeVariant
<VARIANTTYPE
>
524 RubyMetaTypeVariant(VALUE value
)
525 : MetaTypeVariant
<VARIANTTYPE
>(
526 (TYPE(value
) == T_NIL
)
527 ? QVariant().value
<VARIANTTYPE
>()
528 : RubyType
<VARIANTTYPE
>::toVariant(value
)
531 virtual ~RubyMetaTypeVariant() {}