• Skip to content
  • Skip to link menu
KDE 4.1 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

kjsembed

variant_binding.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE libraries
00002     Copyright (C) 2005, 2006 Ian Reinhart Geiser <geiseri@kde.org>
00003     Copyright (C) 2005, 2006 Matt Broadstone <mbroadst@gmail.com>
00004     Copyright (C) 2005, 2006 Richard J. Moore <rich@kde.org>
00005     Copyright (C) 2005, 2006 Erik L. Bunce <kde@bunce.us>
00006     Copyright (C) 2007, 2008 Sebastian Sauer <mail@dipe.org>
00007 
00008     This library is free software; you can redistribute it and/or
00009     modify it under the terms of the GNU Library General Public
00010     License as published by the Free Software Foundation; either
00011     version 2 of the License, or (at your option) any later version.
00012 
00013     This library is distributed in the hope that it will be useful,
00014     but WITHOUT ANY WARRANTY; without even the implied warranty of
00015     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016     Library General Public License for more details.
00017 
00018     You should have received a copy of the GNU Library General Public License
00019     along with this library; see the file COPYING.LIB.  If not, write to
00020     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00021     Boston, MA 02110-1301, USA.
00022 */
00023 
00024 #include "variant_binding.h"
00025 
00026 #include <stdlib.h>
00027 
00028 #include <kjs/PropertyNameArray.h>
00029 #include <kjs/array_instance.h>
00030 
00031 #include <QtCore/QBitRef>
00032 #include <QtCore/QByteRef>
00033 #include <QtCore/QDebug>
00034 #include <QtCore/QObject>
00035 #include <QtGui/QWidget>
00036 
00037 #include "kjseglobal.h"
00038 #include "static_binding.h"
00039 #include "qobject_binding.h"
00040 
00041 //#define KJSEMBED_VARIANT_DEBUG
00042 
00043 using namespace KJSEmbed;
00044 
00045 const KJS::ClassInfo VariantBinding::info = { "VariantBinding", 0, 0, 0 };
00046 
00047 VariantBinding::VariantBinding( KJS::ExecState *exec, const QVariant &value )
00048     : ProxyBinding(exec), m_value(value)
00049 {
00050     StaticBinding::publish( exec, this, VariantFactory::methods() );
00051 }
00052 
00053 void *VariantBinding::pointer()
00054 {
00055     return m_value.data();
00056 }
00057 
00058 KJS::UString VariantBinding::toString(KJS::ExecState *) const
00059 {
00060     return toUString(m_value.toString());
00061 }
00062 
00063 KJS::UString VariantBinding::className() const
00064 {
00065     return m_value.typeName();
00066 }
00067 
00068 QVariant VariantBinding::variant() const
00069 {
00070     return m_value;
00071 }
00072 
00073 void VariantBinding::setValue( const QVariant &val )
00074 {
00075     m_value = val;
00076 }
00077 
00078 QGenericArgument VariantBinding::arg(const char *type) const
00079 {
00080     const void *p = m_value.constData();
00081     //qDebug("Ptr %0x", p );
00082     //qDebug() << p;
00083     return QGenericArgument( type, p );
00084 }
00085 
00086 KJS::JSValue *callName( KJS::ExecState *exec, KJS::JSObject *self, const KJS::List &args )
00087 {
00088     Q_UNUSED( args );
00089     KJSEmbed::VariantBinding *imp = KJSEmbed::extractBindingImp<KJSEmbed::VariantBinding>(exec,  self);
00090     return imp ? KJS::jsString( imp->variant().typeName() ) : KJS::jsNull();
00091 }
00092 
00093 KJS::JSValue *callCast( KJS::ExecState *exec, KJS::JSObject *self, const KJS::List &args )
00094 {
00095     KJSEmbed::VariantBinding *imp = KJSEmbed::extractBindingImp<KJSEmbed::VariantBinding>(exec,  self );
00096     if( imp )
00097     {
00098         QVariant val = imp->variant();
00099         QVariant::Type type = QVariant::nameToType( args[0]->toString(exec).ascii() );
00100         KJS::JSValue *returnValue = KJS::jsBoolean(val.convert(type));
00101         imp->setValue(val);
00102         return returnValue;
00103     }
00104     return KJS::jsNull();
00105 }
00106 
00107 KJS::JSValue *callToString( KJS::ExecState *exec, KJS::JSObject *self, const KJS::List &args )
00108 {
00109     Q_UNUSED( args );
00110     KJSEmbed::VariantBinding *imp = KJSEmbed::extractBindingImp<KJSEmbed::VariantBinding>(exec,  self );
00111     if( imp )
00112     {
00113         //qDebug("Call value to string");
00114         QVariant val = imp->variant();
00115         QString stringVal = val.toString();
00116         if( !stringVal.isEmpty() )
00117             return KJS::jsString( val.toString() );
00118         return KJS::jsString( val.typeName() );
00119     }
00120     return KJS::jsNull();
00121 }
00122 
00123 const Method VariantFactory::VariantMethods[] =
00124 {
00125     {"cast", 1, KJS::DontDelete|KJS::ReadOnly|KJS::DontEnum, &callCast },
00126     {"toString", 0, KJS::DontDelete|KJS::ReadOnly|KJS::DontEnum, &callToString },
00127     {0, 0, 0, 0 }
00128 };
00129 
00130 enum JavaScriptArrayType { None, List, Map };
00131 
00132 JavaScriptArrayType checkArray( KJS::ExecState *exec, KJS::JSValue *val )
00133 {
00134     KJS::JSObject *obj = val->toObject( exec );
00135     if ( toQString(obj->className()) == "Array" )
00136     {
00137         if( !obj->hasProperty(exec, KJS::Identifier("length")) )
00138             return Map;
00139         KJS::JSValue *jslen = obj->get(exec, KJS::Identifier("length"));
00140         const int len = jslen->toNumber(exec);
00141         if ( len > 0 ) {
00142             QByteArray buff;
00143             buff.setNum(len-1);
00144             if( !obj->hasProperty(exec, KJS::Identifier( buff.data() ) ) )
00145                 return Map;
00146         }
00147         return List;
00148     }
00149     else
00150         return None;
00151 }
00152 
00153 QMap<QString, QVariant> KJSEmbed::convertArrayToMap( KJS::ExecState *exec, KJS::JSValue *value )
00154 {
00155     QMap<QString, QVariant> returnMap;
00156     KJS::JSObject *obj = value->toObject(exec);
00157     KJS::PropertyNameArray lst;
00158     obj->getPropertyNames(exec, lst);
00159     KJS::PropertyNameArrayIterator idx = lst.begin();
00160     for( ; idx != lst.end(); idx++ )
00161     {
00162         KJS::Identifier id = *idx;
00163         KJS::JSValue *val  = obj->get(exec, id);
00164         returnMap[toQString(id)] = convertToVariant(exec,val);
00165     }
00166     return returnMap;
00167 }
00168 
00169 QList<QVariant> KJSEmbed::convertArrayToList( KJS::ExecState *exec, KJS::JSValue *value )
00170 {
00171     QList<QVariant> returnList;
00172     /*
00173     KJS::JSObject *obj = value->toObject( exec );
00174     if ( toQString(obj->className() == "Array" )
00175     {
00176         int length = int(obj->get( exec, KJS::Identifier( "length" ) )->toInteger( exec ) );
00177         for ( int index = 0; index < length; ++index )
00178         {
00179             QByteArray buff;
00180             buff.setNum(index);
00181             KJS::JSValue *val = obj->get(exec, KJS::Identifier( buff.data() ) );
00182             if( val )
00183                 returnList += convertToVariant(exec, val );
00184             else
00185                 returnList += QVariant();
00186         }
00187     }
00188     */
00189     KJS::ArrayInstance* arrayImp = extractBindingImp<KJS::ArrayInstance>(exec, value);
00190     if(arrayImp)
00191     {
00192         const unsigned numItems = arrayImp->getLength();
00193         for ( unsigned i = 0; i < numItems; ++i )
00194             returnList.append( convertToVariant(exec, arrayImp->getItem(i)) );
00195     }
00196     return returnList;
00197 }
00198 
00199 QStringList KJSEmbed::convertArrayToStringList( KJS::ExecState *exec, KJS::JSValue *value )
00200 {
00201     QStringList returnList;
00202     /*
00203     KJS::JSObject *obj = value->toObject( exec );
00204     if ( toQString(obj->className()) == "Array" )
00205     {
00206         int length = int( obj->get( exec, KJS::Identifier( "length" ) )->toInteger( exec ) );
00207         for ( int index = 0; index < length; ++index )
00208         {
00209             QByteArray buff;
00210             buff.setNum(index);
00211             KJS::JSValue *val = obj->get(exec, KJS::Identifier( buff.data() ) );
00212             if( val )
00213                 returnList += convertToVariant(exec, val ).value<QString>();
00214             else
00215                 returnList += QString();
00216         }
00217     }
00218     */
00219     KJS::ArrayInstance* arrayImp = extractBindingImp<KJS::ArrayInstance>(exec, value);
00220     if(arrayImp)
00221     {
00222         const unsigned numItems = arrayImp->getLength();
00223         for ( unsigned i = 0; i < numItems; ++i )
00224             returnList.append( convertToVariant(exec, arrayImp->getItem(i)).toString() );
00225     }
00226     return returnList;
00227 }
00228 
00229 QDateTime convertDateToDateTime( KJS::ExecState *exec, KJS::JSValue *value )
00230 {
00231     KJS::List args;
00232     QDateTime returnDateTime;
00233     KJS::JSObject *obj = value->toObject( exec );
00234     if ( toQString(obj->className()) == "Date" )
00235     {
00236         int seconds = int( obj->get( exec, KJS::Identifier( "getSeconds" ) )->toObject( exec )->call( exec, obj, args )->toInteger( exec ) );
00237         int minutes = int( obj->get( exec, KJS::Identifier( "getMinutes" ) )->toObject( exec )->call( exec, obj, args )->toInteger( exec ) );
00238         int hours = int( obj->get( exec, KJS::Identifier( "getHours" ) )->toObject( exec )->call( exec, obj, args )->toInteger( exec ) );
00239         int month = int( obj->get( exec, KJS::Identifier( "getMonth" ) )->toObject( exec )->call( exec, obj, args )->toInteger( exec ) );
00240         int day = int( obj->get( exec, KJS::Identifier( "getDate" ) )->toObject( exec )->call( exec, obj, args )->toInteger( exec ) );
00241         int year = int( obj->get( exec, KJS::Identifier( "getFullYear" ) )->toObject( exec )->call( exec, obj, args )->toInteger( exec ) );
00242         returnDateTime.setDate( QDate( year, month + 1, day ) );
00243         returnDateTime.setTime( QTime( hours, minutes, seconds ) );
00244     }
00245     else
00246     {
00247         // Throw error
00248     }
00249 
00250     return returnDateTime;
00251 }
00252 
00253 QVariant KJSEmbed::convertToVariant( KJS::ExecState *exec, KJS::JSValue *value )
00254 {
00255 #ifdef KJSEMBED_VARIANT_DEBUG
00256     qDebug()<<"KJSEmbed::convertToVariant";
00257 #endif
00258 
00259     QVariant returnValue;
00260     switch( value->type() )
00261     {
00262         case KJS::UndefinedType:
00263         case KJS::NullType:
00264             break;
00265         case KJS::StringType:
00266             returnValue = toQString(value->toString(exec));
00267             break;
00268         case KJS::NumberType:
00269             returnValue = value->toNumber(exec);
00270             break;
00271         case KJS::BooleanType:
00272             returnValue = value->toBoolean(exec);
00273             break;
00274         case KJS::ObjectType:
00275         {
00276             KJS::JSObject *obj = value->toObject(exec);
00277             //qDebug() << "Object type: " << toQString(obj->className());
00278             if ( toQString(obj->className()) == "Array" ) {
00279                 if (checkArray(exec, value) == List)
00280                     returnValue = convertArrayToList(exec, value);
00281                 else
00282                     returnValue = convertArrayToMap(exec, value);
00283             }
00284             else if ( toQString(obj->className()) == "Date" )
00285                 returnValue = convertDateToDateTime( exec, value );
00286             else
00287                 returnValue = extractVariant(exec,value);
00288             //if( returnValue.isNull() ) returnValue = toQString(value->toString(exec));
00289         } break;
00290         default:
00291             returnValue = extractVariant(exec,value);
00292             //if( returnValue.isNull() ) returnValue = toQString(value->toString(exec));
00293             break;
00294     }
00295     return returnValue;
00296 }
00297 
00298 KJS::JSValue *KJSEmbed::convertToValue( KJS::ExecState *exec, const QVariant &value )
00299 {
00300 #ifdef KJSEMBED_VARIANT_DEBUG
00301     qDebug()<<"KJSEmbed::convertToValue typeid="<<value.type()<<"typename="<<value.typeName()<<"toString="<<value.toString();
00302 #endif
00303 
00304     KJS::JSValue *returnValue;
00305     switch( value.type() )
00306     {
00307         case QVariant::Invalid:
00308             returnValue = KJS::jsNull();
00309             break;
00310         case QVariant::Int:
00311             returnValue = KJS::jsNumber( value.value<int>() );
00312             break;
00313         case QVariant::UInt:
00314             returnValue = KJS::jsNumber( value.value<unsigned int>() );
00315             break;
00316         case QVariant::LongLong:
00317             returnValue = KJS::jsNumber( value.value<qlonglong>() );
00318             break;
00319         case QVariant::ULongLong:
00320             returnValue = KJS::jsNumber( value.value<qulonglong>() );
00321             break;
00322         case QVariant::Double:
00323             returnValue = KJS::jsNumber( value.value<double>() );
00324             break;
00325         case QVariant::Bool:
00326             returnValue = KJS::jsBoolean( value.value<bool>() );
00327             break;
00328         case QVariant::ByteArray:
00329             returnValue = KJS::jsString( QString(value.value<QByteArray>()) );
00330             break;
00331         case QVariant::String:
00332             returnValue = KJS::jsString( value.value<QString>() );
00333             break;
00334         case QVariant::StringList:
00335         {
00336             KJS::List items;
00337             QStringList lst = value.value<QStringList>();
00338             QStringList::Iterator idx = lst.begin();
00339             for ( ; idx != lst.end(); ++idx )
00340                 items.append( KJS::jsString( ( *idx ) ) );
00341             returnValue = exec->lexicalInterpreter()->builtinArray()->construct( exec, items );
00342             break;
00343         }
00344         case QVariant::Date: // fall through
00345         case QVariant::DateTime: // fall through
00346         case QVariant::Time:
00347         {
00348             QDateTime dt = QDateTime::currentDateTime();
00349             if ( value.type() == QVariant::Date )
00350                 dt.setDate( value.toDate() );
00351             else if ( value.type() == QVariant::Time )
00352                 dt.setTime( value.toTime() );
00353             else
00354                 dt = value.toDateTime();
00355 
00356             KJS::List items;
00357             items.append( KJS::jsNumber( dt.date().year() ) );
00358             items.append( KJS::jsNumber( dt.date().month() - 1 ) );
00359             items.append( KJS::jsNumber( dt.date().day() ) );
00360             items.append( KJS::jsNumber( dt.time().hour() ) );
00361             items.append( KJS::jsNumber( dt.time().minute() ) );
00362             items.append( KJS::jsNumber( dt.time().second() ) );
00363             items.append( KJS::jsNumber( dt.time().msec() ) );
00364             returnValue = exec->lexicalInterpreter()->builtinDate()->construct( exec, items );
00365             break;
00366         }
00367         case QVariant::List:
00368         {
00369             KJS::List items;
00370             QList<QVariant> lst = value.toList();
00371             foreach( const QVariant &item, lst)
00372                 items.append( convertToValue( exec, item ) );
00373             returnValue = exec->lexicalInterpreter()->builtinArray()->construct( exec, items );
00374             break;
00375         }
00376         case QVariant::Map:
00377         {
00378             QMap<QString,QVariant> map = value.toMap();
00379             QMap<QString,QVariant>::Iterator idx = map.begin();
00380             KJS::JSObject *obj = exec->lexicalInterpreter()->builtinObject()->construct( exec, KJS::List() );
00381             for ( ; idx != map.end(); ++idx )
00382                 obj->put(exec, KJS::Identifier( toUString(idx.key()) ), convertToValue( exec,  idx.value() ) );
00383             returnValue =  obj;
00384             break;
00385         }
00386         default:
00387         {
00388             if( qVariantCanConvert< QWidget* >(value) ) {
00389                 QWidget* widget = qvariant_cast< QWidget* >(value);
00390                 returnValue = widget ? createQObject(exec, widget, KJSEmbed::ObjectBinding::CPPOwned) : KJS::jsNull();
00391             }
00392             else if( qVariantCanConvert< QObject* >(value) ) {
00393                 QObject* object = qvariant_cast< QObject* >(value);
00394                 returnValue = object ? createQObject(exec, object, KJSEmbed::ObjectBinding::CPPOwned) : KJS::jsNull();
00395             }
00396             else {
00397                 returnValue = createVariant(exec, value.typeName(), value );
00398                 if( returnValue->isNull() )
00399                     returnValue = KJS::jsString( value.value<QString>() );
00400             }
00401             break;
00402         }
00403     }
00404     return returnValue;
00405 }
00406 
00407 QVariant KJSEmbed::extractVariant( KJS::ExecState *exec, KJS::JSValue *value )
00408 {
00409 #ifdef KJSEMBED_VARIANT_DEBUG
00410     qDebug()<<"KJSEmbed::extractVariant";
00411 #endif
00412 
00413     KJSEmbed::VariantBinding *imp = KJSEmbed::extractBindingImp<KJSEmbed::VariantBinding>(exec,  value );
00414     if( imp )
00415         return imp->variant();
00416     if( value->type() == KJS::StringType)
00417         return QVariant(toQString(value->toString(exec)));
00418     if( value->type() == KJS::NumberType)
00419         return QVariant(value->toNumber(exec));
00420     if( value->type() == KJS::BooleanType)
00421         return QVariant(value->toBoolean(exec));
00422 
00423     KJS::JSObject *obj = value->toObject( exec );
00424     if ( obj ) {
00425         if(QObjectBinding *objImp = KJSEmbed::extractBindingImp<QObjectBinding>(exec, value)) {
00426             QVariant v;
00427             if( QObject* qobj = objImp->qobject<QObject>() )
00428                 v.setValue(qobj);
00429             return v;
00430         }
00431         if( toQString(obj->className()) == "Array" )
00432             return convertArrayToList( exec, value );
00433     }
00434     return QVariant();
00435 }
00436 
00437 //kate: indent-spaces on; indent-width 4; replace-tabs on; indent-mode cstyle;

kjsembed

Skip menu "kjsembed"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • KIO
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal