/*************************************************************************** * action.h * This file is part of the KDE project * copyright (C)2004-2007 by Sebastian Sauer (mail@dipe.org) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * You should have received a copy of the GNU Library General Public License * along with this program; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. ***************************************************************************/ #ifndef KROSS_ACTION_H #define KROSS_ACTION_H #include #include #include #include #include #include #include #include "errorinterface.h" #include "childreninterface.h" namespace Kross { class Script; /** * The Action class is an abstract container to deal with scripts * like a single standalone script file. Each action holds a reference * to the matching @a Kross::Interpreter created @a Kross::Script * instance. * * The \a Manager takes care of handling the \a Action instances * application by providing access to \a ActionCollection containers * for those \a Action instances. * * Once you've such a Action instance you're able to perform actions * with it like executing scripting code. * * Following sample shows "Hello World." executed with the python * interpreter: * \code * # Create a new Kross::Action instance. * Kross::Action* action = new Kross::Action(0,"MyFirstScript"); * # Set the interpreter we like to use. This could be e.g. "python", "ruby" or "kjs". * action->setInterpreter("python"); * # Set the scripting code. * action->setCode("print \"Hello World.\""); * # Execute the scripting code. * action->trigger(); * \endcode * * Following sample demonstrates how to execute an external python script * file. The script file itself is named "mytest.py" and contains: * \code * # this function got called from within C++ * def myfunction(args): * print "Arguments are: %s" % args * # Import the published QObject's * import MyFirstQObject, MySecondQObject * # Call a slot MyFirstQObject provides. * MyFirstQObject.someSlot("Some string") * # Set a property MySecondQObject provides. * MySecondQObject.someProperty = "Other string" * \endcode * Then you are able to load the script file, publish QObject instances * and let the script do whatever it likes to do: * \code * # Publish a QObject instance for all Kross::Action instances. * Kross::Manager::self().addObject(myqobject1, "MyFirstQObject") * # Create a new Kross::Action instance. * Kross::Action* action = new Kross::Action(0,"MySecondScript"); * # Publish a QObject instance only for the Kross::Action instance. * action->addObject(myqobject2, "MySecondQObject"); * # Set the script file we like to execute. * action->setFile("/home/myuser/mytest.py"); * # Execute the script file. * action->trigger(); * # Call the "myfunction" defined in the "mytest.py" python script. * QVariant result = action->callFunction("myfunction", QVariantList()<<"Arg"); * \endcode */ class KROSSCORE_EXPORT Action : public QAction , public QScriptable , public ChildrenInterface , public ErrorInterface { Q_OBJECT public: /** * Constructor. * * \param parent The parent QObject this \a Action is a child of. * \param name The unique name this Action has. It's used * e.g. at the \a Manager to identify the Action. The * name is accessible via \a QObject::objectName . * \deprecated since 4.3: pass search path to fromDomElement() and toDomElement() */ Action(QObject* parent, const QString& name, const QDir& packagepath = QDir()); //BIC may be removed in favour of the next c'tor /** * Constructor. * * \param parent The parent QObject this \a Action is a child of. * \param url The URL should point to a valid scripting file. * This \a Action will be filled with the content of the * file (e.g. the file is read and \a code should return * its content and it's also tried to determine the * \a interpreter ). Remember to use QUrl c'tor explicitly. * The name will be set to url.path() */ Action(QObject* parent, const QUrl& url); /** * Destructor. */ virtual ~Action(); /** * Method to read settings from the QDomElement \p element that * contains details about e.g. the displayed text, the file to * execute or the used interpreter. * \todo BIC merge */ void fromDomElement(const QDomElement& element); /** * Method to read settings from the QDomElement \p element that * contains details about e.g. the displayed text, the file to * execute or the used interpreter. * * \param searchPath List of directories where to search the script if its path is relative * First item is given the highest priority. */ void fromDomElement(const QDomElement& element, const QStringList& searchPath/* = QStringList()*/); /** * \return a QDomElement that contains the settings like e.g. the * displayed text, the file to execute or the used interpreter * of this \a Action instance. */ QDomElement toDomElement() const; /** * \return a QDomElement that contains the settings like e.g. the * displayed text, the file to execute or the used interpreter * of this \a Action instance. * \param searchPath if given, find the closest directory containing the scriptfile * and write relative filepath */ QDomElement toDomElement(const QStringList& searchPath/* = QStringList()*/) const; /** * Initialize the \a Script instance. * * Normally there is no need to call this function directly because * if will be called internally if needed (e.g. on \a execute ). * * \return true if the initialization was successful else * false is returned. */ bool initialize(); /** * Finalize the \a Script instance and frees any cached or still * running executions. Normally there is no need to call this * function directly because the \a Action will take care * of calling it if needed. */ void finalize(); /** * \return true if the action is finalized, which means the * action is currently not running. */ bool isFinalized() const; /** * \return the \a Kross::Script implementation used by the scripting * backend. This returns NULL until the action got triggered or if * there was an error before that. * * Normaly it shouldn't be necessary to deal with the scripting backend * depending instance of a \a Kross::Script implementation since this * \a Action class already decorates all the things needed. It * may however be useful to provide additional interpreter dependent * functionality. */ Script* script() const; public Q_SLOTS: /** * \return the objectName for this Action. */ QString name() const; /** * \return the version number this Action has. * Per default 0 is returned. */ int version() const; /** * \return the optional description for this Action. */ QString description() const; /** * Set the optional description for this Action. */ void setDescription(const QString& description); /** * Return the name of the icon. */ QString iconName() const; /** * Set the name of the icon to \p iconname . */ void setIconName(const QString& iconname); /** * Return true if this Action is enabled else false is returned. */ bool isEnabled() const; /** * Set the enable state of this Action to \p enabled . */ void setEnabled(bool enabled); /** * \return the script file that should be executed. */ QString file() const; /** * Set the script file that should be executed. */ bool setFile(const QString& scriptfile); /** * \return the scriptcode this Action holds. */ QByteArray code() const; /** * Set the scriptcode \p code this Action should execute. */ void setCode(const QByteArray& code); /** * \return the name of the interpreter. Could be for * example "python" or "ruby". */ QString interpreter() const; /** * Set the name of the interpreter (javascript, python or ruby). */ void setInterpreter(const QString& interpretername); /** * \return the current path the script is running in or * an empty string if there is no current path defined. */ QString currentPath() const; /** * Add a QObject instance to the action. This instance will * be published to scripts. */ void addQObject(QObject* obj, const QString &name = QString()); /** * \return the QObject with the object name \p name . */ QObject* qobject(const QString &name) const; /** * \return a list of QObject object names. */ QStringList qobjectNames() const; /** * \return a map of options this \a Action defines. * The options are returned call-by-ref, so you are able to * manipulate them. */ QVariantMap options() const; /** * \return the value of the option defined with \p name . * If there doesn't exist an option with such a name, * the \p defaultvalue is returned. */ QVariant option(const QString& name, const QVariant& defaultvalue = QVariant()); /** * Set the \a Interpreter::Option value. */ bool setOption(const QString& name, const QVariant& value); /** * \return the list of functionnames. */ QStringList functionNames(); /** * Call a function in the script. * * \param name The name of the function which should be called. * \param args The optional list of arguments. */ QVariant callFunction(const QString& name, const QVariantList& args = QVariantList()); /** * Evaluate some scripting code. * * Example how this can be used: * \code * Kross::Action* a = new Kross::Action(0, "MyScript"); * a->setInterpreter("python"); * a->setCode("def myFunc(x): return x"); * a->trigger(); * int three = a->evaluate("1+2").toInt(); // returns 3 * int nine = a->evaluate("myFunc(9)").toInt(); // returns 9 * \endcode * * \param code The scripting code to evaluate. * \return The return value of the evaluation. */ QVariant evaluate(const QByteArray& code); Q_SIGNALS: /** * This signal is emitted if the content of the Action * was changed. The \a ActionCollection instances this Action * is a child of are connected with this signal to fire up * their own updated signal if an Action of them was updated. */ void updated(); /// This signal is emitted when the data of the Action is changed void dataChanged(Action*); /** * This signal is emitted before the script got executed. */ void started(Kross::Action*); /** * This signal is emitted after the script got executed. */ void finished(Kross::Action*); /** * This signal is emitted once a script finalized. */ void finalized(Kross::Action*); private Q_SLOTS: /** * This private slot is connected with the \a QAction::triggered * signal. To execute the script just emit that signal and this * slot tries to execute the script. */ void slotTriggered(); private: /// \internal d-pointer class. class Private; /// \internal d-pointer instance. Private* const d; }; } Q_DECLARE_METATYPE(Kross::Action*) #endif