Sie sind auf Seite 1von 65

Scripting Your Qt Application

09/25/09

About Me (Kent Hansen)


Working on Qt since 2005 QtScript Qt State Machine framework Plays harmonica and Irish whistle

Goals For This Talk


Give overview of QtScript and things related to it Show how to embed QtScript into your application

Agenda
What is application scripting? QtScript tour (the essentials) Debugger Misc.

Scripting Your Application: What?


Premise: Core functionality implemented in C++ Interface(s) exported to scripting environment Plugin-based, interactive (console), ...

Golden Example: The Web Browser


Script loaded as part of web page Browser exports tree-based API to page (DOM) Script manipulates the page

What is QtScript?
A Qt module A scripting language An engine for evaluating scripts An API for embedding into your application

The QtScript Language


Based on ECMA-262 standard JavaScript minus DOM Object-oriented, dynamically typed Java-like syntax

Disclaimer
This is not a JavaScript tutorial!

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

Our objective: Write an application that uses QtScript to calculate the meaning of life

15

QScriptEngine object
QScriptEngine engine; Vanilla environment Built-in ECMA objects Array, Math, RegExp, Error, ... parseInt(), parseFloat(), ... No Qt-specific script APIs

16

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


JS: myObject.foo = 123; myObject['foo'] = 123;

C++: myObject.setProperty(foo, 123);

23

QScriptValue holds reference to object (I)


QScriptValue object = engine.evaluate( { foo: 123, toString: function() { return 'MyObject(foo=' + this.foo + ')'; } });

24

QScriptValue holds reference to object (II)


QScriptValue same = object; object.setProperty(foo, 456); qDebug() << same.toString();

25

QScriptValue called as function


JS: myArray.sort(); or myArray['sort'].call(myArray);

C++: myArray.property(sort) .call(myArray);

26

Calling a function with arguments (I)


JS: myObject.myFunction(123, foo);

C++: myFunction.call( myObject, QScriptValueList() << 123 << foo);

27

Calling a function with arguments (II)


QScriptValue adder = engine.evaluate( (function(a, b) { return a+b; }));

QScriptValue result = adder.call( /*thisObject=*/QScriptValue(), QScriptValueList() << 41 << 1);

28

Calling a function as constructor (I)


JS: function Point(x, y) { this.x = x; this.y = y; } ... new Point(10, 20);

29

Calling a function as constructor (II)


C++: QScriptValue p = Point.construct( QScriptValueList() << 10 << 20);

qDebug() << p.property(x).toNumber();

30

QScriptValueIterator class
QScriptValueIterator it(myObject); while (it.hasNext()) { it.next(); qDebug() << it.name(); }

31

Working with JavaScript Arrays (I)


JS: var a = [10, 20, 30]; print(a[0], a['0']); // same property a.foo = 123; a.push(40); a[a.length] = 'appended';

32

Working with JavaScript Arrays (II)


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();

33

Error Handling (I)


// Uh-oh, this script will throw an error! QScriptValue result = engine.evaluate( noSuchVariable);

34

Error Handling (II)


if (result.isError()) { QString message = result.toString(); // Notify user about the problem ... }

35

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


C++:
QScriptEngine engine; QScriptValue global = engine.globalObject(); global.setProperty(meaningOfLife, 42, QScriptValue::ReadOnly);

JS:
var myMeaningOfLife = Math.sqrt(meaningOfLife);

40

Example: Fake Navigator Object


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);

41

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
QScriptEngine engine; QScriptEngineDebugger debugger; debugger.attachTo(&engine);

// evaluate scripts ...

54

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 JS:
var a = Math.random(); debugger; // synchronously run debugger var b = Math.random(); debugger; return a + b;

56

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

Das könnte Ihnen auch gefallen