scripting your qt application
DESCRIPTION
The Qt Script module enables you as a Qt/C++ application developer to seamlessly integrate scripting into your application, providing script authors with an interface for working in the context of your particular Qt application. The Qt Script language is very similar to JavaScript, so many developers and designers should already find it familiar. This session gives an overview of the main steps of embedding Qt Script into an application, and covers some typical patterns of usage. Presentation by Kent Hansen held during Qt Developer Days 2009. http://qt.nokia.com/developer/learning/elearningTRANSCRIPT
Scripting Your Qt Application09/25/09
About Me (Kent Hansen)
• Working on Qt since 2005
• QtScript
• Qt State Machine framework
• Plays harmonica and Irish whistle
2
Goals For This Talk
• Give overview of QtScript and things related to it
• Show how to embed QtScript into your application
3
Agenda
• What is application scripting?
• QtScript tour (the essentials)
• Debugger
• Misc.
4
“Scripting Your Application”: What?
• Premise: Core functionality implemented in C++
• Interface(s) exported to scripting environment
• Plugin-based, interactive (console), ...
5
Golden Example: The Web Browser
• Script loaded as part of web page
• Browser exports tree-based API to page (DOM)
• Script manipulates the page
6
What is QtScript?
• A Qt module
• A scripting language
• An “engine” for evaluating scripts
• An API for embedding into your application
7
The QtScript Language
• Based on ECMA-262 standard–“JavaScript minus DOM”
• Object-oriented, dynamically typed
• Java-like syntax
8
Disclaimer
This is not a JavaScript tutorial!
9
The QtScript Engine
• Executes scripts
• Performs C++ <--> script bridging
• It's re-entrant
10
The QtScript API
• Embed QtScript engine in your application
• Expose C++ objects to script environment
• Work with script values from C++
11
Why should you use QtScript?
• Easy to embed into any Qt application
• Tight integration with rest of Qt
• Easy-to-use API
12
Agenda
• What is application scripting?
• QtScript tour (the essentials)
• Debugger
• Misc.
13
QtScript tour (the essentials)
• Basic embedding (example)
• Working with QScriptValues
• Configuring the script environment
• Qt meta-object system integration
14
Example: Meaning of Life Calculator
15
“Our objective: Write an application that uses
QtScript to calculate the meaning of life”
QScriptEngine object
16
QScriptEngine engine;
• “Vanilla” environment
• Built-in ECMA objects–Array, Math, RegExp, Error, ...–parseInt(), parseFloat(), ...
• No Qt-specific script APIs
Mutating the Environment (I)
17
Mutating the Environment (II)
• Evaluate scripts
• Operate on QtScript values in C++
18
QtScript tour (the essentials)
• Basic embedding (example)
• Working with QScriptValues
• Configuring the script environment
• Qt meta-object system integration
19
QScriptValue class
• Represents a QtScript (JavaScript) value• Undefined• Null• Boolean• Number• String• Object
–Functions, arrays, regexps, errors, ...• Invalid (no value)
20
QScriptValue type checks & conversion
• isXXX(): Tests if value is of a certain type
• toXXX(): Converts to Qt/C++ type
• qscriptvalue_cast(): Converts to C++ type
21
QScriptValue construction
• Constructors for standard Qt/C++ types
• qScriptValueFromValue()• Counterpart to qscriptvalue_cast()
• QScriptEngine::newXXX()• Object, QObject, Array, RegExp
22
QScriptValue property access
23
JS: myObject.foo = 123;
myObject['foo'] = 123;
C++: myObject.setProperty(“foo”, 123);
QScriptValue holds reference to object (I)
24
QScriptValue object = engine.evaluate(“{ foo: 123, toString: function() { return 'MyObject(foo=' + this.foo + ')'; }}”);
QScriptValue holds reference to object (II)
25
QScriptValue same = object;object.setProperty(“foo”, 456);qDebug() << same.toString();
QScriptValue called as function
26
JS: myArray.sort(); or
myArray['sort'].call(myArray);
C++: myArray.property(“sort”)
.call(myArray);
Calling a function with arguments (I)
27
JS: myObject.myFunction(123, “foo”);
C++: myFunction.call(
myObject,
QScriptValueList()
<< 123 << “foo”);
Calling a function with arguments (II)
28
QScriptValue adder = engine.evaluate(
“(function(a, b) { return a+b; })”);
QScriptValue result = adder.call(
/*thisObject=*/QScriptValue(),
QScriptValueList() << 41 << 1);
Calling a function as constructor (I)
29
JS: function Point(x, y) {
this.x = x;
this.y = y;
}
...
new Point(10, 20);
Calling a function as constructor (II)
30
C++:
QScriptValue p = Point.construct(
QScriptValueList() << 10 << 20);
qDebug() << p.property(“x”).toNumber();
QScriptValueIterator class
31
QScriptValueIterator it(myObject);
while (it.hasNext()) {
it.next(); qDebug() << it.name();
}
Working with JavaScript Arrays (I)
32
JS:
var a = [10, 20, 30];
print(a[0], a['0']); // same property
a.foo = 123;
a.push(40);
a[a.length] = 'appended';
Working with JavaScript Arrays (II)
33
C++:
QScriptValue a = engine.evaluate(
“[10, 20, 30]”); // array literal
qDebug() << a.property(“length”).toInt32();
qDebug() << a.property(“0”).toNumber();
// for convenience + speed
qDebug() << a.property(0).toNumber();
Error Handling (I)
34
// Uh-oh, this script will throw an error!
QScriptValue result = engine.evaluate(
“noSuchVariable”);
Error Handling (II)
35
if (result.isError()) {
QString message = result.toString();
// Notify user about the problem ...
}
QScriptValue API Summary
• isXXX(), toXXX()
• property() and setProperty()
• call(), construct()
• QScriptValueIterator for introspection
36
QtScript tour (the essentials)
• Basic embedding (example)
• Working with QScriptValues
• Configuring the script environment
• Qt meta-object system integration
37
The Global Object
• A built-in script object
• Every QScriptEngine has one• QScriptEngine::globalObject()
• Initially contains properties defined by ECMA-262
38
Tailoring Scripting to Your Application
• Design “contract” of C++ <--> script interaction
• Set properties of Global Object
• Evaluate scripts that use your API
• (Optional: Call back into script objects as
appropriate)
39
Example: Meaning of Life Environment
40
C++:QScriptEngine engine;
QScriptValue global = engine.globalObject();
global.setProperty(“meaningOfLife”, 42,
QScriptValue::ReadOnly);
JS:var myMeaningOfLife = Math.sqrt(meaningOfLife);
Example: Fake Navigator Object
41
C++:
QScriptValue navigator = engine.newObject();
navigator.setProperty(“appVersion”, 1);
navigator.setProperty(“appMinorVersion”, 1);
navigator.setProperty(“cookieEnabled”, false);
navigator.setProperty(“browserLanguage”, “en_US”);
navigator.setProperty(“platform”, “No Such OS”);
navigator.setProperty(“userAgent”, “007”);
global.setProperty(“navigator”, navigator);
QtScript tour (the essentials)
• Basic embedding (example)
• Working with QScriptValues
• Configuring the script environment
• Qt meta-object system integration
42
Qt Meta-Object System
• In Qt, QObject-based classes can be introspected
at runtime• Properties• Signals & slots
• QObject::connect()
• Qt Designer property editor
• ...
43
Relax! Leave it to magic
44
QtScript <--> QObject Integration (I)
• QScriptEngine::newQObject(QObject*)
• Returns a script object that acts as proxy
• Proxy delegates property access to
QObject::property() and QObject::setProperty()
45
QtScript <--> QObject Integration (II)
• Proxy provides signals and slots as properties
• Proxy provides named child objects as properties
46
QtScript <--> QObject Integration (III)
• Ownership control
• Customize proxy behavior• Don't expose child objects• Don't expose super class contents
47
Example: Scripting a QLineEdit
48
qScriptConnect() function
• Connect a signal to a script function
• Let scripts define signal handlers
• Application does the “plumbing”
49
Summary of “API essentials”
• QScriptValue
• QScriptEngine• evaluate()• globalObject()• newQObject()
• qScriptConnect()
50
Agenda
• What is application scripting?
• QtScript tour (the essentials)
• Debugger
• Misc.
51
The QtScript Debugger
• Graphical debugger
• Introduced in Qt 4.5
• To make the API available in your application:QT += scripttools#include <QtScriptTools>
52
Debugger Demo
Look at the pretty little demo!
53
The QtScript Debugger API (I)
One class in public API: QScriptEngineDebugger
54
QScriptEngine engine;
QScriptEngineDebugger debugger;
debugger.attachTo(&engine);
// evaluate scripts ...
The QtScript Debugger API (II)
• Debugger actions can be programmatically
triggered
• Individual debugger widgets are accessible
55
Invoking the Debugger from a Script
• Use the debugger keyword
• Becomes no-op if no debugger is attached
56
JS:
var a = Math.random();
debugger; // synchronously run debugger
var b = Math.random();
debugger;
return a + b;
Agenda
• What is application scripting?
• QtScript tour (the essentials)
• Debugger
• Misc.
57
Prototypes...?
58
Prototype-based Inheritance (I)
59
Prototype-based Inheritance: Why care?
• Not every QObject member is a property / signal /
slot
• Not everything is a QObject
• Not everything should/needs to be a QObject
• JS developers are familiar with prototypes
60
Prototype-based Inheritance: How?
• Create a prototype object for the C++ type
• Register the type with Qt's meta-type system
• Associate prototype object with meta-type ID
• Create QScriptValues from the C++ type
(qScriptValueFromValue())
61
Bindings for Qt's APIs (I)
• Available as stand-alone project
• qtscriptgenerator on Qt Labs
(http://labs.qt.nokia.com)
62
Bindings for Qt's APIs (II)
• Creates plugins that can be imported into a script
engine
• Provides bindings for most of Qt's classes
• Makes it possible to write pure script applications
63
Summary
• It's easy to make your Qt application scriptable
with QtScript
• There's a QtScript debugger (also part of Qt)
• You can achieve a lot by mastering a small API
64
Thank You!
Questions?
65