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