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 };
00062
00063 }
00064
00065 Q_GLOBAL_STATIC(Manager, _self)
00066
00067 Manager& Manager::self()
00068 {
00069 return *_self();
00070 }
00071
00072 void* loadLibrary(const char* libname, const char* functionname)
00073 {
00074 QLibrary lib(libname);
00075 lib.setLoadHints( QLibrary::ExportExternalSymbolsHint );
00076 if( ! lib.load() ) {
00077 const QString err = QString("Error: %1").arg(lib.errorString());
00078
00079
00080 foreach(const QString &dir, KStandardDirs().resourceDirs("module")) {
00081 lib.setFileName( QFileInfo(dir, libname).filePath() );
00082 lib.setLoadHints( QLibrary::ExportExternalSymbolsHint );
00083 if( lib.load() )
00084 break;
00085 }
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098 if( ! lib.isLoaded() ) {
00099 #ifdef KROSS_INTERPRETER_DEBUG
00100 if( strcmp(functionname, "krossinterpreter") == 0 )
00101 krossdebug( QString("Kross Interpreter '%1' not available: %2").arg(libname).arg(err) );
00102 else if( strcmp(functionname, "krossmodule") == 0 )
00103 krossdebug( QString("Kross Module '%1' not available: %2").arg(libname).arg(err) );
00104 else
00105 krosswarning( QString("Failed to load unknown type of '%1' library: %2").arg(libname).arg(err) );
00106 #endif
00107 return 0;
00108 }
00109 }
00110 void* funcPtr = lib.resolve(functionname);
00111 Q_ASSERT(funcPtr);
00112 return funcPtr;
00113 }
00114
00115 Manager::Manager()
00116 : QObject()
00117 , QScriptable()
00118 , ChildrenInterface()
00119 , d( new Private() )
00120 {
00121 setObjectName("Kross");
00122 d->collection = new ActionCollection("main");
00123
00124 #ifdef KROSS_PYTHON_LIBRARY
00125 if( void* funcPtr = loadLibrary(KROSS_PYTHON_LIBRARY, "krossinterpreter") ) {
00126 d->interpreterinfos.insert("python",
00127 new InterpreterInfo("python",
00128 funcPtr,
00129 "*.py",
00130 QStringList() << "text/x-python"
00131 )
00132 );
00133 }
00134 #endif
00135
00136 #ifdef KROSS_RUBY_LIBRARY
00137 if( void* funcPtr = loadLibrary(KROSS_RUBY_LIBRARY, "krossinterpreter") ) {
00138 InterpreterInfo::Option::Map options;
00139 options.insert("safelevel", new InterpreterInfo::Option(
00140 i18n("Level of safety of the Ruby interpreter"),
00141 QVariant(0) ));
00142 d->interpreterinfos.insert("ruby",
00143 new InterpreterInfo("ruby",
00144 funcPtr,
00145 "*.rb",
00146 QStringList() << "application/x-ruby",
00147 options
00148 )
00149 );
00150 }
00151 #endif
00152
00153 #ifdef KROSS_JAVA_LIBRARY
00154 if( void* funcPtr = loadLibrary(KROSS_JAVA_LIBRARY, "krossinterpreter") ) {
00155 d->interpreterinfos.insert("java",
00156 new InterpreterInfo("java",
00157 funcPtr,
00158 "*.java *.class *.jar",
00159 QStringList() << "application/java"
00160 )
00161 );
00162 }
00163 #endif
00164
00165 #ifdef KROSS_KJS_LIBRARY
00166 if( void* funcPtr = loadLibrary(KROSS_KJS_LIBRARY, "krossinterpreter") ) {
00167 d->interpreterinfos.insert("javascript",
00168 new InterpreterInfo("javascript",
00169 funcPtr,
00170 "*.js",
00171 QStringList() << "application/javascript"
00172 )
00173 );
00174 }
00175 #endif
00176
00177 #ifdef KROSS_FALCON_LIBRARY
00178 if( void* funcPtr = loadLibrary(KROSS_FALCON_LIBRARY, "krossinterpreter") ) {
00179 d->interpreterinfos.insert("falcon",
00180 new InterpreterInfo("falcon",
00181 funcPtr,
00182 "*.fal",
00183 QStringList() << "application/x-falcon"
00184 )
00185 );
00186 }
00187 #endif
00188
00189 #ifdef KROSS_QTSCRIPT_LIBRARY
00190 if( void* funcPtr = loadLibrary(KROSS_QTSCRIPT_LIBRARY, "krossinterpreter") ) {
00191 d->interpreterinfos.insert("qtscript",
00192 new InterpreterInfo("qtscript",
00193 funcPtr,
00194 "*.es",
00195 QStringList() << "application/ecmascript"
00196 )
00197 );
00198 }
00199 #endif
00200
00201
00202 QHash<QString, InterpreterInfo*>::Iterator it( d->interpreterinfos.begin() );
00203 for(; it != d->interpreterinfos.end(); ++it)
00204 if( it.value() )
00205 d->interpreters << it.key();
00206 d->interpreters.sort();
00207
00208
00209 ChildrenInterface::addObject(this, "Kross");
00210 }
00211
00212 Manager::~Manager()
00213 {
00214 qDeleteAll(d->interpreterinfos.values());
00215 qDeleteAll(d->modules.values());
00216 delete d->collection;
00217 delete d;
00218 }
00219
00220 QHash< QString, InterpreterInfo* > Manager::interpreterInfos() const
00221 {
00222 return d->interpreterinfos;
00223 }
00224
00225 bool Manager::hasInterpreterInfo(const QString& interpretername) const
00226 {
00227 return d->interpreterinfos.contains(interpretername) && d->interpreterinfos[interpretername];
00228 }
00229
00230 InterpreterInfo* Manager::interpreterInfo(const QString& interpretername) const
00231 {
00232 return hasInterpreterInfo(interpretername) ? d->interpreterinfos[interpretername] : 0;
00233 }
00234
00235 const QString Manager::interpreternameForFile(const QString& file)
00236 {
00237 QRegExp rx;
00238 rx.setPatternSyntax(QRegExp::Wildcard);
00239 for(QHash<QString, InterpreterInfo*>::Iterator it = d->interpreterinfos.begin(); it != d->interpreterinfos.end(); ++it) {
00240 if( ! it.value() )
00241 continue;
00242 foreach(const QString &wildcard, it.value()->wildcard().split(" ", QString::SkipEmptyParts)) {
00243 rx.setPattern( wildcard );
00244 if( rx.exactMatch(file) )
00245 return it.value()->interpreterName();
00246 }
00247 }
00248 return QString();
00249 }
00250
00251 Interpreter* Manager::interpreter(const QString& interpretername) const
00252 {
00253 if( ! hasInterpreterInfo(interpretername) ) {
00254 krosswarning( QString("No such interpreter '%1'").arg(interpretername) );
00255 return 0;
00256 }
00257 return d->interpreterinfos[interpretername]->interpreter();
00258 }
00259
00260 QStringList Manager::interpreters() const
00261 {
00262 return d->interpreters;
00263 }
00264
00265 ActionCollection* Manager::actionCollection() const
00266 {
00267 return d->collection;
00268 }
00269
00270 bool Manager::hasAction(const QString& name)
00271 {
00272 return findChild< Action* >(name) != 0L;
00273 }
00274
00275 QObject* Manager::action(const QString& name)
00276 {
00277 Action* action = findChild< Action* >(name);
00278 if(! action) {
00279 action = new Action(this, name);
00280 #if 0
00281 d->actioncollection->insert(action);
00282 #endif
00283 }
00284 return action;
00285 }
00286
00287 QObject* Manager::module(const QString& modulename)
00288 {
00289 if( d->modules.contains(modulename) ) {
00290 QObject* obj = d->modules[modulename];
00291 if( obj )
00292 return obj;
00293 }
00294
00295 if( modulename.isEmpty() || modulename.contains( QRegExp("[^a-zA-Z0-9]") ) ) {
00296 krosswarning( QString("Invalid module name '%1'").arg(modulename) );
00297 return 0;
00298 }
00299
00300 QByteArray libraryname = QString("krossmodule%1").arg(modulename).toLower().toLatin1();
00301
00302 #if 0
00303 KLibLoader* loader = KLibLoader::self();
00304 KLibrary* lib = loader->library( libraryname, QLibrary::ExportExternalSymbolsHint );
00305 if( ! lib ) {
00306 lib = loader->library( QString("lib%1").arg(libraryname), QLibrary::ExportExternalSymbolsHint );
00307 if( ! lib ) {
00308 krosswarning( QString("Failed to load module '%1': %2").arg(modulename).arg(loader->lastErrorMessage()) );
00309 return 0;
00310 }
00311 }
00312
00313 def_module_func func;
00314 func = (def_module_func) lib->resolveFunction("krossmodule");
00315 if( ! func ) {
00316 krosswarning( QString("Failed to determinate init function in module '%1'").arg(modulename) );
00317 return 0;
00318 }
00319
00320 QObject* module = (QObject*) (func)();
00321 lib->unload();
00322
00323 if( ! module ) {
00324 krosswarning( QString("Failed to load module object '%1'").arg(modulename) );
00325 return 0;
00326 }
00327 #else
00328 if( void* funcPtr = loadLibrary(libraryname, "krossmodule") ) {
00329 def_module_func func = (def_module_func) funcPtr;
00330 Q_ASSERT( func );
00331 QObject* module = (QObject*) (func)();
00332 Q_ASSERT( module );
00333
00334 d->modules.insert(modulename, module);
00335 return module;
00336 }
00337 else {
00338 krosswarning( QString("Failed to load module '%1'").arg(modulename) );
00339 }
00340 #endif
00341 return 0;
00342 }
00343
00344 bool Manager::executeScriptFile(const QUrl& file)
00345 {
00346 krossdebug( QString("Manager::executeScriptFile() file='%1'").arg(file.toString()) );
00347 Action* action = new Action(0 , file);
00348 action->trigger();
00349 bool ok = ! action->hadError();
00350 delete action;
00351 return ok;
00352 }
00353
00354 void Manager::addQObject(QObject* obj, const QString &name)
00355 {
00356 this->addObject(obj, name);
00357 }
00358
00359 QObject* Manager::qobject(const QString &name) const
00360 {
00361 return this->object(name);
00362 }
00363
00364 QStringList Manager::qobjectNames() const
00365 {
00366 return this->objects().keys();
00367 }
00368
00369 #include "manager.moc"