• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.14.38 API Reference
  • KDE Home
  • Contact Us
 

kjsembed

  • kjsembed
  • kjsembed
qobject_binding.cpp
Go to the documentation of this file.
1/* This file is part of the KDE libraries
2 Copyright (C) 2005, 2006 Ian Reinhart Geiser <geiseri@kde.org>
3 Copyright (C) 2005, 2006 Matt Broadstone <mbroadst@gmail.com>
4 Copyright (C) 2005, 2006 Richard J. Moore <rich@kde.org>
5 Copyright (C) 2005, 2006 Erik L. Bunce <kde@bunce.us>
6 Copyright (C) 2007, 2008 Sebastian Sauer <mail@dipe.org>
7
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Library General Public
10 License as published by the Free Software Foundation; either
11 version 2 of the License, or (at your option) any later version.
12
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Library General Public License for more details.
17
18 You should have received a copy of the GNU Library General Public License
19 along with this library; see the file COPYING.LIB. If not, write to
20 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA.
22*/
23#include "qobject_binding.h"
24
25#include <QtCore/QObject>
26#include <QtCore/QArgument>
27#include <QtCore/QMetaEnum>
28#include <QtCore/QMetaType>
29#include <QtCore/QVariant>
30#include <QtCore/QVector>
31#include <QtCore/QUrl>
32#include <QtCore/QDebug>
33#include <QWidget>
34
35#include "slotproxy.h"
36#include "eventproxy.h"
37#include "jseventmapper.h"
38#include "pointer.h"
39#include "variant_binding.h"
40
41#include <kjs/array_instance.h>
42#include <kjs/function_object.h>
43
44//#define CREATEQOBJ_DIAG
45
46using namespace KJSEmbed;
47
48QByteArray createSignal( const QByteArray &sig )
49{
50 return '2' + sig;
51}
52
53QByteArray createSlot( const QByteArray &slt )
54{
55 return '1' + slt;
56}
57
58bool validSlot(const QMetaMethod& method, QObjectBinding::AccessFlags accessflags)
59{
60 switch( method.access() ) {
61 case QMetaMethod::Private: {
62 if(! (accessflags & QObjectBinding::PrivateSlots)) return false;
63 } break;
64 case QMetaMethod::Protected: {
65 if(! (accessflags & QObjectBinding::ProtectedSlots)) return false;
66 } break;
67 case QMetaMethod::Public: {
68 if(! (accessflags & QObjectBinding::PublicSlots)) return false;
69 } break;
70 }
71 if(method.attributes() & QMetaMethod::Scriptable) {
72 if(! (accessflags & QObjectBinding::ScriptableSlots)) return false;
73 }
74 else {
75 if(! (accessflags & QObjectBinding::NonScriptableSlots)) return false;
76 }
77 return true;
78}
79
80bool validSignal(const QMetaMethod& method, QObjectBinding::AccessFlags accessflags)
81{
82 switch( method.access() ) {
83 case QMetaMethod::Private: {
84 if(! (accessflags & QObjectBinding::PrivateSignals)) return false;
85 } break;
86 case QMetaMethod::Protected: {
87 if(! (accessflags & QObjectBinding::ProtectedSignals)) return false;
88 } break;
89 case QMetaMethod::Public: {
90 if(! (accessflags & QObjectBinding::PublicSignals)) return false;
91 } break;
92 }
93 if(method.attributes() & QMetaMethod::Scriptable) {
94 if(! (accessflags & QObjectBinding::ScriptableSignals)) return false;
95 }
96 else {
97 if(! (accessflags & QObjectBinding::NonScriptableSignals)) return false;
98 }
99 return true;
100}
101
102bool validProperty(const QMetaProperty& property, QObjectBinding::AccessFlags accessflags)
103{
104 if(property.isScriptable()) {
105 if(! (accessflags & QObjectBinding::ScriptableProperties)) return false;
106 }
107 else {
108 if(! (accessflags & QObjectBinding::NonScriptableProperties)) return false;
109 }
110 return true;
111}
112
113KJS::JSValue *callConnect( KJS::ExecState *exec, KJS::JSObject *self, const KJS::List &args )
114{
115 KJSEmbed::QObjectBinding *imp = KJSEmbed::extractBindingImp<KJSEmbed::QObjectBinding>(exec, self );
116 if( !imp ) // No implementation, so we need to use the first argument as we are a global static invocation.
117 imp = KJSEmbed::extractBindingImp<KJSEmbed::QObjectBinding>(exec, args[0] );
118 if( !imp )
119 return KJS::throwError(exec, KJS::GeneralError, i18n("Wrong object type."));
120 //return KJSEmbed::throwError(exec, i18n("Wrong object type."));
121
122 if( args.size() > 2)
123 {
124 KJSEmbed::QObjectBinding *senderImp = KJSEmbed::extractBindingImp<KJSEmbed::QObjectBinding>(exec, args[0] );
125 if( !senderImp )
126 {
127 return KJS::throwError(exec, KJS::GeneralError, i18n("First argument must be a QObject."));
128 //return KJSEmbed::throwError(exec, i18n("First argument must be a QObject"));
129 }
130 QObject* receiver = 0;
131 QObject* sender = senderImp->object<QObject>();
132 QByteArray signal = createSignal(args[1]->toString(exec).ascii());
133 QByteArray slot;
134 KJSEmbed::QObjectBinding *receiverImp = 0;
135 if( args.size() >= 4)
136 {
137 slot = createSlot(args[3]->toString(exec).ascii());
138 receiverImp = KJSEmbed::extractBindingImp<KJSEmbed::QObjectBinding>(exec, args[2] );
139 if( !receiverImp )
140 receiver = new SlotProxy(args[2]->toObject(exec), exec->dynamicInterpreter(), sender, args[3]->toString(exec).ascii() );
141 else
142 receiver = receiverImp->object<QObject>();
143 }
144 else
145 {
146 receiverImp = imp;
147 receiver = imp->object<QObject>();
148 slot = createSlot(args[2]->toString(exec).ascii());
149 }
150
151 const QMetaObject *senderMetaObject = sender->metaObject();
152 QMetaMethod senderMetaMethod = senderMetaObject->method( senderMetaObject->indexOfSignal(signal.constData()) );
153
154 const QMetaObject *receiverMetaObject = receiver->metaObject();
155 QMetaMethod receiverMetaMethod = receiverMetaObject->method( receiverMetaObject->indexOfSlot(slot.constData()) );
156
157 if( validSignal(senderMetaMethod, senderImp->access()) && ( !receiverImp || validSlot(receiverMetaMethod, receiverImp->access()) ) )
158 {
159 return KJS::jsBoolean(QObject::connect(sender, signal.constData(), receiver, slot.constData()));
160 }
161
162 return KJS::jsBoolean(false);
163 }
164 return KJS::throwError(exec, KJS::GeneralError, i18n("Incorrect number of arguments."));
165 //return KJSEmbed::throwError(exec, i18n("Incorrect number of arguments."));
166}
167
168QByteArray extractMemberName( const QMetaMethod &member )
169{
170 QString sig = member.signature();
171 return sig.left( sig.indexOf('(') ).toLatin1();
172}
173
174void QObjectBinding::publishQObject( KJS::ExecState *exec, KJS::JSObject *target, QObject *object)
175{
176 KJSEmbed::QObjectBinding *imp = KJSEmbed::extractBindingImp<KJSEmbed::QObjectBinding>(exec, target);
177 Q_ASSERT(imp);
178
179 // Add the children the QObject has.
180 if (imp->access() & QObjectBinding::ChildObjects) {
181 //TODO uh, this one is dirty cause it may eat a lot of time to publish things that may not
182 //got accessed anyway. Better solution would be to provide access to them on demand only. That
183 //would also allow to manipulate the QObject-tree at runtime what is currently not possible.
184 QObjectList children = object->children();
185 QObjectList::Iterator child = children.begin();
186 for( ; child != children.end(); ++child)
187 {
188 QString objectName = (*child)->objectName();
189 if( !objectName.isEmpty() )
190 {
191 KJS::JSObject *childObject = KJSEmbed::createQObject(exec, *child);
192 KJSEmbed::QObjectBinding *childImp = KJSEmbed::extractBindingImp<KJSEmbed::QObjectBinding>(exec, childObject);
193 if(childImp)
194 {
195 childImp->setAccess( imp->access() ); // inherit access from parent
196 target->put(exec, KJS::Identifier(toUString(objectName)), childObject);
197 }
198 }
199 }
200 }
201
202 // Add slots of the current object.
203 const QMetaObject *metaObject = object->metaObject();
204 int methods = metaObject->methodCount();
205 for( int idx = 0; idx < methods; ++idx )
206 {
207 QMetaMethod member = metaObject->method(idx);
208 if(validSlot(member, imp->access()))
209 {
210 target->put(exec, KJS::Identifier( extractMemberName( member ) ),
211 new SlotBinding(exec,member), KJS::DontDelete|KJS::ReadOnly|KJS::Function);
212 }
213 }
214
215 // Add enums as read only uints.
216 int enums = metaObject->enumeratorCount();
217 for( int idx = 0; idx < enums; ++idx )
218 {
219 QMetaEnum enumerator = metaObject->enumerator(idx);
220 int keys = enumerator.keyCount();
221 for( int key = 0; key < keys; ++key)
222 {
223 target->put(exec, KJS::Identifier( enumerator.key(key) ),
224 KJS::jsNumber(enumerator.value(key)), KJS::DontDelete|KJS::ReadOnly);
225 }
226 }
227}
228
229QObjectBinding::QObjectBinding( KJS::ExecState *exec, QObject *object )
230 : ObjectBinding(exec, object->metaObject()->className(), object)
231 , m_evproxy(0)
232 , m_access( AllSlots | AllSignals | AllProperties | AllObjects )
233{
234 if( object->parent() != 0 )
235 {
236 setOwnership( ObjectBinding::QObjOwned );
237 }
238 else
239 {
240 setOwnership( ObjectBinding::JSOwned );
241 }
242
243 m_cleanupHandler = new QObjectCleanupHandler();
244 watchObject(object);
245
246 StaticBinding::publish( exec, this, QObjectFactory::methods() );
247 QObjectBinding::publishQObject(exec, this, object);
248
249 // Make "connect" a global static method.
250 exec->dynamicInterpreter()->globalObject()->put(exec, "connect", new StaticBinding(exec, &QObjectFactory::methods()[0]) );
251}
252
253QObjectBinding::~QObjectBinding()
254{
255 if( m_cleanupHandler->isEmpty() )
256 {
257 setOwnership( ObjectBinding::QObjOwned );
258 }
259 else if( object<QObject>()->parent() != 0 )
260 {
261 setOwnership( ObjectBinding::QObjOwned );
262 m_cleanupHandler->remove(object<QObject>());
263 }
264 else if( ownership() != ObjectBinding::JSOwned )
265 {
266 m_cleanupHandler->remove(object<QObject>());
267 }
268 else
269 {
270 m_cleanupHandler->remove(object<QObject>());
271 }
272
273 delete m_cleanupHandler;
274}
275
276void QObjectBinding::watchObject( QObject *object )
277{
278 m_cleanupHandler->add( object );
279}
280
281bool QObjectBinding::getOwnPropertySlot( KJS::ExecState *exec, const KJS::Identifier &propertyName, KJS::PropertySlot &slot )
282{
283 // qDebug() << "getOwnPropertySlot called";
284 QObject *obj = object<QObject>();
285 const QMetaObject *meta = obj->metaObject();
286 int propIndex = meta->indexOfProperty( propertyName.ascii() );
287 if ( propIndex != -1 ) {
288 if(! validProperty(meta->property(propIndex), m_access))
289 return false;
290 // qDebug() << "getOwnPropertySlot found the property " << propertyName.ascii();
291 slot.setCustom( this, propertyGetter );
292 return true;
293 }
294 return ObjectBinding::getOwnPropertySlot( exec, propertyName, slot );
295}
296
297KJS::JSValue *QObjectBinding::propertyGetter( KJS::ExecState *exec, KJS::JSObject*,
298 const KJS::Identifier &propertyName, const KJS::PropertySlot&slot )
299{
300 // qDebug() << "Getter was called";
301 QObjectBinding *self = static_cast<QObjectBinding *>(slot.slotBase());
302 QObject *obj = self->object<QObject>();
303
304 QVariant val = obj->property( propertyName.ascii() );
305 if ( val.isValid() ) {
306 return convertToValue( exec, val );
307 }
308 qDebug() << QString("propertyGetter called but no property, name was '%1'").arg(propertyName.ascii());
309 return 0; // ERROR
310}
311
312QObjectBinding::AccessFlags QObjectBinding::access() const
313{
314 return m_access;
315}
316
317void QObjectBinding::setAccess(QObjectBinding::AccessFlags access)
318{
319 m_access = access;
320}
321
322void QObjectBinding::put(KJS::ExecState *exec, const KJS::Identifier &propertyName, KJS::JSValue *value, int attr )
323{
324 QObject *obj = object<QObject>();
325 if ( obj && !m_cleanupHandler->isEmpty() )
326 {
327 // Properties
328 const QMetaObject *meta = obj->metaObject();
329
330 if ( int propIndex = meta->indexOfProperty( propertyName.ascii() ) != -1 )
331 {
332 QMetaProperty prop = meta->property(propIndex);
333 if(! validProperty(prop, m_access))
334 return;
335
336 bool propSet = false;
337 QVariant val = convertToVariant( exec, value );
338 if ( prop.isEnumType() )
339 {
340 propSet = obj->setProperty( propertyName.ascii(), val.toUInt() );
341 }
342 else if ( val.isValid() /*&& meta->property(propIndex).isWritable() <- wtf?*/ )
343 {
344 propSet = obj->setProperty( propertyName.ascii(), val );
345 }
346 /*
347 if( !propSet )
348 {
349 KJSEmbed::throwError(exec,
350 i18n("Setting property %1 failed: property invalid, read-only or does not exist").arg(propertyName.ascii()));
351 }
352 */
353
354 }
355
356 if (JSEventMapper::mapper()->isEventHandler(propertyName) )
357 {
358 if ( !m_evproxy )
359 m_evproxy = new KJSEmbed::EventProxy( this, exec->dynamicInterpreter() );
360 if( value )
361 m_evproxy->addFilter( JSEventMapper::mapper()->findEventType( propertyName ) );
362 else
363 m_evproxy->removeFilter( JSEventMapper::mapper()->findEventType( propertyName ) );
364 }
365 }
366 //qDebug() << "Forward put";
367 // Set a property value
368 ObjectBinding::put(exec, propertyName, value, attr);
369}
370
371bool QObjectBinding::canPut(KJS::ExecState *exec, const KJS::Identifier &propertyName) const
372{
373 QObject *obj = object<QObject>();
374 if ( obj && !m_cleanupHandler->isEmpty() )
375 {
376 // Properties
377 const QMetaObject *meta = obj->metaObject();
378 if ( int propIndex = meta->indexOfProperty( propertyName.ascii() ) != -1 )
379 {
380 QMetaProperty prop = meta->property(propIndex);
381 return validProperty(prop, m_access) && prop.isWritable();
382 }
383 }
384 return ObjectBinding::canPut(exec,propertyName);
385}
386
387KJS::UString QObjectBinding::className() const
388{
389 return toUString( typeName() );
390}
391
392KJS::UString QObjectBinding::toString(KJS::ExecState *exec) const
393{
394 Q_UNUSED( exec );
395 QString s( "%1 (%2)" );
396 s = s.arg( object<QObject>()->objectName() );
397 s = s.arg( typeName() );
398 return toUString( s );
399}
400
401PointerBase *getArg( KJS::ExecState *exec, const QList<QByteArray> &types, const KJS::List &args, int idx, QString& errorText)
402{
403 //qDebug("Index %d, args size %d, types size %d", idx, args.size(), types.size() );
404
405 if( types.size() == 0 && idx == 0 )
406 return new NullPtr();
407 if ( args.size() <= idx )
408 return new NullPtr();
409
410 if ( types.size() <= idx )
411 {
412 const QString firstPart = i18np("The slot asked for %1 argument", "The slot asked for %1 arguments", idx);
413 const QString secondPart = i18np("but there is only %1 available", "but there are only %1 available", types.size());
414 errorText = i18nc("%1 is 'the slot asked for foo arguments', %2 is 'but there are only bar available'", "%1, %2.");
415
416 return 0;
417 }
418
419 QVariant::Type varianttype = QVariant::nameToType( types[idx].constData() );
420 //qDebug( QString("type=%1 argtype=%2 variantType=%3 (%4)").arg(types[idx].constData()).arg(args[idx]->type()).arg(varianttype).arg(QVariant::typeToName(varianttype)).toLatin1() );
421 switch( varianttype ) {
422 case QVariant::Int:
423 if( args[idx]->type() == KJS::NumberType )
424 return new Value<int>( int( args[idx]->toInteger(exec) ) );
425 break;
426 case QVariant::UInt:
427 if( args[idx]->type() == KJS::NumberType )
428 return new Value<uint>( uint( args[idx]->toInteger(exec) ) );
429 break;
430 case QVariant::LongLong:
431 if( args[idx]->type() == KJS::NumberType )
432 return new Value<qlonglong>( qlonglong( args[idx]->toInteger(exec) ) );
433 break;
434 case QVariant::ULongLong:
435 if( args[idx]->type() == KJS::NumberType )
436 return new Value<qulonglong>( qulonglong( args[idx]->toInteger(exec) ) );
437 break;
438 case QVariant::Double:
439 if( args[idx]->type() == KJS::NumberType )
440 return new Value<double>( args[idx]->toNumber(exec) );
441 //if ( types[idx] == "float" ) return new Value<float>( args[idx]->toNumber(exec) );
442 //if ( types[idx] == "qreal" ) return new Value<qreal>( args[idx]->toNumber(exec) );
443 break;
444 case QVariant::Bool:
445 if( args[idx]->type() == KJS::BooleanType )
446 return new Value<bool>( args[idx]->toBoolean(exec) );
447 break;
448 case QVariant::ByteArray:
449 if( args[idx]->type() == KJS::StringType )
450 return new Value<QByteArray>( toQString(args[idx]->toString(exec)).toUtf8() );
451 break;
452 case QVariant::String:
453 if( args[idx]->type() == KJS::StringType )
454 return new Value<QString>( toQString(args[idx]->toString(exec)) );
455 break;
456 case QVariant::StringList:
457 if( args[idx]->type() == KJS::ObjectType )
458 return new Value<QStringList>( convertArrayToStringList(exec, args[idx]) );
459 break;
460 case QVariant::Size:
461 if( VariantBinding *valImp = KJSEmbed::extractBindingImp<VariantBinding>(exec,args[idx]) )
462 return new Value<QSize>( valImp->variant().value<QSize>() );
463 break;
464 case QVariant::SizeF:
465 if( VariantBinding *valImp = KJSEmbed::extractBindingImp<VariantBinding>(exec,args[idx]) )
466 return new Value<QSizeF>( valImp->variant().value<QSizeF>() );
467 break;
468 case QVariant::Point:
469 if( VariantBinding *valImp = KJSEmbed::extractBindingImp<VariantBinding>(exec,args[idx]) )
470 return new Value<QPoint>( valImp->variant().value<QPoint>() );
471 break;
472 case QVariant::PointF:
473 if( VariantBinding *valImp = KJSEmbed::extractBindingImp<VariantBinding>(exec,args[idx]) )
474 return new Value<QPointF>( valImp->variant().value<QPointF>() );
475 break;
476 case QVariant::Rect:
477 if( VariantBinding *valImp = KJSEmbed::extractBindingImp<VariantBinding>(exec,args[idx]) )
478 return new Value<QRect>( valImp->variant().value<QRect>() );
479 break;
480 case QVariant::RectF:
481 if( VariantBinding *valImp = KJSEmbed::extractBindingImp<VariantBinding>(exec,args[idx]) )
482 return new Value<QRectF>( valImp->variant().value<QRectF>() );
483 break;
484 case QVariant::Color:
485 if( args[idx]->type() == KJS::StringType )
486 return new Value<QColor>( QColor(toQString(args[idx]->toString(exec))) );
487 if( VariantBinding *valImp = KJSEmbed::extractBindingImp<VariantBinding>(exec,args[idx]) )
488 return new Value<QColor>( valImp->variant().value<QColor>() );
489 break;
490 case QVariant::Url:
491 if( args[idx]->type() == KJS::StringType )
492 return new Value<QUrl>( toQString(args[idx]->toString(exec) ));
493 if( VariantBinding *valImp = KJSEmbed::extractBindingImp<VariantBinding>(exec,args[idx]) )
494 return new Value<QUrl>( valImp->variant().value<QUrl>() );
495 break;
496 case QVariant::List:
497 if( args[idx]->type() == KJS::ObjectType )
498 return new Value<QVariantList>( convertArrayToList(exec, args[idx]) );
499 break;
500 case QVariant::Map:
501 if( args[idx]->type() == KJS::ObjectType )
502 return new Value<QVariantMap>( convertArrayToMap(exec, args[idx]) );
503 break;
504 case QVariant::UserType: // fall through
505 default:
506 if( args[idx]->type() == KJS::NullType )
507 return new NullPtr();
508 if( args[idx]->type() == KJS::StringType )
509 {
510 if( strcmp(types[idx].constData(),"KUrl") == 0 ) //downcast to QUrl
511 return new Value<QUrl>( toQString(args[idx]->toString(exec) ));
512 }
513 if( args[idx]->type() == KJS::ObjectType )
514 {
515 if(QObjectBinding *objImp = KJSEmbed::extractBindingImp<QObjectBinding>(exec, args[idx]))
516 {
517 //qDebug("\tQObjectBinding");
518 if( QObject* qObj = objImp->qobject<QObject>() )
519 return new Value<void*>(qObj);
520 }
521 else if(ObjectBinding *objImp = KJSEmbed::extractBindingImp<ObjectBinding>(exec, args[idx]))
522 {
523 //qDebug("\tObjectBinding");
524 return new Value<void*>(objImp->voidStar());
525 }
526 if(VariantBinding *valImp = KJSEmbed::extractBindingImp<VariantBinding>(exec,args[idx]))
527 {
528 //qDebug() << "\tVariantBinding typeName=" << valImp->variant().typeName() << "type=" << valImp->variant().type() << "userType=" << valImp->variant().userType() << " variant=" << valImp->variant();
529 QVariant var = valImp->variant();
530
531 // if the variant is the appropriate type, return its data
532 if ((var.type() == varianttype) ||
533 ((var.type() == QVariant::UserType) &&
534 (types[idx].constData() == var.typeName())))
535 return new Value<void*>(valImp->variant().data());
536 else if ((var.type() != QVariant::UserType) &&
537 var.canConvert(varianttype))
538 {
539 // is convertable type, so convert it, and return if successful
540 if (var.convert(varianttype))
541 return new Value<void*>(valImp->variant().data());
542 }
543 else if ((var.type() == QVariant::UserType) &&
544 var.canConvert<QObject*>())
545 {
546 QObject* qObj = var.value<QObject*>();
547 if (!qObj)
548 qObj = reinterpret_cast<QObject*>(var.value<QWidget*>());
549 if (qObj) {
550 QByteArray typeName = types[idx].constData();
551 typeName.replace("*", ""); //krazy:exclude=doublequote_chars
552 if (qObj->inherits(typeName))
553 return new Value<void*>(qObj);
554 }
555 }
556 }
557 }
558
559 QVariant v = KJSEmbed::extractVariant(exec, args[idx]);
560 if (! v.isNull())
561 return new Value<QVariant>(v);
562
563 break;
564 }
565
566 qDebug("Cast failure %s value Type %d", types[idx].constData(), args[idx]->type() );
567 // construct a meaningful exception message
568 QString jsType;
569 KJS::JSObject* jsObj = args[idx]->getObject();
570 if (jsObj)
571 {
572 const KJS::ClassInfo* ci = jsObj->classInfo();
573 if (ci && ci->className)
574 jsType = ci->className;
575 if (jsType.isEmpty())
576 jsType = toQString(jsObj->className());
577 }
578
579 if (jsType.isEmpty())
580 {
581 switch(args[idx]->type())
582 {
583 case KJS::UnspecifiedType:
584 jsType = "jsUnspecified";
585 break;
586 case KJS::NumberType:
587 jsType = "jsNumber";
588 break;
589 case KJS::BooleanType:
590 jsType = "jsBoolean";
591 break;
592 case KJS::UndefinedType:
593 jsType = "jsUndefined";
594 break;
595 case KJS::NullType:
596 jsType = "jsNull";
597 break;
598 case KJS::StringType:
599 jsType = "jsString";
600 break;
601 case KJS::ObjectType:
602 jsType = "jsObject";
603 break;
604 case KJS::GetterSetterType:
605 jsType = "jsGetterSetter";
606 break;
607 default:
608 jsType = QString::number(args[idx]->type());
609 break;
610 }
611 }
612
613 errorText = i18n("Failure to cast to %1 value from Type %2 (%3)",
614 types[idx].constData(), jsType, toQString(args[idx]->toString(exec)));
615
616 return 0;
617}
618
619KJS::JSValue *SlotBinding::callAsFunction( KJS::ExecState *exec, KJS::JSObject *self, const KJS::List &args )
620{
621 QObjectBinding *imp = extractBindingImp<QObjectBinding>(exec,self);
622 if( imp == 0 )
623 return KJS::jsNull();
624
625 PointerBase *qtArgs[10];
626 void *param[11];
627
628 QObject *object = imp->object<QObject>();
629 int count = object->metaObject()->methodCount();
630 QMetaMethod metaMember;
631 int offset = 0;
632 bool success = false;
633 for(; offset < count; ++offset)
634 {
635 metaMember = object->metaObject()->method(offset);
636 if( extractMemberName(metaMember) == m_memberName )
637 {
638 if( metaMember.parameterTypes().size() == args.size() && validSlot(metaMember, imp->access()) )
639 {
640 success = true;
641 break;
642 }
643 }
644 }
645
646 if( !success )
647 {
648 return KJS::throwError(exec, KJS::GeneralError, i18n("No such method '%1'.", m_memberName.constData()));
649 //return KJSEmbed::throwError(exec, i18n("Call to '%1' failed.").arg(m_memberName.constData()));
650 }
651
652 QList<QByteArray> types = metaMember.parameterTypes();
653
654 QVariant::Type returnTypeId = QVariant::nameToType( metaMember.typeName() );
655 int tp = QMetaType::type( metaMember.typeName() );
656 PointerBase *qtRet = new Value<void*>(0);
657
658 bool returnIsMetaType = (
659 returnTypeId == QVariant::UserType ||
660 returnTypeId == QVariant::Size || returnTypeId == QVariant::SizeF ||
661 returnTypeId == QVariant::Point || returnTypeId == QVariant::PointF ||
662 returnTypeId == QVariant::Rect || returnTypeId == QVariant::RectF ||
663 returnTypeId == QVariant::Color
664 );
665 QVariant returnValue = returnIsMetaType ? QVariant(tp, (void*)0) : QVariant(returnTypeId);
666 QGenericReturnArgument returnArgument(metaMember.typeName(), &returnValue);
667 param[0] = returnIsMetaType ? qtRet->voidStar() : returnArgument.data();
668
669 QString errorText;
670 for( int idx = 0; idx < 10; ++idx)
671 {
672 qtArgs[idx] = getArg(exec, types, args, idx, errorText);
673 if (!qtArgs[idx]) {
674 for( int i = 0; i < idx; ++i)
675 delete qtArgs[i];
676 delete qtRet;
677 return KJS::throwError(exec, KJS::GeneralError, i18n("Call to method '%1' failed, unable to get argument %2: %3", m_memberName.constData(), idx, errorText));
678 }
679 param[idx+1] = qtArgs[idx]->voidStar();
680 }
681
682 success = object->qt_metacall(QMetaObject::InvokeMetaMethod, offset, param) < 0;
683
684 KJS::JSValue *jsReturnValue = 0;
685 if( success ) {
686 switch( returnTypeId ) {
687 case QVariant::Invalid: // fall through
688 case QVariant::UserType: {
689 switch( tp ) {
690 case QMetaType::QWidgetStar: {
691 QVariant v(tp, param[0]);
692 QWidget* widget = v.value< QWidget* >();
693 if( widget )
694 jsReturnValue = KJSEmbed::createQObject(exec, widget, KJSEmbed::ObjectBinding::CPPOwned);
695 } break;
696 case QMetaType::QObjectStar: {
697 QVariant v(tp,param[0]);
698 QObject* obj = v.value< QObject* >();
699 if( obj )
700 jsReturnValue = KJSEmbed::createQObject(exec, obj, KJSEmbed::ObjectBinding::CPPOwned);
701 } break;
702 default:
703 break;
704 }
705 } break;
706 default:
707 if( returnIsMetaType )
708 returnValue = QVariant(tp, param[0]);
709 break;
710 }
711 if(! jsReturnValue)
712 jsReturnValue = KJSEmbed::convertToValue(exec, returnValue);
713 }
714
715 for( int idx = 0; idx < 10; ++idx)
716 delete qtArgs[idx];
717 delete qtRet;
718
719 if( !success )
720 return KJS::throwError(exec, KJS::GeneralError, i18n("Call to '%1' failed.", m_memberName.constData()));
721
722 return jsReturnValue;
723}
724
725SlotBinding::SlotBinding(KJS::ExecState *exec, const QMetaMethod &member )
726 : KJS::InternalFunctionImp(static_cast<KJS::FunctionPrototype*>(exec->lexicalInterpreter()->builtinFunctionPrototype()),
727 KJS::Identifier(toUString(extractMemberName(member))))
728{
729 m_memberName = extractMemberName(member);
730 int count = member.parameterNames().count();
731 putDirect( exec->propertyNames().length, count, LengthFlags );
732}
733
734
735KJS::JSObject* KJSEmbed::createQObject(KJS::ExecState *exec, QObject *value, KJSEmbed::ObjectBinding::Ownership owner)
736{
737 if ( 0 == value )
738 return new KJS::JSObject();
739
740 const QMetaObject *meta = value->metaObject();
741 KJS::JSObject *parent = exec->dynamicInterpreter()->globalObject();
742 KJS::JSObject *returnValue;
743 int pos;
744 QString clazz;
745 do
746 {
747 clazz = meta->className();
748
749#ifdef CREATEQOBJ_DIAG
750 qDebug() << "clazz=" << clazz;
751#endif
752 // strip off namespace since they aren't included
753 if ((pos = clazz.lastIndexOf("::")) != -1)
754 clazz.remove(0, pos + 2);
755#ifdef CREATEQOBJ_DIAG
756 qDebug() << "cleaned clazz=" << clazz;
757#endif
758 if ( parent->hasProperty( exec, KJS::Identifier(toUString(clazz)) ) )
759 {
760#ifdef CREATEQOBJ_DIAG
761 qDebug() << "createQObject(): clazz=" << clazz << " value=" << value;
762#endif
763 Pointer<QObject> pov(value);
764 returnValue = StaticConstructor::bind(exec, clazz, pov);
765 if ( returnValue )
766 return returnValue;
767
768#ifdef CREATEQOBJ_DIAG
769 qDebug("\tresort to construct() method.");
770#endif
771 returnValue = StaticConstructor::construct( exec, parent, toUString(clazz) );
772 if( returnValue )
773 {
774 // If it is a value type setValue
775 KJSEmbed::QObjectBinding *imp = extractBindingImp<QObjectBinding>(exec, returnValue );
776 if( imp )
777 {
778 imp->setObject( value );
779 imp->watchObject( value );
780 imp->setOwnership( owner );
781 KJSEmbed::QObjectBinding::publishQObject( exec, returnValue, value);
782 }
783 else
784 {
785 KJS::throwError(exec, KJS::TypeError, i18n("%1 is not an Object type", clazz ));
786 return new KJS::JSObject();
787 }
788 }
789 else
790 {
791 KJS::throwError(exec, KJS::TypeError, i18n("Could not construct value"));
792 return new KJS::JSObject();
793 }
794 return returnValue;
795 }
796 else
797 {
798#ifdef CREATEQOBJ_DIAG
799 qDebug("%s not a bound type, move up the chain", meta->className() );
800#endif
801 meta = meta->superClass();
802 }
803
804 }
805 while( meta );
806
807 KJSEmbed::QObjectBinding *imp = new KJSEmbed::QObjectBinding(exec, value);
808 imp->setOwnership( owner );
809
810 return imp;
811}
812
813START_QOBJECT_METHOD( callParent, QObject )
814 //TODO it would be better, if each QObjectBinding remembers it's parent rather then
815 //creating a new instance each time. That wouldn't only be more logical, but also
816 //does prevent losing of additional information like e.g. the access-level.
817 if( imp->access() & QObjectBinding::GetParentObject )
818 {
819 QObject *parent = imp->object<QObject>()->parent();
820 KJS::JSObject *parentObject = KJSEmbed::createQObject(exec, parent);
821 KJSEmbed::QObjectBinding *parentImp = KJSEmbed::extractBindingImp<KJSEmbed::QObjectBinding>(exec, parentObject);
822 if( parentImp ) {
823 parentImp->setAccess( imp->access() ); // inherit access from child since we don't know the access-level of the parent here :-(
824 }
825 result = parentObject;
826 }
827END_QOBJECT_METHOD
828START_QOBJECT_METHOD( callIsWidgetType, QObject )
829 result = KJS::jsBoolean(object->isWidgetType());
830END_QOBJECT_METHOD
831START_QOBJECT_METHOD( callInherits, QObject)
832 QByteArray className = KJSEmbed::extractQString(exec, args, 0).toLatin1();
833 result = KJS::jsBoolean(object->inherits(className.constData()));
834END_QOBJECT_METHOD
835START_QOBJECT_METHOD( callSetParent, QObject )
836 if( imp->access() & QObjectBinding::SetParentObject )
837 {
838 QObject *parent = KJSEmbed::extractObject<QObject>(exec, args, 0, 0);
839 object->setParent(parent);
840 }
841END_QOBJECT_METHOD
842START_QOBJECT_METHOD( callFindChild, QObject )
843 if( imp->access() & QObjectBinding::ChildObjects )
844 {
845 QString childName = KJSEmbed::extractQString(exec, args, 0);
846 QObject *child = object->findChild<QObject*>(childName);
847 KJS::JSObject *childObject = KJSEmbed::createQObject(exec, child);
848 KJSEmbed::QObjectBinding *childImp = KJSEmbed::extractBindingImp<KJSEmbed::QObjectBinding>(exec, childObject);
849 if( childImp ) {
850 childImp->setAccess( imp->access() ); // inherit access from parent
851 }
852 result = childObject;
853 }
854END_QOBJECT_METHOD
855
856START_METHOD_LUT(QObjectFactory)
857 {"connect", 4, KJS::DontDelete|KJS::ReadOnly, &callConnect },
858 {"parent", 0, KJS::DontDelete|KJS::ReadOnly, &callParent },
859 {"inherits", 1, KJS::DontDelete|KJS::ReadOnly, &callInherits },
860 {"isWidgetType", 0, KJS::DontDelete|KJS::ReadOnly, &callIsWidgetType },
861 {"setParent", 1, KJS::DontDelete|KJS::ReadOnly, &callSetParent },
862 {"findChild", 1, KJS::DontDelete|KJS::ReadOnly, &callFindChild }
863END_METHOD_LUT
864
865NO_ENUMS( QObjectFactory )
866NO_STATICS( QObjectFactory )
867
868//kate: indent-spaces on; indent-width 4; replace-tabs on; indent-mode cstyle;
START_METHOD_LUT
#define START_METHOD_LUT(TYPE)
Definition: binding_support.h:127
NO_ENUMS
#define NO_ENUMS(TYPE)
Definition: binding_support.h:147
NO_STATICS
#define NO_STATICS(TYPE)
Definition: binding_support.h:153
END_METHOD_LUT
#define END_METHOD_LUT
Definition: binding_support.h:135
KJSEmbed::EventProxy
Filters events for a QObject and forwards them to a JS handler.
Definition: eventproxy.h:45
KJSEmbed::EventProxy::addFilter
void addFilter(QEvent::Type t)
Adds an event type to those we forward to JS.
Definition: eventproxy.cpp:52
KJSEmbed::EventProxy::removeFilter
void removeFilter(QEvent::Type t)
Removes an event type from those we forward to JS.
Definition: eventproxy.cpp:69
KJSEmbed::JSEventMapper::mapper
static JSEventMapper * mapper()
Return the global event mapper.
Definition: jseventmapper.cpp:284
KJSEmbed::ObjectBinding
Definition: object_binding.h:89
KJSEmbed::ObjectBinding::typeName
const char * typeName() const
Definition: object_binding.cpp:45
KJSEmbed::ObjectBinding::object
T * object() const
Definition: object_binding.h:119
KJSEmbed::ObjectBinding::setOwnership
void setOwnership(Ownership owner)
Definition: object_binding.cpp:70
KJSEmbed::ObjectBinding::Ownership
Ownership
Definition: object_binding.h:91
KJSEmbed::ObjectBinding::QObjOwned
@ QObjOwned
Definition: object_binding.h:91
KJSEmbed::ObjectBinding::CPPOwned
@ CPPOwned
Definition: object_binding.h:91
KJSEmbed::ObjectBinding::JSOwned
@ JSOwned
Definition: object_binding.h:91
KJSEmbed::ObjectBinding::setObject
void setObject(T *ptr)
Definition: object_binding.h:133
KJSEmbed::ObjectBinding::ownership
Ownership ownership() const
Definition: object_binding.cpp:65
KJSEmbed::QObjectBinding
Definition: qobject_binding.h:80
KJSEmbed::QObjectBinding::put
void put(KJS::ExecState *exec, const KJS::Identifier &propertyName, KJS::JSValue *value, int attr=KJS::None)
Set the value value of the property propertyName .
Definition: qobject_binding.cpp:322
KJSEmbed::QObjectBinding::canPut
bool canPut(KJS::ExecState *exec, const KJS::Identifier &propertyName) const
Definition: qobject_binding.cpp:371
KJSEmbed::QObjectBinding::propertyGetter
static KJS::JSValue * propertyGetter(KJS::ExecState *exec, KJS::JSObject *, const KJS::Identifier &name, const KJS::PropertySlot &)
Callback used to get properties.
Definition: qobject_binding.cpp:297
KJSEmbed::QObjectBinding::className
KJS::UString className() const
Definition: qobject_binding.cpp:387
KJSEmbed::QObjectBinding::QObjectBinding
QObjectBinding(KJS::ExecState *exec, QObject *object)
Definition: qobject_binding.cpp:229
KJSEmbed::QObjectBinding::access
AccessFlags access() const
Definition: qobject_binding.cpp:312
KJSEmbed::QObjectBinding::watchObject
void watchObject(QObject *object)
Add the QObject object to the internal QObjectCleanupHandler to watch the lifetime of the QObject to ...
Definition: qobject_binding.cpp:276
KJSEmbed::QObjectBinding::PrivateSignals
@ PrivateSignals
Publish private signals.
Definition: qobject_binding.h:106
KJSEmbed::QObjectBinding::NonScriptableSignals
@ NonScriptableSignals
Publish signals that don't have Q_SCRIPTABLE defined.
Definition: qobject_binding.h:105
KJSEmbed::QObjectBinding::ChildObjects
@ ChildObjects
Provide access to the child QObject's the QObject has.
Definition: qobject_binding.h:117
KJSEmbed::QObjectBinding::NonScriptableSlots
@ NonScriptableSlots
Publish slots that don't have Q_SCRIPTABLE defined.
Definition: qobject_binding.h:98
KJSEmbed::QObjectBinding::ProtectedSlots
@ ProtectedSlots
Publish protected slots.
Definition: qobject_binding.h:100
KJSEmbed::QObjectBinding::ScriptableProperties
@ ScriptableProperties
Publish properties that have Q_SCRIPTABLE defined.
Definition: qobject_binding.h:111
KJSEmbed::QObjectBinding::ProtectedSignals
@ ProtectedSignals
Publish protected signals.
Definition: qobject_binding.h:107
KJSEmbed::QObjectBinding::NonScriptableProperties
@ NonScriptableProperties
Publish properties that don't have Q_SCRIPTABLE defined.
Definition: qobject_binding.h:112
KJSEmbed::QObjectBinding::PrivateSlots
@ PrivateSlots
Publish private slots.
Definition: qobject_binding.h:99
KJSEmbed::QObjectBinding::PublicSignals
@ PublicSignals
Publish public signals.
Definition: qobject_binding.h:108
KJSEmbed::QObjectBinding::PublicSlots
@ PublicSlots
Publish public slots.
Definition: qobject_binding.h:101
KJSEmbed::QObjectBinding::ScriptableSignals
@ ScriptableSignals
Publish signals that have Q_SCRIPTABLE defined.
Definition: qobject_binding.h:104
KJSEmbed::QObjectBinding::ScriptableSlots
@ ScriptableSlots
Publish slots that have Q_SCRIPTABLE defined.
Definition: qobject_binding.h:97
KJSEmbed::QObjectBinding::getOwnPropertySlot
bool getOwnPropertySlot(KJS::ExecState *exec, const KJS::Identifier &propertyName, KJS::PropertySlot &slot)
Called to ask if we have a callback for the named property.
Definition: qobject_binding.cpp:281
KJSEmbed::QObjectBinding::setAccess
void setAccess(AccessFlags access)
Set the defined Access flags to access .
Definition: qobject_binding.cpp:317
KJSEmbed::QObjectBinding::~QObjectBinding
virtual ~QObjectBinding()
Definition: qobject_binding.cpp:253
KJSEmbed::QObjectBinding::publishQObject
static void publishQObject(KJS::ExecState *exec, KJS::JSObject *target, QObject *object)
Definition: qobject_binding.cpp:174
KJSEmbed::QObjectBinding::toString
KJS::UString toString(KJS::ExecState *exec) const
Definition: qobject_binding.cpp:392
KJSEmbed::SlotBinding
Definition: qobject_binding.h:195
KJSEmbed::SlotBinding::m_memberName
QByteArray m_memberName
Definition: qobject_binding.h:203
KJSEmbed::SlotBinding::SlotBinding
SlotBinding(KJS::ExecState *exec, const QMetaMethod &memberName)
Definition: qobject_binding.cpp:725
KJSEmbed::SlotBinding::callAsFunction
KJS::JSValue * callAsFunction(KJS::ExecState *exec, KJS::JSObject *self, const KJS::List &args)
Definition: qobject_binding.cpp:619
KJSEmbed::SlotProxy
Definition: slotproxy.h:42
KJSEmbed::StaticBinding
A binding method that is used in VariantBinding and ObjectBinding.
Definition: static_binding.h:40
KJSEmbed::StaticBinding::publish
static void publish(KJS::ExecState *exec, KJS::JSObject *object, const Method *methods)
Publishes an array of Methods to an object.
Definition: static_binding.cpp:60
KJSEmbed::StaticConstructor::construct
KJS::JSObject * construct(KJS::ExecState *exec, const KJS::List &args)
Calls the callback that will in turn create a new instance of this object with the arguments passed i...
Definition: static_binding.cpp:79
KJSEmbed::StaticConstructor::bind
static KJS::JSObject * bind(KJS::ExecState *exec, const QString &className, PointerBase &objPtr)
Definition: static_binding.cpp:130
KJSEmbed::VariantBinding
QVariant based binding.
Definition: variant_binding.h:89
QObject
QWidget
result
END_VARIANT_METHOD result
Definition: color.cpp:85
eventproxy.h
if
if(file->open((QIODevice::OpenModeFlag) KJSEmbed::extractInt(exec, args, 0)))
Definition: fileio.cpp:64
jseventmapper.h
KJSEmbed
Definition: application.h:33
KJSEmbed::extractQString
QString KJSEMBED_EXPORT extractQString(KJS::ExecState *exec, const KJS::List &args, int idx, const QString defaultValue=QString())
Extracts a QString from an argument list.
Definition: binding_support.cpp:34
KJSEmbed::convertToVariant
QVariant KJSEMBED_EXPORT convertToVariant(KJS::ExecState *exec, KJS::JSValue *value)
Convert a KJS::JSValue into a QVariant object.
Definition: variant_binding.cpp:253
KJSEmbed::convertArrayToStringList
QStringList KJSEMBED_EXPORT convertArrayToStringList(KJS::ExecState *exec, KJS::JSValue *value)
Convert a KJS::JSValue inot a QStringList.
Definition: variant_binding.cpp:199
KJSEmbed::toQString
QString toQString(const KJS::UString &u)
Definition: kjseglobal.h:58
KJSEmbed::convertToValue
KJSEMBED_EXPORT KJS::JSValue * convertToValue(KJS::ExecState *exec, const QVariant &value)
Convert a QVariant to a KJS::JSValue.
Definition: variant_binding.cpp:298
KJSEmbed::createQObject
KJSEMBED_EXPORT KJS::JSObject * createQObject(KJS::ExecState *exec, QObject *value, KJSEmbed::ObjectBinding::Ownership owner=KJSEmbed::ObjectBinding::JSOwned)
Returns a binding object for the specified QObject.
Definition: qobject_binding.cpp:735
KJSEmbed::extractVariant
QVariant KJSEMBED_EXPORT extractVariant(KJS::ExecState *exec, KJS::JSValue *value)
Extracts a QVariant from a KJS::JSValue if the conversion fails a QVariant::Null is returned.
Definition: variant_binding.cpp:407
KJSEmbed::toUString
KJS::UString toUString(const QString &qs)
Definition: kjseglobal.h:66
KJSEmbed::convertArrayToList
QList< QVariant > KJSEMBED_EXPORT convertArrayToList(KJS::ExecState *exec, KJS::JSValue *value)
Convert a KJS::JSValue into a QList.
Definition: variant_binding.cpp:169
KJSEmbed::convertArrayToMap
QMap< QString, QVariant > KJSEMBED_EXPORT convertArrayToMap(KJS::ExecState *exec, KJS::JSValue *value)
Convert a KJS::JSValue that contains an associative array into a QMap.
Definition: variant_binding.cpp:153
KJS
Implement QString-KJS::UString conversion methods.
Definition: kjs_object_model.h:29
KJS::throwError
JSObject * throwError(ExecState *e, ErrorType t, const QString &m)
Definition: binding_support.h:241
pointer.h
parent
QObject * parent
Definition: qaction_binding.cpp:48
validSignal
bool validSignal(const QMetaMethod &method, QObjectBinding::AccessFlags accessflags)
Definition: qobject_binding.cpp:80
className
END_QOBJECT_METHOD QByteArray className
Definition: qobject_binding.cpp:832
extractMemberName
QByteArray extractMemberName(const QMetaMethod &member)
Definition: qobject_binding.cpp:168
validProperty
bool validProperty(const QMetaProperty &property, QObjectBinding::AccessFlags accessflags)
Definition: qobject_binding.cpp:102
createSignal
QByteArray createSignal(const QByteArray &sig)
Definition: qobject_binding.cpp:48
callConnect
KJS::JSValue * callConnect(KJS::ExecState *exec, KJS::JSObject *self, const KJS::List &args)
Definition: qobject_binding.cpp:113
createSlot
QByteArray createSlot(const QByteArray &slt)
Definition: qobject_binding.cpp:53
getArg
PointerBase * getArg(KJS::ExecState *exec, const QList< QByteArray > &types, const KJS::List &args, int idx, QString &errorText)
Definition: qobject_binding.cpp:401
validSlot
bool validSlot(const QMetaMethod &method, QObjectBinding::AccessFlags accessflags)
Definition: qobject_binding.cpp:58
qobject_binding.h
START_QOBJECT_METHOD
#define START_QOBJECT_METHOD(METHODNAME, TYPE)
A simple pointer syle method.
Definition: qobject_binding.h:45
END_QOBJECT_METHOD
#define END_QOBJECT_METHOD
End a variant method started by START_QOBJECT_METHOD.
Definition: qobject_binding.h:60
object
return object
Definition: qpainter_binding.cpp:514
value
QVariant value
Definition: settings.cpp:35
key
END_QOBJECT_METHOD QString key
Definition: settings.cpp:34
keys
QStringList keys
Definition: settings.cpp:29
slotproxy.h
LengthFlags
#define LengthFlags
Definition: static_binding.h:32
NullPtr
Definition: pointer.h:104
PointerBase
Definition: pointer.h:32
PointerBase::voidStar
virtual void * voidStar()=0
Pointer
Definition: pointer.h:43
Value
Definition: pointer.h:74
widget
END_METHOD_LUT QSvgWidget * widget
Definition: svg_binding.cpp:106
variant_binding.h
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kjsembed

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

kdelibs-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal