00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "manager.h"
00021 #include "interpreter.h"
00022 #include "action.h"
00023 #include "actioncollection.h"
00024
00025 #include <QtCore/QObject>
00026 #include <QtCore/QArgument>
00027 #include <QtCore/QFile>
00028 #include <QtCore/QRegExp>
00029 #include <QtCore/QFileInfo>
00030 #include <QtCore/QPointer>
00031 #include <QtCore/QLibrary>
00032 #include <QtCore/QCoreApplication>
00033
00034 #include <kstandarddirs.h>
00035 #include <klocale.h>
00036
00037 extern "C"
00038 {
00039 typedef QObject* (*def_module_func)();
00040 }
00041
00042 using namespace Kross;
00043
00044 namespace Kross {
00045
00047 class Manager::Private
00048 {
00049 public:
00051 QHash< QString, InterpreterInfo* > interpreterinfos;
00052
00054 QStringList interpreters;
00055
00057 QHash< QString, QPointer<QObject> > modules;
00058
00060 ActionCollection* collection;
00061
00063 QHash<QByteArray, MetaTypeHandler*> wrappers;
00064
00066 bool strictTypesEnabled;
00067 };
00068
00069 }
00070
00071 Q_GLOBAL_STATIC(Manager, _self)
00072
00073 Manager& Manager::self()
00074 {
00075 return *_self();
00076 }
00077
00078 void* loadLibrary(const char* libname, const char* functionname)
00079 {
00080 QLibrary lib(libname);
00081 lib.setLoadHints( QLibrary::ExportExternalSymbolsHint );
00082 if( ! lib.load() ) {
00083 const QString err = QString("Error: %1").arg(lib.errorString());
00084
00085
00086 foreach(const QString &dir, KStandardDirs().resourceDirs("module")) {
00087 lib.setFileName( QFileInfo(dir, libname).filePath() );
00088 lib.setLoadHints( QLibrary::ExportExternalSymbolsHint );
00089 if( lib.load() )
00090 break;
00091 }
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104 if( ! lib.isLoaded() ) {
00105 #ifdef KROSS_INTERPRETER_DEBUG
00106 if( strcmp(functionname, "krossinterpreter") == 0 )
00107 krossdebug( QString("Kross Interpreter '%1' not available: %2").arg(libname).arg(err) );
00108 else if( strcmp(functionname, "krossmodule") == 0 )
00109 krossdebug( QString("Kross Module '%1' not available: %2").arg(libname).arg(err) );
00110 else
00111 krosswarning( QString("Failed to load unknown type of '%1' library: %2").arg(libname).arg(err) );
00112 #endif
00113 return 0;
00114 }
00115 }
00116 void* funcPtr = lib.resolve(functionname);
00117 Q_ASSERT(funcPtr);
00118 return funcPtr;
00119 }
00120
00121 Manager::Manager()
00122 : QObject()
00123 , QScriptable()
00124 , ChildrenInterface()
00125 , d( new Private() )
00126 {
00127 d->strictTypesEnabled = true;
00128 setObjectName("Kross");
00129 d->collection = new ActionCollection("main");
00130
00131 #ifdef KROSS_PYTHON_LIBRARY
00132 if( void* funcPtr = loadLibrary(KROSS_PYTHON_LIBRARY, "krossinterpreter") ) {
00133 d->interpreterinfos.insert("python",
00134 new InterpreterInfo("python",
00135 funcPtr,
00136 "*.py",
00137 QStringList() << "text/x-python"
00138 )
00139 );
00140 }
00141 #endif
00142
00143 #ifdef KROSS_RUBY_LIBRARY
00144 if( void* funcPtr = loadLibrary(KROSS_RUBY_LIBRARY, "krossinterpreter") ) {
00145 InterpreterInfo::Option::Map options;
00146 options.insert("safelevel", new InterpreterInfo::Option(
00147 i18n("Level of safety of the Ruby interpreter"),
00148 QVariant(0) ));
00149 d->interpreterinfos.insert("ruby",
00150 new InterpreterInfo("ruby",
00151 funcPtr,
00152 "*.rb",
00153 QStringList() << "application/x-ruby",
00154 options
00155 )
00156 );
00157 }
00158 #endif
00159
00160 #ifdef KROSS_JAVA_LIBRARY
00161 if( void* funcPtr = loadLibrary(KROSS_JAVA_LIBRARY, "krossinterpreter") ) {
00162 d->interpreterinfos.insert("java",
00163 new InterpreterInfo("java",
00164 funcPtr,
00165 "*.java *.class *.jar",
00166 QStringList() << "application/java"
00167 )
00168 );
00169 }
00170 #endif
00171
00172 #ifdef KROSS_KJS_LIBRARY
00173 if( void* funcPtr = loadLibrary(KROSS_KJS_LIBRARY, "krossinterpreter") ) {
00174 d->interpreterinfos.insert("javascript",
00175 new InterpreterInfo("javascript",
00176 funcPtr,
00177 "*.js",
00178 QStringList() << "application/javascript"
00179 )
00180 );
00181 }
00182 #endif
00183
00184 #ifdef KROSS_FALCON_LIBRARY
00185 if( void* funcPtr = loadLibrary(KROSS_FALCON_LIBRARY, "krossinterpreter") ) {
00186 d->interpreterinfos.insert("falcon",
00187 new InterpreterInfo("falcon",
00188 funcPtr,
00189 "*.fal",
00190 QStringList() << "application/x-falcon"
00191 )
00192 );
00193 }
00194 #endif
00195
00196 #ifdef KROSS_QTSCRIPT_LIBRARY
00197 if( void* funcPtr = loadLibrary(KROSS_QTSCRIPT_LIBRARY, "krossinterpreter") ) {
00198 d->interpreterinfos.insert("qtscript",
00199 new InterpreterInfo("qtscript",
00200 funcPtr,
00201 "*.es",
00202 QStringList() << "application/ecmascript"
00203 )
00204 );
00205 }
00206 #endif
00207
00208 #ifdef KROSS_LUA_LIBRARY
00209 if( void* funcPtr = loadLibrary(KROSS_LUA_LIBRARY, "krossinterpreter") ) {
00210 d->interpreterinfos.insert("lua",
00211 new InterpreterInfo("lua",
00212 funcPtr,
00213 "*.lua *.luac",
00214 QStringList() << "application/x-lua"
00215 )
00216 );
00217 }
00218 #endif
00219
00220
00221 QHash<QString, InterpreterInfo*>::Iterator it( d->interpreterinfos.begin() );
00222 for(; it != d->interpreterinfos.end(); ++it)
00223 if( it.value() )
00224 d->interpreters << it.key();
00225 d->interpreters.sort();
00226
00227
00228 ChildrenInterface::addObject(this, "Kross");
00229 }
00230
00231 Manager::~Manager()
00232 {
00233 qDeleteAll(d->wrappers);
00234 qDeleteAll(d->interpreterinfos);
00235 qDeleteAll(d->modules);
00236 delete d->collection;
00237 delete d;
00238 }
00239
00240 QHash< QString, InterpreterInfo* > Manager::interpreterInfos() const
00241 {
00242 return d->interpreterinfos;
00243 }
00244
00245 bool Manager::hasInterpreterInfo(const QString& interpretername) const
00246 {
00247 return d->interpreterinfos.contains(interpretername) && d->interpreterinfos[interpretername];
00248 }
00249
00250 InterpreterInfo* Manager::interpreterInfo(const QString& interpretername) const
00251 {
00252 return hasInterpreterInfo(interpretername) ? d->interpreterinfos[interpretername] : 0;
00253 }
00254
00255 const QString Manager::interpreternameForFile(const QString& file)
00256 {
00257 QRegExp rx;
00258 rx.setPatternSyntax(QRegExp::Wildcard);
00259 for(QHash<QString, InterpreterInfo*>::Iterator it = d->interpreterinfos.begin(); it != d->interpreterinfos.end(); ++it) {
00260 if( ! it.value() )
00261 continue;
00262 foreach(const QString &wildcard, it.value()->wildcard().split(' ', QString::SkipEmptyParts)) {
00263 rx.setPattern( wildcard );
00264 if( rx.exactMatch(file) )
00265 return it.value()->interpreterName();
00266 }
00267 }
00268 return QString();
00269 }
00270
00271 Interpreter* Manager::interpreter(const QString& interpretername) const
00272 {
00273 if( ! hasInterpreterInfo(interpretername) ) {
00274 krosswarning( QString("No such interpreter '%1'").arg(interpretername) );
00275 return 0;
00276 }
00277 return d->interpreterinfos[interpretername]->interpreter();
00278 }
00279
00280 QStringList Manager::interpreters() const
00281 {
00282 return d->interpreters;
00283 }
00284
00285 ActionCollection* Manager::actionCollection() const
00286 {
00287 return d->collection;
00288 }
00289
00290 bool Manager::hasAction(const QString& name)
00291 {
00292 return findChild< Action* >(name) != 0L;
00293 }
00294
00295 QObject* Manager::action(const QString& name)
00296 {
00297 Action* action = findChild< Action* >(name);
00298 if(! action) {
00299 action = new Action(this, name);
00300 #if 0
00301 d->actioncollection->insert(action);
00302 #endif
00303 }
00304 return action;
00305 }
00306
00307 QObject* Manager::module(const QString& modulename)
00308 {
00309 if( d->modules.contains(modulename) ) {
00310 QObject* obj = d->modules[modulename];
00311 if( obj )
00312 return obj;
00313 }
00314
00315 if( modulename.isEmpty() || modulename.contains( QRegExp("[^a-zA-Z0-9]") ) ) {
00316 krosswarning( QString("Invalid module name '%1'").arg(modulename) );
00317 return 0;
00318 }
00319
00320 QByteArray libraryname = QString("krossmodule%1").arg(modulename).toLower().toLatin1();
00321
00322 #if 0
00323 KLibLoader* loader = KLibLoader::self();
00324 KLibrary* lib = loader->library( libraryname, QLibrary::ExportExternalSymbolsHint );
00325 if( ! lib ) {
00326 lib = loader->library( QString("lib%1").arg(libraryname), QLibrary::ExportExternalSymbolsHint );
00327 if( ! lib ) {
00328 krosswarning( QString("Failed to load module '%1': %2").arg(modulename).arg(loader->lastErrorMessage()) );
00329 return 0;
00330 }
00331 }
00332
00333 def_module_func func;
00334 func = (def_module_func) lib->resolveFunction("krossmodule");
00335 if( ! func ) {
00336 krosswarning( QString("Failed to determinate init function in module '%1'").arg(modulename) );
00337 return 0;
00338 }
00339
00340 QObject* module = (QObject*) (func)();
00341 lib->unload();
00342
00343 if( ! module ) {
00344 krosswarning( QString("Failed to load module object '%1'").arg(modulename) );
00345 return 0;
00346 }
00347 #else
00348 if( void* funcPtr = loadLibrary(libraryname, "krossmodule") ) {
00349 def_module_func func = (def_module_func) funcPtr;
00350 Q_ASSERT( func );
00351 QObject* module = (QObject*) (func)();
00352 Q_ASSERT( module );
00353
00354 d->modules.insert(modulename, module);
00355 return module;
00356 }
00357 else {
00358 krosswarning( QString("Failed to load module '%1'").arg(modulename) );
00359 }
00360 #endif
00361 return 0;
00362 }
00363
00364 bool Manager::executeScriptFile(const QUrl& file)
00365 {
00366 krossdebug( QString("Manager::executeScriptFile() file='%1'").arg(file.toString()) );
00367 Action* action = new Action(0 , file);
00368 action->trigger();
00369 bool ok = ! action->hadError();
00370 delete action;
00371 return ok;
00372 }
00373
00374 void Manager::addQObject(QObject* obj, const QString &name)
00375 {
00376 this->addObject(obj, name);
00377 }
00378
00379 QObject* Manager::qobject(const QString &name) const
00380 {
00381 return this->object(name);
00382 }
00383
00384 QStringList Manager::qobjectNames() const
00385 {
00386 return this->objects().keys();
00387 }
00388
00389 MetaTypeHandler* Manager::metaTypeHandler(const QByteArray& typeName) const
00390 {
00391 return d->wrappers.contains(typeName) ? d->wrappers[typeName] : 0;
00392 }
00393
00394 void Manager::registerMetaTypeHandler(const QByteArray& typeName, MetaTypeHandler::FunctionPtr* handler)
00395 {
00396 d->wrappers.insert(typeName, new MetaTypeHandler(handler));
00397 }
00398
00399 void Manager::registerMetaTypeHandler(const QByteArray& typeName, MetaTypeHandler::FunctionPtr2* handler)
00400 {
00401 d->wrappers.insert(typeName, new MetaTypeHandler(handler));
00402 }
00403
00404 void Manager::registerMetaTypeHandler(const QByteArray& typeName, MetaTypeHandler* handler)
00405 {
00406 d->wrappers.insert(typeName, handler);
00407 }
00408
00409 bool Manager::strictTypesEnabled() const
00410 {
00411 return d->strictTypesEnabled;
00412 }
00413
00414 void Manager::setStrictTypesEnabled(bool enabled)
00415 {
00416 d->strictTypesEnabled = enabled;
00417 }
00418
00419 bool Manager::hasHandlerAssigned(const QByteArray& typeName) const
00420 {
00421 return d->wrappers.contains(typeName);
00422 }
00423
00424 #include "manager.moc"