File indexing completed on 2024-03-24 15:37:23

0001 /***************************************************************************
0002  * action.h
0003  * This file is part of the KDE project
0004  * copyright (C)2004-2007 by Sebastian Sauer (mail@dipe.org)
0005  *
0006  * This program is free software; you can redistribute it and/or
0007  * modify it under the terms of the GNU Library General Public
0008  * License as published by the Free Software Foundation; either
0009  * version 2 of the License, or (at your option) any later version.
0010  * This program is distributed in the hope that it will be useful,
0011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013  * Library General Public License for more details.
0014  * You should have received a copy of the GNU Library General Public License
0015  * along with this program; see the file COPYING.  If not, write to
0016  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0017  * Boston, MA 02110-1301, USA.
0018  ***************************************************************************/
0019 
0020 #ifndef KROSS_ACTION_H
0021 #define KROSS_ACTION_H
0022 
0023 #include <QVariant>
0024 #include <QObject>
0025 #include <QDir>
0026 #include <QUrl>
0027 #include <QAction>
0028 #include <QDomAttr>
0029 #include <QScriptable>
0030 
0031 #include "errorinterface.h"
0032 #include "childreninterface.h"
0033 
0034 namespace Kross
0035 {
0036 
0037 class Script;
0038 
0039 /**
0040  * The Action class is an abstract container to deal with scripts
0041  * like a single standalone script file. Each action holds a reference
0042  * to the matching @a Kross::Interpreter created @a Kross::Script
0043  * instance.
0044  *
0045  * The \a Manager takes care of handling the \a Action instances
0046  * application by providing access to \a ActionCollection containers
0047  * for those \a Action instances.
0048  *
0049  * Once you've such a Action instance you're able to perform actions
0050  * with it like executing scripting code.
0051  *
0052  * Following sample shows "Hello World." executed with the python
0053  * interpreter:
0054  * \code
0055  * # Create a new Kross::Action instance.
0056  * Kross::Action* action = new Kross::Action(0,"MyFirstScript");
0057  * # Set the interpreter we like to use. This could be e.g. "python" or "ruby".
0058  * action->setInterpreter("python");
0059  * # Set the scripting code.
0060  * action->setCode("print \"Hello World.\"");
0061  * # Execute the scripting code.
0062  * action->trigger();
0063  * \endcode
0064  *
0065  * Following sample demonstrates how to execute an external python script
0066  * file. The script file itself is named "mytest.py" and contains:
0067  * \code
0068  * # this function got called from within C++
0069  * def myfunction(args):
0070  *     print "Arguments are: %s" % args
0071  * # Import the published QObject's
0072  * import MyFirstQObject, MySecondQObject
0073  * # Call a slot MyFirstQObject provides.
0074  * MyFirstQObject.someSlot("Some string")
0075  * # Set a property MySecondQObject provides.
0076  * MySecondQObject.someProperty = "Other string"
0077  * \endcode
0078  * Then you are able to load the script file, publish QObject instances
0079  * and let the script do whatever it likes to do:
0080  * \code
0081  * # Publish a QObject instance for all Kross::Action instances.
0082  * Kross::Manager::self().addObject(myqobject1, "MyFirstQObject")
0083  * # Create a new Kross::Action instance.
0084  * Kross::Action* action = new Kross::Action(0,"MySecondScript");
0085  * # Publish a QObject instance only for the Kross::Action instance.
0086  * action->addObject(myqobject2, "MySecondQObject");
0087  * # Set the script file we like to execute.
0088  * action->setFile("/home/myuser/mytest.py");
0089  * # Execute the script file.
0090  * action->trigger();
0091  * # Call the "myfunction" defined in the "mytest.py" python script.
0092  * QVariant result = action->callFunction("myfunction", QVariantList()<<"Arg");
0093  * \endcode
0094  */
0095 class KROSSCORE_EXPORT Action
0096     : public QAction
0097     , public QScriptable
0098     , public ChildrenInterface
0099     , public ErrorInterface
0100 {
0101     Q_OBJECT
0102 
0103 public:
0104 
0105     /**
0106       * Constructor.
0107       *
0108       * \param parent The parent QObject this \a Action is a child of.
0109       * \param name The unique name this Action has. It's used
0110       * e.g. at the \a Manager to identify the Action. The
0111       * name is accessible via \a QObject::objectName .
0112       * \deprecated since 4.3: pass search path to fromDomElement() and toDomElement()
0113       */
0114     Action(QObject *parent, const QString &name, const QDir &packagepath = QDir()); //BIC may be removed in favour of the next c'tor
0115 
0116     /**
0117      * Constructor.
0118      *
0119      * \param parent The parent QObject this \a Action is a child of.
0120      * \param url The URL should point to a valid scripting file.
0121      * This \a Action will be filled with the content of the
0122      * file (e.g. the file is read and \a code should return
0123      * its content and it's also tried to determine the
0124      * \a interpreter ). Remember to use QUrl c'tor explicitly.
0125      * The name will be set to url.path()
0126      */
0127     Action(QObject *parent, const QUrl &url);
0128 
0129     /**
0130      * Destructor.
0131      */
0132     ~Action() override;
0133 
0134     /**
0135      * Method to read settings from the QDomElement \p element that
0136      * contains details about e.g. the displayed text, the file to
0137      * execute or the used interpreter.
0138      * \todo BIC merge
0139      */
0140     void fromDomElement(const QDomElement &element);
0141 
0142     /**
0143      * Method to read settings from the QDomElement \p element that
0144      * contains details about e.g. the displayed text, the file to
0145      * execute or the used interpreter.
0146      *
0147      * \param searchPath List of directories where to search the script if its path is relative
0148      * First item is given the highest priority.
0149      */
0150     void fromDomElement(const QDomElement &element, const QStringList &searchPath/* = QStringList()*/);
0151 
0152     /**
0153      * \return a QDomElement that contains the settings like e.g. the
0154      * displayed text, the file to execute or the used interpreter
0155      * of this \a Action instance.
0156      */
0157     QDomElement toDomElement() const;
0158 
0159     /**
0160      * \return a QDomElement that contains the settings like e.g. the
0161      * displayed text, the file to execute or the used interpreter
0162      * of this \a Action instance.
0163      * \param searchPath if given, find the closest directory containing the scriptfile
0164      *  and write relative filepath
0165      */
0166     QDomElement toDomElement(const QStringList &searchPath/* = QStringList()*/) const;
0167 
0168     /**
0169      * Initialize the \a Script instance.
0170      *
0171      * Normally there is no need to call this function directly because
0172      * if will be called internally if needed (e.g. on \a execute ).
0173      *
0174      * \return true if the initialization was successful else
0175      * false is returned.
0176      */
0177     bool initialize();
0178 
0179     /**
0180      * Finalize the \a Script instance and frees any cached or still
0181      * running executions. Normally there is no need to call this
0182      * function directly because the \a Action will take care
0183      * of calling it if needed.
0184      */
0185     void finalize();
0186 
0187     /**
0188      * \return true if the action is finalized, which means the
0189      * action is currently not running.
0190      */
0191     bool isFinalized() const;
0192 
0193     /**
0194      * \return the \a Kross::Script implementation used by the scripting
0195      * backend. This returns NULL until the action got triggered or if
0196      * there was an error before that.
0197      *
0198      * Normally it shouldn't be necessary to deal with the scripting backend
0199      * depending instance of a \a Kross::Script implementation since this
0200      * \a Action class already decorates all the things needed. It
0201      * may however be useful to provide additional interpreter dependent
0202      * functionality.
0203      */
0204     Script *script() const;
0205 
0206 public Q_SLOTS:
0207 
0208     /**
0209      * \return the objectName for this Action.
0210      */
0211     QString name() const;
0212 
0213     /**
0214      * \return the version number this Action has.
0215      * Per default 0 is returned.
0216      */
0217     int version() const;
0218 
0219     /**
0220      * \return the optional description for this Action.
0221      */
0222     QString description() const;
0223 
0224     /**
0225      * Set the optional description for this Action.
0226      */
0227     void setDescription(const QString &description);
0228 
0229     /**
0230      * Return the name of the icon.
0231      */
0232     QString iconName() const;
0233 
0234     /**
0235      * Set the name of the icon to \p iconname .
0236      */
0237     void setIconName(const QString &iconname);
0238 
0239     /**
0240      * Return true if this Action is enabled else false is returned.
0241      */
0242     bool isEnabled() const;
0243 
0244     /**
0245      * Set the enable state of this Action to \p enabled .
0246      */
0247     void setEnabled(bool enabled);
0248 
0249     /**
0250      * \return the script file that should be executed.
0251      */
0252     QString file() const;
0253 
0254     /**
0255      * Set the script file that should be executed.
0256      */
0257     bool setFile(const QString &scriptfile);
0258 
0259     /**
0260      * \return the scriptcode this Action holds.
0261      */
0262     QByteArray code() const;
0263 
0264     /**
0265      * Set the scriptcode \p code this Action should execute.
0266      */
0267     void setCode(const QByteArray &code);
0268 
0269     /**
0270      * \return the name of the interpreter. Could be for
0271      * example "python" or "ruby".
0272      */
0273     QString interpreter() const;
0274 
0275     /**
0276      * Set the name of the interpreter (javascript, python or ruby).
0277      */
0278     void setInterpreter(const QString &interpretername);
0279 
0280     /**
0281      * \return the current path the script is running in or
0282      * an empty string if there is no current path defined.
0283      */
0284     QString currentPath() const;
0285 
0286     /**
0287      * Add a QObject instance to the action. This instance will
0288      * be published to scripts.
0289      */
0290     void addQObject(QObject *obj, const QString &name = QString());
0291 
0292     /**
0293      * \return the QObject with the object name \p name .
0294      */
0295     QObject *qobject(const QString &name) const;
0296 
0297     /**
0298      * \return a list of QObject object names.
0299      */
0300     QStringList qobjectNames() const;
0301 
0302     /**
0303      * \return a map of options this \a Action defines.
0304      * The options are returned call-by-ref, so you are able to
0305      * manipulate them.
0306      */
0307     QVariantMap options() const;
0308 
0309     /**
0310      * \return the value of the option defined with \p name .
0311      * If there doesn't exist an option with such a name,
0312      * the \p defaultvalue is returned.
0313      */
0314     QVariant option(const QString &name, const QVariant &defaultvalue = QVariant());
0315 
0316     /**
0317      * Set the \a Interpreter::Option value.
0318      */
0319     bool setOption(const QString &name, const QVariant &value);
0320 
0321     /**
0322      * \return the list of functionnames.
0323      */
0324     QStringList functionNames();
0325 
0326     /**
0327      * Call a function in the script.
0328      *
0329      * \param name The name of the function which should be called.
0330      * \param args The optional list of arguments.
0331      */
0332     QVariant callFunction(const QString &name, const QVariantList &args = QVariantList());
0333 
0334     /**
0335      * Evaluate some scripting code.
0336      *
0337      * Example how this can be used:
0338      * \code
0339      * Kross::Action* a = new Kross::Action(0, "MyScript");
0340      * a->setInterpreter("python");
0341      * a->setCode("def myFunc(x): return x");
0342      * a->trigger();
0343      * int three = a->evaluate("1+2").toInt(); // returns 3
0344      * int nine = a->evaluate("myFunc(9)").toInt(); // returns 9
0345      * \endcode
0346      *
0347      * \param code The scripting code to evaluate.
0348      * \return The return value of the evaluation.
0349      */
0350     QVariant evaluate(const QByteArray &code);
0351 
0352 Q_SIGNALS:
0353 
0354     /**
0355      * This signal is emitted if the content of the Action
0356      * was changed. The \a ActionCollection instances this Action
0357      * is a child of are connected with this signal to fire up
0358      * their own updated signal if an Action of them was updated.
0359      */
0360     void updated();
0361 
0362     /// This signal is emitted when the data of the Action is changed
0363     void dataChanged(Action *);
0364 
0365     /**
0366      * This signal is emitted before the script got executed.
0367      */
0368     void started(Kross::Action *);
0369 
0370     /**
0371      * This signal is emitted after the script got executed.
0372      */
0373     void finished(Kross::Action *);
0374 
0375     /**
0376      * This signal is emitted once a script finalized.
0377      */
0378     void finalized(Kross::Action *);
0379 
0380 private Q_SLOTS:
0381 
0382     /**
0383      * This private slot is connected with the \a QAction::triggered
0384      * signal. To execute the script just emit that signal and this
0385      * slot tries to execute the script.
0386      */
0387     void slotTriggered();
0388 
0389 private:
0390     /// \internal d-pointer class.
0391     class Private;
0392     /// \internal d-pointer instance.
0393     Private *const d;
0394 };
0395 
0396 }
0397 
0398 #endif
0399