diff options
author | Casper van Donderen <casper.vandonderen@nokia.com> | 2012-06-05 12:51:07 +0200 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-06-05 15:18:03 +0200 |
commit | 4629dc71525a638c0bae89ad67990a1ff14ea9c4 (patch) | |
tree | ff81b70586896e7b2f1c718e3b5385fae4483cc3 /src | |
parent | f6fdd296d47e1ce44c07aab81098c20a5260f7fd (diff) | |
download | qtscript-4629dc71525a638c0bae89ad67990a1ff14ea9c4.tar.gz |
Doc: Modularize QtScript documentation.
Change-Id: I042d9bafe4f48a8cd23306f0864b6872776d0153
Reviewed-by: Kent Hansen <kent.hansen@nokia.com>
Diffstat (limited to 'src')
32 files changed, 5041 insertions, 48 deletions
diff --git a/src/script/api/qscriptable.cpp b/src/script/api/qscriptable.cpp index af25685..6348fb7 100644 --- a/src/script/api/qscriptable.cpp +++ b/src/script/api/qscriptable.cpp @@ -65,7 +65,7 @@ QT_BEGIN_NAMESPACE The following is what subclassing QScriptable typically looks like: - \snippet doc/src/snippets/code/src_script_qscriptable.cpp 0 + \snippet code/src_script_qscriptable.cpp 0 The only difference from regular QObject subclassing is that you also inherit from QScriptable. @@ -73,7 +73,7 @@ QT_BEGIN_NAMESPACE In the implementation of your slots, you can then use the functions inherited from QScriptable: - \snippet doc/src/snippets/code/src_script_qscriptable.cpp 1 + \snippet code/src_script_qscriptable.cpp 1 \sa {Default Prototypes Example}, QScriptEngine::newFunction() */ diff --git a/src/script/api/qscriptclass.cpp b/src/script/api/qscriptclass.cpp index 68de186..6a1cc2a 100644 --- a/src/script/api/qscriptclass.cpp +++ b/src/script/api/qscriptclass.cpp @@ -357,7 +357,7 @@ bool QScriptClass::supportsExtension(Extension extension) const result of the function call. In the following example the sum of the arguments to the script function are added up and returned: - \snippet doc/src/snippets/code/src_script_qscriptclass.cpp 0 + \snippet code/src_script_qscriptclass.cpp 0 If you implement the HasInstance extension, Qt Script will call this function as part of evaluating the \c{instanceof} operator, as diff --git a/src/script/api/qscriptcontext.cpp b/src/script/api/qscriptcontext.cpp index bd9b696..8996654 100644 --- a/src/script/api/qscriptcontext.cpp +++ b/src/script/api/qscriptcontext.cpp @@ -56,7 +56,7 @@ QT_BEGIN_NAMESPACE QScriptEngine::newFunction()) that will be called from script code. For example, when the script code - \snippet doc/src/snippets/code/src_script_qscriptcontext.cpp 0 + \snippet code/src_script_qscriptcontext.cpp 0 is evaluated, a QScriptContext will be created, and the context will carry the arguments as QScriptValues; in this particular case, the @@ -76,7 +76,7 @@ QT_BEGIN_NAMESPACE native "instance method", you typically fetch the thisObject() and access one or more of its properties: - \snippet doc/src/snippets/code/src_script_qscriptcontext.cpp 1 + \snippet code/src_script_qscriptcontext.cpp 1 Use isCalledAsConstructor() to determine if the function was called as a constructor (e.g. \c{"new foo()"} (as constructor) or just @@ -100,7 +100,7 @@ QT_BEGIN_NAMESPACE evaluated in the context of the parent context, e.g. to implement an include() function: - \snippet doc/src/snippets/code/src_script_qscriptcontext.cpp 2 + \snippet code/src_script_qscriptcontext.cpp 2 Use backtrace() to get a human-readable backtrace associated with this context. This can be useful for debugging purposes when diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp index 8002454..8b3b844 100644 --- a/src/script/api/qscriptengine.cpp +++ b/src/script/api/qscriptengine.cpp @@ -106,7 +106,7 @@ QT_BEGIN_NAMESPACE Use evaluate() to evaluate script code; this is the C++ equivalent of the built-in script function \c{eval()}. - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 0 + \snippet code/src_script_qscriptengine.cpp 0 evaluate() returns a QScriptValue that holds the result of the evaluation. The QScriptValue class provides functions for converting @@ -116,13 +116,13 @@ QT_BEGIN_NAMESPACE The following code snippet shows how a script function can be defined and then invoked from C++ using QScriptValue::call(): - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 1 + \snippet code/src_script_qscriptengine.cpp 1 As can be seen from the above snippets, a script is provided to the engine in the form of a string. One common way of loading scripts is by reading the contents of a file and passing it to evaluate(): - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 2 + \snippet code/src_script_qscriptengine.cpp 2 Here we pass the name of the file as the second argument to evaluate(). This does not affect evaluation in any way; the second @@ -139,7 +139,7 @@ QT_BEGIN_NAMESPACE want to configure a script engine by adding one or more properties to the Global Object: - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 3 + \snippet code/src_script_qscriptengine.cpp 3 Adding custom properties to the scripting environment is one of the standard means of providing a scripting API that is specific to your @@ -159,7 +159,7 @@ QT_BEGIN_NAMESPACE Calling clearExceptions() will cause any uncaught exceptions to be cleared. - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 4 + \snippet code/src_script_qscriptengine.cpp 4 The checkSyntax() function can be used to determine whether code can be usefully passed to evaluate(). @@ -182,7 +182,7 @@ QT_BEGIN_NAMESPACE properties of the proxy object. No binding code is needed because it is done dynamically using the Qt meta object system. - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 5 + \snippet code/src_script_qscriptengine.cpp 5 Use qScriptConnect() to connect a C++ signal to a script function; this is the Qt Script equivalent of QObject::connect(). When a @@ -243,17 +243,17 @@ QT_BEGIN_NAMESPACE argument to newFunction(). Here is an example of a function that returns the sum of its first two arguments: - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 6 + \snippet code/src_script_qscriptengine.cpp 6 To expose this function to script code, you can set it as a property of the Global Object: - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 7 + \snippet code/src_script_qscriptengine.cpp 7 Once this is done, script code can call your function in the exact same manner as a "normal" script function: - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 8 + \snippet code/src_script_qscriptengine.cpp 8 \section1 Long-running Scripts @@ -2078,12 +2078,12 @@ QScriptValue QScriptEngine::undefinedValue() wrapping a custom type, by having registered the defaultPrototype() of that type. Example: - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 9 + \snippet code/src_script_qscriptengine.cpp 9 To wrap a custom type and provide a constructor for it, you'd typically do something like this: - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 10 + \snippet code/src_script_qscriptengine.cpp 10 */ QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionSignature fun, const QScriptValue &prototype, @@ -2336,7 +2336,7 @@ QScriptValue QScriptEngine::newActivationObject() functions (analogous to how properties work in \l{Qt's Property System}). Example: - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 11 + \snippet code/src_script_qscriptengine.cpp 11 When the property \c{foo} of the script object is subsequently accessed in script code, \c{getSetFoo()} will be invoked to handle @@ -2351,7 +2351,7 @@ QScriptValue QScriptEngine::newActivationObject() (QScriptValue::PropertyGetter or QScriptValue::PropertySetter) when setting the property, e.g.: - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 12 + \snippet code/src_script_qscriptengine.cpp 12 \sa QScriptValue::call() */ @@ -2449,7 +2449,7 @@ QScriptValue QScriptEngine::newDate(const QDateTime &value) Example: - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 27 + \snippet code/src_script_qscriptengine.cpp 27 \sa newQObject(), scriptValueFromQMetaObject() */ @@ -2471,7 +2471,7 @@ QScriptValue QScriptEngine::newQMetaObject( This function is used in combination with one of the Q_SCRIPT_DECLARE_QMETAOBJECT() macro. Example: - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 13 + \snippet code/src_script_qscriptengine.cpp 13 \sa QScriptEngine::newQMetaObject() */ @@ -2525,27 +2525,27 @@ QScriptValue QScriptEngine::newQMetaObject( different results.) Given the input - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 14 + \snippet code/src_script_qscriptengine.cpp 14 canEvaluate() will return true, since the program appears to be complete. Given the input - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 15 + \snippet code/src_script_qscriptengine.cpp 15 canEvaluate() will return false, since the if-statement is not complete, but is syntactically correct so far. Given the input - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 16 + \snippet code/src_script_qscriptengine.cpp 16 canEvaluate() will return true, but evaluate() will throw a SyntaxError given the same input. Given the input - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 17 + \snippet code/src_script_qscriptengine.cpp 17 canEvaluate() will return true, even though the code is clearly not syntactically valid QtScript code. evaluate() will throw a SyntaxError when this code is evaluated. Given the input - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 18 + \snippet code/src_script_qscriptengine.cpp 18 canEvaluate() will return true, but evaluate() will throw a ReferenceError if \c{foo} is not defined in the script environment. @@ -2695,7 +2695,7 @@ QScriptContext *QScriptEngine::currentContext() const \l{QScriptContext::activationObject()}{activationObject}() to initialize local variables that will be available to scripts. Example: - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 19 + \snippet code/src_script_qscriptengine.cpp 19 In the above example, the new variable "tmp" defined in the script will be local to the context; in other words, the script doesn't @@ -3945,28 +3945,28 @@ QStringList QScriptEngine::importedExtensions() const specify custom conversion of our type \c{MyStruct}. Here's the C++ type: - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 20 + \snippet code/src_script_qscriptengine.cpp 20 We must declare it so that the type will be known to QMetaType: - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 21 + \snippet code/src_script_qscriptengine.cpp 21 Next, the \c{MyStruct} conversion functions. We represent the \c{MyStruct} value as a script object and just copy the properties: - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 22 + \snippet code/src_script_qscriptengine.cpp 22 Now we can register \c{MyStruct} with the engine: - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 23 + \snippet code/src_script_qscriptengine.cpp 23 Working with \c{MyStruct} values is now easy: - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 24 + \snippet code/src_script_qscriptengine.cpp 24 If you want to be able to construct values of your custom type from script code, you have to register a constructor function for the type. For example: - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 25 + \snippet code/src_script_qscriptengine.cpp 25 \sa qScriptRegisterSequenceMetaType(), qRegisterMetaType() */ @@ -4006,7 +4006,7 @@ QStringList QScriptEngine::importedExtensions() const type, it must be declared using Q_DECLARE_METATYPE() as well. Example: - \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 26 + \snippet code/src_script_qscriptengine.cpp 26 \sa qScriptRegisterMetaType() */ diff --git a/src/script/api/qscriptengineagent.cpp b/src/script/api/qscriptengineagent.cpp index 7317431..48bb997 100644 --- a/src/script/api/qscriptengineagent.cpp +++ b/src/script/api/qscriptengineagent.cpp @@ -66,12 +66,12 @@ QT_BEGIN_NAMESPACE Evaluating the following script will result in scriptUnload() being called immediately after evaluation has completed: - \snippet doc/src/snippets/code/src_script_qscriptengineagent.cpp 0 + \snippet code/src_script_qscriptengineagent.cpp 0 Evaluating the following script will \b{not} result in a call to scriptUnload() when evaluation has completed: - \snippet doc/src/snippets/code/src_script_qscriptengineagent.cpp 1 + \snippet code/src_script_qscriptengineagent.cpp 1 The script isn't unloaded because it defines a function (\c{cube}) that remains in the script environment after evaluation has diff --git a/src/script/api/qscriptvalue.cpp b/src/script/api/qscriptvalue.cpp index 45e164c..9fb15c7 100644 --- a/src/script/api/qscriptvalue.cpp +++ b/src/script/api/qscriptvalue.cpp @@ -71,7 +71,7 @@ QScriptValues. Use setProperty() to set a property of an object, and call property() to retrieve the value of a property. - \snippet doc/src/snippets/code/src_script_qscriptvalue.cpp 0 + \snippet code/src_script_qscriptvalue.cpp 0 Each property can have a set of attributes; these are specified as the third (optional) argument to setProperty(). The attributes of a @@ -79,7 +79,7 @@ following code snippet creates a property that cannot be modified by script code: - \snippet doc/src/snippets/code/src_script_qscriptvalue.cpp 1 + \snippet code/src_script_qscriptvalue.cpp 1 If you want to iterate over the properties of a script object, use the QScriptValueIterator class. @@ -1551,7 +1551,7 @@ QScriptValue::PropertyFlags QScriptValue::propertyFlags(const QScriptString &nam QScriptEngine::hasUncaughtException() to determine if an exception occurred. - \snippet doc/src/snippets/code/src_script_qscriptvalue.cpp 2 + \snippet code/src_script_qscriptvalue.cpp 2 \sa construct() */ @@ -1629,7 +1629,7 @@ QScriptValue QScriptValue::call(const QScriptValue &thisObject, One common usage of this function is to forward native function calls to another function: - \snippet doc/src/snippets/code/src_script_qscriptvalue.cpp 3 + \snippet code/src_script_qscriptvalue.cpp 3 \sa construct(), QScriptContext::argumentsObject() */ diff --git a/src/script/api/qscriptvalueiterator.cpp b/src/script/api/qscriptvalueiterator.cpp index 3b1c176..ddaff90 100644 --- a/src/script/api/qscriptvalueiterator.cpp +++ b/src/script/api/qscriptvalueiterator.cpp @@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE beginning of the sequence of properties. Here's how to iterate over all the properties of a QScriptValue: - \snippet doc/src/snippets/code/src_script_qscriptvalueiterator.cpp 0 + \snippet code/src_script_qscriptvalueiterator.cpp 0 The next() advances the iterator. The name(), value() and flags() functions return the name, value and flags of the last item that was @@ -66,14 +66,14 @@ QT_BEGIN_NAMESPACE own properties; i.e. it does not follow the prototype chain. You can use a loop like this to follow the prototype chain: - \snippet doc/src/snippets/code/src_script_qscriptvalueiterator.cpp 1 + \snippet code/src_script_qscriptvalueiterator.cpp 1 Note that QScriptValueIterator will not automatically skip over properties that have the QScriptValue::SkipInEnumeration flag set; that flag only affects iteration in script code. If you want, you can skip over such properties with code like the following: - \snippet doc/src/snippets/code/src_script_qscriptvalueiterator.cpp 2 + \snippet code/src_script_qscriptvalueiterator.cpp 2 \sa QScriptValue::property() */ diff --git a/src/script/doc/images/qtscript-debugger.png b/src/script/doc/images/qtscript-debugger.png Binary files differnew file mode 100644 index 0000000..c417d0b --- /dev/null +++ b/src/script/doc/images/qtscript-debugger.png diff --git a/src/script/doc/qtscript.qdocconf b/src/script/doc/qtscript.qdocconf new file mode 100644 index 0000000..19c8bfd --- /dev/null +++ b/src/script/doc/qtscript.qdocconf @@ -0,0 +1,93 @@ +include(global/qt-html-templates-offline.qdocconf) +include(global/qt-cpp-ignore.qdocconf) + +project = QtScript +description = Qt Script Reference Documentation +url = http://qt-project.org/doc/qt-5.0/qtscript +version = 5.0.0 + +sourceencoding = UTF-8 +outputencoding = UTF-8 +naturallanguage = en_US +qhp.projects = QtScript + +qhp.QtScript.file = qtscript.qhp +qhp.QtScript.namespace = org.qt-project.qtscript.500 +qhp.QtScript.virtualFolder = qdoc +qhp.QtScript.indexTitle = Qt Script Reference Documentation +qhp.QtScript.indexRoot = + +qhp.QtScript.filterAttributes = qtscript 5.0.0 qtrefdoc +qhp.QtScript.customFilters.Qt.name = QtScript 5.0.0 +qhp.QtScript.customFilters.Qt.filterAttributes = qtscript 5.0.0 +qhp.QtScript.subprojects = classes overviews examples +qhp.QtScript.subprojects.classes.title = Classes +qhp.QtScript.subprojects.classes.indexTitle = Qt Script's Classes +qhp.QtScript.subprojects.classes.selectors = class fake:headerfile +qhp.QtScript.subprojects.classes.sortPages = true +qhp.QtScript.subprojects.overviews.title = Overviews +qhp.QtScript.subprojects.overviews.indexTitle = All Overviews and HOWTOs +qhp.QtScript.subprojects.overviews.selectors = fake:page,group,module +qhp.QtScript.subprojects.examples.title = Qt Script Examples +qhp.QtScript.subprojects.examples.indexTitle = Qt Script Examples +qhp.QtScript.subprojects.examples.selectors = fake:example + +dita.metadata.default.author = Qt Project +dita.metadata.default.permissions = all +dita.metadata.default.publisher = Qt Project +dita.metadata.default.copyryear = 2012 +dita.metadata.default.copyrholder = Nokia +dita.metadata.default.audience = programmer + +sources.fileextensions = "*.c++ *.cc *.cpp *.cxx *.mm *.qml *.qdoc" +headers.fileextensions = "*.ch *.h *.h++ *.hh *.hpp *.hxx" + +examples.fileextensions = "*.cpp *.h *.js *.xq *.svg *.xml *.ui *.qhp *.qhcp *.qml *.css" +examples.imageextensions = "*.png" + +outputdir = ../../../doc/qtscript +tagfile = ../../../doc/qtscript/qtscript.tags + +HTML.generatemacrefs = "true" +HTML.nobreadcrumbs = "true" + +HTML.templatedir = . + +HTML.stylesheets = global/style/offline.css + +HTML.headerstyles = \ + " <link rel=\"stylesheet\" type=\"text/css\" href=\"style/offline.css\" />\n" + +HTML.endheader = \ + "</head>\n" \ + +defines = Q_QDOC \ + QT_.*_SUPPORT \ + QT_.*_LIB \ + QT_COMPAT \ + QT_KEYPAD_NAVIGATION \ + QT_NO_EGL \ + Q_WS_.* \ + Q_OS_.* \ + Q_BYTE_ORDER \ + QT_DEPRECATED \ + QT_DEPRECATED_* \ + Q_NO_USING_KEYWORD \ + __cplusplus \ + Q_COMPILER_INITIALIZER_LISTS + +versionsym = QT_VERSION_STR + +codeindent = 1 + +depends += qtcore + +headerdirs += .. + +sourcedirs += .. + +exampledirs += ../../../examples \ + ../ \ + snippets + +imagedirs += images diff --git a/src/script/doc/snippets/code/doc_src_qtscript.cpp b/src/script/doc/snippets/code/doc_src_qtscript.cpp new file mode 100644 index 0000000..2ec5efc --- /dev/null +++ b/src/script/doc/snippets/code/doc_src_qtscript.cpp @@ -0,0 +1,568 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//! [0] +#include <QtScript> +//! [0] + +//! [13] +Q_PROPERTY(bool enabled READ enabled WRITE setEnabled) +//! [13] + +//! [18] +QScriptValue myQObjectConstructor(QScriptContext *context, QScriptEngine *engine) +{ + // let the engine manage the new object's lifetime. + return engine->newQObject(new MyQObject(), QScriptEngine::ScriptOwnership); +} +//! [18] + + +//! [19] +class MyObject : public QObject +{ + Q_OBJECT + +public: + MyObject( ... ); + + void aNonScriptableFunction(); + +public slots: // these functions (slots) will be available in QtScript + void calculate( ... ); + void setEnabled( bool enabled ); + bool isEnabled() const; + +private: + .... + +}; +//! [19] + + +//! [20] +class MyObject : public QObject +{ + Q_OBJECT + + public: + Q_INVOKABLE void thisMethodIsInvokableInQtScript(); + void thisMethodIsNotInvokableInQtScript(); + + ... +}; +//! [20] + + +//! [23] +class MyObject : public QObject +{ + Q_OBJECT + // define the enabled property + Q_PROPERTY( bool enabled WRITE setEnabled READ isEnabled ) + +public: + MyObject( ... ); + + void aNonScriptableFunction(); + +public slots: // these functions (slots) will be available in QtScript + void calculate( ... ); + void setEnabled( bool enabled ); + bool isEnabled() const; + +private: + .... + +}; +//! [23] + + +//! [24] +Q_PROPERTY(int nonScriptableProperty READ foo WRITE bar SCRIPTABLE false) +//! [24] + + +//! [25] +class MyObject : public QObject +{ + Q_OBJECT + // define the enabled property + Q_PROPERTY( bool enabled WRITE setEnabled READ isEnabled ) + +public: + MyObject( ... ); + + void aNonScriptableFunction(); + +public slots: // these functions (slots) will be available in QtScript + void calculate( ... ); + void setEnabled( bool enabled ); + bool isEnabled() const; + +signals: // the signals + void enabledChanged( bool newState ); + +private: + .... + +}; +//! [25] + + +//! [34] +QScriptValue Person_ctor(QScriptContext *context, QScriptEngine *engine) +{ + QString name = context->argument(0).toString(); + context->thisObject().setProperty("name", name); + return engine->undefinedValue(); +} +//! [34] + + +//! [35] +QScriptValue Person_prototype_toString(QScriptContext *context, QScriptEngine *engine) +{ + QString name = context->thisObject().property("name").toString(); + QString result = QString::fromLatin1("Person(name: %0)").arg(name); + return result; +} +//! [35] + + +//! [36] +QScriptEngine engine; +QScriptValue ctor = engine.newFunction(Person_ctor); +ctor.property("prototype").setProperty("toString", engine.newFunction(Person_prototype_toString)); +QScriptValue global = engine.globalObject(); +global.setProperty("Person", ctor); +//! [36] + + +//! [37] +QScriptValue Employee_ctor(QScriptContext *context, QScriptEngine *engine) +{ + QScriptValue super = context->callee().property("prototype").property("constructor"); + super.call(context->thisObject(), QScriptValueList() << context->argument(0)); + context->thisObject().setProperty("salary", context->argument(1)); + return engine->undefinedValue(); +} +//! [37] + + +//! [38] +QScriptValue empCtor = engine.newFunction(Employee_ctor); +empCtor.setProperty("prototype", global.property("Person").construct()); +global.setProperty("Employee", empCtor); +//! [38] + + +//! [39] +Q_DECLARE_METATYPE(QPointF) +Q_DECLARE_METATYPE(QPointF*) + +QScriptValue QPointF_prototype_x(QScriptContext *context, QScriptEngine *engine) +{ + // Since the point is not to be modified, it's OK to cast to a value here + QPointF point = qscriptvalue_cast<QPointF>(context->thisObject()); + return point.x(); +} + +QScriptValue QPointF_prototype_setX(QScriptContext *context, QScriptEngine *engine) +{ + // Cast to a pointer to be able to modify the underlying C++ value + QPointF *point = qscriptvalue_cast<QPointF*>(context->thisObject()); + if (!point) + return context->throwError(QScriptContext::TypeError, "QPointF.prototype.setX: this object is not a QPointF"); + point->setX(context->argument(0).toNumber()); + return engine->undefinedValue(); +} +//! [39] + + +//! [43] +class MyObject : public QObject +{ + Q_OBJECT + ... +}; + +Q_DECLARE_METATYPE(MyObject*) + +QScriptValue myObjectToScriptValue(QScriptEngine *engine, MyObject* const &in) +{ return engine->newQObject(in); } + +void myObjectFromScriptValue(const QScriptValue &object, MyObject* &out) +{ out = qobject_cast<MyObject*>(object.toQObject()); } + +... + +qScriptRegisterMetaType(&engine, myObjectToScriptValue, myObjectFromScriptValue); +//! [43] + +//! [44] +QScriptValue QPoint_ctor(QScriptContext *context, QScriptEngine *engine) +{ + int x = context->argument(0).toInt32(); + int y = context->argument(1).toInt32(); + return engine->toScriptValue(QPoint(x, y)); +} + +... + +engine.globalObject().setProperty("QPoint", engine.newFunction(QPoint_ctor)); +//! [44] + +//! [45] +QScriptValue myPrintFunction(QScriptContext *context, QScriptEngine *engine) +{ + QString result; + for (int i = 0; i < context->argumentCount(); ++i) { + if (i > 0) + result.append(" "); + result.append(context->argument(i).toString()); + } + + QScriptValue calleeData = context->callee().data(); + QPlainTextEdit *edit = qobject_cast<QPlainTextEdit*>(calleeData.toQObject()); + edit->appendPlainText(result); + + return engine->undefinedValue(); +} +//! [45] + +//! [46] +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + + QScriptEngine eng; + QPlainTextEdit edit; + + QScriptValue fun = eng.newFunction(myPrintFunction); + fun.setData(eng.newQObject(&edit)); + eng.globalObject().setProperty("print", fun); + + eng.evaluate("print('hello', 'world')"); + + edit.show(); + return app.exec(); +} +//! [46] + + +//! [47] +QScriptEngine eng; +QLineEdit *edit = new QLineEdit(...); +QScriptValue handler = eng.evaluate("(function(text) { print('text was changed to', text); })"); +qScriptConnect(edit, SIGNAL(textChanged(const QString &)), QScriptValue(), handler); +//! [47] + +//! [48] +QLineEdit *edit1 = new QLineEdit(...); +QLineEdit *edit2 = new QLineEdit(...); + +QScriptValue handler = eng.evaluate("(function() { print('I am', this.name); })"); +QScriptValue obj1 = eng.newObject(); +obj1.setProperty("name", "the walrus"); +QScriptValue obj2 = eng.newObject(); +obj2.setProperty("name", "Sam"); + +qScriptConnect(edit1, SIGNAL(returnPressed()), obj1, handler); +qScriptConnect(edit2, SIGNAL(returnPressed()), obj2, handler); +//! [48] + +//! [52] +QScriptValue getProperty(QScriptContext *ctx, QScriptEngine *eng) +{ + QString name = ctx->argument(0).toString(); + return ctx->thisObject().property(name); +} +//! [52] + +//! [53] +QScriptValue myCompare(QScriptContext *ctx, QScriptEngine *eng) +{ + double first = ctx->argument(0).toNumber(); + double second = ctx->argument(1).toNumber(); + int result; + if (first == second) + result = 0; + else if (first < second) + result = -1; + else + result = 1; + return result; +} +//! [53] + +//! [54] +QScriptEngine eng; +QScriptValue comparefn = eng.newFunction(myCompare); +QScriptValue array = eng.evaluate("new Array(10, 5, 20, 15, 30)"); +array.property("sort").call(array, QScriptValueList() << comparefn); + +// prints "5,10,15,20,30" +qDebug() << array.toString(); +//! [54] + +//! [55] +QScriptValue rectifier(QScriptContext *ctx, QScriptEngine *eng) +{ + QRectF magicRect = qscriptvalue_cast<QRectF>(ctx->callee().data()); + QRectF sourceRect = qscriptvalue_cast<QRectF>(ctx->argument(0)); + return eng->toScriptValue(sourceRect.intersected(magicRect)); +} + +... + +QScriptValue fun = eng.newFunction(rectifier); +QRectF magicRect = QRectF(10, 20, 30, 40); +fun.setData(eng.toScriptValue(magicRect)); +eng.globalObject().setProperty("rectifier", fun); +//! [55] + +//! [58] +QScriptValue add(QScriptContext *ctx, QScriptEngine *eng) +{ + double a = ctx->argument(0).toNumber(); + double b = ctx->argument(1).toNumber(); + return a + b; +} +//! [58] + +//! [62] +QScriptValue add(QScriptContext *ctx, QScriptEngine *eng) +{ + if (ctx->argumentCount() != 2) + return ctx->throwError("add() takes exactly two arguments"); + double a = ctx->argument(0).toNumber(); + double b = ctx->argument(1).toNumber(); + return a + b; +} +//! [62] + +//! [63] +QScriptValue add(QScriptContext *ctx, QScriptEngine *eng) +{ + if (ctx->argumentCount() != 2) + return ctx->throwError("add() takes exactly two arguments"); + if (!ctx->argument(0).isNumber()) + return ctx->throwError(QScriptContext::TypeError, "add(): first argument is not a number"); + if (!ctx->argument(1).isNumber()) + return ctx->throwError(QScriptContext::TypeError, "add(): second argument is not a number"); + double a = ctx->argument(0).toNumber(); + double b = ctx->argument(1).toNumber(); + return a + b; +} +//! [63] + +//! [65] +QScriptValue concat(QScriptContext *ctx, QScriptEngine *eng) +{ + QString result = ""; + for (int i = 0; i < ctx->argumentCount(); ++i) + result += ctx->argument(i).toString(); + return result; +} +//! [65] + +//! [67] +QScriptValue sort(QScriptContext *ctx, QScriptEngine *eng) +{ + QScriptValue comparefn = ctx->argument(0); + if (comparefn.isUndefined()) + comparefn = /* the built-in comparison function */; + else if (!comparefn.isFunction()) + return ctx->throwError(QScriptContext::TypeError, "sort(): argument is not a function"); + ... +} +//! [67] + +//! [69] +QScriptValue foo(QScriptContext *ctx, QScriptEngine *eng) +{ + QScriptValue bar = eng->globalObject().property("bar"); + QScriptValue arguments = ctx->argumentsObject(); + qDebug() << "calling bar() with" << arguments.property("length").toInt32() << "arguments"; + QScriptValue result = bar.apply(ctx->thisObject(), arguments); + qDebug() << "bar() returned" << result.toString(); + return result; +} +//! [69] + +//! [72] +QScriptValue counter(QScriptContext *ctx, QScriptEngine *eng) +{ + QScriptValue act = ctx->activationObject(); + act.setProperty("count", 0); + QScriptValue result = eng->newFunction(counter_inner); + result.setScope(act); + return result; +} +//! [72] + +//! [73] +QScriptValue counter_inner(QScriptContext *ctx, QScriptEngine *eng) +{ + QScriptValue outerAct = ctx->callee().scope(); + double count = outerAct.property("count").toNumber(); + outerAct.setProperty("count", count+1); + return count; +} +//! [73] + +//! [74] +QScriptValue counter_hybrid(QScriptContext *ctx, QScriptEngine *eng) +{ + QScriptValue act = ctx->activationObject(); + act.setProperty("count", 0); + return eng->evaluate("(function() { return count++; })"); +} +//! [74] + +//! [76] +QScriptValue Person_ctor(QScriptContext *ctx, QScriptEngine *eng) +{ + QScriptValue object; + if (ctx->isCalledAsConstructor()) { + object = ctx->thisObject(); + } else { + object = eng->newObject(); + object.setPrototype(ctx->callee().property("prototype")); + } + object.setProperty("name", ctx->argument(0)); + return object; +} +//! [76] + +//! [77] +QScriptContext *ctx = eng.pushContext(); +QScriptValue act = ctx->activationObject(); +act.setProperty("digit", 7); + +qDebug() << eng.evaluate("digit + 1").toNumber(); // 8 + +eng.popContext(); +//! [77] + +//! [78] +QScriptValue getSet(QScriptContext *ctx, QScriptEngine *eng) +{ + QScriptValue obj = ctx->thisObject(); + QScriptValue data = obj.data(); + if (!data.isValid()) { + data = eng->newObject(); + obj.setData(data); + } + QScriptValue result; + if (ctx->argumentCount() == 1) { + QString str = ctx->argument(0).toString(); + str.replace("Roberta", "Ken"); + result = str; + data.setProperty("x", result); + } else { + result = data.property("x"); + } + return result; +} +//! [78] + +//! [79] +QScriptEngine eng; +QScriptValue obj = eng.newObject(); +obj.setProperty("x", eng.newFunction(getSet), + QScriptValue::PropertyGetter|QScriptValue::PropertySetter); +//! [79] + +//! [91] +QScriptValue object = engine.evaluate("({ unitName: 'Celsius', toKelvin: function(x) { return x + 273; } })"); +QScriptValue toKelvin = object.property("toKelvin"); +QScriptValue result = toKelvin.call(object, QScriptValueList() << 100); +qDebug() << result.toNumber(); // 373 +//! [91] + +//! [92] +QScriptValue add = engine.globalObject().property("add"); +qDebug() << add.call(QScriptValue(), QScriptValueList() << 1 << 2).toNumber(); // 3 +//! [92] + +//! [93] +typedef QSharedPointer<QXmlStreamReader> XmlStreamReaderPointer; + +Q_DECLARE_METATYPE(XmlStreamReaderPointer) + +QScriptValue constructXmlStreamReader(QScriptContext *context, QScriptEngine *engine) +{ + if (!context->isCalledAsConstructor()) + return context->throwError(QScriptContext::SyntaxError, "please use the 'new' operator"); + + QIODevice *device = qobject_cast<QIODevice*>(context->argument(0).toQObject()); + if (!device) + return context->throwError(QScriptContext::TypeError, "please supply a QIODevice as first argument"); + + // Create the C++ object + QXmlStreamReader *reader = new QXmlStreamReader(device); + + XmlStreamReaderPointer pointer(reader); + + // store the shared pointer in the script object that we are constructing + return engine->newVariant(context->thisObject(), QVariant::fromValue(pointer)); +} +//! [93] + +//! [94] +QScriptValue xmlStreamReader_atEnd(QScriptContext *context, QScriptEngine *) +{ + XmlStreamReaderPointer reader = qscriptvalue_cast<XmlStreamReaderPointer>(context->thisObject()); + if (!reader) + return context->throwError(QScriptContext::TypeError, "this object is not an XmlStreamReader"); + return reader->atEnd(); +} +//! [94] + +//! [95] + QScriptEngine engine; + QScriptValue xmlStreamReaderProto = engine.newObject(); + xmlStreamReaderProto.setProperty("atEnd", engine.newFunction(xmlStreamReader_atEnd)); + + QScriptValue xmlStreamReaderCtor = engine.newFunction(constructXmlStreamReader, xmlStreamReaderProto); + engine.globalObject().setProperty("XmlStreamReader", xmlStreamReaderCtor); +//! [95] diff --git a/src/script/doc/snippets/code/doc_src_qtscript.js b/src/script/doc/snippets/code/doc_src_qtscript.js new file mode 100644 index 0000000..ccc7d40 --- /dev/null +++ b/src/script/doc/snippets/code/doc_src_qtscript.js @@ -0,0 +1,444 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//! [2] +function myInterestingScriptFunction() { + // ... +} +// ... +myQObject.somethingChanged.connect(myInterestingScriptFunction); +//! [2] + + +//! [3] +myQObject.somethingChanged.connect(myOtherQObject.doSomething); +//! [3] + + +//! [4] +myQObject.somethingChanged.disconnect(myInterestingFunction); +myQObject.somethingChanged.disconnect(myOtherQObject.doSomething); +//! [4] + + +//! [5] +var obj = { x: 123 }; +var fun = function() { print(this.x); }; +myQObject.somethingChanged.connect(obj, fun); +//! [5] + + +//! [6] +myQObject.somethingChanged.disconnect(obj, fun); +//! [6] + + +//! [7] +var obj = { x: 123, fun: function() { print(this.x); } }; +myQObject.somethingChanged.connect(obj, "fun"); +//! [7] + + +//! [8] +myQObject.somethingChanged.disconnect(obj, "fun"); +//! [8] + + +//! [9] +try { + myQObject.somethingChanged.connect(myQObject, "slotThatDoesntExist"); +} catch (e) { + print(e); +} +//! [9] + + +//! [10] +myQObject.somethingChanged("hello"); +//! [10] + + +//! [11] +myQObject.myOverloadedSlot(10); // will call the int overload +myQObject.myOverloadedSlot("10"); // will call the QString overload +//! [11] + + +//! [12] +myQObject['myOverloadedSlot(int)']("10"); // call int overload; the argument is converted to an int +myQObject['myOverloadedSlot(QString)'](10); // call QString overload; the argument is converted to a string +//! [12] + + +//! [14] +myQObject.enabled = true; + +// ... + +myQObject.enabled = !myQObject.enabled; +//! [14] + + +//! [15] +myDialog.okButton +//! [15] + + +//! [16] +myDialog.okButton.objectName = "cancelButton"; +// from now on, myDialog.cancelButton references the button +//! [16] + + +//! [17] +var okButton = myDialog.findChild("okButton"); +if (okButton != null) { + // do something with the OK button +} + +var buttons = myDialog.findChildren(RegExp("button[0-9]+")); +for (var i = 0; i < buttons.length; ++i) { + // do something with buttons[i] +} +//! [17] + + +//! [21] +var obj = new MyObject; +obj.setEnabled( true ); +print( "obj is enabled: " + obj.isEnabled() ); +//! [21] + + +//! [22] +var obj = new MyObject; +obj.enabled = true; +print( "obj is enabled: " + obj.enabled ); +//! [22] + + +//! [26] +function enabledChangedHandler( b ) +{ + print( "state changed to: " + b ); +} + +function init() +{ + var obj = new MyObject(); + // connect a script function to the signal + obj["enabledChanged(bool)"].connect(enabledChangedHandler); + obj.enabled = true; + print( "obj is enabled: " + obj.enabled ); +} +//! [26] + + +//! [27] +var o = new Object(); +o.foo = 123; +print(o.hasOwnProperty('foo')); // true +print(o.hasOwnProperty('bar')); // false +print(o); // calls o.toString(), which returns "[object Object]" +//! [27] + + +//! [28] +function Person(name) +{ + this.name = name; +} +//! [28] + + +//! [29] +Person.prototype.toString = function() { return "Person(name: " + this.name + ")"; } +//! [29] + + +//! [30] +var p1 = new Person("John Doe"); +var p2 = new Person("G.I. Jane"); +print(p1); // "Person(name: John Doe)" +print(p2); // "Person(name: G.I. Jane)" +//! [30] + + +//! [31] +print(p1.hasOwnProperty('name')); // 'name' is an instance variable, so this returns true +print(p1.hasOwnProperty('toString')); // returns false; inherited from prototype +print(p1 instanceof Person); // true +print(p1 instanceof Object); // true +//! [31] + + +//! [32] +function Employee(name, salary) +{ + Person.call(this, name); // call base constructor + + this.salary = salary; +} + +// set the prototype to be an instance of the base class +Employee.prototype = new Person(); + +// initialize prototype +Employee.prototype.toString = function() { + // ... +} +//! [32] + + +//! [33] +var e = new Employee("Johnny Bravo", 5000000); +print(e instanceof Employee); // true +print(e instanceof Person); // true +print(e instanceof Object); // true +print(e instanceof Array); // false +//! [33] + + +//! [40] +var o = new Object(); +(o.__proto__ === Object.prototype); // this evaluates to true +//! [40] + + +//! [41] +var o = new Object(); +o.__defineGetter__("x", function() { return 123; }); +var y = o.x; // 123 +//! [41] + + +//! [42] +var o = new Object(); +o.__defineSetter__("x", function(v) { print("and the value is:", v); }); +o.x = 123; // will print "and the value is: 123" +//! [42] + + +//! [49] +var getProperty = function(name) { return this[name]; }; + +name = "Global Object"; // creates a global variable +print(getProperty("name")); // "Global Object" + +var myObject = { name: 'My Object' }; +print(getProperty.call(myObject, "name")); // "My Object" + +myObject.getProperty = getProperty; +print(myObject.getProperty("name")); // "My Object" + +getProperty.name = "The getProperty() function"; +getProperty.getProperty = getProperty; +getProperty.getProperty("name"); // "The getProperty() function" +//! [49] + +//! [50] +var o = { a: 1, b: 2, sum: function() { return a + b; } }; +print(o.sum()); // reference error, or sum of global variables a and b!! +//! [50] + +//! [51] +var o = { a: 1, b: 2, sum: function() { return this.a + this.b; } }; +print(o.sum()); // 3 +//! [51] + +//! [56] +function add(a, b) { + return a + b; +} +//! [56] + +//! [57] +function add() { + return arguments[0] + arguments[1]; +} +//! [57] + +//! [59] +function add() { + if (arguments.length != 2) + throw Error("add() takes exactly two arguments"); + return arguments[0] + arguments[1]; +} +//! [59] + +//! [60] +function add() { + if (arguments.length != 2) + throw Error("add() takes exactly two arguments"); + if (typeof arguments[0] != "number") + throw TypeError("add(): first argument is not a number"); + if (typeof arguments[1] != "number") + throw TypeError("add(): second argument is not a number"); + return arguments[0] + arguments[1]; +} +//! [60] + +//! [61] +function add() { + if (arguments.length != 2) + throw Error("add() takes exactly two arguments"); + return Number(arguments[0]) + Number(arguments[1]); +} +//! [61] + +//! [64] +function concat() { + var result = ""; + for (var i = 0; i < arguments.length; ++i) + result += String(arguments[i]); + return result; +} +//! [64] + +//! [66] +function sort(comparefn) { + if (comparefn == undefined) + comparefn = fn; /* replace fn with the built-in comparison function */ + else if (typeof comparefn != "function") + throw TypeError("sort(): argument must be a function"); + // ... +} +//! [66] + +//! [68] +function foo() { + // Let bar() take care of this. + print("calling bar() with " + arguments.length + "arguments"); + var result = bar.apply(this, arguments); + print("bar() returned" + result); + return result; +} +//! [68] + +//! [70] +function counter() { + var count = 0; + return function() { + return count++; + } +} +//! [70] + +//! [71] +var c1 = counter(); // create a new counter function +var c2 = counter(); // create a new counter function +print(c1()); // 0 +print(c1()); // 1 +print(c2()); // 0 +print(c2()); // 1 +//! [71] + +//! [75] +function Book(isbn) { + this.isbn = isbn; +} + +var coolBook1 = new Book("978-0131872493"); +var coolBook2 = new Book("978-1593271473"); +//! [75] + +//! [80] +obj.x = "Roberta sent me"; +print(obj.x); // "Ken sent me" +obj.x = "I sent the bill to Roberta"; +print(obj.x); // "I sent the bill to Ken" +//! [80] + +//! [81] +obj = {}; +obj.__defineGetter__("x", function() { return this._x; }); +obj.__defineSetter__("x", function(v) { print("setting x to", v); this._x = v; }); +obj.x = 123; +//! [81] + +//! [82] +myButton.text = qsTr("Hello world!"); +//! [82] + +//! [83] +myButton.text = qsTranslate("MyAwesomeScript", "Hello world!"); +//! [83] + +//! [84] +FriendlyConversation.prototype.greeting = function(type) +{ + if (FriendlyConversation['greeting_strings'] == undefined) { + FriendlyConversation['greeting_strings'] = [ + QT_TR_NOOP("Hello"), + QT_TR_NOOP("Goodbye") + ]; + } + return qsTr(FriendlyConversation.greeting_strings[type]); +} +//! [84] + +//! [85] +FriendlyConversation.prototype.greeting = function(type) +{ + if (FriendlyConversation['greeting_strings'] == undefined) { + FriendlyConversation['greeting_strings'] = [ + QT_TRANSLATE_NOOP("FriendlyConversation", "Hello"), + QT_TRANSLATE_NOOP("FriendlyConversation", "Goodbye") + ]; + } + return qsTranslate("FriendlyConversation", FriendlyConversation.greeting_strings[type]); +} +//! [85] + +//! [86] +FileCopier.prototype.showProgress = function(done, total, currentFileName) +{ + this.label.text = qsTr("%1 of %2 files copied.\nCopying: %3") + .arg(done) + .arg(total) + .arg(currentFileName); +} +//! [86] + +//! [90] +({ unitName: "Celsius", + toKelvin: function(x) { return x + 273; } + }) +//! [90] diff --git a/src/script/doc/snippets/code/doc_src_qtscript.pro b/src/script/doc/snippets/code/doc_src_qtscript.pro new file mode 100644 index 0000000..b0ed6f8 --- /dev/null +++ b/src/script/doc/snippets/code/doc_src_qtscript.pro @@ -0,0 +1,43 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#! [1] +QT += script +#! [1] diff --git a/src/script/doc/snippets/code/doc_src_qtscript.qdoc b/src/script/doc/snippets/code/doc_src_qtscript.qdoc new file mode 100644 index 0000000..988f055 --- /dev/null +++ b/src/script/doc/snippets/code/doc_src_qtscript.qdoc @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//! [87] +lupdate myscript.qs -ts myscript_la.ts +//! [87] + +//! [88] +lupdate -extensions qs scripts/ -ts scripts_la.ts +//! [88] + +//! [89] +lrelease myscript_la.ts +//! [89] diff --git a/src/script/doc/snippets/code/doc_src_qtscriptextensions.js b/src/script/doc/snippets/code/doc_src_qtscriptextensions.js new file mode 100644 index 0000000..cdc498f --- /dev/null +++ b/src/script/doc/snippets/code/doc_src_qtscriptextensions.js @@ -0,0 +1,47 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//! [0] +print("importing " + __extension__); +__setupPackage__("cool.stuff"); + +cool.stuff.add = function(a, b) { return a + b; } +cool.stuff.subtract = function(a, b) { return a - b; } +//! [0] diff --git a/src/script/doc/snippets/code/src_script_qscriptable.cpp b/src/script/doc/snippets/code/src_script_qscriptable.cpp new file mode 100644 index 0000000..d7193ca --- /dev/null +++ b/src/script/doc/snippets/code/src_script_qscriptable.cpp @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//! [0] +class MyScriptableObject: public QObject, + protected QScriptable +{ + Q_OBJECT +... + +public slots: + void doSomething(); + double doSomethingElse(); +} +//! [0] + + +//! [1] +void MyScriptableObject::doSomething() +{ + context()->throwError("Threw an error from a slot"); +} + +double MyScriptableObject::doSomethingElse() +{ + return qscriptvalue_cast<double>(thisObject()); +} +//! [1] diff --git a/src/script/doc/snippets/code/src_script_qscriptclass.cpp b/src/script/doc/snippets/code/src_script_qscriptclass.cpp new file mode 100644 index 0000000..04c8dcc --- /dev/null +++ b/src/script/doc/snippets/code/src_script_qscriptclass.cpp @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//! [0] +if (extension == Callable) { + QScriptContext *context = qvariant_cast<QScriptContext*>(argument); + QScriptEngine *engine = context->engine(); + double sum = 0; + for (int i = 0; i < context->argumentCount(); ++i) + sum += context->argument(i).toNumber(); + return sum; +} +//! [0] diff --git a/src/script/doc/snippets/code/src_script_qscriptcontext.cpp b/src/script/doc/snippets/code/src_script_qscriptcontext.cpp new file mode 100644 index 0000000..8f9f51e --- /dev/null +++ b/src/script/doc/snippets/code/src_script_qscriptcontext.cpp @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//! [0] +foo(20.5, "hello", new Object()) +//! [0] + + +//! [1] +QScriptValue Person_prototype_fullName(QScriptContext *context, QScriptEngine *engine) +{ + QScriptValue self = context->thisObject(); + QString result; + result += self.property("firstName").toString(); + result += QLatin1String(" "); + result += self.property("lastName").toString(); + return result; +} +//! [1] + + +//! [2] +QScriptValue myInclude(QScriptContext *ctx, QScriptEngine *eng) +{ + QString fileName = ctx->argument(0).toString(); + QString contents = readTheFile(fileName); + ctx->setActivationObject(ctx->parentContext()->activationObject()); + ctx->setThisObject(ctx->parentContext()->thisObject()); + return eng->evaluate(contents, fileName); +} +//! [2] diff --git a/src/script/doc/snippets/code/src_script_qscriptengine.cpp b/src/script/doc/snippets/code/src_script_qscriptengine.cpp new file mode 100644 index 0000000..76daa0c --- /dev/null +++ b/src/script/doc/snippets/code/src_script_qscriptengine.cpp @@ -0,0 +1,332 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//! [0] +QScriptEngine myEngine; +QScriptValue three = myEngine.evaluate("1 + 2"); +//! [0] + + +//! [1] +QScriptValue fun = myEngine.evaluate("(function(a, b) { return a + b; })"); +QScriptValueList args; +args << 1 << 2; +QScriptValue threeAgain = fun.call(QScriptValue(), args); +//! [1] + + +//! [2] +QString fileName = "helloworld.qs"; +QFile scriptFile(fileName); +if (!scriptFile.open(QIODevice::ReadOnly)) + // handle error +QTextStream stream(&scriptFile); +QString contents = stream.readAll(); +scriptFile.close(); +myEngine.evaluate(contents, fileName); +//! [2] + + +//! [3] +myEngine.globalObject().setProperty("myNumber", 123); +... +QScriptValue myNumberPlusOne = myEngine.evaluate("myNumber + 1"); +//! [3] + + +//! [4] +QScriptValue result = myEngine.evaluate(...); +if (myEngine.hasUncaughtException()) { + int line = myEngine.uncaughtExceptionLineNumber(); + qDebug() << "uncaught exception at line" << line << ":" << result.toString(); +} +//! [4] + + +//! [5] +QPushButton button; +QScriptValue scriptButton = myEngine.newQObject(&button); +myEngine.globalObject().setProperty("button", scriptButton); + +myEngine.evaluate("button.checkable = true"); + +qDebug() << scriptButton.property("checkable").toBoolean(); +scriptButton.property("show").call(); // call the show() slot +//! [5] + + +//! [6] +QScriptValue myAdd(QScriptContext *context, QScriptEngine *engine) +{ + QScriptValue a = context->argument(0); + QScriptValue b = context->argument(1); + return a.toNumber() + b.toNumber(); +} +//! [6] + + +//! [7] +QScriptValue fun = myEngine.newFunction(myAdd); +myEngine.globalObject().setProperty("myAdd", fun); +//! [7] + + +//! [8] +QScriptValue result = myEngine.evaluate("myAdd(myNumber, 1)"); +//! [8] + + +//! [9] +QScriptValue Foo(QScriptContext *context, QScriptEngine *engine) +{ + if (context->calledAsConstructor()) { + // initialize the new object + context->thisObject().setProperty("bar", ...); + // ... + // return a non-object value to indicate that the + // thisObject() should be the result of the "new Foo()" expression + return engine->undefinedValue(); + } else { + // not called as "new Foo()", just "Foo()" + // create our own object and return that one + QScriptValue object = engine->newObject(); + object.setPrototype(context->callee().property("prototype")); + object.setProperty("baz", ...); + return object; + } +} + +... + +QScriptValue fooProto = engine->newObject(); +fooProto.setProperty("whatever", ...); +engine->globalObject().setProperty("Foo", engine->newFunction(Foo, fooProto)); +//! [9] + + +//! [10] +class Bar { ... }; + +Q_DECLARE_METATYPE(Bar) + +QScriptValue constructBar(QScriptContext *context, QScriptEngine *engine) +{ + Bar bar; + // initialize from arguments in context, if desired + ... + return engine->toScriptValue(bar); +} + +class BarPrototype : public QObject, public QScriptable +{ +// provide the scriptable interface of this type using slots and properties +... +}; + +... + +// create and register the Bar prototype and constructor in the engine +BarPrototype *barPrototypeObject = new BarPrototype(...); +QScriptValue barProto = engine->newQObject(barPrototypeObject); +engine->setDefaultPrototype(qMetaTypeId<Bar>, barProto); +QScriptValue barCtor = engine->newFunction(constructBar, barProto); +engine->globalObject().setProperty("Bar", barCtor); +//! [10] + + +//! [11] +static QScriptValue getSetFoo(QScriptContext *context, QScriptEngine *engine) +{ + QScriptValue callee = context->callee(); + if (context->argumentCount() == 1) // writing? + callee.setProperty("value", context->argument(0)); + return callee.property("value"); +} + +.... + +QScriptValue object = engine.newObject(); +object.setProperty("foo", engine.newFunction(getSetFoo), + QScriptValue::PropertyGetter | QScriptValue::PropertySetter); +//! [11] + + +//! [12] +QScriptValue object = engine.newObject(); +object.setProperty("foo", engine.newFunction(getFoo), QScriptValue::PropertyGetter); +object.setProperty("foo", engine.newFunction(setFoo), QScriptValue::PropertySetter); +//! [12] + + +//! [13] +Q_SCRIPT_DECLARE_QMETAOBJECT(QLineEdit, QWidget*) + +... + +QScriptValue lineEditClass = engine.scriptValueFromQMetaObject<QLineEdit>(); +engine.globalObject().setProperty("QLineEdit", lineEditClass); +//! [13] + + +//! [14] +if (hello && world) + print("hello world"); +//! [14] + + +//! [15] +if (hello && +//! [15] + + +//! [16] +0 = 0 +//! [16] + + +//! [17] +./test.js +//! [17] + + +//! [18] +foo["bar"] +//! [18] + + +//! [19] +QScriptEngine engine; +QScriptContext *context = engine.pushContext(); +context->activationObject().setProperty("myArg", 123); +engine.evaluate("var tmp = myArg + 42"); +... +engine.popContext(); +//! [19] + + +//! [20] +struct MyStruct { + int x; + int y; +}; +//! [20] + + +//! [21] +Q_DECLARE_METATYPE(MyStruct) +//! [21] + + +//! [22] +QScriptValue toScriptValue(QScriptEngine *engine, const MyStruct &s) +{ + QScriptValue obj = engine->newObject(); + obj.setProperty("x", s.x); + obj.setProperty("y", s.y); + return obj; +} + +void fromScriptValue(const QScriptValue &obj, MyStruct &s) +{ + s.x = obj.property("x").toInt32(); + s.y = obj.property("y").toInt32(); +} +//! [22] + + +//! [23] +qScriptRegisterMetaType(engine, toScriptValue, fromScriptValue); +//! [23] + + +//! [24] +MyStruct s = qscriptvalue_cast<MyStruct>(context->argument(0)); +... +MyStruct s2; +s2.x = s.x + 10; +s2.y = s.y + 20; +QScriptValue v = engine->toScriptValue(s2); +//! [24] + + +//! [25] +QScriptValue createMyStruct(QScriptContext *, QScriptEngine *engine) +{ + MyStruct s; + s.x = 123; + s.y = 456; + return engine->toScriptValue(s); +} +... +QScriptValue ctor = engine.newFunction(createMyStruct); +engine.globalObject().setProperty("MyStruct", ctor); +//! [25] + + +//! [26] +Q_DECLARE_METATYPE(QVector<int>) + +... + +qScriptRegisterSequenceMetaType<QVector<int> >(engine); +... +QVector<int> v = qscriptvalue_cast<QVector<int> >(engine->evaluate("[5, 1, 3, 2]")); +qSort(v.begin(), v.end()); +QScriptValue a = engine->toScriptValue(v); +qDebug() << a.toString(); // outputs "[1, 2, 3, 5]" +//! [26] + +//! [27] +QScriptValue mySpecialQObjectConstructor(QScriptContext *context, + QScriptEngine *engine) +{ + QObject *parent = context->argument(0).toQObject(); + QObject *object = new QObject(parent); + return engine->newQObject(object, QScriptEngine::ScriptOwnership); +} + +... + +QScriptValue ctor = engine.newFunction(mySpecialQObjectConstructor); +QScriptValue metaObject = engine.newQMetaObject(&QObject::staticMetaObject, ctor); +engine.globalObject().setProperty("QObject", metaObject); + +QScriptValue result = engine.evaluate("new QObject()"); +//! [27] diff --git a/src/script/doc/snippets/code/src_script_qscriptengineagent.cpp b/src/script/doc/snippets/code/src_script_qscriptengineagent.cpp new file mode 100644 index 0000000..206cd2f --- /dev/null +++ b/src/script/doc/snippets/code/src_script_qscriptengineagent.cpp @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//! [0] +var a = Math.random() + 2; +//! [0] + + +//! [1] +function cube(a) { + return a * a * a; +} + +var a = cube(3); +//! [1] diff --git a/src/script/doc/snippets/code/src_script_qscriptvalue.cpp b/src/script/doc/snippets/code/src_script_qscriptvalue.cpp new file mode 100644 index 0000000..5fa8e48 --- /dev/null +++ b/src/script/doc/snippets/code/src_script_qscriptvalue.cpp @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//! [0] +QScriptEngine myEngine; +QScriptValue myObject = myEngine.newObject(); +QScriptValue myOtherObject = myEngine.newObject(); +myObject.setProperty("myChild", myOtherObject); +myObject.setProperty("name", "John Doe"); +//! [0] + + +//! [1] +QScriptValue val(&myEngine, 123); +myObject.setProperty("myReadOnlyProperty", val, QScriptValue::ReadOnly); +//! [1] + + +//! [2] +QScriptEngine engine; +engine.evaluate("function fullName() { return this.firstName + ' ' + this.lastName; }"); +engine.evaluate("somePerson = { firstName: 'John', lastName: 'Doe' }"); + +QScriptValue global = engine.globalObject(); +QScriptValue fullName = global.property("fullName"); +QScriptValue who = global.property("somePerson"); +qDebug() << fullName.call(who).toString(); // "John Doe" + +engine.evaluate("function cube(x) { return x * x * x; }"); +QScriptValue cube = global.property("cube"); +QScriptValueList args; +args << 3; +qDebug() << cube.call(QScriptValue(), args).toNumber(); // 27 +//! [2] + + +//! [3] +QScriptValue myNativeFunction(QScriptContext *ctx, QScriptEngine *) +{ + QScriptValue otherFunction = ...; + return otherFunction.call(ctx->thisObject(), ctx->argumentsObject()); +} +//! [3] diff --git a/src/script/doc/snippets/code/src_script_qscriptvalueiterator.cpp b/src/script/doc/snippets/code/src_script_qscriptvalueiterator.cpp new file mode 100644 index 0000000..e26b999 --- /dev/null +++ b/src/script/doc/snippets/code/src_script_qscriptvalueiterator.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//! [0] +QScriptValue object; +... +QScriptValueIterator it(object); +while (it.hasNext()) { + it.next(); + qDebug() << it.name() << ": " << it.value().toString(); +} +//! [0] + + +//! [1] +QScriptValue obj = ...; // the object to iterate over +while (obj.isObject()) { + QScriptValueIterator it(obj); + while (it.hasNext()) { + it.next(); + qDebug() << it.name(); + } + obj = obj.prototype(); +} +//! [1] + + +//! [2] +while (it.hasNext()) { + it.next(); + if (it.flags() & QScriptValue::SkipInEnumeration) + continue; + qDebug() << "found enumerated property:" << it.name(); +} +//! [2] diff --git a/src/script/doc/snippets/qtscript/evaluation/main.cpp b/src/script/doc/snippets/qtscript/evaluation/main.cpp new file mode 100644 index 0000000..6917c47 --- /dev/null +++ b/src/script/doc/snippets/qtscript/evaluation/main.cpp @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtScript> + +int main(int argc, char *argv[]) +{ + //! [0] + QScriptEngine engine; + qDebug() << "the magic number is:" << engine.evaluate("1 + 2").toNumber(); + //! [0] + return 0; +} diff --git a/src/script/doc/snippets/qtscript/registeringobjects/main.cpp b/src/script/doc/snippets/qtscript/registeringobjects/main.cpp new file mode 100644 index 0000000..32dc699 --- /dev/null +++ b/src/script/doc/snippets/qtscript/registeringobjects/main.cpp @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QObject> +#include <QtScript> +#include "myobject.h" + +int main(int argc, char *argv[]) +{ + //! [0] + QScriptEngine engine; + QObject *someObject = new MyObject; + QScriptValue objectValue = engine.newQObject(someObject); + engine.globalObject().setProperty("myObject", objectValue); + //! [0] + qDebug() << "myObject's calculate() function returns" + << engine.evaluate("myObject.calculate(10)").toNumber(); + return 0; +} diff --git a/src/script/doc/snippets/qtscript/registeringvalues/main.cpp b/src/script/doc/snippets/qtscript/registeringvalues/main.cpp new file mode 100644 index 0000000..1aa100e --- /dev/null +++ b/src/script/doc/snippets/qtscript/registeringvalues/main.cpp @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtScript> + +int main(int argc, char *argv[]) +{ + QScriptEngine engine; + //! [0] + engine.globalObject().setProperty("foo", 123); + qDebug() << "foo times two is:" << engine.evaluate("foo * 2").toNumber(); + //! [0] + return 0; +} + diff --git a/src/script/doc/src/ecmascript.qdoc b/src/script/doc/src/ecmascript.qdoc new file mode 100644 index 0000000..4abb8f4 --- /dev/null +++ b/src/script/doc/src/ecmascript.qdoc @@ -0,0 +1,342 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** GNU Free Documentation License +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms +** and conditions contained in a signed written agreement between you +** and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \page ecmascript.html + \title ECMAScript Reference + \brief A list of objects, functions and properties supported by QtScript. + + This reference contains a list of built-in objects, functions and + properties supported by QtScript. For a detailed description, see + the \l{ECMA-262} specification. + + \tableofcontents + + \section1 The Global Object + + \section2 Value Properties + + \list + \li NaN + \li Infinity + \li undefined + \endlist + + \section2 Function Properties + + \list + \li eval(x) + \li parseInt(string, radix) + \li parseFloat(string) + \li isNaN(number) + \li isFinite(number) + \li decodeURI(encodedURI) + \li decodeURIComponent(encodedURIComponent) + \li encodeURI(uri) + \li encodeURIComponent(uriComponent) + \endlist + + \section2 Constructor Properties + + \list + \li Object + \li Function + \li Array + \li String + \li Boolean + \li Number + \li Date + \li RegExp + \li Error + \li EvalError + \li RangeError + \li ReferenceError + \li SyntaxError + \li TypeError + \li URIError + \endlist + + \section2 Other Properties + + \list + \li Math + \li JSON + \endlist + + \section1 Object Objects + + \section2 Object Constructor + + \section3 Function Properties + + \list + \li getPrototypeOf(O) + \li getOwnPropertyDescriptor(O, P) + \li getOwnPropertyNames(O) + \li create(O [, Properties]) + \li defineProperty(O, P, Attributes) + \li defineProperties(O, Properties) + \li keys(O) + \endlist + + \section2 Object Prototype Object + + \section3 Function Properties + + \list + \li toString() + \li toLocaleString() + \li valueOf() + \li hasOwnProperty(V) + \li isPrototypeOf(V) + \li propertyIsEnumerable(V) + \endlist + + \section1 Function Objects + + \section2 Function Prototype Object + + \section3 Function Properties + + \list + \li toString() + \li apply(thisArg, argArray) + \li call(thisArg [, arg1 [, arg2, ...]]) + \endlist + + \section1 Array Objects + + \section2 Array Prototype Object + + \section3 Function Properties + + \list + \li toString() + \li toLocaleString() + \li concat([item1 [, item2 [, ...]]]) + \li join(separator) + \li pop() + \li push([item1 [, item2 [, ...]]]) + \li reverse() + \li shift() + \li slice(start, end) + \li sort(comparefn) + \li splice(start, deleteCount[, item1 [, item2 [, ...]]]) + \li unshift([item1 [, item2 [, ...]]]) + \li indexOf(searchElement [, fromIndex]) + \li lastIndexOf(searchElement [, fromIndex]) + \li every(callbackfn [, thisArg]) + \li some(callbackfn [, thisArg]) + \li forEach(callbackfn [, thisArg]) + \li map(callbackfn [, thisArg]) + \li filter(callbackfn [, thisArg]) + \li reduce(callbackfn [, initialValue]) + \li reduceRight(callbackfn [, initialValue]) + \endlist + + \section1 String Objects + + \section2 String Prototype Object + + \section3 Function Properties + + \list + \li toString() + \li valueOf() + \li charAt(pos) + \li charCodeAt(pos) + \li concat([string1 [, string2 [, ...]]]) + \li indexOf(searchString ,position) + \li lastIndexOf(searchString, position) + \li localeCompare(that) + \li match(regexp) + \li replace(searchValue, replaceValue) + \li search(regexp) + \li slice(start, end) + \li split(separator, limit) + \li substring(start, end) + \li toLowerCase() + \li toLocaleLowerCase() + \li toUpperCase() + \li toLocaleUpperCase() + \li trim() + \endlist + + \section1 Boolean Objects + + \section2 Boolean Prototype Object + + \section3 Function Properties + + \list + \li toString() + \li valueOf() + \endlist + + \section1 Number Objects + + \section2 Number Prototype Object + + \section3 Function Properties + + \list + \li toString(radix) + \li toLocaleString() + \li toFixed(fractionDigits) + \li toExponential(fractionDigits) + \li toPrecision(precision) + \endlist + + \section1 The Math Object + + \section2 Value Properties + + \list + \li E + \li LN10 + \li LN2 + \li LOG2E + \li LOG10E + \li PI + \li SQRT1_2 + \li SQRT2 + \endlist + + \section2 Function Properties + + \list + \li abs(x) + \li acos(x) + \li asin(x) + \li atan(x) + \li atan2(y, x) + \li ceil(x) + \li cos(x) + \li exp(x) + \li floor(x) + \li log(x) + \li max([value1 [, value2 [, ...]]]) + \li min([value1 [, value2 [, ...]]]) + \li pow(x, y) + \li random() + \li round(x) + \li sin(x) + \li sqrt(x) + \li tan(x) + \endlist + + \section1 Date Objects + + \section2 Date Prototype Object + + \section3 Function Properties + + \list + \li toString() + \li toDateString() + \li toTimeString() + \li toLocaleString() + \li toLocaleDateString() + \li toLocaleTimeString() + \li valueOf() + \li getTime() + \li getFullYear() + \li getUTCFullYear() + \li getMonth() + \li getUTCMonth() + \li getDate() + \li getUTCDate() + \li getDay() + \li getUTCDay() + \li getHours() + \li getUTCHours() + \li getMinutes() + \li getUTCMinutes() + \li getSeconds() + \li getUTCSeconds() + \li getMilliseconds() + \li getUTCMilliseconds() + \li getTimeZoneOffset() + \li setTime(time) + \li setMilliseconds(ms) + \li setUTCMilliseconds(ms) + \li setSeconds(sec [, ms]) + \li setUTCSeconds(sec [, ms]) + \li setMinutes(min [, sec [, ms]]) + \li setUTCMinutes(min [, sec [, ms]]) + \li setHours(hour [, min [, sec [, ms]]]) + \li setUTCHours(hour [, min [, sec [, ms]]]) + \li setDate(date) + \li setUTCDate(date) + \li setMonth(month [, date]) + \li setUTCMonth(month [, date]) + \li setFullYear(year [, month [, date]]) + \li setUTCFullYear(year [, month [, date]]) + \li toUTCString() + \li toISOString() + \li toJSON() + \endlist + + \section1 RegExp Objects + + \section2 RegExp Prototype Object + + \section3 Function Properties + + \list + \li exec(string) + \li test(string) + \li toString() + \endlist + + \section1 Error Objects + + \section2 Error Prototype Object + + \section3 Value Properties + + \list + \li name + \li message + \endlist + + \section3 Function Properties + + \list + \li toString() + \endlist + + \section1 The JSON Object + + \section2 Function Properties + + \list + \li parse(text [, reviver]) + \li stringify(value [, replacer [, space]]) + \endlist + +*/ diff --git a/src/script/doc/src/external-resources.qdoc b/src/script/doc/src/external-resources.qdoc new file mode 100644 index 0000000..ee75931 --- /dev/null +++ b/src/script/doc/src/external-resources.qdoc @@ -0,0 +1,42 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** GNU Free Documentation License +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms +** and conditions contained in a signed written agreement between you +** and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \externalpage http://www.ecma-international.org/publications/standards/Ecma-262.htm + \title ECMA-262 +*/ + +/*! + \externalpage http://www.davidflanagan.com/javascript5/ + \title JavaScript: The Definitive Guide +*/ + +/*! + \externalpage http://qt.nokia.com/products/library/modular-class-library#info_scripting + \title Qt Script for Applications (QSA) +*/ + diff --git a/src/script/doc/src/qtscript.qdoc b/src/script/doc/src/qtscript.qdoc new file mode 100644 index 0000000..077f811 --- /dev/null +++ b/src/script/doc/src/qtscript.qdoc @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** GNU Free Documentation License +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms +** and conditions contained in a signed written agreement between you +** and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \module QtScript + \title QtScript Module + \since 4.3 + \ingroup modules + + \brief The QtScript module provides classes for making Qt applications scriptable. + + The QtScript module only provides core scripting facilities; the + QtScriptTools module provides additional Qt Script-related + components that application developers may find useful. + + To include the definitions of the module's classes, use the + following directive: + + \snippet code/doc_src_qtscript.cpp 0 + + To link against the module, add this line to your \l qmake \c .pro file: + + \snippet code/doc_src_qtscript.pro 1 + + For detailed information on how to make your application + scriptable with QtScript, see \l{Making Applications + Scriptable}. + + \section1 License Information + + Qt Commercial Edition licensees that wish to distribute applications that + use the QtScript module need to be aware of their obligations under the + GNU Library General Public License (LGPL). + + Developers using the Open Source Edition can choose to redistribute + the module under the appropriate version of the GNU LGPL. + + \legalese + QtScript is licensed under the GNU Library General Public License. + Individual contributor names and copyright dates can be found + inline in the code. + + This library 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 library 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 library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + \endlegalese + +*/ + diff --git a/src/script/doc/src/qtscriptdebugger-manual.qdoc b/src/script/doc/src/qtscriptdebugger-manual.qdoc new file mode 100644 index 0000000..4120464 --- /dev/null +++ b/src/script/doc/src/qtscriptdebugger-manual.qdoc @@ -0,0 +1,422 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** GNU Free Documentation License +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms +** and conditions contained in a signed written agreement between you +** and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \page qtscriptdebugger-manual.html + \title Qt Script Debugger Manual + \brief A manual describing how to use the Qt Script debugger. + + The Qt Script debugger is a tool for debugging script execution in + Qt applications that use Qt Script. Application developers can embed + the debugger into their application through the + QScriptEngineDebugger class. This manual describes how to use the + debugger. We assume that the reader is somewhat familiar with + general debugging concepts and existing debugging tools. + + We assume that the debugger has been integrated into the application + through the QScriptEngineDebugger::standardWindow() + function, which provides the standard debugger configuration. + + \tableofcontents + + \section1 Getting Started + + The following image shows the debugger as created with + \l{QScriptEngineDebugger::}{standardWindow()}: + + \image qtscript-debugger.png Running a script under the Qt Script debugger. + + The debugger will start, i.e., take control over the script's + execution when any of these conditions are met: + + \list + \li The \c{debugger} statement is encountered in the script. + \li Clicking the \uicontrol Interrupt menu item from the \uicontrol Debug + menu in the main window. + \li A breakpoint is reached. + \li An uncaught script exception is thrown. + \endlist + + Once the debugger is started, the execution state can be inspected, + e.g., the value of variables can be queried and the current program + stack shown. New breakpoints can be set. + + The debugger will resume, i.e., give the control back to the script + engine, when the user clicks \uicontrol Continue menu item from the \uicontrol + Debug menu. It will be invoked again if one of the conditions + described in the list above is met. + + \section1 Overview of Debugger Components + + The debugger's functionality is divided into a series of components, + each being a widget that can be shown in the main window of the + debugger. The following table describes each component and how they + relate to each other. + + \table + \header + \li Component + \li Description + \row + \li Console Widget + \li The console widget provides a command-line interface to the + debugger's functionality, and also serves as an interactive script + interpreter. The set of commands and their syntax is inspired by + GDB, the GNU Debugger. Commands and script variables are + auto-completed through the TAB key. + + Any console command that causes a change in the debugger or debugger + target's state will immediately be reflected in the other debugger + components (e.g. breakpoints or local variables changed). + + The console provides a simple and powerful way of manipulating the + script environment. For example, typing "x" and hitting enter will + evaluate "x" in the current stack frame and display the result. + Typing "x = 123" will assign the value 123 to the variable \c{x} in + the current scope (or create a global variable \c{x} if there isn't + one -- scripts evaluated through the console can have arbitrary side + effects, so be careful). + + \row + \li Stack Widget + \li The stack widget shows a backtrace of the script execution state. + Each row represents one frame in the stack. A row contains the + frame index (0 being the inner-most frame), the name of the script function, + and the location (file name and line number). To select a particular + stack frame to inspect, click on its row. + + \row + \li Locals Widget + \li The locals widget shows the variables that are local to the + currently selected stack frame; that is, the properties of the + objects in the scope chain and the \c{this}-object. Objects can be + expanded, so that their properties can be examined, recursively. + Properties whose value has changed are shown in bold font. + + Properties that are not read-only can be edited. Double-click on the + value and type in the new value; the value can be an arbitrary + expression. The expression will be evaluated in the associated stack + frame. While typing, you can press the TAB key to get possible + completions for the expression. + + \row + \li Code Widget + \li The code widget shows the code of the currently selected script. + The widget displays an arrow in the left margin, marking the + code line that is being executed. + Clicking in the margin of a line will cause a breakpoint to be + toggled at that line. A breakpoint has to be set on a line that + contains an actual statement in order to be useful.When an uncaught script exception occurs, the + offending line will be shown with a red background. + + The code widget is read-only; it cannot currently be used to edit + and (re)evaluate scripts. This is however possible from the + command-line interface, see \l{Console Command Reference}. + + \row + \li Scripts Widget + + \li The scripts widget shows the scripts that are currently loaded in + the script engine. Clicking on a script will cause its code to be + shown in the code widget. When a script is no longer referenced by + the debugger target it is removed from the scripts widget. Code + evaluated through QScriptEngine::evaluate() without a name specified, will be + displayed in the widget as Anonymous. + + \row + \li Breakpoints Widget + + \li The breakpoints widget shows all the breakpoints that are set. A + breakpoint can be disabled or enabled by clicking the checkbox next + to the breakpoint's ID (the ID is provided so that the breakpoint + can be manipulated through the console widget as well). + + A condition can be associated with the breakpoint; the condition can + be an arbitrary expression that should evaluate to true or + false. The breakpoint will only be triggered when its location is + reached \b{and} the condition evaluates to true. + + Similarly, if the breakpoint's ignore-count is set to N, the + breakpoint will be ignored the next N times it is hit. + + A new breakpoint can be set by clicking the New Breakpoint button + and typing in a location of the form <filename>\b{:}<linenumber>. + The breakpoint location can refer to an already loaded script, or + one that has not been loaded yet. + + \row + \li Debug Output Widget + \li The debug output widget shows messages generated by the print() + script function. Scripts can use the special variables \c{__FILE__} + and \c{__LINE__} to include the current location information in the + messages. + + \row + \li Error Log Widget + \li The error log widget shows error messages that have been generated. + All uncaught exceptions that occur in the engine will appear here. + + \endtable + + \section2 Resuming Script Evaluation + + Script evaluation can be resumed in one of the following ways: + + \list + \li \b{Continue}: Evaluation will resume normally. + \li \b{Step Into}: Evaluation will resume until the next statement is reached. + \li \b{Step Over}: Evaluation will resume until the next statement is reached; + but if the current statement is a function call, the debugger + will treat it as a single statement. + \li \b{Step Out}: Evaluation will resume until the current function exits and + the next statement is reached. + \li \b{Run to Cursor}: Run until the statement at the cursor is reached. + \li \b{Run to New Script}: Run until the first statement of a new script is reached. + \endlist + + In any case, script evaluation can also be stopped due to either of the + following reasons: + + \list + \li A \c{debugger} statement is encountered. + \li A breakpoint is hit. + \li An uncaught script exception occurs. + \endlist + + \section2 Resuming After an Uncaught Exception + + When an uncaught script exception occurs, it is not possible to + continue evaluating the current function normally. However, you can + use the console command \b{return} to catch the exception and + return a value to the calling function. + + \section1 Console Command Reference + + Note that you can also get help on the available commands by typing + ".help" in the console. + + \section2 Breakpoint-related Commands + + Break points is set + + \section3 break <location> + + Sets a breakpoint at a given code line. + + \code + .break foo.qs:123 + \endcode + + This command sets a breakpoint at \c{foo.qs}, line 123. + + \code + .break 123 + \endcode + + This command sets a breakpoint at line 123 in the current script; the current script + is the script associated with the current stack frame. + + Each breakpoint has a unique identifier (an integer) associated with it. + This identifier is needed by other breakpoint-related commands. + + \section3 clear <location> + + \code + .clear foo.qs:123 + \endcode + + clears (deletes) the breakpoint at \c{foo.qs}, line 123. + + \code + clear 123 + \endcode + + clears (deletes) the breakpoint at line 123 in the current script; + the current script is the script associated with the current stack + frame. + + \section3 condition <breakpoint-id> <expression> + + Sets a condition for a breakpoint. + + \code + .condition 1 i > 42 + \endcode + + specifies that breakpoint 1 should only be triggered if the variable \c{i} + is greater than 42. + + The expression can be an arbitrary one, i.e. it can have + side-effects. It can be any valid QScript conditional + expression. + + \section3 delete <breakpoint-id> + + Deletes a breakpoint, i.e., removes it from the current debugging + session. + + \section3 disable <breakpoint-id> + + Disables a breakpoint. The breakpoint will continue to exist, but + will not stop program execution. + + \section3 enable <breakpoint-id> + + Enables a breakpoint. Breakpoints are enabled by default, so you + only need to use this command if you have disabled to breakpoint + previously. + + \section3 ignore <breakpoint-id> <count> + + Sets the ignore-count of a breakpoint, i.e., the breakpoint will not + stop the program execution unless it have been reached \c count + times. This can, for instance, be useful in loops to stop at a + specific iteration. + + \code + .ignore 1 5 + \endcode + + Specifies that breakpoint 1 should be ignored the next 5 times it is + hit. + + \section3 info breakpoints + + Lists the breakpoints that are set. + + \code + .info breakpoints + \endcode + + \section3 tbreak <location> + + Sets a temporary breakpoint. This command is identical to the + \c{break} command, only the breakpoint will be automatically deleted + the first time it is hit. + + \section2 File-related Commands + + \section3 list <location> + + Lists the contents of a script around a given location, where the + location is given as a line number and, optionally, the name of the + file from which you will print. If only a line number is given, \c + {.list} will use the file of the current stack frame. + + \code + .list foo.qs:125 + \endcode + + When no arguments are given, \c{list} will incrementally list + sections of the current script. + + \section3 info scripts + + Lists the scripts that are currently loaded. + + \section2 Execution-related Commands + + \section3 advance <location> + + Advances execution to a given location. The syntax of the location + is the same as for setting breakpoints. For example: + + \code + .advance foo.qs:125 + \endcode + + \section3 continue + + Continues execution normally, i.e, gives the execution control over + the script back to the QScriptEngine. + + \section3 eval <program> + + Evaluates a program. + + \section3 finish + + Continues execution until the current function exits and the next + statement is reached (i.e., the statement after the call to the + function). + + \section3 interrupt + + Requests that execution should be interrupted. Interruption will + occur as soon as a new script statement is reached. + + \section3 next <count = 1> + + Continues execution until a new statement is reached; but if the + current statement is a function call, the function call will be + treated as a single statement. This will be done \c count times + before execution is stopped; the default is one. + + \section3 return <expression> + + Makes the current frame return to its caller. If \c expression is + given, it will sent as the result of the function (i.e., replacing + the functions return value). \c expression can be any valid QScript + expression. + + \section3 step <count = 1> + + Continues execution until a new statement is reached. If the number + \c count is given as argument, this will be done \c count times + before execution is stopped. As opposed to \l{next <count = 1>}, \c + step will enter functions when encountering a function call + statement. + + \section2 Stack-related Commands + + \section3 backtrace + + Shows a backtrace of the current execution. The trace will list the + function name and its position in the script for each stack frame. + + \section3 down + + Selects the previous (inner) stack frame. The execution will not + return to this frame, but you will get access to its local + variables. + + \section3 frame <index> + + This command moves to the stack frame with the given \c index. The + index of the frame on the top of the stack is 0. Previous frames are + numbered from 1 and upwards (the bottom frame in the stack has the + largest index). + + \section3 info locals + + Lists the variables that are in the scope of the current frame. + + \section3 up + + Selects the next (outer) stack frame. + +*/ diff --git a/src/script/doc/src/qtscriptextensions.qdoc b/src/script/doc/src/qtscriptextensions.qdoc new file mode 100644 index 0000000..86870f8 --- /dev/null +++ b/src/script/doc/src/qtscriptextensions.qdoc @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** GNU Free Documentation License +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms +** and conditions contained in a signed written agreement between you +** and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \page qtscriptextensions.html + \title Creating QtScript Extensions + \brief A guide to creating and using QtScript extensions. + + QtScript extensions can make additional functionality available to scripts + evaluated by a QScriptEngine. Extensions are imported by calling + the QScriptEngine::importExtension() function. + + There are three ways to create an extension: + + \list + \li Subclass QScriptExtensionPlugin and implement the desired functionality. + \li Implement the functionality in a script file. + \li Use a hybrid approach, where part of the functionality is implemented in a + QScriptExtensionPlugin, and part is implemented in a script file. + \endlist + + The (dot-qualified) extension name is used to determine the path (relative to + the application's plugin path) where QScriptEngine will look for the script + file that will initialize the extension; if a file called \c{__init__.js} + (usually located in \c{[application plugin path]/script/foo/}) is + found in the corresponding folder, its contents will be evaluated by the engine + when the extension is imported. + As an example, if the extension is called \c{"foo.bar.baz"}, the engine will look + for \c{__init__.js} in \c{foo/bar/baz}. Additionally, before importing + \c{"foo.bar.baz"}, the engine will ensure that the extensions \c{"foo"} and \c{"foo.bar"} + are imported, locating and evaluating the corresponding \c{__init__.js} + in the same manner (in folders \c{foo} and \c{foo/bar}, respectively). + + The contents of \c{__init__.js} are evaluated in a new QScriptContext, + as if it were the body of a function. The engine's Global Object acts as + the \c{this} object. The following local variables are initially available + to the script: + + \list + \li \b{__extension__}: The name of the extension (e.g. \c{"foo.bar.baz"}). + \li \b{__setupPackage__}: A convenience function for setting up a "namespace" in the script environment. A typical application is to call \c{__setupPackage__()} with \c{__extension__} as argument; e.g. \c{__setupPackage__("foo.bar.baz")} would ensure that the object chain represented by the expression \c{foo.bar.baz} exists in the script environment. (This function is semantically equivalent to QScriptExtensionPlugin::setupPackage().) + \li \b{__postInit__}: By default, this variable is undefined. If you assign a function to it, that function will be called \b{after} the C++ plugin's initialize() function has been called. You can use this to perform further initialization that depends on e.g. native functions that the C++ plugin registers. + \endlist + + An example of a simple \c{__init__.js}: + + \snippet code/doc_src_qtscriptextensions.js 0 + + QScriptEngine will look for a QScriptExtensionPlugin that provides + the relevant extension by querying each plugin for its keys() + until a match is found. The plugin's initialize() function will be + called \b{after} the relevant \c{__init__.js} (if any) has been + evaluated. + + Continuining with the example of our imaginary extension \c{"foo.bar.baz"}, + the following steps will be performed by QScriptEngine::importExtension(): + + \list + \li If it exists, \c{foo/__init__.js} is evaluated. + \li If a plugin with \c{"foo"} in its list of keys is found, its initialize() function is called with \c{"foo"} as key. + \li If it exists, \c{foo/bar/__init__.js} is evaluated. + \li If a plugin with \c{"foo.bar"} in its list of keys is found, its initialize() function is called with \c{"foo.bar"} as key. + \li If it exists, \c{foo/bar/baz/__init__.js} is evaluated. + \li If a plugin with "foo.bar.baz" in its list of keys is found, its initialize() function is called with \c{"foo.bar.baz"} as key. + \endlist + + \section1 Static Extensions + + When an extension is compiled and linked into your application as a + static plugin, Qt Script will look for the optional \c{__init__.js} + script in a resource, prefixed by \c{:/qtscriptextension}. For example, + if the extension key is "foo.bar", Qt Script will evaluate the contents + of the file \c{:/qtscriptextension/foo/bar/__init__.js}, if it + exists. Note that if the resource is built into the plugin, you may + need to use the Q_INIT_RESOURCE() macro to initialize the resource + before importing the extension. +*/ diff --git a/src/script/doc/src/scripting.qdoc b/src/script/doc/src/scripting.qdoc new file mode 100644 index 0000000..d421eab --- /dev/null +++ b/src/script/doc/src/scripting.qdoc @@ -0,0 +1,1877 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** GNU Free Documentation License +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms +** and conditions contained in a signed written agreement between you +** and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \group script + \title Scripting Classes and Overviews + + \brief Classes that add scripting capabilities to Qt applications. +*/ + +/*! + \page scripting.html + \title Making Applications Scriptable + \ingroup frameworks-technologies + + Qt 4.3 and later provides support for application scripting with ECMAScript. + The following guides and references cover aspects of programming with + ECMAScript and Qt. + + \tableofcontents + + \section1 Scripting Classes + + The following classes add scripting capabilities to Qt applications. + + \annotatedlist script + + \section1 Language Overview + + Qt Script is based on the ECMAScript scripting language, as defined + in standard \l{ECMA-262}. Microsoft's JScript, and Netscape's + JavaScript are also based on the ECMAScript standard. For an + overview of ECMAScript, see the + \l{ECMAScript Reference}{ECMAScript reference}. + If you are not familiar with the ECMAScript language, there are + several existing tutorials and books that cover this subject, such + as \l{JavaScript: The Definitive Guide}. + + Existing users of \l{Qt Script for Applications (QSA)} may find the + \l{Moving from QSA to Qt Script} document useful when porting + QSA scripts to Qt Script. + + \section1 Basic Usage + + To evaluate script code, you create a QScriptEngine and call its + evaluate() function, passing the script code (text) to evaluate + as argument. + + \snippet qtscript/evaluation/main.cpp 0 + + The return value will be the result of the evaluation (represented + as a QScriptValue object); this can be converted to standard C++ + and Qt types. + + Custom properties can be made available to scripts by registering + them with the script engine. This is most easily done by setting + properties of the script engine's \e{Global Object}: + + \snippet qtscript/registeringvalues/main.cpp 0 + + This places the properties in the script environment, thus making them + available to script code. + + \section1 Making a QObject Available to the Script Engine + + Any QObject-based instance can be made available for use with scripts. + + When a QObject is passed to the QScriptEngine::newQObject() function, + a Qt Script wrapper object is created that can be used to make the + QObject's signals, slots, properties, and child objects available + to scripts. + + Here's an example of making an instance of a QObject subclass + available to script code under the name \c{"myObject"}: + + \snippet qtscript/registeringobjects/main.cpp 0 + + This will create a global variable called \c{myObject} in the + script environment. The variable serves as a proxy to the + underlying C++ object. Note that the name of the script variable + can be anything; i.e., it is not dependent upon QObject::objectName(). + + The \l{QScriptEngine::}{newQObject()} function accepts two additional + optional arguments: one is the ownership mode, and the other is a + collection of options that allow you to control certain aspects of how + the QScriptValue that wraps the QObject should behave. We will come + back to the usage of these arguments later. + + \section2 Using Signals and Slots + + Qt Script adapts Qt's central \l{Signals and Slots} feature for + scripting. There are three principal ways to use signals and slots + with Qt Script: + + \list + \li \b{Hybrid C++/script}: C++ application code connects a + signal to a script function. The script function can, for example, be + a function that the user has typed in, or one that you have read from a + file. This approach is useful if you have a QObject but don't want + to expose the object itself to the scripting environment; you just + want a script to be able to define how a signal should be reacted + to, and leave it up to the C++ side of your application to establish + the connection. + + \li \b{Hybrid script/C++}: A script can connect signals and slots + to establish connections between pre-defined objects that the + application exposes to the scripting environment. In this scenario, + the slots themselves are still written in C++, but the definition of + the connections is fully dynamic (script-defined). + + \li \b{Purely script-defined}: A script can both define signal + handler functions (effectively "slots written in Qt Script"), + \e{and} set up the connections that utilize those handlers. For + example, a script can define a function that will handle the + QLineEdit::returnPressed() signal, and then connect that signal to the + script function. + \endlist + + Use the qScriptConnect() function to connect a C++ signal to a + script function. In the following example a script signal handler is + defined that will handle the QLineEdit::textChanged() signal: + + \snippet code/doc_src_qtscript.cpp 47 + + The first two arguments to qScriptConnect() are the same + as you would pass to QObject::connect() to establish a normal C++ + connection. The third argument is the script object that will act + as the \c this object when the signal handler is invoked; in the above + example we pass an invalid script value, so the \c this object will + be the Global Object. The fourth argument is the script function + ("slot") itself. The following example shows how the \c this argument + can be put to use: + + \snippet code/doc_src_qtscript.cpp 48 + + We create two QLineEdit objects and define a single signal handler + function. The connections use the same handler function, but the + function will be invoked with a different \c this object depending on + which object's signal was triggered, so the output of the print() + statement will be different for each. + + In script code, Qt Script uses a different syntax for connecting to + and disconnecting from signals than the familiar C++ syntax; i.e., + QObject::connect(). + To connect to a signal, you reference the relevant signal as a property + of the sender object, and invoke its \c{connect()} function. There + are three overloads of \c{connect()}, each with a corresponding + \c{disconnect()} overload. The following subsections describe these + three forms. + + \section3 Signal to Function Connections + + \c{connect(function)} + + In this form of connection, the argument to \c{connect()} is the + function to connect to the signal. + + \snippet code/doc_src_qtscript.js 2 + + The argument can be a Qt Script function, as in the above + example, or it can be a QObject slot, as in + the following example: + + \snippet code/doc_src_qtscript.js 3 + + When the argument is a QObject slot, the argument types of the + signal and slot do not necessarily have to be compatible; + QtScript will, if necessary, perform conversion of the signal + arguments to match the argument types of the slot. + + To disconnect from a signal, you invoke the signal's + \c{disconnect()} function, passing the function to disconnect + as argument: + + \snippet code/doc_src_qtscript.js 4 + + When a script function is invoked in response to a signal, the + \c this object will be the Global Object. + + \section3 Signal to Member Function Connections + + \c{connect(thisObject, function)} + + In this form of the \c{connect()} function, the first argument + is the object that will be bound to the variable, \c this, when + the function specified using the second argument is invoked. + + If you have a push button in a form, you typically want to do + something involving the form in response to the button's + \c{clicked} signal; passing the form as the \c this object + makes sense in such a case. + + \snippet code/doc_src_qtscript.js 5 + + To disconnect from the signal, pass the same arguments to \c{disconnect()}: + + \snippet code/doc_src_qtscript.js 6 + + \section3 Signal to Named Member Function Connections + + \c{connect(thisObject, functionName)} + + In this form of the \c{connect()} function, the first argument is + the object that will be bound to the variable, \c this, when + a function is invoked in response to the signal. The second argument + specifies the name of a function that is connected to the signal, + and this refers to a member function of the object passed as the + first argument (\c thisObject in the above scheme). + + Note that the function is resolved when the connection is made, not + when the signal is emitted. + + \snippet code/doc_src_qtscript.js 7 + + To disconnect from the signal, pass the same arguments to \c{disconnect()}: + + \snippet code/doc_src_qtscript.js 8 + + \section3 Error Handling + + When \c{connect()} or \c{disconnect()} succeeds, the function will + return \c{undefined}; otherwise, it will throw a script exception. + You can obtain an error message from the resulting \c{Error} object. + Example: + + \snippet code/doc_src_qtscript.js 9 + + \section3 Emitting Signals from Scripts + + To emit a signal from script code, you simply invoke the signal + function, passing the relevant arguments: + + \snippet code/doc_src_qtscript.js 10 + + It is currently not possible to define a new signal in a script; + i.e., all signals must be defined by C++ classes. + + \section3 Overloaded Signals and Slots + + When a signal or slot is overloaded, QtScript will attempt to + pick the right overload based on the actual types of the QScriptValue arguments + involved in the function invocation. For example, if your class has slots + \c{myOverloadedSlot(int)} and \c{myOverloadedSlot(QString)}, the following + script code will behave reasonably: + + \snippet code/doc_src_qtscript.js 11 + + You can specify a particular overload by using array-style property access + with the \l{QMetaObject::normalizedSignature()}{normalized signature} of + the C++ function as the property name: + + \snippet code/doc_src_qtscript.js 12 + + If the overloads have different number of arguments, QtScript will + pick the overload with the argument count that best matches the + actual number of arguments passed to the slot. + + For overloaded signals, Qt Script will throw an error if you try to connect + to the signal by name; you have to refer to the signal with the full + normalized signature of the particular overload you want to connect to. + + \section2 Accessing Properties + + The properties of the QObject are available as properties + of the corresponding QtScript object. When you manipulate + a property in script code, the C++ get/set method for that + property will automatically be invoked. For example, if your + C++ class has a property declared as follows: + + \snippet code/doc_src_qtscript.cpp 13 + + then script code can do things like the following: + + \snippet code/doc_src_qtscript.js 14 + + \section2 Accessing Child QObjects + + Every named child of the QObject (that is, for which + QObject::objectName() is not an empty string) is by default available as + a property of the QtScript wrapper object. For example, + if you have a QDialog with a child widget whose \c{objectName} property is + \c{"okButton"}, you can access this object in script code through + the expression + + \snippet code/doc_src_qtscript.js 15 + + Since \c{objectName} is itself a Q_PROPERTY, you can manipulate + the name in script code to, for example, rename an object: + + \snippet code/doc_src_qtscript.js 16 + + You can also use the functions \c{findChild()} and \c{findChildren()} + to find children. These two functions behave identically to + QObject::findChild() and QObject::findChildren(), respectively. + + For example, we can use these functions to find objects using strings + and regular expressions: + + \snippet code/doc_src_qtscript.js 17 + + You typically want to use \c{findChild()} when manipulating a form + that uses nested layouts; that way the script is isolated from the + details about which particular layout a widget is located in. + + \section2 Controlling QObject Ownership + + Qt Script uses garbage collection to reclaim memory used by script + objects when they are no longer needed; an object's memory can be + automatically reclaimed when it is no longer referenced anywhere in + the scripting environment. Qt Script lets you control what happens + to the underlying C++ QObject when the wrapper object is reclaimed + (i.e., whether the QObject is deleted or not); you do this when you + create an object by passing an ownership mode as the second argument + to QScriptEngine::newQObject(). + + Knowing how Qt Script deals with ownership is important, since it can + help you avoid situations where a C++ object isn't deleted when it + should be (causing memory leaks), or where a C++ object \e{is} + deleted when it shouldn't be (typically causing a crash if C++ code + later tries to access that object). + + \section3 Qt Ownership + + By default, the script engine does not take ownership of the + QObject that is passed to QScriptEngine::newQObject(); the object + is managed according to Qt's object ownership (see + \l{Object Trees & Ownership}). This mode is appropriate + when, for example, you are wrapping C++ objects that are part of + your application's core; that is, they should persist regardless of + what happens in the scripting environment. Another way of stating + this is that the C++ objects should outlive the script engine. + + \section3 Script Ownership + + Specifying QScriptEngine::ScriptOwnership as the ownership mode + will cause the script engine to take full ownership of the QObject + and delete it when it determines that it is safe to do so + (i.e., when there are no more references to it in script code). + This ownership mode is appropriate if the QObject does not have a + parent object, and/or the QObject is created in the context of the + script engine and is not intended to outlive the script engine. + + For example, a constructor function that constructs QObjects + only to be used in the script environment is a good candidate: + + \snippet code/doc_src_qtscript.cpp 18 + + \section3 Auto-Ownership + + With QScriptEngine::AutoOwnership the ownership is based on whether + the QObject has a parent or not. + If the QtScript garbage collector finds that the QObject is no + longer referenced within the script environment, the QObject will + be deleted \e{only} if it does not have a parent. + + \section3 What Happens When Someone Else Deletes the QObject? + + It is possible that a wrapped QObject is deleted outside of + Qt Script's control; i.e., without regard to the ownership mode + specified. In this case, the wrapper object will still + be an object (unlike the C++ pointer it wraps, the script object + won't become null). Any attempt to access properties of the script + object will, however, result in a script exception being thrown. + + Note that QScriptValue::isQObject() will still return true for a + deleted QObject, since it tests the type of the script object, not + whether the internal pointer is non-null. In other words, if + QScriptValue::isQObject() returns true but QScriptValue::toQObject() + returns a null pointer, this indicates that the QObject has been + deleted outside of Qt Script (perhaps accidentally). + + \section2 Customizing Access to the QObject + + QScriptEngine::newQObject() can take a third argument which allows + you to control various aspects of the access to the QObject through + the QtScript wrapper object it returns. + + QScriptEngine::ExcludeChildObjects specifies that child objects of + the QObject should not appear as properties of the wrapper object. + + QScriptEngine::ExcludeSuperClassProperties and + QScriptEngine::ExcludeSuperClassMethods can be used to avoid + exposing members that are inherited from the QObject's superclass. + This is useful for defining a "pure" interface where inherited members + don't make sense from a scripting perspective; e.g., you don't want + script authors to be able to change the \c{objectName} property of + the object or invoke the \c{deleteLater()} slot. + + QScriptEngine::AutoCreateDynamicProperties specifies that properties + that don't already exist in the QObject should be created as dynamic + properties of the QObject, rather than as properties of the QtScript + wrapper object. If you want new properties to truly become persistent + properties of the QObject, rather than properties that are destroyed + along with the wrapper object (and that aren't shared if the QObject + is wrapped multiple times with QScriptEngine::newQObject()), you + should use this option. + + QScriptEngine::SkipMethodsInEnumeration specifies that signals and + slots should be skipped when enumerating the properties of the QObject + wrapper in a for-in script statement. This is useful when defining + prototype objects, since by convention function properties of + prototypes should not be enumerable. + + \section2 Making a QObject-based Class New-able from a Script + + The QScriptEngine::newQObject() function is used to wrap an + existing QObject instance, so that it can be made available to + scripts. A different scenario is that you want scripts to be + able to construct new objects, not just access existing ones. + + The Qt meta-type system currently does not provide dynamic + binding of constructors for QObject-based classes. If you want to + make such a class new-able from scripts, Qt Script can generate + a reasonable script constructor for you; see + QScriptEngine::scriptValueFromQMetaObject(). + + You can also use QScriptEngine::newFunction() to wrap your own + factory function, and add it to the script environment; see + QScriptEngine::newQMetaObject() for an example. + + \section2 Enum Values + + Values for enums declared with Q_ENUMS are not available as + properties of individual wrapper objects; rather, they are + properties of the QMetaObject wrapper object that can be created + with QScriptEngine::newQMetaObject(). + + \section1 Conversion Between QtScript and C++ Types + + QtScript will perform type conversion when a value needs to be + converted from the script side to the C++ side or vice versa; for + instance, when a C++ signal triggers a script function, when + you access a QObject property in script code, or when + you call QScriptEngine::toScriptValue() or + QScriptEngine::fromScriptValue() in C++. QtScript provides default + conversion operations for many of the built-in Qt types. You can + change the conversion operation for a type (including your custom + C++ types) by registering your own conversion functions with + qScriptRegisterMetaType(). + + \section2 Default Conversion from Qt Script to C++ + + The following table describes the default conversion from a + QScriptValue to a C++ type. + + \table 80% + \header \li C++ Type \li Default Conversion + \row \li bool \li QScriptValue::toBool() + \row \li int \li QScriptValue::toInt32() + \row \li uint \li QScriptValue::toUInt32() + \row \li float \li float(QScriptValue::toNumber()) + \row \li double \li QScriptValue::toNumber() + \row \li short \li short(QScriptValue::toInt32()) + \row \li ushort \li QScriptValue::toUInt16() + \row \li char \li char(QScriptValue::toInt32()) + \row \li uchar \li unsigned char(QScriptValue::toInt32()) + \row \li qlonglong \li qlonglong(QScriptValue::toInteger()) + \row \li qulonglong \li qulonglong(QScriptValue::toInteger()) + \row \li QString \li An empty string if the QScriptValue is null + or undefined; QScriptValue::toString() otherwise. + \row \li QDateTime \li QScriptValue::toDateTime() + \row \li QDate \li QScriptValue::toDateTime().date() + \row \li QRegExp \li QScriptValue::toRegExp() + \row \li QObject* \li QScriptValue::toQObject() + \row \li QWidget* \li QScriptValue::toQObject() + \row \li QVariant \li QScriptValue::toVariant() + \row \li QChar \li If the QScriptValue is a string, the result + is the first character of the string, or a null QChar + if the string is empty; otherwise, the result is a QChar + constructed from the unicode obtained by converting the + QScriptValue to a \c{ushort}. + \row \li QStringList \li If the QScriptValue is an array, the + result is a QStringList constructed from the result of + QScriptValue::toString() for each array element; otherwise, + the result is an empty QStringList. + \row \li QVariantList \li If the QScriptValue is an array, the result + is a QVariantList constructed from the result of + QScriptValue::toVariant() for each array element; otherwise, + the result is an empty QVariantList. + \row \li QVariantMap \li If the QScriptValue is an object, the result + is a QVariantMap with a (key, value) pair of the form + (propertyName, propertyValue.toVariant()) for each property, + using QScriptValueIterator to iterate over the object's + properties. + \row \li QObjectList \li If the QScriptValue is an array, the result + is a QObjectList constructed from the result of + QScriptValue::toQObject() for each array element; otherwise, + the result is an empty QObjectList. + \row \li QList<int> \li If the QScriptValue is an array, the result is + a QList<int> constructed from the result of + QScriptValue::toInt32() for each array element; otherwise, + the result is an empty QList<int>. + \endtable + + Additionally, QtScript will handle the following cases: + + \list + \li If the QScriptValue is a QObject and the target type name ends with + \c * (i.e., it is a pointer), the QObject pointer will be cast to the + target type with qobject_cast(). + \li If the QScriptValue is a QVariant and the target type name ends with + \c * (i.e., it is a pointer), and the \l{QVariant::userType()}{userType()} + of the QVariant is the type that the target type points to, the result + is a pointer to the QVariant's data. + \li If the QScriptValue is a QVariant and it can be converted to the + target type (according to QVariant::canConvert()), the QVariant will + be cast to the target type with qvariant_cast(). + \endlist + + \section2 Default Conversion from C++ to Qt Script + + The following table describes the default behavior when a QScriptValue is + constructed from a C++ type: + + \table 80% + \header \li C++ Type \li Default Construction + \row \li void \li QScriptEngine::undefinedValue() + \row \li bool \li QScriptValue(engine, value) + \row \li int \li QScriptValue(engine, value) + \row \li uint \li QScriptValue(engine, value) + \row \li float \li QScriptValue(engine, value) + \row \li double \li QScriptValue(engine, value) + \row \li short \li QScriptValue(engine, value) + \row \li ushort \li QScriptValue(engine, value) + \row \li char \li QScriptValue(engine, value) + \row \li uchar \li QScriptValue(engine, value) + \row \li QString \li QScriptValue(engine, value) + \row \li qlonglong \li QScriptValue(engine, qsreal(value)). Note that + the conversion may lead to loss of precision, since not all + 64-bit integers can be represented using the qsreal type. + \row \li qulonglong \li QScriptValue(engine, qsreal(value)). Note that + the conversion may lead to loss of precision, since not all + 64-bit unsigned integers can be represented using the qsreal + type. + \row \li QChar \li QScriptValue(this, value.unicode()) + \row \li QDateTime \li \l{QScriptEngine::newDate()}{QScriptEngine::newDate}(value) + \row \li QDate \li \l{QScriptEngine::newDate()}{QScriptEngine::newDate}(value) + \row \li QRegExp \li \l{QScriptEngine::newRegExp()}{QScriptEngine::newRegExp}(value) + \row \li QObject* \li \l{QScriptEngine::newQObject()}{QScriptEngine::newQObject}(value) + \row \li QWidget* \li \l{QScriptEngine::newQObject()}{QScriptEngine::newQObject}(value) + \row \li QVariant \li \l{QScriptEngine::newVariant()}{QScriptEngine::newVariant}(value) + \row \li QStringList \li A new script array (created with + QScriptEngine::newArray()), whose elements are created using + the QScriptValue(QScriptEngine *, QString) constructor for + each element of the list. + \row \li QVariantList \li A new script array (created with + QScriptEngine::newArray()), whose elements are created using + QScriptEngine::newVariant() for each element of the list. + \row \li QVariantMap \li A new script object (created with + QScriptEngine::newObject()), whose properties are initialized + according to the (key, value) pairs of the map. + \row \li QObjectList \li A new script array (created with + QScriptEngine::newArray()), whose elements are created using + QScriptEngine::newQObject() for each element of the list. + \row \li QList<int> \li A new script array (created with + QScriptEngine::newArray()), whose elements are created using + the QScriptValue(QScriptEngine *, int) constructor for each + element of the list. + \endtable + + Other types (including custom types) will be wrapped using + QScriptEngine::newVariant(). For null pointers of any type, the + result is QScriptEngine::nullValue(). + + \section1 How to Design and Implement Application Objects + + This section explains how to implement application objects and + provides the necessary technical background material. + + \section2 Making a C++ object available to Scripts Written in QtScript + + Making C++ classes and objects available to a scripting language is + not trivial because scripting languages tend to be more dynamic than + C++, and it must be possible to introspect objects (query information + such as function names, function signatures, properties, etc., at + run-time). Standard C++ does not provide features for this. + + We can achieve the functionality we want by extending C++, using + C++'s own facilities so our code is still standard C++. The Qt + meta-object system provides the necessary additional functionality. + It allows us to write using an extended C++ syntax, but converts this + into standard C++ using a small utility program called \l{moc} + (Meta-Object Compiler). Classes that wish to take advantage of the + meta-object facilities are either subclasses of QObject, or use the + \c{Q_OBJECT} macro. Qt has used this approach for many years and it has + proven to be solid and reliable. QtScript uses this meta-object + technology to provide scripters with dynamic access to C++ classes + and objects. + + To completely understand how to make C++ objects available to Qt + Script, some basic knowledge of the Qt meta-object system is very + helpful. We recommend that you read about the Qt \l{Object Model} + and \l{The Meta-Object System}, which are useful for understanding + how to implement application objects. + + However, this knowledge is not essential in the simplest cases. + To make an object available in QtScript, it must derive from + QObject. All classes which derive from QObject can be introspected + and can provide the information needed by the scripting engine at + run-time; e.g., class name, functions, signatures. Because we obtain + the information we need about classes dynamically at run-time, there + is no need to write wrappers for QObject derived classes. + + \section2 Making C++ Class Member Functions Available in QtScript + + The meta-object system also makes information about signals and slots + dynamically available at run-time. By default, for QObject subclasses, + only the signals and slots are automatically made available to scripts. + This is very convenient because, in practice, we normally only want to + make specially chosen functions available to scripters. When you create + a QObject subclass, make sure that the functions you want to expose to + QtScript are public slots. + + For example, the following class definition enables scripting only for + certain functions: + + \snippet code/doc_src_qtscript.cpp 19 + + In the example above, aNonScriptableFunction() is not declared as a + slot, so it will not be available in QtScript. The other three + functions will automatically be made available in QtScript because + they are declared in the \c{public slots} section of the class + definition. + + It is possible to make any function script-invokable by specifying + the \c{Q_INVOKABLE} modifier when declaring the function: + + \snippet code/doc_src_qtscript.cpp 20 + + Once declared with \c{Q_INVOKABLE}, the method can be invoked from + QtScript code just as if it were a slot. Although such a method is + not a slot, you can still specify it as the target function in a + call to \c{connect()} in script code; \c{connect()} accepts both + native and non-native functions as targets. + + As discussed in \l{Default Conversion from Qt Script to C++}, Qt + Script handles conversion for many C++ types. If your function takes + arguments for which Qt Script does not handle conversion, you need + to supply conversion functions. This is done using the + qScriptRegisterMetaType() function. + + \section2 Making C++ Class Properties Available in QtScript + + In the previous example, if we wanted to get or set a property using + QtScript we would have to write code like the following: + + \snippet code/doc_src_qtscript.js 21 + + Scripting languages often provide a property syntax to modify and + retrieve properties (in our case the enabled state) of an + object. Many script programmers would want to write the above code + like this: + + \snippet code/doc_src_qtscript.js 22 + + To make this possible, you must define properties in the C++ QObject + subclass. For example, the following \c MyObject class declaration + declares a boolean property called \c enabled, which uses the function + \c{setEnabled(bool)} as its setter function and \c{isEnabled()} as its + getter function: + + \snippet code/doc_src_qtscript.cpp 23 + + The only difference from the original code is the use of the macro + \c{Q_PROPERTY}, which takes the type and name of the property, and + the names of the setter and getter functions as arguments. + + If you don't want a property of your class to be accessible in + QtScript, you set the \c{SCRIPTABLE} attribute to \c false when + declaring the property; by default, the \c{SCRIPTABLE} attribute is + \c true. For example: + + \snippet code/doc_src_qtscript.cpp 24 + + \section2 Reacting to C++ Objects Signals in Scripts + + In the Qt object model, signals are used as a notification mechanism + between QObjects. This means one object can connect a signal to + another object's slot and, every time the signal is emitted, the slot + is called. This connection is established using the QObject::connect() + function. + + The signals and slots mechanism is also available to QtScript + programmers. The code to declare a signal in C++ is the same, + regardless of whether the signal will be connected to a slot in C++ + or in QtScript. + + \snippet code/doc_src_qtscript.cpp 25 + + The only change we have made to the code in the previous section is + to declare a signals section with the relevant signal. Now, the + script writer can define a function and connect to the object like + this: + + \snippet code/doc_src_qtscript.js 26 + + \section2 Design of Application Objects + + The previous section described how to implement C++ objects which + can be used in QtScript. Application objects are the same kind of + objects, and they make your application's functionality available to + QtScript scripters. Since the C++ application is already written + in Qt, many objects are already QObjects. The easiest approach would + be to simply add all these QObjects as application objects to the + scripting engine. For small applications this might be sufficient, + but for larger applications this is probably not the right + approach. The problem is that this method reveals too much of the + internal API and gives script programmers access to application + internals which should not be exposed. + + Generally, the best way of making application functionality available + to scripters is to code some QObjects which define the applications + public API using signals, slots, and properties. This gives you + complete control of the functionality made available by the + application. The implementations of these objects simply call the + functions in the application which do the real work. So, instead of + making all your QObjects available to the scripting engine, just add + the wrapper QObjects. + + \section3 Returning QObject Pointers + + If you have a slot that returns a QObject pointer, you should note + that, by default, Qt Script only handles conversion of the types + QObject* and QWidget*. This means that if your slot is declared + with a signature like "MyObject* getMyObject()", QtScript doesn't + automatically know that MyObject* should be handled in the same way + as QObject* and QWidget*. The simplest way to solve this is to only + use QObject* and QWidget* in the method signatures of your scripting + interface. + + Alternatively, you can register conversion functions for your custom + type with the qScriptRegisterMetaType() function. In this way, you + can preserve the precise typing in your C++ declarations, while + still allowing pointers to your custom objects to flow seamlessly + between C++ and scripts. Example: + + \snippet code/doc_src_qtscript.cpp 43 + + \section1 Function Objects and Native Functions + + In Qt Script, functions are first-class values; they are objects that + can have properties of their own, just like any other type of + object. They can be stored in variables and passed as arguments to + other functions. Knowing how function calls in Qt Script behave is + useful when you want to define and use your own script functions. + This section discusses this matter, and also explains how you can + implement native functions; that is, Qt Script functions written in + C++, as opposed to functions written in the scripting language + itself. Even if you will be relying mostly on the dynamic QObject + binding that Qt Script provides, knowing about these powerful + concepts and techniques is important to understand what's actually + going on when script functions are executed. + + \section2 Calling a Qt Script Function from C++ + + Calling a Qt Script function from C++ is achieved with the + QScriptValue::call() function. A typical scenario is that you evaluate a + script that defines a function, and at some point you want to call that + function from C++, perhaps passing it some arguments, and then handle the + result. The following script defines a Qt Script object that has a + toKelvin() function: + + \snippet code/doc_src_qtscript.js 90 + + The toKelvin() function takes a temperature in Kelvin as argument, and + returns the temperature converted to Celsius. The following snippet shows + how the toKelvin() function might be obtained and called from C++: + + \snippet code/doc_src_qtscript.cpp 91 + + If a script defines a global function, you can access the function as a + property of QScriptEngine::globalObject(). For example, the following script + defines a global function add(): + + \snippet code/doc_src_qtscript.js 56 + + C++ code might call the add() function as follows: + + \snippet code/doc_src_qtscript.cpp 92 + + As already mentioned, functions are just values in Qt Script; a function by + itself is not "tied to" a particular object. This is why you have to specify + a \c{this} object (the first argument to QScriptValue::call()) that the + function should be applied to. + + If the function is supposed to act as a method (i.e. it can only be applied + to a certain class of objects), it is up to the function itself to check + that it is being called with a compatible \c{this} object. + + Passing an invalid QScriptValue as the \c{this} argument to + QScriptValue::call() indicates that the Global Object should be used as the + \c{this} object; in other words, that the function should be invoked as a + global function. + + \section2 The \c this Object + + When a Qt Script function is invoked from a script, the \e{way} in which it + is invoked determines the \c this object when the function body is executed, + as the following script example illustrates: + + \snippet code/doc_src_qtscript.js 49 + + An important thing to note is that in Qt Script, unlike C++ and Java, the + \c this object is not part of the execution scope. This means that + member functions (i.e., functions that operate on \c this) must always + use the \c this keyword to access the object's properties. For example, + the following script probably doesn't do what you want: + + \snippet code/doc_src_qtscript.js 50 + + You will get a reference error saying that 'a is not defined' or, worse, + two totally unrelated global variables \c a and \c b will be used to + perform the computation, if they exist. Instead, the script should look + like this: + + \snippet code/doc_src_qtscript.js 51 + + Accidentally omitting the \c this keyword is a typical source of + error for programmers who are used to the scoping rules of C++ and Java. + + \section2 Wrapping a Native Function + + Qt Script provides QScriptEngine::newFunction() as a way of wrapping a + C++ function pointer; this enables you to implement a function in + C++ and add it to the script environment, so that scripts can invoke + your function as if it were a "normal" script function. Here is how the + previous \c{getProperty()} function can be written in C++: + + \snippet code/doc_src_qtscript.cpp 52 + + Call QScriptEngine::newFunction() to wrap the function. This will + produce a special type of function object that carries a pointer to + the C++ function internally. Once the resulting wrapper has been + added to the scripting environment (e.g., by setting it as a property + of the Global Object), scripts can call the function without having + to know nor care that it is, in fact, a native function. + + Note that the name of the C++ function doesn't matter in the + scripting sense; the name by which the function is invoked by + scripts depends only on what you call the script object property + in which you store the function wrapper. + + It is currently not possible to wrap member functions; i.e., methods + of a C++ class that require a \c this object. + + \section2 The QScriptContext Object + + A QScriptContext holds all the state associated with a particular + invocation of your function. Through the QScriptContext, you can: + \list + \li Get the arguments that were passed to the function. + \li Get the \c this object. + \li Find out whether the function was called with the \c new operator + (the significance of this will be explained later). + \li Throw a script error. + \li Get the function object that's being invoked. + \li Get the activation object (the object used to hold local variables). + \endlist + + The following sections explain how to make use of this + functionality. + + \section2 Processing Function Arguments + + Two things are worth noting about function arguments: + + \list 1 + \li Any script function \mdash including native functions \mdash can + be invoked with any number of arguments. This means that it is up to + the function itself to check the argument count if necessary, and act + accordingly (e.g., throw an error if the number of arguments is + too large, or prepare a default value if the number is too small). + \li A value of any type can be supplied as an argument to any + function. This means that it is up to you to check the type of the + arguments if necessary, and act accordingly (e.g., throw an error + if an argument is not an object of a certain type). + \endlist + + In summary: Qt Script does not automatically enforce any constraints on the + number or type of arguments involved in a function call. + + \section3 Formal Parameters and the Arguments Object + + A native Qt Script function is analogous to a script function that defines no + formal parameters and only uses the built-in \c arguments variable to + process its arguments. To see this, let's first consider how a + script would normally define an \c{add()} function that takes two + arguments, adds them together and returns the result: + + \snippet code/doc_src_qtscript.js 56 + + When a script function is defined with formal parameters, their + names can be viewed as mere aliases of properties of the \c + arguments object; for example, in the \c{add(a, b)} definition's + function body, \c a and \c arguments[0] refer to the same + variable. This means that the \c{add()} function can equivalently be + written like this: + + \snippet code/doc_src_qtscript.js 57 + + This latter form closely matches what a native implementation + typically looks like: + + \snippet code/doc_src_qtscript.cpp 58 + + \section3 Checking the Number of Arguments + + Again, remember that the presence (or lack) of formal parameter + names in a function definition does not affect how the function + may be invoked; \c{add(1, 2, 3)} is allowed by the engine, as is + \c{add(42)}. In the case of the \c {add()} function, the function + really needs two arguments in order to do something useful. This + can be expressed by the script definition as follows: + + \snippet code/doc_src_qtscript.js 59 + + This would result in an error being thrown if a script invokes + \c{add()} with anything other than two arguments. The native + function can be modified to perform the same check: + + \snippet code/doc_src_qtscript.cpp 62 + + \section3 Checking the Types of Arguments + + In addition to expecting a certain number of arguments, a function might + expect that those arguments are of certain types (e.g., that the first + argument is a number and that the second is a string). Such a function + should explicitly check the type of arguments and/or perform a conversion, + or throw an error if the type of an argument is incompatible. + + As it is, the native implementation of \c{add()} shown above doesn't + have the exact same semantics as the script counterpart; this is + because the behavior of the Qt Script \c{+} operator depends on the + types of its operands (for example, if one of the operands is a string, + string concatenation is performed). To give the script function + stricter semantics (namely, that it should only add numeric + operands), the argument types can be tested: + + \snippet code/doc_src_qtscript.js 60 + + Then an invocation like \c{add("foo", new Array())} will + cause an error to be thrown. + + The C++ version can call QScriptValue::isNumber() to perform similar + tests: + + \snippet code/doc_src_qtscript.cpp 63 + + A less strict script implementation might settle for performing an + explicit to-number conversion before applying the \c{+} operator: + + \snippet code/doc_src_qtscript.js 61 + + In a native implementation, this is equivalent to calling + QScriptValue::toNumber() without performing any type test first, + since QScriptValue::toNumber() will automatically perform a type + conversion if necessary. + + To check if an argument is of a certain object type (class), + scripts can use the \c instanceof operator (e.g., \c{"arguments[0] + instanceof Array"} evaluates to true if the first argument is an + Array object); native functions can call QScriptValue::instanceOf(). + + To check if an argument is of a custom C++ type, you typically use + qscriptvalue_cast() and check if the result is valid. For object types, + this means casting to a pointer and checking if it is non-zero; for + value types, the class should have an \c{isNull()}, \c{isValid()} + or similar method. Alternatively, since most custom types are + transported in \l{QVariant}s, you can check if the script value is a + QVariant using QScriptValue::isVariant(), and then check if the + QVariant can be converted to your type using QVariant::canConvert(). + + \section3 Functions with Variable Numbers of Arguments + + Because of the presence of the built-in \c arguments object, + implementing functions that take a variable number of arguments + is simple. In fact, as we have seen, in the technical sense \e{all} + Qt Script functions can be seen as variable-argument functions. + As an example, consider a concat() function that takes an arbitrary + number of arguments, converts the arguments to their string + representation and concatenates the results; for example, + \c{concat("Qt", " ", "Script ", 101)} would return "Qt Script 101". + A script definition of \c{concat()} might look like this: + + \snippet code/doc_src_qtscript.js 64 + + Here is an equivalent native implementation: + + \snippet code/doc_src_qtscript.cpp 65 + + A second use case for a variable number of arguments is to implement + optional arguments. Here's how a script definition typically does + it: + + \snippet code/doc_src_qtscript.js 66 + + And here's the native equivalent: + + \snippet code/doc_src_qtscript.cpp 67 + + A third use case for a variable number of arguments is to simulate + C++ overloads. This involves checking the number of arguments and/or + their type at the beginning of the function body (as already shown), + and acting accordingly. It might be worth thinking twice before + doing this, and instead favor unique function names; e.g., having + separate \c{processNumber(number)} and \c{processString(string)} + functions rather than a generic \c{process(anything)} function. + On the caller side, this makes it harder for scripts to accidentally + call the wrong overload (since they don't know or don't comprehend + your custom sophisticated overloading resolution rules), and on the + callee side, you avoid the need for potentially complex (read: + error-prone) checks to resolve ambiguity. + + \section3 Accessing the Arguments Object + + Most native functions use the QScriptContext::argument() function to + access function arguments. However, it is also possible to access + the built-in \c arguments object itself (the one referred to by the + \c arguments variable in script code), by calling the + QScriptContext::argumentsObject() function. This has three principal + applications: + + \list + \li The \c arguments object can be used to easily forward a function + call to another function. In script code, this is what it + typically looks like: + + \snippet code/doc_src_qtscript.js 68 + + For example, \c{foo(10, 20, 30)} would result in the \c{foo()} function + executing the equivalent of \c{bar(10, 20, 30)}. This is useful if + you want to perform some special pre- or post-processing when + calling a function (e.g., to log the call to \c{bar()} without having + to modify the \c{bar()} function itself, like the above example), or if + you want to call a "base implementation" from a prototype + function that has the exact same "signature". In C++, the forwarding + function might look like this: + + \snippet code/doc_src_qtscript.cpp 69 + + \li The arguments object can serve as input to a QScriptValueIterator, + providing a generic way to iterate over the arguments. A debugger + might use this to display the arguments object in a general purpose + "Qt Script Object Explorer", for example. + + \li The arguments object can be serialized (e.g., with JSON) and transferred + to another entity (e.g., a script engine running in another thread), + where the object can be deserialized and passed as argument to + another script function. + \endlist + + \section2 Constructor Functions + + Some script functions are constructors; they are expected to initialize + new objects. The following snippet is a small example: + + \snippet code/doc_src_qtscript.js 75 + + There is nothing special about constructor functions. In fact, any + script function can act as a constructor function (i.e., any function + can serve as the operand to \c{new}). Some functions behave differently + depending on whether they are called as part of a \c{new} expression + or not; for example, the expression \c{new Number(1)} will create a + Number object, whereas \c{Number("123")} will perform a type + conversion. Other functions, like \c{Array()}, will always create + and initialize a new object (e.g., \c{new Array()} and \c{Array()} have + the same effect). + + A native Qt Script function can call the + QScriptContext::isCalledAsConstructor() function to determine if it + is being called as a constructor or as a regular function. When a + function is called as a constructor (i.e., it is the operand in a + \c{new} expression), this has two important implications: + + \list + \li The \c this object, QScriptContext::thisObject(), contains + the new object to be initialized; the engine creates this + new object automatically before invoking your function. This means + that your native constructor function normally doesn't have to (and + shouldn't) create a new object when it is called as a + constructor, since the engine has already prepared a new + object. Instead your function should operate on the supplied + \c this object. + \li The constructor function should return an undefined value, + QScriptEngine::undefinedValue(), to tell the engine that the + \c this object should be the final result of the \c new + operator. Alternatively, the function can return the \c this + object itself. + \endlist + + When QScriptContext::isCalledAsConstructor() returns false, how your + constructor handles this case depends on what behavior you desire. + If, like the built-in \c{Number()} function, a plain function call should + perform a type conversion of its argument, then you perform the conversion + and return the result. If, on the other hand, you want your constructor + to behave \e{as if it was called as a constructor} (with + \c{new}), you have to explicitly create a new object (that is, + ignore the \c this object), initialize that object, and return it. + + The following example implements a constructor function that always + creates and initializes a new object: + + \snippet code/doc_src_qtscript.cpp 76 + + Given this constructor, scripts would be able to use either the + expression \c{new Person("Bob")} or \c{Person("Bob")} to create a + new \c{Person} object; both behave in the same way. + + There is no equivalent way for a function defined in script + code to determine whether or not it was invoked as a constructor. + + Note that, even though it is not considered good practice, there is + nothing that stops you from choosing to ignore the default + constructed (\c this) object when your function is called as a + constructor and creating your own object anyway; simply have the + constructor return that object. The object will "override" the + default object that the engine constructed (i.e., the default + object will simply be discarded internally). + + \section2 Associating Data with a Function + + Even if a function is global \mdash i.e., not associated with any particular + (type of) object \mdash you might still want to associate some data with it, + so that it becomes self-contained; for example, the function could have + a pointer to some C++ resource that it needs to access. If your application + only uses a single script engine, or the same C++ resource can/should be + shared among all script engines, you can simply use a static C++ variable + and access it from within the native Qt Script function. + + In the case where a static C++ variable or singleton class is + not appropriate, you can call QScriptValue::setProperty() on the + function object, but be aware that those properties will also be + accessible to script code. The alternative is to use QScriptValue::setData(); + this data is not script-accessible. The implementation can access this + internal data through the QScriptContext::callee() function, which + returns the function object being invoked. The following example + shows how this might be used: + + \snippet code/doc_src_qtscript.cpp 55 + + \section2 Native Functions as Arguments to Functions + + As previously mentioned, a function object can be passed as argument + to another function; this is also true for native functions, + naturally. As an example, here's a native comparison function + that compares its two arguments numerically: + + \snippet code/doc_src_qtscript.cpp 53 + + The above function can be passed as argument to the standard + \c{Array.prototype.sort} function to sort an array numerically, + as the following C++ code illustrates: + + \snippet code/doc_src_qtscript.cpp 54 + + Note that, in this case, we are truly treating the native function + object as a value \mdash i.e., we don't store it as a property of the + scripting environment \mdash we simply pass it on as an "anonymous" + argument to another script function and then forget about it. + + \section2 The Activation Object + + Every Qt Script function invocation has an \e{activation object} + associated with it; this object is accessible through the + QScriptContext::activationObject() function. The activation object + is a script object whose properties are the local variables + associated with the invocation (including the arguments for which + the script function has a corresponding formal parameter name). + Thus, getting, modifying, creating and deleting local variables + from C++ is done using the regular QScriptValue::property() and + QScriptValue::setProperty() functions. The activation object itself + is not directly accessible from script code (but it is implicitly + accessed whenever a local variable is read from or written to). + + For C++ code, there are two principal applications of the + activation object: + + \list + \li The activation object provides a standard way to traverse the + variables associated with a function call, by using it as the input + to QScriptValueIterator. This is useful for debugging purposes. + + \li The activation object can be used to prepare local variables + that should be available when a script is evaluated inline; this + can be viewed as a way of passing arguments to the script + itself. This technique is typically used in conjunction with + QScriptEngine::pushContext(), as in the following example: + + \snippet code/doc_src_qtscript.cpp 77 + + We create a temporary execution context, create a local variable + for it, evaluate the script, and finally restore the old context. + \endlist + + \section2 Property Getters and Setters + + A script object property can be defined in terms of a getter/setter + function, similar to how a Qt C++ property has read and write + functions associated with it. This makes it possible for a script to + use expressions like \c{object.x} instead of \c{object.getX()}; the + getter/setter function for \c{x} will implicitly be invoked + whenever the property is accessed. To scripts, the property looks + and behaves just like a regular object property. + + A single Qt Script function can act as both getter and setter for + a property. When it is called as a getter, the argument count is 0. + When it is called as a setter, the argument count is 1; the argument + is the new value of the property. In the following example, we + define a native combined getter/setter that transforms the value + slightly: + + \snippet code/doc_src_qtscript.cpp 78 + + The example uses the internal data of the object to store and + retrieve the transformed value. Alternatively, the property + could be stored in another, "hidden" property of the object itself + (e.g., \c{__x__}). A native function is free to implement whatever + storage scheme it wants, as long as the external behavior of the + property itself is consistent (e.g., that scripts should not be able + to distinguish it from a regular property). + + The following C++ code shows how an object property can be defined + in terms of the native getter/setter: + + \snippet code/doc_src_qtscript.cpp 79 + + When the property is accessed, like in the following script, the + getter/setter does its job behind the scenes: + + \snippet code/doc_src_qtscript.js 80 + + \note It is important that the setter function, not just the getter, + returns the value of the property; i.e., the setter should \e{not} + return QScriptValue::UndefinedValue. This is because the result of + the property assignment is the value returned by the setter, and + not the right-hand side expression. Also note that you normally + should not attempt to read the same property that the getter modifies + within the getter itself, since this will cause the getter to be + called recursively. + + You can remove a property getter/setter by calling + QScriptValue::setProperty(), passing an invalid QScriptValue + as the getter/setter. Remember to specify the + QScriptValue::PropertyGetter/QScriptValue::PropertySetter flag(s), + otherwise the only thing that will happen is that the setter will be + invoked with an invalid QScriptValue as its argument! + + Property getters and setters can be defined and installed by script + code as well, as in the following example: + + \snippet code/doc_src_qtscript.js 81 + + Getters and setters can only be used to implement "a priori + properties"; i.e., the technique can't be used to react to an access + to a property that the object doesn't already have. To gain total + control of property access in this way, you need to subclass + QScriptClass. + + \section1 Making Use of Prototype-Based Inheritance + + In ECMAScript, inheritance is based on the concept of \e{shared + prototype objects}; this is quite different from the class-based + inheritance familiar to C++ programmers. With QtScript, you can + associate a custom prototype object with a C++ type using + QScriptEngine::setDefaultPrototype(); this is the key to providing + a script interface to that type. Since the QtScript module is built + on top of Qt's meta-type system, this can be done for any C++ type. + + You might be wondering when exactly you would need to use this + functionality in your application; isn't the automatic binding + provided by QScriptEngine::newQObject() enough? No, not under all + circumstances. + Firstly, not every C++ type is derived from QObject; types that + are not QObjects cannot be introspected through Qt's meta-object + system (they do not have properties, signals and slots). Secondly, + even if a type is QObject-derived, the functionality you want to + expose to scripts might not all be available, since it is unusual to + define every function to be a slot (and it's not always + possible/desirable to change the C++ API to make it so). + + It is perfectly possible to solve this problem by using "conventional" + C++ techniques. For instance, the QRect class could effectively be + made scriptable by creating a QObject-based C++ wrapper class with + \c{x}, \c{y}, \c{width} properties and so on, which forwarded property + access and function calls to the wrapped value. However, as we shall + see, by taking advantage of the ECMAScript object model and combining + it with Qt's meta-object system, we can arrive at a solution that is + more elegant, consistent and lightweight, supported by a small API. + + This section explains the underlying concepts of prototype-based + inheritance. Once these concepts are understood, the associated + practices can be applied throughout the QtScript API in order to + create well-behaved, consistent bindings to C++ that will fit nicely + into the ECMAScript universe. + + When experimenting with QtScript objects and inheritance, it can be + helpful to use the interactive interpreter included with the + \l{Qt Script Examples}, located in \c{examples/script/qscript}. + + \section2 Prototype Objects and Shared Properties + + The purpose of a QtScript \e{prototype object} is to define + behavior that should be shared by a set of other QtScript + objects. We say that objects which share the same prototype object + belong to the same \e{class} (again, on the technical side this + should not to be confused with the class constructs of languages + like C++ and Java; ECMAScript has no such construct). + + The basic prototype-based inheritance mechanism works as follows: Each + QtScript object has an internal link to another object, its + \e{prototype}. When a property is looked up in an object, and the + object itself does not have the property, the property is looked up + in the prototype object instead; if the prototype has the property, + then that property is returned. Otherwise, the property is looked up + in the prototype of the prototype object, and so on; this chain of + objects constitutes a \e{prototype chain}. The chain of prototype + objects is followed until the property is found or the end of the + chain is reached. + + For example, when you create a new object by the expression \c{new + Object()}, the resulting object will have as its prototype the + standard \c{Object} prototype, \c{Object.prototype}; through this + prototype relation, the new object inherits a set of properties, + including the \c{hasOwnProperty()} function and \c{toString()} + function: + + \snippet code/doc_src_qtscript.js 27 + + The \c{toString()} function itself is not defined in \c{o} (since we + did not assign anything to \c{o.toString}), so instead the + \c{toString()} function in the standard \c{Object} prototype is + called, which returns a highly generic string representation of + \c{o} ("[object Object]"). + + Note that the properties of the prototype object are not \e{copied} to + the new object; only a \e{link} from the new object to the prototype + object is maintained. This means that changes done to the prototype + object will immediately be reflected in the behavior of all objects + that have the modified object as their prototype. + + \section2 Defining Classes in a Prototype-Based Universe + + In QtScript, a class is not defined explicitly; there is no + \c{class} keyword. Instead, you define a new class in two steps: + + \list 1 + \li Define a \e{constructor function} that will initialize new objects. + \li Set up a \e{prototype object} that defines the class interface, and + assign this object to the public \c{prototype} property of the + constructor function. + \endlist + + With this arrangement, the constructor's public \c{prototype} + property will automatically be set as the prototype of objects created + by applying the \c{new} operator to your constructor function; + e.g., the prototype of an object created by \c{new Foo()} will be the + value of \c{Foo.prototype}. + + Functions that don't operate on the \c this object ("static" methods) + are typically stored as properties of the constructor function, not + as properties of the prototype object. The same is true for + constants, such as enum values. + + The following code defines a simple constructor function for a class + called \c{Person}: + + \snippet code/doc_src_qtscript.js 28 + + Next, you want to set up \c{Person.prototype} as your prototype + object; i.e., define the interface that should be common to all + \c{Person} objects. QtScript automatically creates a default + prototype object (by the expression \c{new Object()}) for every + script function; you can add properties to this object, or you can + assign your own custom object. (Generally speaking, any QtScript + object can act as prototype for any other object.) + + Here's an example of how you might want to override the + \c{toString()} function that \c{Person.prototype} inherits from + \c{Object.prototype}, to give your \c{Person} objects a more + appropriate string representation: + + \snippet code/doc_src_qtscript.js 29 + + This resembles the process of reimplementing a virtual function + in C++. Henceforth, when the property named \c{toString} is + looked up in a \c{Person} object, it will be resolved in + \c{Person.prototype}, not in \c{Object.prototype} as before: + + \snippet code/doc_src_qtscript.js 30 + + There are also some other interesting things we can learn about a + \c{Person} object: + + \snippet code/doc_src_qtscript.js 31 + + The \c{hasOwnProperty()} function is not inherited from + \c{Person.prototype}, but rather from \c{Object.prototype}, which is + the prototype of \c{Person.prototype} itself; i.e., the prototype + chain of \c{Person} objects is \c{Person.prototype} followed by + \c{Object.prototype}. This prototype chain establishes a \e{class + hierarchy}, as demonstrated by applying the \c{instanceof} operator; + \c{instanceof} checks if the value of the public \c{prototype} + property of the constructor function on the right-hand side is + reached by following the prototype chain of the object on the + left-hand side. + + When defining subclasses, there's a general pattern you can use. The + following example shows how one can create a subclass of \c{Person} + called \c{Employee}: + + \snippet code/doc_src_qtscript.js 32 + + Again, you can use the \c{instanceof} to verify that the + class relationship between \c{Employee} and \c{Person} has been + correctly established: + + \snippet code/doc_src_qtscript.js 33 + + This shows that the prototype chain of \c{Employee} objects is the + same as that of \c{Person} objects, but with \c{Employee.prototype} + added to the front of the chain. + + \section2 Prototype-Based Programming with the QtScript C++ API + + You can use QScriptEngine::newFunction() to wrap + native functions. When implementing a constructor function, + you also pass the prototype object as an argument to + QScriptEngine::newFunction(). + You can call QScriptValue::construct() to call a constructor + function, and you can use QScriptValue::call() from within a + native constructor function if you need to call a base class + constructor. + + The QScriptable class provides a convenient way to implement a + prototype object in terms of C++ slots and properties. Take a look + at the \l{Default Prototypes Example} to see how this is done. + Alternatively, the prototype functionality can be implemented in + terms of standalone native functions that you wrap with + QScriptEngine::newFunction() and set as properties of your prototype + object by calling QScriptValue::setProperty(). + + In the implementation of your prototype functions, you use + QScriptable::thisObject() (or QScriptContext::thisObject()) to + obtain a reference to the QScriptValue being operated upon; then you + call qscriptvalue_cast() to cast it to your C++ type, and perform + the relevant operations using the usual C++ API for the type. + + You associate a prototype object with a C++ type by calling + QScriptEngine::setDefaultPrototype(). Once this mapping is + established, QtScript will automatically assign the correct + prototype when a value of such a type is wrapped in a QScriptValue; + either when you explicitly call QScriptEngine::toScriptValue(), or + when a value of such a type is returned from a C++ slot and + internally passed back to script code by the engine. This means you + \e{don't} have to implement wrapper classes if you use this + approach. + + As an example, let's consider how the \c{Person} class from the + preceding section can be implemented in terms of the Qt Script API. + We begin with the native constructor function: + + \snippet code/doc_src_qtscript.cpp 34 + + Here's the native equivalent of the \c{Person.prototype.toString} + function we saw before: + + \snippet code/doc_src_qtscript.cpp 35 + + The \c{Person} class can then be initialized as follows: + + \snippet code/doc_src_qtscript.cpp 36 + + The implementation of the \c{Employee} subclass is similar. We + use QScriptValue::call() to call the super-class (Person) constructor: + + \snippet code/doc_src_qtscript.cpp 37 + + The \c{Employee} class can then be initialized as follows: + + \snippet code/doc_src_qtscript.cpp 38 + + When implementing the prototype object of a class, you may want to use + the QScriptable class, as it enables you to define the API of your + script class in terms of Qt properties, signals and slots, and + automatically handles value conversion between the Qt Script and C++ + side. + + \section2 Implementing Prototype Objects for Value-based Types + + When implementing a prototype object for a value-based type -- + e.g. QPointF -- the same general technique applies; you populate + a prototype object with functionality that should be shared + among instances. You then associate the prototype object with + the type by calling QScriptEngine::setDefaultPrototype(). This + ensures that when e.g. a value of the relevant type is returned + from a slot back to the script, the prototype link of the script + value will be initialized correctly. + + When values of the custom type are stored in QVariants -- which Qt + Script does by default --, qscriptvalue_cast() enables you to safely + cast the script value to a pointer to the C++ type. This makes it + easy to do type-checking, and, for prototype functions that should + modify the underlying C++ value, lets you modify the actual value + contained in the script value (and not a copy of it). + + \snippet code/doc_src_qtscript.cpp 39 + + \section2 Implementing Constructors for Value-based Types + + You can implement a constructor function for a value-based type + by wrapping a native factory function. For example, the following + function implements a simple constructor for QPoint: + + \snippet code/doc_src_qtscript.cpp 44 + + In the above code we simplified things a bit, e.g. we didn't check + the argument count to decide which QPoint C++ constructor to use. + In your own constructors you have to do this type of resolution + yourself, i.e. by checking the number of arguments passed to the + native function, and/or by checking the type of the arguments and + converting the arguments to the desired type. If you detect a problem + with the arguments you may want to signal this by throwing a script + exception; see QScriptContext::throwError(). + + \section2 Managing Non-QObject-based Objects + + For value-based types (e.g. QPoint), the C++ object will be destroyed when + the Qt Script object is garbage-collected, so managing the memory of the C++ + object is not an issue. For QObjects, Qt Script provides several + alternatives for managing the underlying C++ object's lifetime; see the + \l{Controlling QObject Ownership} section. However, for polymorphic types + that don't inherit from QObject, and when you can't (or won't) wrap the type + in a QObject, you have to manage the lifetime of the C++ object yourself. + + A behavior that's often reasonable when a Qt Script object wraps a C++ + object, is that the C++ object is deleted when the Qt Script object is + garbage-collected; this is typically the case when the objects can be + constructed by scripts, as opposed to the application providing the scripts + with pre-made "environment" objects. A way of making the lifetime of the C++ + object follow the lifetime of the Qt Script object is by using a shared + pointer class, such as QSharedPointer, to hold a pointer to your object; + when the Qt Script object containing the QSharedPointer is + garbage-collected, the underlying C++ object will be deleted if there are no + other references to the object. + + The following snippet shows a constructor function that constructs + QXmlStreamReader objects that are stored using QSharedPointer: + + \snippet code/doc_src_qtscript.cpp 93 + + Prototype functions can use qscriptvalue_cast() to cast the \c this object + to the proper type: + + \snippet code/doc_src_qtscript.cpp 94 + + The prototype and constructor objects are set up in the usual way: + + \snippet code/doc_src_qtscript.cpp 95 + + Scripts can now construct QXmlStreamReader objects by calling the \c + XmlStreamReader constructor, and when the Qt Script object is + garbage-collected (or the script engine is destroyed), the QXmlStreamReader + object is destroyed as well. + + \section1 Defining Custom Script Classes with QScriptClass + + There are cases where neither the dynamic QObject binding provided + by QScriptEngine::newQObject() or the manual binding provided by + QScriptEngine::newFunction() is sufficient. For example, you might + want to implement a dynamic script proxy to an underlying object; + or you might want to implement an array-like class (i.e. that gives + special treatment to properties that are valid array indexes, and + to the property "length"). In such cases, you can subclass + QScriptClass to achieve the desired behavior. + + QScriptClass allows you to handle all property access for a + (class of) script object through virtual get/set property functions. + Iteration of custom properties is also supported through the + QScriptClassPropertyIterator class; this means you can advertise + properties to be reported by for-in script statements and + QScriptValueIterator. + + \section1 Error Handling and Debugging Facilities + + Syntax errors in scripts will be reported as soon as a script is + evaluated; QScriptEngine::evaluate() will return a SyntaxError object + that you can convert to a string to get a description of the error. + + The QScriptEngine::uncaughtExceptionBacktrace() function gives you + a human-readable backtrace of the last uncaught exception. In order + to get useful filename information in backtraces, you should pass + proper filenames to QScriptEngine::evaluate() when evaluating your + scripts. + + Often an exception doesn't happen at the time the script is evaluated, + but at a later time when a function defined by the script is actually + executed. For C++ signal handlers, this is tricky; consider the case + where the clicked() signal of a button is connected to a script function, + and that script function causes a script exception when it is handling + the signal. Where is that script exception propagated to? + + The solution is to connect to the QScriptEngine::signalHandlerException() + signal; this will give you notification when a signal handler causes + an exception, so that you can find out what happened and/or recover + from it. + + In Qt 4.4 the QScriptEngineAgent class was introduced. QScriptEngineAgent + provides an interface for reporting low-level "events" in a script engine, + such as when a function is entered or when a new script statement is + reached. By subclassing QScriptEngineAgent you can be notified of these + events and perform some action, if you want. QScriptEngineAgent itself + doesn't provide any debugging-specific functionality (e.g. setting + breakpoints), but it is the basis of tools that do. + + The QScriptEngineDebugger class introduced in Qt 4.5 provides a + \l{Qt Script Debugger Manual}{Qt Script debugger} that can be embedded + into your application. + + \section2 Redefining print() + + Qt Script provides a built-in print() function that can be useful for + simple debugging purposes. The built-in print() function writes to + standard output. You can redefine the print() function (or add your + own function, e.g. debug() or log()) that redirects the text to + somewhere else. The following code shows a custom print() that adds + text to a QPlainTextEdit. + + \snippet code/doc_src_qtscript.cpp 45 + + The following code shows how the custom print() function may be + initialized and used. + + \snippet code/doc_src_qtscript.cpp 46 + + A pointer to the QPlainTextEdit is stored as an internal property + of the script function itself, so that it can be retrieved when + the function is called. + + \section1 Using QtScript Extensions + + The QScriptEngine::importExtension() function can be used to load plugins + into a script engine. Plugins typically add some extra functionality to + the engine; for example, a plugin might add full bindings for the Qt + Arthur painting API, so that those classes may be used from Qt Script + scripts. There are currently no script plugins shipped with Qt. + + If you are implementing some Qt Script functionality that you want other + Qt application developers to be able to use, \l{Creating QtScript Extensions} + {developing an extension} (e.g. by subclassing QScriptExtensionPlugin) is + worth looking into. + + \section1 Internationalization + + Since Qt 4.5, Qt Script supports internationalization of scripts by building + on the C++ internationalization functionality (see \l{Internationalization + with Qt}). + + \section2 Use qsTr() for All Literal Text + + Wherever your script uses "quoted text" for text that will be presented to + the user, ensure that it is processed by the QCoreApplication::translate() + function. Essentially all that is necessary to achieve this is to use + the qsTr() script function. Example: + + \snippet code/doc_src_qtscript.js 82 + + This accounts for 99% of the user-visible strings you're likely to write. + + The qsTr() function uses the basename of the script's filename (see + QFileInfo::baseName()) as the translation context; if the filename is not + unique in your project, you should use the qsTranslate() function and pass a + suitable context as the first argument. Example: + + \snippet code/doc_src_qtscript.js 83 + + If you need to have translatable text completely outside a function, there + are two functions to help: QT_TR_NOOP() and QT_TRANSLATE_NOOP(). They merely + mark the text for extraction by the \c lupdate utility described below. At + runtime, these functions simply return the text to translate unmodified. + + Example of QT_TR_NOOP(): + + \snippet code/doc_src_qtscript.js 84 + + Example of QT_TRANSLATE_NOOP(): + + \snippet code/doc_src_qtscript.js 85 + + \section2 Use String.prototype.arg() for Dynamic Text + + The String.prototype.arg() function (which is modeled after QString::arg()) + offers a simple means for substituting arguments: + + \snippet code/doc_src_qtscript.js 86 + + \section2 Produce Translations + + Once you are using qsTr() and/or qsTranslate() throughout your scripts, you + can start producing translations of the user-visible text in your program. + + The \l{Qt Linguist manual} provides further information about + Qt's translation tools, \e{Qt Linguist}, \c lupdate and \c + lrelease. + + Translation of Qt Script scripts is a three-step process: + + \list 1 + + \li Run \c lupdate to extract translatable text from the script source code + of the Qt application, resulting in a message file for translators (a TS + file). The utility recognizes qsTr(), qsTranslate() and the + \c{QT_TR*_NOOP()} functions described above and produces TS files + (usually one per language). + + \li Provide translations for the source texts in the TS file, using + \e{Qt Linguist}. Since TS files are in XML format, you can also + edit them by hand. + + \li Run \c lrelease to obtain a light-weight message file (a QM + file) from the TS file, suitable only for end use. Think of the TS + files as "source files", and QM files as "object files". The + translator edits the TS files, but the users of your application + only need the QM files. Both kinds of files are platform and + locale independent. + + \endlist + + Typically, you will repeat these steps for every release of your + application. The \c lupdate utility does its best to reuse the + translations from previous releases. + + When running \c lupdate, you must specify the location of the script(s), + and the name of the TS file to produce. Examples: + + \snippet code/doc_src_qtscript.qdoc 87 + + will extract translatable text from \c myscript.qs and create the + translation file \c myscript_la.qs. + + \snippet code/doc_src_qtscript.qdoc 88 + + will extract translatable text from all files ending with \c{.qs} in the + \c scripts folder and create the translation file \c scripts_la.qs. + + Alternatively, you can create a separate qmake project file that sets up + the \c SOURCES and \c TRANSLATIONS variables appropriately; then run + \c lupdate with the project file as input. + + \snippet code/doc_src_qtscript.qdoc 89 + + When running \c lrelease, you must specify the name of the TS input + file; or, if you are using a qmake project file to manage script + translations, you specify the name of that file. \c lrelease will create + \c myscript_la.qm, the binary representation of the translation. + + \section2 Apply Translations + + In your application, you must use QTranslator::load() to load the + translation files appropriate for the user's language, and install them + using QCoreApplication::installTranslator(). Finally, you must call + QScriptEngine::installTranslatorFunctions() to make the script translation + functions (qsTr(), qsTranslate() and \c{QT_TR*_NOOP()}) available to scripts + that are subsequently evaluated by QScriptEngine::evaluate(). For scripts + that are using the qsTr() function, the proper filename must be passed as + second argument to QScriptEngine::evaluate(). + + \c linguist, \c lupdate and \c lrelease are installed in the \c bin + subdirectory of the base directory Qt is installed into. Click Help|Manual + in \e{Qt Linguist} to access the user's manual; it contains a tutorial + to get you started. + + See also the \l{Hello Script Example}. + + \section1 ECMAScript Compatibility + + QtScript implements all the built-in objects and properties defined + in the \l{ECMA-262} standard; see the + \l{ECMAScript Reference}{ECMAScript reference} for an overview. + + \section1 QtScript Extensions to ECMAScript + + \list + \li \c{__proto__} \br + The prototype of an object (QScriptValue::prototype()) + can be accessed through its \c{__proto__} property in script code. + This property has the QScriptValue::Undeletable flag set. + For example: + + \snippet code/doc_src_qtscript.js 40 + + \li \c{Object.prototype.__defineGetter__} \br + This function installs a + getter function for a property of an object. The first argument is + the property name, and the second is the function to call to get + the value of that property. When the function is invoked, the + \c this object will be the object whose property is accessed. + For example: + + \snippet code/doc_src_qtscript.js 41 + + \li \c{Object.prototype.__defineSetter__} \br + This function installs a + setter function for a property of an object. The first argument is + the property name, and the second is the function to call to set + the value of that property. When the function is invoked, the + \c this object will be the object whose property is accessed. + For example: + + \snippet code/doc_src_qtscript.js 42 + + \li \c{Function.prototype.connect} \br + This function connects + a signal to a slot. Usage of this function is described in + the section \l{Using Signals and Slots}. + + \li \c{Function.prototype.disconnect} \br + This function disconnects + a signal from a slot. Usage of this function is described in + the section \l{Using Signals and Slots}. + + \li \c{QObject.prototype.findChild} \br + This function is semantically equivalent to QObject::findChild(). + + \li \c{QObject.prototype.findChildren} \br + This function is semantically equivalent to QObject::findChildren(). + + \li \c{QObject.prototype.toString} \br + This function returns a default string representation of a QObject. + + \li \c{gc} \br + This function invokes the garbage collector. + + \li \c{Error.prototype.backtrace} \br + This function returns a human-readable backtrace, in the form of + an array of strings. + + \li Error objects have the following additional properties: + \list + \li \c{lineNumber}: The line number where the error occurred. + \li \c{fileName}: The file name where the error occurred (if a file name + was passed to QScriptEngine::evaluate()). + \li \c{stack}: An array of objects describing the stack. Each object has + the following properties: + \list + \li \c{functionName}: The function name, if available. + \li \c{fileName}: The file name, if available. + \li \c{lineNumber}: The line number, if available. + \endlist + \endlist + + \endlist + + */ diff --git a/src/script/script.pro b/src/script/script.pro index 3c0e5de..a9dac69 100644 --- a/src/script/script.pro +++ b/src/script/script.pro @@ -21,6 +21,8 @@ HEADERS += qtscriptversion.h CONFIG += building-libs +QMAKE_DOCS = $$PWD/doc/qtscript.qdocconf + WEBKITDIR = $$PWD/../3rdparty/javascriptcore GENERATED_SOURCES_DIR = generated diff --git a/src/scripttools/debugging/qscriptenginedebugger.cpp b/src/scripttools/debugging/qscriptenginedebugger.cpp index 3a1333b..b6a8eef 100644 --- a/src/scripttools/debugging/qscriptenginedebugger.cpp +++ b/src/scripttools/debugging/qscriptenginedebugger.cpp @@ -86,7 +86,7 @@ public: To attach the debugger to a script engine, call the attachTo() function. - \snippet doc/src/snippets/code/src.scripttools.qscriptenginedebugger.cpp 0 + \snippet code/src.scripttools.qscriptenginedebugger.cpp 0 Once the debugger has been attached to a script engine, you can proceed to evaluate scripts as usual, e.g. by calling @@ -98,7 +98,7 @@ public: you trigger the action before you begin to \l{QScriptEngine::}{evaluate()} the script. - \snippet doc/src/snippets/scriptdebugger.cpp 2 + \snippet scriptdebugger.cpp 2 By default, the \l{standardWindow()}{standard debugger window} is shown when evaluation is suspended. This can be changed by calling the @@ -140,7 +140,7 @@ public: the function call does not return until the user has finished interacting with the debugger. - \snippet doc/src/snippets/code/src.scripttools.qscriptenginedebugger.cpp 1 + \snippet code/src.scripttools.qscriptenginedebugger.cpp 1 When the Qt Script debugger is running, the C++ application itself is not "frozen". This means that it is possible that more scripts @@ -431,7 +431,7 @@ QScriptEngineDebugger::DebuggerState QScriptEngineDebugger::state() const \l{QScriptEngineDebugger::CodeWidget}{code window} and a \l{QScriptEngineDebugger::StackWidget}{stack widget}. - \snippet doc/src/snippets/scriptdebugger.cpp 0 + \snippet scriptdebugger.cpp 0 Note that you need to set setAutoShowStandardWindow() to false; if not, the standard window will be shown regardless. @@ -454,7 +454,7 @@ QWidget *QScriptEngineDebugger::widget(DebuggerWidget widget) const wish to spice things up with your own groovy icons. The code example below shows how to add actions to a QToolBar. - \snippet doc/src/snippets/scriptdebugger.cpp 1 + \snippet scriptdebugger.cpp 1 Note that QScriptEngineDebugger has already added the actions to its \l{DebuggerWidget}{standard widgets} and \l{standardWindow()}{standard window}. |