1 /************************************************************************
3 * Copyright 2010 Jakob Leben (jakob.leben@gmail.com)
5 * This file is part of SuperCollider Qt GUI.
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 3 of the License, or
10 * (at your option) any later version.
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.
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/>.
20 ************************************************************************/
23 #include "QObjectProxy.h"
25 #include "primitives/prim_QPalette.hpp"
27 #include <PyrObject.h>
28 #include <PyrKernel.h>
30 #include <VMGlobals.h>
38 using namespace QtCollider
;
40 static QPalette::ColorRole paletteColorRoles
[] = {
48 QPalette::HighlightedText
,
51 void Slot::setRect( PyrSlot
*slot
, const QRectF
&r
)
53 PyrObject
*obj
= instantiateObject( gMainVMGlobals
->gc
, SC_CLASS(Rect
), 0, true, true );
54 SetObject( slot
, obj
);
56 PyrSlot
*slots
= obj
->slots
;
57 SetFloat( slots
+0, r
.x() );
58 SetFloat( slots
+1, r
.y() );
59 SetFloat( slots
+2, r
.width() );
60 SetFloat( slots
+3, r
.height() );
63 void Slot::setPoint( PyrSlot
*slot
, const QPointF
&pt
)
65 PyrObject
*obj
= instantiateObject( gMainVMGlobals
->gc
, SC_CLASS(Point
), 0, true, true );
66 SetObject( slot
, obj
);
68 PyrSlot
*slots
= obj
->slots
;
69 SetFloat( slots
+0, pt
.x() );
70 SetFloat( slots
+1, pt
.y() );
73 void Slot::setSize( PyrSlot
*slot
, const QSizeF
&sz
)
75 PyrObject
*obj
= instantiateObject( gMainVMGlobals
->gc
, SC_CLASS(Size
), 0, true, true );
76 SetObject( slot
, obj
);
78 PyrSlot
*slots
= obj
->slots
;
79 SetFloat( slots
+0, sz
.width() );
80 SetFloat( slots
+1, sz
.height() );
83 void Slot::setString( PyrSlot
*slot
, const QString
& arg
)
85 PyrString
*str
= newPyrString( gMainVMGlobals
->gc
,
86 arg
.toUtf8().constData(), 0, true );
87 SetObject( slot
, str
);
90 void Slot::setColor( PyrSlot
*slot
, const QColor
&c
)
97 PyrObject
*obj
= instantiateObject( gMainVMGlobals
->gc
, SC_CLASS(Color
), 0, true, true );
98 SetObject( slot
, obj
);
100 PyrSlot
*slots
= obj
->slots
;
101 SetFloat( slots
+0, c
.red() / 255.0 );
102 SetFloat( slots
+1, c
.green() / 255.0 );
103 SetFloat( slots
+2, c
.blue() / 255.0 );
104 SetFloat( slots
+3, c
.alpha() / 255.0 );
107 void Slot::setPalette( PyrSlot
*slot
, const QPalette
&plt
)
109 PyrGC
*gc
= gMainVMGlobals
->gc
;
110 PyrObject
*obj
= instantiateObject( gc
, SC_CLASS(QPalette
), 0, true, true );
111 SetObject( slot
, obj
);
113 QPalette_Init( gMainVMGlobals
, obj
, plt
);
116 void Slot::setQObject( PyrSlot
*s
, QObject
*o
)
123 QObjectProxy
*proxy
= QObjectProxy::fromObject(o
);
124 if( proxy
&& proxy
->scObject() )
125 SetObject( s
, proxy
->scObject() );
130 void Slot::setTreeWidgetItem( PyrSlot
*s
, const SafePtr
<QcTreeWidget::Item
> & itemPtr
)
132 PyrObject
*obj
= instantiateObject( gMainVMGlobals
->gc
, SC_CLASS(QTreeViewItem
), 0, true, true );
133 QcTreeWidget::Item::initialize( gMainVMGlobals
, obj
, itemPtr
);
137 void Slot::setVariantList( PyrSlot
*slot
, const VariantList
& varList
)
139 VMGlobals
*g
= gMainVMGlobals
;
141 int count
= varList
.data
.count();
143 PyrObject
*array
= newPyrArray( g
->gc
, count
, 0, true );
144 SetObject( slot
, array
);
147 PyrSlot
*s
= array
->slots
;
148 for( i
= 0; i
< count
; ++i
, ++s
) {
149 if( !Slot::setVariant( s
, varList
.data
[i
] ) ) {
150 qcDebugMsg(1, "WARNING: Could not set one slot of array" );
153 g
->gc
->GCWrite( array
, s
);
157 template<typename numeric_type
>
158 static void setNumeric( PyrSlot
*, numeric_type
);
162 void setNumeric
<double>( PyrSlot
*s
, double val
)
168 void setNumeric
<int>( PyrSlot
*s
, int val
)
173 template<typename numeric_type
>
174 static void setNumericVector( PyrSlot
*slot
, const QVector
<numeric_type
> & vec
)
176 VMGlobals
*g
= gMainVMGlobals
;
178 int count
= vec
.count();
180 PyrObject
*array
= newPyrArray( g
->gc
, count
, 0, true );
181 SetObject( slot
, array
);
183 PyrSlot
*s
= array
->slots
;
184 Q_FOREACH( numeric_type val
, vec
) {
185 setNumeric
<numeric_type
>( s
, val
);
191 bool Slot::setVariant( PyrSlot
*slot
, const QVariant
&val
)
194 int type
= val
.userType();
197 case QMetaType::Bool
:
198 b_val
= val
.toBool();
199 if( b_val
) SetTrue( slot
);
200 else SetFalse( slot
);
203 case QMetaType::QPoint
:
204 case QMetaType::QPointF
:
205 Slot::setPoint( slot
, val
.toPointF() );
208 case QMetaType::QSize
:
209 case QMetaType::QSizeF
:
210 Slot::setSize( slot
, val
.toSizeF() );
213 case QMetaType::QRect
:
214 case QMetaType::QRectF
:
215 Slot::setRect( slot
, val
.toRectF() );
218 case QMetaType::QChar
:
219 SetChar( slot
, val
.toChar().toLatin1() );
222 case QMetaType::QString
:
223 Slot::setString( slot
, val
.toString() );
226 case QMetaType::QColor
:
227 Slot::setColor( slot
, val
.value
<QColor
>() );
230 case QMetaType::QPalette
:
231 Slot::setPalette( slot
, val
.value
<QPalette
>() );
234 case QMetaType::Float
:
235 case QMetaType::Double
:
236 SetFloat( slot
, val
.value
<double>() );
240 SetInt( slot
, val
.toInt() );
243 case QMetaType::QObjectStar
:
244 Slot::setQObject( slot
, val
.value
<QObject
*>() );
247 case QMetaType::QWidgetStar
:
248 Slot::setQObject( slot
, val
.value
<QWidget
*>() );
251 case QMetaType::Void
:
256 if( type
== qMetaTypeId
<PyrObject
*>() ) {
257 SetObject( slot
, val
.value
<PyrObject
*>() );
259 else if( type
== qMetaTypeId
<VariantList
>() ) {
260 Slot::setVariantList( slot
, val
.value
<VariantList
>() );
262 else if( type
== qMetaTypeId
< QVector
<double> >() ) {
263 setNumericVector( slot
, val
.value
< QVector
<double> >() );
265 else if( type
== qMetaTypeId
< QVector
<int> >() ) {
266 setNumericVector( slot
, val
.value
< QVector
<int> >() );
268 else if( type
== qMetaTypeId
<QcTreeWidget::ItemPtr
>() ) {
269 Slot::setTreeWidgetItem( slot
, val
.value
< QtCollider::SafePtr
<QcTreeWidget::Item
> >() );
272 qcErrorMsg( "the QVariant could not be interpreted!" );
280 bool Slot::toBool( PyrSlot
*slot
)
282 return IsTrue( slot
);
285 int Slot::toInt( PyrSlot
*slot
)
288 if( slotIntVal( slot
, &i
) ) return 0;
292 float Slot::toFloat( PyrSlot
*slot
)
295 if( slotFloatVal( slot
, &f
) ) return 0.f
;
299 double Slot::toDouble( PyrSlot
*slot
)
302 if( slotDoubleVal( slot
, &d
) ) return 0.0;
306 QString
Slot::toString( PyrSlot
*slot
)
309 return QString::fromUtf8( slotRawSymbol(slot
)->name
);
311 else if( isKindOfSlot( slot
, class_string
) ) {
312 int len
= slotRawObject( slot
)->size
;
313 return QString::fromUtf8( slotRawString(slot
)->s
, len
);
318 QPointF
Slot::toPoint( PyrSlot
*slot
)
320 if( !isKindOfSlot( slot
, SC_CLASS(Point
) ) ) {
323 PyrSlot
*slots
= slotRawObject( slot
)->slots
;
326 err
= slotFloatVal( slots
+0, &x
); if( err
) return QPointF();
327 err
= slotFloatVal( slots
+1, &y
); if( err
) return QPointF();
328 return QPointF( x
, y
);
331 QRectF
Slot::toRect( PyrSlot
*slot
)
333 if( !isKindOfSlot( slot
, SC_CLASS(Rect
) ) ) {
337 PyrSlot
*slots
= slotRawObject( slot
)->slots
;
339 for( int i
=0; i
<4; ++i
)
341 int err
= slotFloatVal(slots
+ i
, &bounds
[i
]);
342 if( err
) return QRectF();
345 return QRectF( bounds
[0], bounds
[1], bounds
[2], bounds
[3] );
348 QSizeF
Slot::toSize( PyrSlot
*slot
)
350 if( !isKindOfSlot( slot
, SC_CLASS(Size
) ) ) {
354 PyrSlot
*slots
= slotRawObject( slot
)->slots
;
355 float w
= 0.f
, h
= 0.f
;
356 slotFloatVal( slots
+0, &w
);
357 slotFloatVal( slots
+1, &h
);
359 return QSizeF( w
, h
);
362 namespace QtCollider
{
365 QColor
asColor( PyrObject
*obj
)
367 PyrSlot
*slots
= obj
->slots
;
372 err
= slotFloatVal(slots
+0, &r
);
373 if (err
) return QColor();
374 err
= slotFloatVal(slots
+1, &g
);
375 if (err
) return QColor();
376 err
= slotFloatVal(slots
+2, &b
);
377 if (err
) return QColor();
378 err
= slotFloatVal(slots
+3, &a
);
379 if (err
) return QColor();
380 return QColor( r
*255, g
*255, b
*255, a
*255 );
386 QColor
Slot::toColor( PyrSlot
*slot
)
388 if( NotObj(slot
) ) return QColor();
390 PyrObject
*obj
= slotRawObject(slot
);
391 PyrClass
*klass
= obj
->classptr
;
393 if( klass
== SC_CLASS(Color
) )
396 if( klass
== SC_CLASS(Gradient
) || klass
== SC_CLASS(HiliteGradient
) )
398 qcWarningMsg("WARNING: Gradient and HiliteGradient are not supported yet."
399 " Using the average gradient color instead.");
401 QColor
c1( toColor(obj
->slots
+0) );
402 QColor
c2( toColor(obj
->slots
+1) );
403 QColor
mix( (c1
.red() + c2
.red()) / 2,
404 (c1
.green() + c2
.green()) / 2,
405 (c1
.blue() + c2
.blue()) / 2 );
412 QFont
Slot::toFont( PyrSlot
*slot
)
414 if( !isKindOfSlot( slot
, SC_CLASS(QFont
) ) )
417 PyrSlot
*slots
= slotRawObject(slot
)->slots
;
419 QString family
= Slot::toString( slots
+0 );
420 float fSize
= Slot::toFloat( slots
+1 );
421 bool bold
= IsTrue( slots
+2 );
422 bool italic
= IsTrue( slots
+3 );
423 bool isPtSize
= IsTrue( slots
+4 );
427 if( !family
.isEmpty() ) f
.setFamily( family
);
431 f
.setPointSizeF( fSize
);
434 int pixSize
= ( fSize
> 1.f
? qRound(fSize
) : 1 );
435 f
.setPixelSize( pixSize
);
441 f
.setItalic( italic
);
446 QPalette
Slot::toPalette( PyrSlot
*slot
)
448 if( !isKindOfSlot( slot
, SC_CLASS(QPalette
) ) )
451 QPalette
*p
= QPALETTE_FROM_OBJECT(slotRawObject(slot
));
455 VariantList
Slot::toVariantList( PyrSlot
*slot
)
457 if( isKindOfSlot( slot
, class_array
) ) {
458 PyrObject
*obj
= slotRawObject( slot
);
459 PyrSlot
*slots
= obj
->slots
;
460 int size
= obj
->size
;
462 for( int i
= 0; i
< size
; ++i
, ++slots
)
463 list
.data
<< Slot::toVariant( slots
);
466 else if( isKindOfSlot( slot
, class_symbolarray
) ) {
467 PyrSymbolArray
*symarray
= slotRawSymbolArray( slot
);
468 PyrSymbol
**symbols
= symarray
->symbols
;
469 int size
= symarray
->size
;
471 for( int i
= 0; i
< size
; ++i
, ++symbols
)
472 list
.data
<< QVariant( QString( (*symbols
)->name
) );
476 return VariantList();
479 #define WRONG_OBJECT_FORMAT false
481 template<typename DEST
, typename ORIG
>
482 inline static void copy( QVector
<DEST
> & dest
, PyrSlot
*orig
, int size
)
484 ORIG
*array
= (ORIG
*) orig
;
485 for( int i
= 0; i
< size
; ++i
)
486 dest
<< DEST(array
[i
]);
489 template<typename numeric_type
>
490 static QVector
<numeric_type
> toNumericVector( PyrObject
*obj
)
492 int size
= obj
->size
;
493 PyrSlot
*slots
= obj
->slots
;
495 QVector
<numeric_type
> vector
;
496 vector
.reserve(size
);
498 switch (obj
->obj_format
) {
500 copy
<numeric_type
, double>( vector
, slots
, size
); break;
502 copy
<numeric_type
, float>( vector
, slots
, size
); break;
504 copy
<numeric_type
, int32
>( vector
, slots
, size
); break;
506 copy
<numeric_type
, int16
>( vector
, slots
, size
); break;
508 copy
<numeric_type
, int8
>( vector
, slots
, size
); break;
510 Q_ASSERT( WRONG_OBJECT_FORMAT
);
516 QObjectProxy
* Slot::toObjectProxy( PyrSlot
*slot
)
518 if( !isKindOfSlot( slot
, SC_CLASS(QObject
) ) ) return 0;
519 QObjectProxy
*proxy
= 0;
520 PyrSlot
*proxySlot
= slotRawObject( slot
)->slots
;
521 if( IsPtr( proxySlot
) ) proxy
= (QObjectProxy
*) slotRawPtr( proxySlot
);
525 QcTreeWidget::ItemPtr
Slot::toTreeWidgetItem( PyrSlot
*slot
)
527 if( !isKindOfSlot( slot
, SC_CLASS(QTreeViewItem
) ) ) return QcTreeWidget::ItemPtr();
528 PyrSlot
*ptrSlot
= slotRawObject(slot
)->slots
+0;
529 if( IsPtr( ptrSlot
) ) {
530 QcTreeWidget::ItemPtr
*safePtr
= static_cast<QcTreeWidget::ItemPtr
*>( slotRawPtr(ptrSlot
) );
534 return QcTreeWidget::ItemPtr();
538 QVariant
Slot::toVariant( PyrSlot
*slot
)
541 switch (GetTag(slot
)) {
545 return QVariant( toInt(slot
) );
547 return QVariant( toString(slot
) );
549 return QVariant( QChar(slotRawChar(slot
)) );
551 return QVariant( false );
553 return QVariant( true );
556 PyrObject
*obj
= slotRawObject(slot
);
557 PyrClass
*klass
= obj
->classptr
;
558 unsigned char format
= obj
->obj_format
;
560 if( format
== obj_double
|| format
== obj_float
)
561 return QVariant::fromValue
< QVector
<double> >( toNumericVector
<double>(obj
) );
563 else if( format
== obj_int32
|| format
== obj_int16
|| format
== obj_int8
)
564 return QVariant::fromValue
< QVector
<int> >( toNumericVector
<int>(obj
) );
566 else if( isKindOfSlot( slot
, class_string
) ) {
567 return QVariant( toString(slot
) );
569 else if( isKindOfSlot( slot
, SC_CLASS(Point
) ) ) {
570 return QVariant( toPoint( slot
) );
572 else if( isKindOfSlot( slot
, SC_CLASS(Rect
) ) ) {
573 return QVariant( toRect(slot
) );
575 else if( isKindOfSlot( slot
, SC_CLASS(Size
) ) ) {
576 return QVariant( toSize(slot
) );
578 else if( klass
== SC_CLASS(Color
) ||
579 klass
== SC_CLASS(Gradient
) ||
580 klass
== SC_CLASS(HiliteGradient
) )
582 return QVariant::fromValue
<QColor
>( toColor(slot
) );
584 else if( isKindOfSlot( slot
, SC_CLASS(QFont
) ) ) {
585 return QVariant::fromValue
<QFont
>( toFont(slot
) );
587 else if( isKindOfSlot( slot
, SC_CLASS(QPalette
) ) ) {
588 return QVariant::fromValue
<QPalette
>( toPalette(slot
) );
590 else if( isKindOfSlot( slot
, SC_CLASS(QObject
) ) ) {
591 proxy
= toObjectProxy(slot
);
592 return QVariant::fromValue
<QObjectProxy
*>( proxy
);
594 else if( isKindOfSlot( slot
, class_array
) || isKindOfSlot( slot
, class_symbolarray
) ) {
595 return QVariant::fromValue
<VariantList
>( toVariantList(slot
) );
597 else if( isKindOfSlot( slot
, SC_CLASS(QTreeViewItem
) ) ) {
598 return QVariant::fromValue
<QcTreeWidget::ItemPtr
>( toTreeWidgetItem(slot
) );
601 QString className
= Slot::toString( &slotRawObject(slot
)->classptr
->name
);
602 qcWarningMsg(QString("WARNING: Do not know how to use an instance of class '%1'").arg(className
));
607 return QVariant( toDouble( slot
) );
611 using namespace Slot
;
613 void QtCollider::Variant::setData( PyrSlot
*slot
)
616 switch (GetTag(slot
)) {
618 _type
= QMetaType::Void
;
622 _type
= QMetaType::Int
;
623 _ptr
= new int( toInt(slot
) );
626 _type
= QMetaType::QString
;
627 _ptr
= new QString( toString(slot
) );
630 _type
= QMetaType::QChar
;
631 _ptr
= new QChar( slotRawChar(slot
) );
634 _type
= QMetaType::Bool
;
635 _ptr
= new bool( false );
638 _type
= QMetaType::Bool
;
639 _ptr
= new bool( true );
643 PyrObject
*obj
= slotRawObject(slot
);
644 PyrClass
*klass
= obj
->classptr
;
645 unsigned char format
= obj
->obj_format
;
647 if( format
== obj_double
|| format
== obj_float
) {
648 _type
= qMetaTypeId
< QVector
<double> >();
649 _ptr
= new QVector
<double>( toNumericVector
<double>(obj
) );
651 else if( format
== obj_int32
|| format
== obj_int16
|| format
== obj_int8
) {
652 _type
= qMetaTypeId
< QVector
<int> >();
653 _ptr
= new QVector
<int>( toNumericVector
<int>(obj
) );
655 else if( isKindOfSlot( slot
, class_string
) ) {
656 _type
= QMetaType::QString
;
657 _ptr
= new QString( toString(slot
) );
659 else if( isKindOfSlot( slot
, SC_CLASS(Point
) ) ) {
660 _type
= QMetaType::QPointF
;
661 _ptr
= new QPointF( toPoint(slot
) );
663 else if( isKindOfSlot( slot
, SC_CLASS(Rect
) ) ) {
664 _type
= QMetaType::QRectF
;
665 _ptr
= new QRectF( toRect(slot
) );
667 else if( isKindOfSlot( slot
, SC_CLASS(Size
) ) ) {
668 _type
= QMetaType::QSizeF
;
669 _ptr
= new QSizeF( toSize(slot
) );
671 else if( klass
== SC_CLASS(Color
) ||
672 klass
== SC_CLASS(Gradient
) ||
673 klass
== SC_CLASS(HiliteGradient
) )
675 _type
= QMetaType::QColor
;
676 _ptr
= new QColor( toColor(slot
) );
678 else if( isKindOfSlot( slot
, class_array
) || isKindOfSlot( slot
, class_symbolarray
) ) {
679 _type
= qMetaTypeId
<VariantList
>();
680 _ptr
= new VariantList( toVariantList(slot
) );
682 else if( isKindOfSlot( slot
, SC_CLASS(QObject
) ) ) {
683 proxy
= toObjectProxy(slot
);
685 _type
= QMetaType::Void
;
689 _type
= qMetaTypeId
<QObjectProxy
*>();
690 _ptr
= new QObjectProxy
*( proxy
);
693 else if( isKindOfSlot( slot
, SC_CLASS(QTreeViewItem
) ) ) {
694 _type
= qMetaTypeId
<QcTreeWidget::ItemPtr
>();
695 _ptr
= new QcTreeWidget::ItemPtr( toTreeWidgetItem(slot
) );
698 QString className
= Slot::toString( &slotRawObject(slot
)->classptr
->name
);
699 qcWarningMsg(QString("WARNING: Do not know how to use an instance of class '%1'").arg(className
));
700 _type
= QMetaType::Void
;
706 _type
= QMetaType::Double
;
707 _ptr
= new double( toDouble(slot
) );