• Skip to content
  • Skip to link menu
KDE 4.3 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

Kross

action.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  * action.cpp
00003  * This file is part of the KDE project
00004  * copyright (C)2004-2006 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 "action.h"
00021 #include "actioncollection.h"
00022 #include "interpreter.h"
00023 #include "script.h"
00024 #include "manager.h"
00025 #include "wrapperinterface.h"
00026 
00027 #include <QtCore/QFile>
00028 #include <QtCore/QFileInfo>
00029 
00030 #include <kdebug.h>
00031 #include <klocale.h>
00032 #include <kicon.h>
00033 #include <kmimetype.h>
00034 
00035 using namespace Kross;
00036 
00037 namespace Kross {
00038 
00040     class Action::Private
00041     {
00042         public:
00043 
00049             Script* script;
00050 
00055             int version;
00056 
00061             QString description;
00062 
00066             QString iconname;
00067 
00071             QByteArray code;
00072 
00077             QString interpretername;
00078 
00085             QString scriptfile;
00086 
00092             QStringList searchpath;
00093 
00098             QMap< QString, QVariant > options;
00099 
00100             Private() : script(0), version(0) {}
00101     };
00102 
00103 }
00104 
00105 enum InitOptions{Enable=1};
00106 void static init(Action* th, const QString& name, int options=0)
00107 {
00108     th->setEnabled(options&Enable);
00109     th->setObjectName(name);
00110     #ifdef KROSS_ACTION_DEBUG
00111         krossdebug( QString("Action::Action(QObject*,QString,QDir) Ctor name='%1'").arg(th->objectName()) );
00112     #endif
00113     QObject::connect(th, SIGNAL(triggered(bool)), th, SLOT(slotTriggered()));
00114 }
00115 
00116 Action::Action(QObject* parent, const QString& name, const QDir& packagepath)
00117     : QAction(parent)
00118     , QScriptable()
00119     , ChildrenInterface()
00120     , ErrorInterface()
00121     , d( new Private() )
00122 {
00123     init(this,name);
00124     d->searchpath=QStringList(packagepath.absolutePath());
00125 }
00126 
00127 Action::Action(QObject* parent, const QUrl& url)
00128     : QAction(parent)
00129     , ChildrenInterface()
00130     , ErrorInterface()
00131     , d( new Private() )
00132 {
00133     init(this,url.path(),Enable);
00134     QFileInfo fi( url.toLocalFile() );
00135     setText( fi.fileName() );
00136     setIconName( KMimeType::iconNameForUrl(url) );
00137     setFile( url.toLocalFile() );
00138 }
00139 
00140 Action::~Action()
00141 {
00142     #ifdef KROSS_ACTION_DEBUG
00143         krossdebug( QString("Action::~Action() Dtor name='%1'").arg(objectName()) );
00144     #endif
00145     finalize();
00146     ActionCollection *coll = qobject_cast<ActionCollection*>(parent());
00147     if ( coll ) {
00148         coll->removeAction(this);
00149     }
00150     delete d;
00151 }
00152 
00153 
00154 void Action::fromDomElement(const QDomElement& element)
00155 {
00156     fromDomElement(element, d->searchpath);
00157 }
00158 
00159 void Action::fromDomElement(const QDomElement& element, const QStringList& searchPath)
00160 {
00161     if( element.isNull() )
00162         return;
00163 
00164     QString file = element.attribute("file");
00165     if( ! file.isEmpty() ) {
00166         if( QFileInfo(file).exists() ) {
00167             setFile(file);
00168         }
00169         else {
00170             foreach (const QString& packagepath, searchPath) {
00171                 QFileInfo fi(QDir(packagepath), file);
00172                 if( fi.exists() ) {
00173                     setFile( fi.absoluteFilePath() );
00174                     break;
00175                 }
00176             }
00177         }
00178     }
00179 
00180     d->version = QVariant( element.attribute("version",QString(d->version)) ).toInt();
00181 
00182     setText( i18n( element.attribute("text").toUtf8() ) );
00183     setDescription( i18n( element.attribute("comment").toUtf8() ) );
00184     setEnabled( true );
00185     setInterpreter( element.attribute("interpreter") );
00186     setEnabled( QVariant(element.attribute("enabled","true")).toBool() && isEnabled() );
00187 
00188     QString icon = element.attribute("icon");
00189     if( icon.isEmpty() && ! d->scriptfile.isNull() )
00190         icon = KMimeType::iconNameForUrl( KUrl(d->scriptfile) );
00191     setIconName( icon );
00192 
00193     const QString code = element.attribute("code");
00194     if( ! code.isNull() )
00195         setCode(code.toUtf8());
00196 
00197     for(QDomNode node = element.firstChild(); ! node.isNull(); node = node.nextSibling()) {
00198         QDomElement e = node.toElement();
00199         if( ! e.isNull() ) {
00200             if( e.tagName() == "property" ) {
00201                 const QString n = e.attribute("name", QString());
00202                 if( ! n.isNull() ) {
00203                     #ifdef KROSS_ACTION_DEBUG
00204                         krossdebug(QString("Action::readDomElement: Setting property name=%1 value=%2").arg(n).arg(e.text()));
00205                     #endif
00206                     setProperty(n.toLatin1().constData(), QVariant(e.text()));
00207                 }
00208             }
00209         }
00210     }
00211 }
00212 
00213 QDomElement Action::toDomElement() const
00214 {
00215     return toDomElement(QStringList());
00216 }
00217 
00218 QDomElement Action::toDomElement(const QStringList& searchPath) const
00219 {
00220     QDomDocument doc;
00221     QDomElement e = doc.createElement("script");
00222     e.setAttribute("name", objectName());
00223     if( d->version > 0 )
00224         e.setAttribute("version", QString(d->version));
00225     if( ! text().isNull() )
00226         e.setAttribute("text", text());
00227     if( ! description().isNull() )
00228         e.setAttribute("comment", description());
00229     if( ! iconName().isNull() )
00230         e.setAttribute("icon", iconName());
00231     if( ! isEnabled() )
00232         e.setAttribute("enabled", "false");
00233     if( ! interpreter().isNull() )
00234         e.setAttribute("interpreter", interpreter());
00235 
00236 
00237     QString fileName=file();
00238     if (!searchPath.isEmpty()) {
00239         //fileName=QDir(searchPath.first()).relativeFilePath(fileName); //prefer absname if it is short?
00240         foreach(const QString& packagepath, searchPath) {
00241             QString nfn=QDir(packagepath).relativeFilePath(file());
00242             if (nfn.length()<fileName.length())
00243                 fileName=nfn;
00244         }
00245     }
00246 
00247     if( ! fileName.isNull() ) {
00248         e.setAttribute("file", fileName);
00249     }
00250     
00251     QList<QByteArray> props=dynamicPropertyNames();
00252     foreach(const QByteArray& prop, props) {
00253         QDomElement p = doc.createElement("property");
00254         p.setAttribute("name", QString::fromLatin1(prop));
00255         p.appendChild(doc.createTextNode(property(prop.constData()).toString()));
00256         e.appendChild(p);
00257     }
00258     /*
00259     else if( ! code().isNull() ) {
00260         e.setAttribute("code", code());
00261     }
00262     */
00263 
00264     return e;
00265 }
00266 
00267 Kross::Script* Action::script() const
00268 {
00269     return d->script;
00270 }
00271 
00272 QString Action::name() const
00273 {
00274     return objectName();
00275 }
00276 
00277 int Action::version() const
00278 {
00279     return d->version;
00280 }
00281 
00282 QString Action::description() const
00283 {
00284     return d->description;
00285 }
00286 
00287 void Action::setDescription(const QString& description)
00288 {
00289     d->description = description;
00290     emit dataChanged(this);
00291     emit updated();
00292 }
00293 
00294 QString Action::iconName() const
00295 {
00296     return d->iconname;
00297 }
00298 
00299 void Action::setIconName(const QString& iconname)
00300 {
00301     setIcon( KIcon(iconname) );
00302     d->iconname = iconname;
00303     emit dataChanged(this);
00304     emit updated();
00305 }
00306 
00307 bool Action::isEnabled() const
00308 {
00309     return QAction::isEnabled();
00310 }
00311 
00312 void Action::setEnabled(bool enabled)
00313 {
00314     QAction::setEnabled(enabled);
00315     emit dataChanged(this);
00316     emit updated();
00317 }
00318 
00319 QByteArray Action::code() const
00320 {
00321     return d->code;
00322 }
00323 
00324 void Action::setCode(const QByteArray& code)
00325 {
00326     if( d->code != code ) {
00327         finalize();
00328         d->code = code;
00329         emit dataChanged(this);
00330         emit updated();
00331     }
00332 }
00333 
00334 QString Action::interpreter() const
00335 {
00336     return d->interpretername;
00337 }
00338 
00339 void Action::setInterpreter(const QString& interpretername)
00340 {
00341     if( d->interpretername != interpretername ) {
00342         finalize();
00343         d->interpretername = interpretername;
00344         setEnabled( Manager::self().interpreters().contains(interpretername) );
00345         if (!isEnabled())
00346             krosswarning("Action::setInterpreter: interpreter not found: "+interpretername);
00347         emit dataChanged(this);
00348         emit updated();
00349     }
00350 }
00351 
00352 QString Action::file() const
00353 {
00354     return d->scriptfile;
00355 }
00356 
00357 bool Action::setFile(const QString& scriptfile)
00358 {
00359     if( d->scriptfile != scriptfile ) {
00360         finalize();
00361         if ( scriptfile.isNull() ) {
00362             if( ! d->scriptfile.isNull() )
00363                 d->interpretername.clear();
00364             d->scriptfile.clear();
00365             d->searchpath.clear();
00366         }
00367         else {
00368             d->scriptfile = scriptfile;
00369             d->interpretername = Manager::self().interpreternameForFile(scriptfile);
00370             if( d->interpretername.isNull() )
00371                 return false;
00372         }
00373     }
00374     return true;
00375 }
00376 
00377 QString Action::currentPath() const
00378 {
00379     return file().isEmpty()?QString():QFileInfo(file()).absolutePath();//obey Qt docs and don't cheat
00380 }
00381 
00382 QVariantMap Action::options() const
00383 {
00384     return d->options;
00385 }
00386 
00387 void Action::addQObject(QObject* obj, const QString &name)
00388 {
00389     this->addObject(obj, name);
00390 }
00391 
00392 QObject* Action::qobject(const QString &name) const
00393 {
00394     return this->object(name);
00395 }
00396 
00397 QStringList Action::qobjectNames() const
00398 {
00399     return this->objects().keys();
00400 }
00401 
00402 QVariant Action::option(const QString& name, const QVariant& defaultvalue)
00403 {
00404     if(d->options.contains(name))
00405         return d->options[name];
00406     InterpreterInfo* info = Manager::self().interpreterInfo( d->interpretername );
00407     return info ? info->optionValue(name, defaultvalue) : defaultvalue;
00408 }
00409 
00410 bool Action::setOption(const QString& name, const QVariant& value)
00411 {
00412     InterpreterInfo* info = Manager::self().interpreterInfo( d->interpretername );
00413     if(info) {
00414         if(info->hasOption(name)) {
00415             d->options.insert(name, value);
00416             return true;
00417         } else krosswarning( QString("Kross::Action::setOption(%1, %2): No such option").arg(name).arg(value.toString()) );
00418     } else krosswarning( QString("Kross::Action::setOption(%1, %2): No such interpreterinfo").arg(name).arg(value.toString()) );
00419     return false;
00420 }
00421 
00422 QStringList Action::functionNames()
00423 {
00424     if(! d->script) {
00425         if(! initialize())
00426             return QStringList();
00427     }
00428     return d->script->functionNames();
00429 }
00430 
00431 QVariant Action::callFunction(const QString& name, const QVariantList& args)
00432 {
00433     if(! d->script) {
00434         if(! initialize())
00435             return QVariant();
00436     }
00437     return d->script->callFunction(name, args);
00438 }
00439 
00440 QVariant Action::evaluate(const QByteArray& code)
00441 {
00442     if(! d->script) {
00443         if(! initialize())
00444             return QVariant();
00445     }
00446     return d->script->evaluate(code);
00447 }
00448 
00449 bool Action::initialize()
00450 {
00451     finalize();
00452 
00453     if( ! d->scriptfile.isNull() ) {
00454         QFile f( d->scriptfile );
00455         if( ! f.exists() ) {
00456             setError(i18n("Scriptfile \"%1\" does not exist.", d->scriptfile));
00457             return false;
00458         }
00459         if( d->interpretername.isNull() ) {
00460             setError(i18n("Failed to determine interpreter for scriptfile \"%1\"", d->scriptfile));
00461             return false;
00462         }
00463         if( ! f.open(QIODevice::ReadOnly) ) {
00464             setError(i18n("Failed to open scriptfile \"%1\"", d->scriptfile));
00465             return false;
00466         }
00467         d->code = f.readAll();
00468         f.close();
00469     }
00470 
00471     Interpreter* interpreter = Manager::self().interpreter(d->interpretername);
00472     if( ! interpreter ) {
00473         InterpreterInfo* info = Manager::self().interpreterInfo(d->interpretername);
00474         if( info )
00475             setError(i18n("Failed to load interpreter \"%1\"", d->interpretername));
00476         else
00477             setError(i18n("No such interpreter \"%1\"", d->interpretername));
00478         return false;
00479     }
00480 
00481     d->script = interpreter->createScript(this);
00482     if( ! d->script ) {
00483         setError(i18n("Failed to create script for interpreter \"%1\"", d->interpretername));
00484         return false;
00485     }
00486 
00487     if( d->script->hadError() ) {
00488         setError(d->script);
00489         finalize();
00490         return false;
00491     }
00492 
00493     clearError(); // clear old exception
00494     return true;
00495 }
00496 
00497 void Action::finalize()
00498 {
00499     if( d->script )
00500         emit finalized(this);
00501     delete d->script;
00502     d->script = 0;
00503 }
00504 
00505 bool Action::isFinalized() const
00506 {
00507     return d->script == 0;
00508 }
00509 
00510 void Action::slotTriggered()
00511 {
00512     #ifdef KROSS_ACTION_DEBUG
00513         krossdebug( QString("Action::slotTriggered() name=%1").arg(objectName()) );
00514     #endif
00515 
00516     emit started(this);
00517 
00518     if( ! d->script ) {
00519         if( ! initialize() )
00520             Q_ASSERT( hadError() );
00521     }
00522 
00523     if( hadError() ) {
00524         #ifdef KROSS_ACTION_DEBUG
00525             krossdebug( QString("Action::slotTriggered() on init, errorMessage=%2").arg(errorMessage()) );
00526         #endif
00527     }
00528     else {
00529         d->script->execute();
00530         if( d->script->hadError() ) {
00531             #ifdef KROSS_ACTION_DEBUG
00532                 krossdebug( QString("Action::slotTriggered() after exec, errorMessage=%2").arg(errorMessage()) );
00533             #endif
00534             setError(d->script);
00535             //emit finished(this);
00536             finalize();
00537             //return;
00538         }
00539     }
00540 
00541     emit finished(this);
00542 }
00543 
00544 // --------
00545 
00546 // interface files
00547 WrapperInterface::~WrapperInterface()
00548 {
00549 }
00550 
00551 #include "action.moc"

Kross

Skip menu "Kross"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.6.1
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal