scriptcontainer.cpp

00001 /***************************************************************************
00002  * scriptcontainer.cpp
00003  * This file is part of the KDE project
00004  * copyright (C)2004-2005 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 "scriptcontainer.h"
00021 #include "../api/object.h"
00022 #include "../api/list.h"
00023 #include "../api/interpreter.h"
00024 #include "../api/script.h"
00025 #include "../main/manager.h"
00026 #include "mainmodule.h"
00027 
00028 #include <qfile.h>
00029 
00030 using namespace Kross::Api;
00031 
00032 namespace Kross { namespace Api {
00033 
00034     /// @internal
00035     class ScriptContainerPrivate
00036     {
00037         public:
00038 
00039             /**
00040             * The \a Script instance the \a ScriptContainer uses
00041             * if initialized. It will be NULL as long as we
00042             * didn't initialized it what will be done on
00043             * demand.
00044             */
00045             Script* script;
00046 
00047             /**
00048             * The unique name the \a ScriptContainer is
00049             * reachable as.
00050             */
00051             QString name;
00052 
00053             /**
00054             * The scripting code.
00055             */
00056             QString code;
00057 
00058             /**
00059             * The name of the interpreter. This could be
00060             * something like "python" for the python
00061             * binding.
00062             */
00063             QString interpretername;
00064 
00065             /**
00066             * The name of the scriptfile that should be
00067             * executed. Those scriptfile will be readed
00068             * and the content will be used to set the
00069             * scripting code and, if not defined, the
00070             * used interpreter.
00071             */
00072             QString scriptfile;
00073 
00074             /**
00075             * Map of options that overwritte the \a InterpreterInfo::Option::Map
00076             * standard options.
00077             */
00078             QMap<QString, QVariant> options;
00079 
00080     };
00081 
00082 }}
00083 
00084 ScriptContainer::ScriptContainer(const QString& name)
00085     : MainModule(name)
00086     , d( new ScriptContainerPrivate() ) // initialize d-pointer class
00087 {
00088     kdDebug() << QString("ScriptContainer::ScriptContainer() Ctor name='%1'").arg(name) << endl;
00089 
00090     d->script = 0;
00091     d->name = name;
00092 }
00093 
00094 ScriptContainer::~ScriptContainer()
00095 {
00096     kdDebug() << QString("ScriptContainer::~ScriptContainer() Dtor name='%1'").arg(d->name) << endl;
00097 
00098     finalize();
00099     delete d;
00100 }
00101 
00102 const QString& ScriptContainer::getName() const
00103 {
00104     return d->name;
00105 }
00106 
00107 void ScriptContainer::setName(const QString& name)
00108 {
00109     d->name = name;
00110 }
00111 
00112 const QString& ScriptContainer::getCode() const
00113 {
00114     return d->code;
00115 }
00116 
00117 void ScriptContainer::setCode(const QString& code)
00118 {
00119     finalize();
00120     d->code = code;
00121 }
00122 
00123 const QString& ScriptContainer::getInterpreterName() const
00124 {
00125     return d->interpretername;
00126 }
00127 
00128 void ScriptContainer::setInterpreterName(const QString& interpretername)
00129 {
00130     finalize();
00131     d->interpretername = interpretername;
00132 }
00133 
00134 const QString& ScriptContainer::getFile() const
00135 {
00136     return d->scriptfile;
00137 }
00138 
00139 void ScriptContainer::setFile(const QString& scriptfile)
00140 {
00141     finalize();
00142     d->scriptfile = scriptfile;
00143 }
00144 
00145 QMap<QString, QVariant>& ScriptContainer::getOptions()
00146 {
00147     return d->options;
00148 }
00149 
00150 const QVariant& ScriptContainer::getOption(const QString name, QVariant defaultvalue, bool /*recursive*/)
00151 {
00152     if(d->options.contains(name))
00153         return d->options[name];
00154     Kross::Api::InterpreterInfo* info = Kross::Api::Manager::scriptManager()->getInterpreterInfo( d->interpretername );
00155     return info ? info->getOptionValue(name, defaultvalue) : defaultvalue;
00156 }
00157 
00158 bool ScriptContainer::setOption(const QString name, const QVariant& value)
00159 {
00160     Kross::Api::InterpreterInfo* info = Kross::Api::Manager::scriptManager()->getInterpreterInfo( d->interpretername );
00161     if(info) {
00162         if(info->hasOption(name)) {
00163             d->options.replace(name, value);
00164             return true;
00165         } else kdWarning() << QString("Kross::Api::ScriptContainer::setOption(%1, %2): No such option").arg(name).arg(value.toString()) << endl;
00166     } else kdWarning() << QString("Kross::Api::ScriptContainer::setOption(%1, %2): No such interpreterinfo").arg(name).arg(value.toString()) << endl;
00167     return false;
00168 }
00169 
00170 Object::Ptr ScriptContainer::execute()
00171 {
00172     if(! d->script)
00173         if(! initialize())
00174             return 0;
00175 
00176     if(hadException())
00177         return 0;
00178 
00179     Object::Ptr r = d->script->execute();
00180     if(d->script->hadException()) {
00181         setException( d->script->getException() );
00182         finalize();
00183         return 0;
00184     }
00185     return r;
00186 }
00187 
00188 const QStringList ScriptContainer::getFunctionNames()
00189 {
00190     return d->script ? d->script->getFunctionNames() : QStringList(); //FIXME init before if needed?
00191 }
00192 
00193 Object::Ptr ScriptContainer::callFunction(const QString& functionname, List::Ptr arguments)
00194 {
00195     if(! d->script)
00196         if(! initialize())
00197             return 0;
00198 
00199     if(hadException())
00200         return 0;
00201 
00202     if(functionname.isEmpty()) {
00203         setException( new Exception(QString("No functionname defined for ScriptContainer::callFunction().")) );
00204         finalize();
00205         return 0;
00206     }
00207 
00208     Object::Ptr r = d->script->callFunction(functionname, arguments);
00209     if(d->script->hadException()) {
00210         setException( d->script->getException() );
00211         finalize();
00212         return 0;
00213     }
00214     return r;
00215 }
00216 
00217 const QStringList ScriptContainer::getClassNames()
00218 {
00219     return d->script ? d->script->getClassNames() : QStringList(); //FIXME init before if needed?
00220 }
00221 
00222 Object::Ptr ScriptContainer::classInstance(const QString& classname)
00223 {
00224     if(! d->script)
00225         if(! initialize())
00226             return 0;
00227 
00228     if(hadException())
00229         return 0;
00230 
00231     Object::Ptr r = d->script->classInstance(classname);
00232     if(d->script->hadException()) {
00233         setException( d->script->getException() );
00234         finalize();
00235         return 0;
00236     }
00237     return r;
00238 }
00239 
00240 bool ScriptContainer::initialize()
00241 {
00242     finalize();
00243 
00244     if(! d->scriptfile.isNull()) {
00245         kdDebug() << QString("Kross::Api::ScriptContainer::initialize() file=%1").arg(d->scriptfile) << endl;
00246 
00247         if(d->interpretername.isNull()) {
00248             d->interpretername = Manager::scriptManager()->getInterpreternameForFile( d->scriptfile );
00249             if(d->interpretername.isNull()) {
00250                 setException( new Exception(QString("Failed to determinate interpreter for scriptfile '%1'").arg(d->scriptfile)) );
00251                 return false;
00252             }
00253         }
00254 
00255         QFile f( d->scriptfile );
00256         if(! f.open(IO_ReadOnly)) {
00257             setException( new Exception(QString("Failed to open scriptfile '%1'").arg(d->scriptfile)) );
00258             return false;
00259         }
00260         d->code = QString( f.readAll() );
00261         f.close();
00262     }
00263 
00264     Interpreter* interpreter = Manager::scriptManager()->getInterpreter(d->interpretername);
00265     if(! interpreter) {
00266         setException( new Exception(QString("Unknown interpreter '%1'").arg(d->interpretername)) );
00267         return false;
00268     }
00269 
00270     d->script = interpreter->createScript(this);
00271     if(! d->script) {
00272         setException( new Exception(QString("Failed to create script for interpreter '%1'").arg(d->interpretername)) );
00273         return false;
00274     }
00275     if(d->script->hadException()) {
00276         setException( d->script->getException() );
00277         finalize();
00278         return false;
00279     }
00280     setException( 0 ); // clear old exception
00281 
00282     return true;
00283 }
00284 
00285 void ScriptContainer::finalize()
00286 {
00287     delete d->script;
00288     d->script = 0;
00289 }
00290 
00291 

Generated on Thu Feb 9 17:59:11 2006 for Kross by  doxygen 1.4.6