Kross
values_p.h
Go to the documentation of this file.
00001 /*************************************************************************** 00002 * plugin.cpp 00003 * This file is part of the KDE project 00004 * copyright (C)2007 by Sebastian Sauer (mail@dipe.org) 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Library General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2 of the License, or (at your option) any later version. 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 * Library General Public License for more details. 00014 * You should have received a copy of the GNU Library General Public License 00015 * along with this program; see the file COPYING. If not, write to 00016 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00017 * Boston, MA 02110-1301, USA. 00018 ***************************************************************************/ 00019 00020 #include "plugin.h" 00021 00022 #include "../core/manager.h" 00023 #include "../core/object.h" 00024 00025 #include <QByteArray> 00026 #include <QUrl> 00027 #include <QColor> 00028 #include <QRect> 00029 #include <QPoint> 00030 #include <QSize> 00031 #include <QWidget> 00032 #include <QLayout> 00033 #include <QVBoxLayout> 00034 #include <QUiLoader> 00035 #include <QAbstractItemView> 00036 #include <QAbstractItemModel> 00037 #include <QStringListModel> 00038 #include <QScriptClass> 00039 #include <QScriptContext> 00040 #include <QScriptValueIterator> 00041 #include <QDebug> 00042 00043 #include <kurl.h> 00044 #include <klocale.h> 00045 00046 using namespace Kross; 00047 00048 namespace Kross { 00049 00054 class EcmaObject : public QScriptClass, public Kross::Object 00055 { 00056 public: 00057 explicit EcmaObject(QScriptEngine* engine, const QScriptValue& object = QScriptValue()) 00058 : QScriptClass(engine), Kross::Object(), m_object(object) {} 00059 virtual ~EcmaObject() {} 00060 virtual QString name() const { return "KrossObject"; } 00061 virtual QScriptValue prototype() const { return m_object; } 00062 00063 virtual QVariant callMethod(const QString& name, const QVariantList& args = QVariantList()) 00064 { 00065 QScriptValue function = m_object.property(name); 00066 if( ! function.isFunction() ) { 00067 krosswarning( QString("EcmaScript::callFunction No such function \"%1\"").arg(name) ); 00068 if( QScriptContext* context = engine()->currentContext() ) 00069 context->throwError(QScriptContext::ReferenceError, i18n("No such function \"%1\"", name)); 00070 return QVariant(); 00071 } 00072 QScriptValueList arguments; 00073 foreach(const QVariant &v, args) 00074 arguments << engine()->toScriptValue(v); 00075 QScriptValue result = function.call(m_object, arguments); 00076 return result.toVariant(); 00077 } 00078 00079 virtual QStringList methodNames() 00080 { 00081 QStringList methods; 00082 QScriptValueIterator it( m_object ); 00083 while( it.hasNext() ) { 00084 it.next(); 00085 if( it.value().isFunction() ) 00086 methods << it.name(); 00087 } 00088 return methods; 00089 } 00090 00091 private: 00092 QScriptValue m_object; 00093 }; 00094 00095 QScriptValue toByteArray(QScriptEngine *e, const QByteArray &ba) { 00096 return ba.isNull() ? e->nullValue() : e->newVariant(ba); 00097 } 00098 void fromByteArray(const QScriptValue &v, QByteArray &ba) { 00099 ba = v.isNull() ? QByteArray() : v.toString().toUtf8(); 00100 } 00101 00102 QScriptValue toUrl(QScriptEngine *e, const QUrl &url) { 00103 return e->newVariant( url.toString() ); 00104 } 00105 void fromUrl(const QScriptValue &v, QUrl &url) { 00106 url.setUrl( v.toString() ); 00107 } 00108 00109 QScriptValue toKUrl(QScriptEngine *e, const KUrl &url) { 00110 return e->newVariant( url.url() ); 00111 } 00112 void fromKUrl(const QScriptValue &v, KUrl &url) { 00113 url.setUrl( v.toString() ); 00114 } 00115 00116 QScriptValue toColor(QScriptEngine *e, const QColor &c) { 00117 return c.isValid() ? e->newVariant(c.name()) : e->nullValue(); 00118 } 00119 void fromColor(const QScriptValue &v, QColor &c) { 00120 c.setNamedColor( v.isNull() ? QString() : v.toString() ); 00121 } 00122 00123 QScriptValue toRect(QScriptEngine *e, const QRect &r) { 00124 return e->toScriptValue( QVariantList() << r.x() << r.y() << r.width() << r.height() ); 00125 } 00126 void fromRect(const QScriptValue &v, QRect &r) { 00127 r = v.isArray() ? QRect(v.property(0).toInt32(),v.property(1).toInt32(),v.property(2).toInt32(),v.property(3).toInt32()) : QRect(); 00128 } 00129 QScriptValue toRectF(QScriptEngine *e, const QRectF &r) { 00130 return e->toScriptValue( QVariantList() << r.x() << r.y() << r.width() << r.height() ); 00131 } 00132 void fromRectF(const QScriptValue &v, QRectF &r) { 00133 r = v.isArray() ? QRectF(v.property(0).toNumber(),v.property(1).toNumber(),v.property(2).toNumber(),v.property(3).toNumber()) : QRectF(); 00134 } 00135 00136 QScriptValue toPoint(QScriptEngine *e, const QPoint &p) { 00137 return e->toScriptValue( QVariantList() << p.x() << p.y() ); 00138 } 00139 void fromPoint(const QScriptValue &v, QPoint &p) { 00140 p = v.isArray() ? QPoint(v.property(0).toInt32(),v.property(1).toInt32()) : QPoint(); 00141 } 00142 QScriptValue toPointF(QScriptEngine *e, const QPointF &p) { 00143 return e->toScriptValue( QVariantList() << p.x() << p.y() ); 00144 } 00145 void fromPointF(const QScriptValue &v, QPointF &p) { 00146 p = v.isArray() ? QPointF(v.property(0).toNumber(),v.property(1).toNumber()) : QPointF(); 00147 } 00148 00149 QScriptValue toSize(QScriptEngine *e, const QSize &s) { 00150 return e->toScriptValue( QVariantList() << s.width() << s.height() ); 00151 } 00152 void fromSize(const QScriptValue &v, QSize &s) { 00153 s = v.isArray() ? QSize(v.property(0).toInt32(),v.property(1).toInt32()) : QSize(); 00154 } 00155 QScriptValue toSizeF(QScriptEngine *e, const QSizeF &s) { 00156 return e->toScriptValue( QVariantList() << s.width() << s.height() ); 00157 } 00158 void fromSizeF(const QScriptValue &v, QSizeF &s) { 00159 s = v.isArray() ? QSizeF(v.property(0).toNumber(),v.property(1).toNumber()) : QSizeF(); 00160 } 00161 00162 /* 00163 QScriptValue toVariantList(QScriptEngine *e, const QVariantList &l) { 00164 const int len = l.size(); 00165 QScriptValue a = e->newArray(len); 00166 for(int i = 0; i < len; ++i) 00167 a.setProperty(i, e->toScriptValue(l[i])); 00168 return a; 00169 } 00170 void fromVariantList(const QScriptValue &v, QVariantList &l) { 00171 l.clear(); 00172 const int len = v.isArray() ? v.property("length").toInt32() : 0; 00173 for(int i = 0; i < len; ++i) 00174 l << v.property(i).toVariant(); 00175 } 00176 */ 00177 00178 QScriptValue toObjPtr(QScriptEngine *e, const Kross::Object::Ptr &ptr) { 00179 const EcmaObject* obj = dynamic_cast<const EcmaObject*>( ptr.data() ); 00180 return obj ? obj->prototype() : e->nullValue(); 00181 } 00182 void fromObjPtr(const QScriptValue &v, Kross::Object::Ptr &ptr) { 00183 ptr = new EcmaObject(v.engine(), v); 00184 } 00185 00186 QScriptValue createWidget(QScriptContext *context, QScriptEngine *engine) { 00187 const QString widgetname = context->callee().prototype().property("className").toString(); 00188 Q_ASSERT( ! widgetname.isEmpty() ); 00189 QWidget *parent = qscriptvalue_cast<QWidget*>(context->argument(0)); 00190 QUiLoader loader; 00191 QWidget *widget = loader.createWidget(widgetname, parent); 00192 if( ! widget ) 00193 return context->throwError(QScriptContext::TypeError, QString("No such QWidget \"%1\"").arg(widgetname)); 00194 if( parent && parent->layout() ) 00195 parent->layout()->addWidget(widget); 00196 QScriptValue result = engine->newQObject(widget); 00197 //result.setPrototype(context->callee().prototype()); 00198 return result; 00199 } 00200 00201 QScriptValue addWidgetLayout(QScriptContext *c, QScriptEngine *engine) { 00202 if( QLayout *layout = dynamic_cast<QLayout*>( qscriptvalue_cast<QObject*>(c->thisObject()) ) ) { 00203 QGridLayout *gridLayout = dynamic_cast<QGridLayout*>(layout); 00204 QObject *obj = qscriptvalue_cast<QObject*>( c->argument(0) ); 00205 if( QWidget *w = dynamic_cast<QWidget*>(obj) ) { 00206 if( gridLayout ) 00207 gridLayout->addWidget(w, c->argument(1).toInt32(), c->argument(2).toInt32(), (Qt::Alignment)c->argument(3).toInt32()); 00208 else 00209 layout->addWidget(w); 00210 } 00211 else if( QLayout *l = dynamic_cast<QLayout*>( qscriptvalue_cast<QObject*>(c->argument(0)) ) ) { 00212 if( gridLayout ) 00213 gridLayout->addLayout(l, c->argument(1).toInt32(), c->argument(2).toInt32(), (Qt::Alignment)c->argument(3).toInt32()); 00214 else if( QBoxLayout *bl = dynamic_cast<QBoxLayout*>(layout) ) 00215 bl->addLayout(l); 00216 } 00217 } 00218 return engine->nullValue(); 00219 } 00220 QScriptValue createLayout(QScriptContext *context, QScriptEngine *engine, QLayout *layout) { 00221 QObject *parent = qscriptvalue_cast<QObject*>(context->argument(0)); 00222 if( QWidget *parentWidget = dynamic_cast<QWidget*>(parent) ) 00223 parentWidget->setLayout(layout); 00224 else if( QBoxLayout *parentLayout = dynamic_cast<QBoxLayout*>(parent) ) 00225 parentLayout->addLayout(layout); 00226 QScriptValue obj = engine->newQObject(layout); 00227 obj.setProperty("addWidget", engine->newFunction(addWidgetLayout)); 00228 obj.setProperty("addLayout", engine->newFunction(addWidgetLayout)); 00229 return obj; 00230 } 00231 QScriptValue createVBoxLayout(QScriptContext *context, QScriptEngine *engine) { 00232 return createLayout(context, engine, new QVBoxLayout()); 00233 } 00234 QScriptValue createHBoxLayout(QScriptContext *context, QScriptEngine *engine) { 00235 return createLayout(context, engine, new QHBoxLayout()); 00236 } 00237 QScriptValue createGridLayout(QScriptContext *context, QScriptEngine *engine) { 00238 return createLayout(context, engine, new QGridLayout()); 00239 } 00240 QScriptValue includeFunction(QScriptContext *context, QScriptEngine *engine) { 00241 if (context->argumentCount() < 1) 00242 return engine->nullValue(); 00243 return engine->importExtension(context->argument(0).toString()); 00244 } 00245 00250 void initializeCore(QScriptEngine *engine) { 00251 QScriptValue global = engine->globalObject(); 00252 00253 // compatibility to kjs/kjsembed 00254 if( ! global.property("println").isValid() ) 00255 global.setProperty("println", global.property("print")); 00256 00257 // register common used types 00258 qScriptRegisterMetaType< QByteArray >(engine, toByteArray, fromByteArray); 00259 qScriptRegisterMetaType< QUrl >(engine, toUrl, fromUrl); 00260 qScriptRegisterMetaType< KUrl >(engine, toKUrl, fromKUrl); 00261 qScriptRegisterMetaType< QColor >(engine, toColor, fromColor); 00262 qScriptRegisterMetaType< QRect >(engine, toRect, fromRect); 00263 qScriptRegisterMetaType< QRectF >(engine, toRectF, fromRectF); 00264 qScriptRegisterMetaType< QPoint >(engine, toPoint, fromPoint); 00265 qScriptRegisterMetaType< QPointF >(engine, toPointF, fromPointF); 00266 qScriptRegisterMetaType< QSize >(engine, toSize, fromSize); 00267 qScriptRegisterMetaType< QSizeF >(engine, toSizeF, fromSizeF); 00268 00269 // we should probably go with an own wrapper for QVariant/QObject... 00270 //qScriptRegisterMetaType< QVariant >(engine, toVariant, fromVariant); 00271 //qScriptRegisterMetaType< QVariantList >(engine, toVariantList, fromVariantList); 00272 00273 // register the Kross::Object::Ptr wrapper 00274 qScriptRegisterMetaType< Kross::Object::Ptr >(engine, toObjPtr, fromObjPtr); 00275 00276 // register the include function that allows to importExtension 00277 global.setProperty("include", engine->newFunction(includeFunction)); 00278 } 00279 00284 void initializeGui(QScriptEngine *engine) { 00285 QScriptValue global = engine->globalObject(); 00286 00287 // register UI widgets 00288 QUiLoader loader; 00289 foreach(const QString &widgetname, loader.availableWidgets()) { 00290 QScriptValue proto = engine->newObject(); 00291 proto.setProperty("className", QScriptValue(engine, widgetname)); 00292 QScriptValue func = engine->newFunction(createWidget); 00293 func.setPrototype(proto); 00294 global.setProperty(widgetname, func); 00295 } 00296 00297 // register layouts 00298 global.setProperty("QVBoxLayout", engine->newFunction(createVBoxLayout)); 00299 global.setProperty("QHBoxLayout", engine->newFunction(createHBoxLayout)); 00300 global.setProperty("QGridLayout", engine->newFunction(createGridLayout)); 00301 } 00302 00303 }
KDE 4.6 API Reference