* Added command line tool example similar to 'sopranocmd'
[kdebindings.git] / ruby / krossruby / rubyvariant.h
blob630c0db06b70991bf89957ecf41ce4c822c21f7d
1 /***************************************************************************
2 * rubyvariant.h
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>
27 #include <QString>
28 #include <QStringList>
29 #include <QVariant>
30 #include <QMetaType>
31 #include <QSize>
32 #include <QPoint>
33 #include <QRect>
34 #include <QUrl>
35 #include <QDate>
36 #include <QTime>
37 #include <QDateTime>
38 #include <QColor>
40 namespace Kross {
42 /**
43 * The RubyType helper classes used to cast between QVariant
44 * and VALUE values.
46 * Following QVariant::Type's are implemented;
47 * \li QVariant::Invalid
48 * \li QVariant::Int
49 * \li QVariant::UInt
50 * \li QVariant::Double
51 * \li QVariant::Bool
52 * \li QVariant::LongLong
53 * \li QVariant::ULongLong
54 * \li QVariant::ByteArray
55 * \li QVariant::String
56 * \li QVariant::StringList
57 * \li QVariant::Size
58 * \li QVariant::SizeF
59 * \li QVariant::Point
60 * \li QVariant::PointF
61 * \li QVariant::Rect
62 * \li QVariant::RectF
63 * \li QVariant::Color
64 * \li QVariant::Url
65 * \li QVariant::Date
66 * \li QVariant::Time
67 * \li QVariant::DateTime
68 * \li QVariant::List
69 * \li QVariant::Map
71 * Following QVariant::Type's are unimplemented yet (do we need them anyways?);
72 * \li QVariant::BitArray
73 * \li QVariant::Bitmap
74 * \li QVariant::Brush
75 * \li QVariant::Char
76 * \li QVariant::Cursor
77 * \li QVariant::Font
78 * \li QVariant::Icon
79 * \li QVariant::Image
80 * \li QVariant::KeySequence
81 * \li QVariant::Line
82 * \li QVariant::LineF
83 * \li QVariant::Locale
84 * \li QVariant::Palette
85 * \li QVariant::Pen
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>
96 struct RubyType
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(); }
105 /// \internal
106 template<>
107 struct RubyType<QVariant>
109 static VALUE toVALUE(const QVariant& v);
110 static QVariant toVariant(VALUE value);
113 /// \internal
114 template<>
115 struct RubyType<int>
117 inline static VALUE toVALUE(int i) {
118 return INT2FIX(i);
120 inline static int toVariant(VALUE value) {
121 switch( TYPE(value) ) {
122 case T_FIXNUM:
123 return FIX2INT(value);
124 case T_BIGNUM:
125 return rb_big2int(value);
126 case T_FLOAT:
127 return (int)(RFLOAT(value)->value);
128 default:
129 break;
131 rb_raise(rb_eTypeError, "Integer must be a fixed number");
132 return 0;
136 /// \internal
137 template<>
138 struct RubyType<uint>
140 inline static VALUE toVALUE(uint i) {
141 return UINT2NUM(i);
143 inline static uint toVariant(VALUE value) {
144 switch( TYPE(value) ) {
145 case T_FIXNUM:
146 return FIX2UINT(value);
147 case T_BIGNUM:
148 return rb_big2uint(value);
149 case T_FLOAT:
150 return (uint)(RFLOAT(value)->value);
151 default:
152 break;
154 rb_raise(rb_eTypeError, "Unsigned integer must be a fixed number");
155 return 0;
159 /// \internal
160 template<>
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);
171 /// \internal
172 template<>
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) ) {
180 case T_TRUE:
181 return true;
182 case T_FALSE:
183 return false;
184 default: {
185 rb_raise(rb_eTypeError, "Boolean value expected");
186 return false;
187 } break;
192 /// \internal
193 template<>
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);
204 /// \internal
205 template<>
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);
216 /// \internal
217 template<>
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 );
230 if( length < 0 )
231 return QByteArray("");
232 char* ca = rb_str2cstr(value, &length);
233 return QByteArray(ca, length);
237 /// \internal
238 template<>
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");
247 return QString();
249 return STR2CSTR(value);
253 /// \internal
254 template<>
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()));
261 return l;
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");
266 return QSize();
268 return QSize( RubyType<int>::toVariant( rb_ary_entry(value,0) ), RubyType<int>::toVariant( rb_ary_entry(value,1) ) );
272 /// \internal
273 template<>
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()));
280 return l;
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");
285 return QSizeF();
287 return QSizeF( RubyType<double>::toVariant( rb_ary_entry(value,0) ), RubyType<double>::toVariant( rb_ary_entry(value,1) ) );
292 /// \internal
293 template<>
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()));
300 return l;
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");
305 return QPoint();
307 return QPoint( RubyType<int>::toVariant( rb_ary_entry(value,0) ), RubyType<int>::toVariant( rb_ary_entry(value,1) ) );
311 /// \internal
312 template<>
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()));
319 return l;
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");
324 return QPointF();
326 return QPointF( RubyType<double>::toVariant( rb_ary_entry(value,0) ), RubyType<double>::toVariant( rb_ary_entry(value,1) ) );
330 /// \internal
331 template<>
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()));
340 return l;
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");
345 return QRect();
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) ) );
352 /// \internal
353 template<>
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()));
362 return l;
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");
367 return QRectF();
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) ) );
374 /// \internal
375 template<>
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();
386 /// \internal
387 template<>
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) );
398 /// \internal
399 template<>
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);
410 /// \internal
411 template<>
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);
422 /// \internal
423 template<>
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);
434 /// \internal
435 template<>
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));
442 return l;
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();
449 QStringList l;
450 for(int i = 0; i < RARRAY(value)->len; i++)
451 l.append( RubyType<QString>::toVariant( rb_ary_entry(value, i) ) );
452 return l;
456 /// \internal
457 template<>
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));
464 return l;
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();
471 QVariantList l;
472 for(int i = 0; i < RARRAY(value)->len; i++)
473 l.append( RubyType<QVariant>::toVariant( rb_ary_entry(value, i) ) );
474 return l;
478 /// \internal
479 template<>
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()) );
487 return h;
489 inline static int convertHash(VALUE key, VALUE value, VALUE vmap) {
490 QVariantMap* map;
491 Data_Get_Struct(vmap, QVariantMap, map);
492 if (key != Qundef)
493 map->insert(STR2CSTR(key), RubyType<QVariant>::toVariant(value));
494 return ST_CONTINUE;
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();
501 QVariantMap map;
502 VALUE vmap = Data_Wrap_Struct(rb_cObject, 0,0, &map);
503 rb_hash_foreach(value, (int (*)(...))convertHash, vmap);
504 return map;
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
515 public:
516 static MetaType* create(const char* typeName, int typeId, int metaTypeId, VALUE value = Qnil);
519 /// \internal
520 template<typename VARIANTTYPE>
521 class RubyMetaTypeVariant : public MetaTypeVariant<VARIANTTYPE>
523 public:
524 RubyMetaTypeVariant(VALUE value)
525 : MetaTypeVariant<VARIANTTYPE>(
526 (TYPE(value) == T_NIL)
527 ? QVariant().value<VARIANTTYPE>()
528 : RubyType<VARIANTTYPE>::toVariant(value)
529 ) {}
531 virtual ~RubyMetaTypeVariant() {}
536 #endif