summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--demos/declarative/contacts/FieldText.qml40
-rw-r--r--demos/declarative/contacts/RemoveButton.qml23
-rw-r--r--demos/declarative/flickr/common/MediaLineEdit.qml10
-rwxr-xr-xdemos/declarative/samegame/content/samegame.js36
-rw-r--r--demos/declarative/samegame/samegame.qml8
-rw-r--r--demos/declarative/webbrowser/fieldtext/FieldText.qml2
-rw-r--r--examples/declarative/layouts/Button.qml25
-rw-r--r--examples/declarative/tutorials/contacts/1_Drawing_and_Animation/1/RemoveButton.qml11
-rw-r--r--examples/declarative/webview/content/FieldText.qml2
-rw-r--r--examples/declarative/xmldata/yahoonews.qml2
-rw-r--r--src/3rdparty/javascriptcore/JavaScriptCore/runtime/Executable.cpp20
-rw-r--r--src/3rdparty/javascriptcore/JavaScriptCore/runtime/Executable.h1
-rw-r--r--src/corelib/animation/qabstractanimation.cpp6
-rw-r--r--src/declarative/fx/qfxgraphicsobjectcontainer.cpp119
-rw-r--r--src/declarative/fx/qfxgraphicsobjectcontainer.h8
-rw-r--r--src/declarative/fx/qfxgridview.cpp15
-rw-r--r--src/declarative/fx/qfxlistview.cpp19
-rw-r--r--src/declarative/fx/qfxvisualitemmodel.cpp76
-rw-r--r--src/declarative/qml/qml.pri21
-rw-r--r--src/declarative/qml/qmlbinding.cpp59
-rw-r--r--src/declarative/qml/qmlbinding.h1
-rw-r--r--src/declarative/qml/qmlbinding_p.h15
-rw-r--r--src/declarative/qml/qmlcompileddata.cpp9
-rw-r--r--src/declarative/qml/qmlcompiler.cpp108
-rw-r--r--src/declarative/qml/qmlcompiler_p.h16
-rw-r--r--src/declarative/qml/qmlcomponent.cpp3
-rw-r--r--src/declarative/qml/qmlcomponentjs_p.h8
-rw-r--r--src/declarative/qml/qmlcompositetypedata_p.h22
-rw-r--r--src/declarative/qml/qmlcompositetypemanager.cpp152
-rw-r--r--src/declarative/qml/qmlcompositetypemanager_p.h6
-rw-r--r--src/declarative/qml/qmlcontext.cpp97
-rw-r--r--src/declarative/qml/qmlcontext_p.h18
-rw-r--r--src/declarative/qml/qmlcontextscriptclass.cpp211
-rw-r--r--src/declarative/qml/qmlcontextscriptclass_p.h98
-rw-r--r--src/declarative/qml/qmldeclarativedata_p.h5
-rw-r--r--src/declarative/qml/qmlengine.cpp662
-rw-r--r--src/declarative/qml/qmlengine_p.h153
-rw-r--r--src/declarative/qml/qmlexpression.cpp236
-rw-r--r--src/declarative/qml/qmlexpression_p.h48
-rw-r--r--src/declarative/qml/qmlglobalscriptclass.cpp94
-rw-r--r--src/declarative/qml/qmlglobalscriptclass_p.h (renamed from src/declarative/util/qmlscript.h)55
-rw-r--r--src/declarative/qml/qmlinstruction.cpp2
-rw-r--r--src/declarative/qml/qmlinstruction_p.h8
-rw-r--r--src/declarative/qml/qmlintegercache.cpp106
-rw-r--r--src/declarative/qml/qmlintegercache_p.h106
-rw-r--r--src/declarative/qml/qmlmetaproperty.cpp662
-rw-r--r--src/declarative/qml/qmlmetaproperty_p.h65
-rw-r--r--src/declarative/qml/qmlmetatype.cpp206
-rw-r--r--src/declarative/qml/qmlobjectscriptclass.cpp303
-rw-r--r--src/declarative/qml/qmlobjectscriptclass_p.h111
-rw-r--r--src/declarative/qml/qmlparser.cpp2
-rw-r--r--src/declarative/qml/qmlparser_p.h5
-rw-r--r--src/declarative/qml/qmlpropertycache.cpp213
-rw-r--r--src/declarative/qml/qmlpropertycache_p.h152
-rw-r--r--src/declarative/qml/qmlscript.cpp82
-rw-r--r--src/declarative/qml/qmlscriptparser.cpp51
-rw-r--r--src/declarative/qml/qmlscriptparser_p.h2
-rw-r--r--src/declarative/qml/qmltypenamecache.cpp94
-rw-r--r--src/declarative/qml/qmltypenamecache_p.h112
-rw-r--r--src/declarative/qml/qmltypenamescriptclass.cpp163
-rw-r--r--src/declarative/qml/qmltypenamescriptclass_p.h91
-rw-r--r--src/declarative/qml/qmlvaluetypescriptclass.cpp151
-rw-r--r--src/declarative/qml/qmlvaluetypescriptclass_p.h89
-rw-r--r--src/declarative/qml/qmlvme.cpp20
-rw-r--r--src/declarative/qml/qmlxmlhttprequest.cpp24
-rw-r--r--src/declarative/util/qmlpackage.cpp2
-rw-r--r--src/declarative/util/qmlscript.cpp205
-rw-r--r--src/declarative/util/util.pri2
-rw-r--r--src/script/api/qscriptengine.cpp224
-rw-r--r--src/script/api/qscriptengine.h27
-rw-r--r--src/script/api/qscriptengine_p.h2
-rw-r--r--src/script/api/qscriptvalue.cpp5
-rw-r--r--src/script/bridge/bridge.pri8
-rw-r--r--src/script/bridge/qscriptdeclarativeclass.cpp316
-rw-r--r--src/script/bridge/qscriptdeclarativeclass_p.h127
-rw-r--r--src/script/bridge/qscriptdeclarativeobject.cpp192
-rw-r--r--src/script/bridge/qscriptdeclarativeobject_p.h125
-rw-r--r--src/script/bridge/qscriptobject_p.h3
-rw-r--r--tests/auto/declarative/qmlecmascript/data/ScopeObject.qml14
-rw-r--r--tests/auto/declarative/qmlecmascript/data/attachedProperty.qml11
-rw-r--r--tests/auto/declarative/qmlecmascript/data/extendedObjectPropertyLookup.qml8
-rw-r--r--tests/auto/declarative/qmlecmascript/data/objectsCompareAsEqual.qml15
-rw-r--r--tests/auto/declarative/qmlecmascript/data/scope.qml48
-rw-r--r--tests/auto/declarative/qmlecmascript/data/scriptAccess.js7
-rw-r--r--tests/auto/declarative/qmlecmascript/data/scriptAccess.qml17
-rw-r--r--tests/auto/declarative/qmlecmascript/data/selfDeletingBinding.2.qml17
-rw-r--r--tests/auto/declarative/qmlecmascript/data/selfDeletingBinding.qml18
-rw-r--r--tests/auto/declarative/qmlecmascript/data/signalParameterTypes.qml16
-rw-r--r--tests/auto/declarative/qmlecmascript/testtypes.h5
-rw-r--r--tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp132
-rw-r--r--tests/auto/declarative/qmllanguage/data/dynamicObjectProperties.qml13
-rw-r--r--tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp14
-rw-r--r--tools/qmlviewer/qfxtester.cpp8
93 files changed, 5166 insertions, 1755 deletions
diff --git a/demos/declarative/contacts/FieldText.qml b/demos/declarative/contacts/FieldText.qml
index d30d4d8..2e8b60d 100644
--- a/demos/declarative/contacts/FieldText.qml
+++ b/demos/declarative/contacts/FieldText.qml
@@ -9,29 +9,29 @@ Rectangle {
property var label: ""
onTextChanged: { reset() }
signal confirmed
- resources: [
- Script {
- function edit() {
- if (!contacts.mouseGrabbed) {
- fieldText.state='editing';
- contacts.mouseGrabbed=true;
- }
- }
- function confirm() {
- fieldText.text = textEdit.text;
- fieldText.state='';
- contacts.mouseGrabbed=false;
- fieldText.confirmed();
- }
- function reset() {
- textEdit.text = fieldText.text;
- fieldText.state='';
- contacts.mouseGrabbed=false;
+ Script {
+
+ function edit() {
+ if (!contacts.mouseGrabbed) {
+ fieldText.state='editing';
+ contacts.mouseGrabbed=true;
}
-
}
- ]
+ function confirm() {
+ fieldText.text = textEdit.text;
+ fieldText.state='';
+ contacts.mouseGrabbed=false;
+ fieldText.confirmed();
+ }
+ function reset() {
+ textEdit.text = fieldText.text;
+ fieldText.state='';
+ contacts.mouseGrabbed=false;
+ }
+
+ }
+
Image {
id: cancelIcon
width: 22
diff --git a/demos/declarative/contacts/RemoveButton.qml b/demos/declarative/contacts/RemoveButton.qml
index cc858c3..2c3cc9e 100644
--- a/demos/declarative/contacts/RemoveButton.qml
+++ b/demos/declarative/contacts/RemoveButton.qml
@@ -8,21 +8,20 @@ Rectangle {
radius: 5
property var expandedWidth: 230
signal confirmed
- resources: [
- Script {
- function toggle() {
- if (removeButton.state == 'opened') {
- removeButton.state = '';
- contacts.mouseGrabbed=false;
- } else {
- if (!contacts.mouseGrabbed) {
- removeButton.state = 'opened';
- contacts.mouseGrabbed=true;
- }
+ Script {
+ function toggle() {
+ if (removeButton.state == 'opened') {
+ removeButton.state = '';
+ contacts.mouseGrabbed=false;
+ } else {
+ if (!contacts.mouseGrabbed) {
+ removeButton.state = 'opened';
+ contacts.mouseGrabbed=true;
}
}
}
- ]
+ }
+
Image {
id: trashIcon
width: 22
diff --git a/demos/declarative/flickr/common/MediaLineEdit.qml b/demos/declarative/flickr/common/MediaLineEdit.qml
index 4b21f66..f959bc5 100644
--- a/demos/declarative/flickr/common/MediaLineEdit.qml
+++ b/demos/declarative/flickr/common/MediaLineEdit.qml
@@ -6,18 +6,18 @@ Item {
property string label
property string text
- width: Math.max(94,label.width + editor.width + 20)
+ width: Math.max(94,labeltext.width + editor.width + 20)
height: buttonImage.height
states: [
State {
name: "Edit"
PropertyChanges {
- target: label
+ target: labeltext
text: container.label + ": "
}
PropertyChanges {
- target: label
+ target: labeltext
x: 10
}
PropertyChanges {
@@ -78,7 +78,7 @@ Item {
}
Text {
- id: label
+ id: labeltext
font.bold: true
color: "white"
anchors.verticalCenter: container.verticalCenter
@@ -93,7 +93,7 @@ Item {
selectionColor: "green"
width: 0
clip: true
- anchors.left: label.right
+ anchors.left: labeltext.right
anchors.verticalCenter: container.verticalCenter
}
Keys.forwardTo: [(returnKey), (editor)]
diff --git a/demos/declarative/samegame/content/samegame.js b/demos/declarative/samegame/content/samegame.js
index ba2346f..15bafc4 100755
--- a/demos/declarative/samegame/content/samegame.js
+++ b/demos/declarative/samegame/content/samegame.js
@@ -21,9 +21,14 @@ function timeStr(msecs) {
return ret;
}
+function getTileSize()
+{
+ return tileSize;
+}
+
function initBoard()
{
- for(i = 0; i<maxIndex; i++){
+ for(var i = 0; i<maxIndex; i++){
//Delete old blocks
if(board[i] != null)
board[i].destroy();
@@ -38,16 +43,19 @@ function initBoard()
scoreName.forceClose();
dialog.forceClose();
+ var a = new Date();
//Initialize Board
board = new Array(maxIndex);
gameCanvas.score = 0;
- for(xIdx=0; xIdx<maxX; xIdx++){
- for(yIdx=0; yIdx<maxY; yIdx++){
+ for(var xIdx=0; xIdx<maxX; xIdx++){
+ for(var yIdx=0; yIdx<maxY; yIdx++){
board[index(xIdx,yIdx)] = null;
createBlock(xIdx,yIdx);
}
}
timer = new Date();
+
+ print(timer.valueOf() - a.valueOf());
}
var fillFound;//Set after a floodFill call to the number of tiles found
@@ -55,8 +63,8 @@ var floodBoard;//Set to 1 if the floodFill reaches off that node
//NOTE: Be careful with vars named x,y, as the calling object's x,y are still in scope
function handleClick(x,y)
{
- xIdx = Math.floor(x/gameCanvas.tileSize);
- yIdx = Math.floor(y/gameCanvas.tileSize);
+ var xIdx = Math.floor(x/gameCanvas.tileSize);
+ var yIdx = Math.floor(y/gameCanvas.tileSize);
if(xIdx >= maxX || xIdx < 0 || yIdx >= maxY || yIdx < 0)
return;
if(board[index(xIdx, yIdx)] == null)
@@ -102,14 +110,14 @@ function floodFill(xIdx,yIdx,type)
function shuffleDown()
{
//Fall down
- for(xIdx=0; xIdx<maxX; xIdx++){
- fallDist = 0;
- for(yIdx=maxY-1; yIdx>=0; yIdx--){
+ for(var xIdx=0; xIdx<maxX; xIdx++){
+ var fallDist = 0;
+ for(var yIdx=maxY-1; yIdx>=0; yIdx--){
if(board[index(xIdx,yIdx)] == null){
fallDist += 1;
}else{
if(fallDist > 0){
- obj = board[index(xIdx,yIdx)];
+ var obj = board[index(xIdx,yIdx)];
obj.targetY += fallDist * gameCanvas.tileSize;
board[index(xIdx,yIdx+fallDist)] = obj;
board[index(xIdx,yIdx)] = null;
@@ -140,8 +148,8 @@ function shuffleDown()
function victoryCheck()
{
//awards bonuses for no tiles left
- deservesBonus = true;
- for(xIdx=maxX-1; xIdx>=0; xIdx--)
+ var deservesBonus = true;
+ for(var xIdx=maxX-1; xIdx>=0; xIdx--)
if(board[index(xIdx, maxY - 1)] != null)
deservesBonus = false;
if(deservesBonus)
@@ -163,7 +171,7 @@ function floodMoveCheck(xIdx, yIdx, type)
return false;
if(board[index(xIdx, yIdx)] == null)
return false;
- myType = board[index(xIdx, yIdx)].type;
+ var myType = board[index(xIdx, yIdx)].type;
if(type == myType)
return true;
return floodMoveCheck(xIdx + 1, yIdx, myType) ||
@@ -171,7 +179,7 @@ function floodMoveCheck(xIdx, yIdx, type)
}
function createBlock(xIdx,yIdx){
- if(component==null)
+ if(component==null)
component = createComponent(tileSrc);
// Note that we don't wait for the component to become ready. This will
@@ -179,7 +187,7 @@ function createBlock(xIdx,yIdx){
// not be ready immediately. There is a statusChanged signal on the
// component you could use if you want to wait to load remote files.
if(component.isReady){
- dynamicObject = component.createObject();
+ var dynamicObject = component.createObject();
if(dynamicObject == null){
print("error creating block");
print(component.errorsString());
diff --git a/demos/declarative/samegame/samegame.qml b/demos/declarative/samegame/samegame.qml
index 709f4e9..ea7c14c 100644
--- a/demos/declarative/samegame/samegame.qml
+++ b/demos/declarative/samegame/samegame.qml
@@ -5,8 +5,6 @@ Rectangle {
id: screen
width: 490; height: 720
- Script { source: "content/samegame.js" }
-
SystemPalette { id: activePalette; colorGroup: Qt.Active }
Item {
@@ -23,9 +21,11 @@ Rectangle {
property int score: 0
property int tileSize: 40
+ Script { source: "content/samegame.js" }
+
z: 20; anchors.centerIn: parent
- width: parent.width - (parent.width % tileSize);
- height: parent.height - (parent.height % tileSize);
+ width: parent.width - (parent.width % getTileSize());
+ height: parent.height - (parent.height % getTileSize());
MouseRegion {
id: gameMR
diff --git a/demos/declarative/webbrowser/fieldtext/FieldText.qml b/demos/declarative/webbrowser/fieldtext/FieldText.qml
index fe55185..2adfbbf 100644
--- a/demos/declarative/webbrowser/fieldtext/FieldText.qml
+++ b/demos/declarative/webbrowser/fieldtext/FieldText.qml
@@ -10,7 +10,6 @@ Item {
signal cancelled
signal startEdit
- resources: [
Script {
function edit() {
@@ -36,7 +35,6 @@ Item {
}
}
- ]
Image {
id: cancelIcon
diff --git a/examples/declarative/layouts/Button.qml b/examples/declarative/layouts/Button.qml
index 186512b..44d0c7b 100644
--- a/examples/declarative/layouts/Button.qml
+++ b/examples/declarative/layouts/Button.qml
@@ -1,31 +1,18 @@
import Qt 4.6
-Rectangle {
- id: page
- border.color: "black"
- color: "steelblue"
- radius: 5
- width: pix.width + text.width + 13
- height: pix.height + 10
+Rectangle { border.color: "black"; color: "steelblue"; radius: 5; width: pix.width + textelement.width + 13; height: pix.height + 10; id: page
property string text
property string icon
signal clicked
Image { id: pix; x: 5; y:5; source: parent.icon}
-
- Text { id: text; text: page.text; color: "white"; x:pix.width+pix.x+3; anchors.verticalCenter: pix.verticalCenter;}
-
- MouseRegion {
- id: mr
- anchors.fill: parent
- onClicked: { parent.focus = true; page.clicked() }
- }
+ Text { id: textelement; text: page.text; color: "white"; x:pix.width+pix.x+3; anchors.verticalCenter: pix.verticalCenter;}
+ MouseRegion{ id:mr; anchors.fill: parent; onClicked: {parent.focus = true; page.clicked()}}
states:
- State {
- name: "pressed"; when: mr.pressed
- PropertyChanges { target:text; x: 5 }
- PropertyChanges { target:pix; x:text.x+text.width + 3 }
+ State{ name:"pressed"; when:mr.pressed
+ PropertyChanges {target:textelement; x: 5}
+ PropertyChanges {target:pix; x:textelement.x+textelement.width + 3}
}
transitions:
diff --git a/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/1/RemoveButton.qml b/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/1/RemoveButton.qml
deleted file mode 100644
index a8ac7fe..0000000
--- a/examples/declarative/tutorials/contacts/1_Drawing_and_Animation/1/RemoveButton.qml
+++ /dev/null
@@ -1,11 +0,0 @@
-import Qt 4.6
-
-//! [0]
-Rectangle {
- id: removeButton
- width: 30
- height: 30
- color: "red"
- radius: 5
-}
-//! [0]
diff --git a/examples/declarative/webview/content/FieldText.qml b/examples/declarative/webview/content/FieldText.qml
index fe55185..2adfbbf 100644
--- a/examples/declarative/webview/content/FieldText.qml
+++ b/examples/declarative/webview/content/FieldText.qml
@@ -10,7 +10,6 @@ Item {
signal cancelled
signal startEdit
- resources: [
Script {
function edit() {
@@ -36,7 +35,6 @@ Item {
}
}
- ]
Image {
id: cancelIcon
diff --git a/examples/declarative/xmldata/yahoonews.qml b/examples/declarative/xmldata/yahoonews.qml
index bad1d88..6d43f46 100644
--- a/examples/declarative/xmldata/yahoonews.qml
+++ b/examples/declarative/xmldata/yahoonews.qml
@@ -32,7 +32,7 @@ Rectangle {
height: wrapper.height + 10
MouseRegion {
anchors.fill: wrapper
- onPressed: { delegate.ListView.list.currentIndex = index; }
+ onPressed: { delegate.ListView.view.currentIndex = index; }
onClicked: { if (wrapper.state == 'Details') { wrapper.state = '';} else {wrapper.state = 'Details';} }
}
Rectangle {
diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Executable.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Executable.cpp
index 7586746..2457e71 100644
--- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Executable.cpp
+++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Executable.cpp
@@ -59,13 +59,8 @@ FunctionExecutable::~FunctionExecutable()
delete m_codeBlock;
}
-JSObject* EvalExecutable::compile(ExecState* exec, ScopeChainNode* scopeChainNode)
+void EvalExecutable::compile(ExecState*exec, RefPtr<EvalNode> &evalNode, ScopeChainNode* scopeChainNode)
{
- int errLine;
- UString errMsg;
- RefPtr<EvalNode> evalNode = exec->globalData().parser->parse<EvalNode>(&exec->globalData(), exec->lexicalGlobalObject()->debugger(), exec, m_source, &errLine, &errMsg);
- if (!evalNode)
- return Error::create(exec, SyntaxError, errMsg, errLine, m_source.provider()->asID(), m_source.provider()->url());
recordParse(evalNode->features(), evalNode->lineNo(), evalNode->lastLine());
ScopeChain scopeChain(scopeChainNode);
@@ -75,7 +70,18 @@ JSObject* EvalExecutable::compile(ExecState* exec, ScopeChainNode* scopeChainNod
m_evalCodeBlock = new EvalCodeBlock(this, globalObject, source().provider(), scopeChain.localDepth());
OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(evalNode.get(), globalObject->debugger(), scopeChain, m_evalCodeBlock->symbolTable(), m_evalCodeBlock));
generator->generate();
-
+}
+
+JSObject* EvalExecutable::compile(ExecState* exec, ScopeChainNode* scopeChainNode)
+{
+ int errLine;
+ UString errMsg;
+ RefPtr<EvalNode> evalNode = exec->globalData().parser->parse<EvalNode>(&exec->globalData(), exec->lexicalGlobalObject()->debugger(), exec, m_source, &errLine, &errMsg);
+ if (!evalNode)
+ return Error::create(exec, SyntaxError, errMsg, errLine, m_source.provider()->asID(), m_source.provider()->url());
+
+ compile(exec, evalNode, scopeChainNode);
+
evalNode->destroyData();
return 0;
}
diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Executable.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Executable.h
index 76764f9..92eb5dc 100644
--- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Executable.h
+++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Executable.h
@@ -176,6 +176,7 @@ namespace JSC {
}
JSObject* compile(ExecState*, ScopeChainNode*);
+ void compile(ExecState*, RefPtr<EvalNode> &, ScopeChainNode*);
ExceptionInfo* reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*);
static PassRefPtr<EvalExecutable> create(ExecState* exec, const SourceCode& source) { return adoptRef(new EvalExecutable(exec, source)); }
diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp
index 2769040..a8c3504 100644
--- a/src/corelib/animation/qabstractanimation.cpp
+++ b/src/corelib/animation/qabstractanimation.cpp
@@ -231,7 +231,8 @@ void QUnifiedTimer::registerAnimation(QAbstractAnimation *animation)
Q_ASSERT(!QAbstractAnimationPrivate::get(animation)->hasRegisteredTimer);
QAbstractAnimationPrivate::get(animation)->hasRegisteredTimer = true;
animationsToStart << animation;
- startStopAnimationTimer.start(STARTSTOP_TIMER_DELAY, this);
+ if (!startStopAnimationTimer.isActive())
+ startStopAnimationTimer.start(STARTSTOP_TIMER_DELAY, this);
}
void QUnifiedTimer::unregisterAnimation(QAbstractAnimation *animation)
@@ -245,11 +246,12 @@ void QUnifiedTimer::unregisterAnimation(QAbstractAnimation *animation)
// this is needed if we unregister an animation while its running
if (idx <= currentAnimationIdx)
--currentAnimationIdx;
- if (animations.isEmpty())
+ if (animations.isEmpty() && !startStopAnimationTimer.isActive())
startStopAnimationTimer.start(STARTSTOP_TIMER_DELAY, this);
} else {
animationsToStart.removeOne(animation);
}
+
QAbstractAnimationPrivate::get(animation)->hasRegisteredTimer = false;
}
diff --git a/src/declarative/fx/qfxgraphicsobjectcontainer.cpp b/src/declarative/fx/qfxgraphicsobjectcontainer.cpp
index c0cac6c..5a61d12 100644
--- a/src/declarative/fx/qfxgraphicsobjectcontainer.cpp
+++ b/src/declarative/fx/qfxgraphicsobjectcontainer.cpp
@@ -43,9 +43,42 @@
#include <QGraphicsObject>
#include <QGraphicsWidget>
#include <QGraphicsSceneResizeEvent>
+#include <private/qfxitem_p.h>
QT_BEGIN_NAMESPACE
+class QFxGraphicsObjectContainerPrivate : public QFxItemPrivate
+{
+ Q_DECLARE_PUBLIC(QFxGraphicsObjectContainer)
+
+public:
+ QFxGraphicsObjectContainerPrivate() : QFxItemPrivate(), graphicsObject(0), syncedResize(false)
+ { }
+
+ void _q_updateSize();
+
+ void setFiltering(bool on)
+ {
+ Q_Q(QFxGraphicsObjectContainer);
+ if (graphicsObject && graphicsObject->isWidget()) {
+ if (!on) {
+ graphicsObject->removeEventFilter(q);
+ QObject::disconnect(q, SIGNAL(widthChanged()), q, SLOT(_q_updateSize()));
+ QObject::disconnect(q, SIGNAL(heightChanged()), q, SLOT(_q_updateSize()));
+ } else {
+ graphicsObject->installEventFilter(q);
+ QObject::connect(q, SIGNAL(widthChanged()), q, SLOT(_q_updateSize()));
+ QObject::connect(q, SIGNAL(heightChanged()), q, SLOT(_q_updateSize()));
+ }
+ }
+ }
+
+
+ QGraphicsObject *graphicsObject;
+ bool syncedResize;
+};
+
+
/*!
\qmlclass GraphicsObjectContainer QFxGraphicsObjectContainer
\brief The GraphicsObjectContainer element allows you to add QGraphicsObjects into Fluid UI elements.
@@ -61,7 +94,7 @@ QML_DEFINE_NOCREATE_TYPE(QGraphicsObject)
QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,GraphicsObjectContainer,QFxGraphicsObjectContainer)
QFxGraphicsObjectContainer::QFxGraphicsObjectContainer(QFxItem *parent)
-: QFxItem(parent), _graphicsObject(0), _syncedResize(false)
+: QFxItem(*new QFxGraphicsObjectContainerPrivate, parent)
{
}
@@ -71,7 +104,8 @@ QFxGraphicsObjectContainer::~QFxGraphicsObjectContainer()
QGraphicsObject *QFxGraphicsObjectContainer::graphicsObject() const
{
- return _graphicsObject;
+ Q_D(const QFxGraphicsObjectContainer);
+ return d->graphicsObject;
}
/*!
@@ -80,30 +114,45 @@ QGraphicsObject *QFxGraphicsObjectContainer::graphicsObject() const
*/
void QFxGraphicsObjectContainer::setGraphicsObject(QGraphicsObject *object)
{
- if (object == _graphicsObject)
+ Q_D(QFxGraphicsObjectContainer);
+ if (object == d->graphicsObject)
return;
- //### what should we do with previously set object?
+ //### remove previously set item?
+
+ d->setFiltering(false);
+
+ d->graphicsObject = object;
- _graphicsObject = object;
+ if (d->graphicsObject) {
+ d->graphicsObject->setParentItem(this);
- if (_graphicsObject) {
- _graphicsObject->setParentItem(this);
+ if (d->syncedResize && d->graphicsObject->isWidget()) {
+ QGraphicsWidget *gw = static_cast<QGraphicsWidget*>(d->graphicsObject);
+ QSizeF gwSize = gw->size(); //### should we use sizeHint?
+ QSizeF newSize = gwSize;
+ if (heightValid())
+ newSize.setHeight(height());
+ if (widthValid())
+ newSize.setWidth(width());
+ if (gwSize != newSize)
+ gw->resize(newSize);
- if (_syncedResize && _graphicsObject->isWidget()) {
- _graphicsObject->installEventFilter(this);
- QSizeF newSize = static_cast<QGraphicsWidget*>(_graphicsObject)->size(); //### use sizeHint?
- setImplicitWidth(newSize.width());
- setImplicitHeight(newSize.height());
+ gwSize = gw->size();
+ setImplicitWidth(gwSize.width());
+ setImplicitHeight(gwSize.height());
+
+ d->setFiltering(true);
}
}
}
QVariant QFxGraphicsObjectContainer::itemChange(GraphicsItemChange change, const QVariant &value)
{
+ Q_D(QFxGraphicsObjectContainer);
if (change == ItemSceneHasChanged) {
- QGraphicsObject *o = _graphicsObject;
- _graphicsObject = 0;
+ QGraphicsObject *o = d->graphicsObject;
+ d->graphicsObject = 0;
setGraphicsObject(o);
}
return QFxItem::itemChange(change, value);
@@ -111,9 +160,10 @@ QVariant QFxGraphicsObjectContainer::itemChange(GraphicsItemChange change, const
bool QFxGraphicsObjectContainer::eventFilter(QObject *watched, QEvent *e)
{
- if (watched == _graphicsObject && e->type() == QEvent::GraphicsSceneResize) {
- if (_graphicsObject && _graphicsObject->isWidget() && _syncedResize) {
- QSizeF newSize = static_cast<QGraphicsWidget*>(_graphicsObject)->size();
+ Q_D(QFxGraphicsObjectContainer);
+ if (watched == d->graphicsObject && e->type() == QEvent::GraphicsSceneResize) {
+ if (d->graphicsObject && d->graphicsObject->isWidget() && d->syncedResize) {
+ QSizeF newSize = static_cast<QGraphicsWidget*>(d->graphicsObject)->size();
setImplicitWidth(newSize.width());
setImplicitHeight(newSize.height());
}
@@ -142,40 +192,27 @@ bool QFxGraphicsObjectContainer::eventFilter(QObject *watched, QEvent *e)
*/
bool QFxGraphicsObjectContainer::synchronizedResizing() const
{
- return _syncedResize;
+ Q_D(const QFxGraphicsObjectContainer);
+ return d->syncedResize;
}
void QFxGraphicsObjectContainer::setSynchronizedResizing(bool on)
{
- if (on == _syncedResize)
+ Q_D(QFxGraphicsObjectContainer);
+ if (on == d->syncedResize)
return;
- if (_graphicsObject && _graphicsObject->isWidget()) {
- if (!on) {
- _graphicsObject->removeEventFilter(this);
- disconnect(this, SIGNAL(widthChanged()), this, SLOT(_q_updateSize()));
- disconnect(this, SIGNAL(heightChanged()), this, SLOT(_q_updateSize()));
- }
- }
-
- _syncedResize = on;
-
- if (_graphicsObject && _graphicsObject->isWidget()) {
- if (on) {
- _graphicsObject->installEventFilter(this);
- connect(this, SIGNAL(widthChanged()), this, SLOT(_q_updateSize()));
- connect(this, SIGNAL(heightChanged()), this, SLOT(_q_updateSize()));
- }
- }
+ d->syncedResize = on;
+ d->setFiltering(on);
}
-void QFxGraphicsObjectContainer::_q_updateSize()
+void QFxGraphicsObjectContainerPrivate::_q_updateSize()
{
- if (!_graphicsObject || !_graphicsObject->isWidget() || !_syncedResize)
+ if (!graphicsObject || !graphicsObject->isWidget() || !syncedResize)
return;
- QGraphicsWidget *gw = static_cast<QGraphicsWidget*>(_graphicsObject);
- const QSizeF newSize(width(), height());
+ QGraphicsWidget *gw = static_cast<QGraphicsWidget*>(graphicsObject);
+ const QSizeF newSize(width, height);
gw->resize(newSize);
//### will respecting the widgets min/max ever get us in trouble? (all other items always
@@ -189,3 +226,5 @@ void QFxGraphicsObjectContainer::_q_updateSize()
}
QT_END_NAMESPACE
+
+#include "moc_qfxgraphicsobjectcontainer.cpp"
diff --git a/src/declarative/fx/qfxgraphicsobjectcontainer.h b/src/declarative/fx/qfxgraphicsobjectcontainer.h
index a8b7c8c..656a7f8 100644
--- a/src/declarative/fx/qfxgraphicsobjectcontainer.h
+++ b/src/declarative/fx/qfxgraphicsobjectcontainer.h
@@ -51,6 +51,7 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Declarative)
class QGraphicsObject;
+class QFxGraphicsObjectContainerPrivate;
class Q_DECLARATIVE_EXPORT QFxGraphicsObjectContainer : public QFxItem
{
@@ -74,12 +75,9 @@ protected:
QVariant itemChange(GraphicsItemChange change, const QVariant &value);
bool eventFilter(QObject *watched, QEvent *e);
-private Q_SLOTS:
- void _q_updateSize();
-
private:
- QGraphicsObject *_graphicsObject;
- bool _syncedResize;
+ Q_PRIVATE_SLOT(d_func(), void _q_updateSize())
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QFxGraphicsObjectContainer)
};
QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxgridview.cpp b/src/declarative/fx/qfxgridview.cpp
index a8b27f4..2d25d56 100644
--- a/src/declarative/fx/qfxgridview.cpp
+++ b/src/declarative/fx/qfxgridview.cpp
@@ -149,7 +149,7 @@ class QFxGridViewPrivate : public QFxFlickablePrivate
public:
QFxGridViewPrivate()
- : model(0), currentItem(0), tmpCurrent(0), flow(QFxGridView::LeftToRight)
+ : model(0), currentItem(0), flow(QFxGridView::LeftToRight)
, visiblePos(0), visibleIndex(0) , currentIndex(-1)
, cellWidth(100), cellHeight(100), columns(1), requestedIndex(-1)
, highlightComponent(0), highlight(0), trackedItem(0)
@@ -298,7 +298,6 @@ public:
QList<FxGridItem*> visibleItems;
QHash<QFxItem*,int> unrequestedItems;
FxGridItem *currentItem;
- QFxItem *tmpCurrent;
QFxGridView::Flow flow;
int visiblePos;
int visibleIndex;
@@ -640,10 +639,6 @@ void QFxGridViewPrivate::updateCurrent(int modelIndex)
return;
}
- if (tmpCurrent) {
- delete tmpCurrent;
- tmpCurrent = 0;
- }
FxGridItem *oldCurrentItem = currentItem;
currentIndex = modelIndex;
currentItem = createItem(modelIndex);
@@ -821,12 +816,8 @@ void QFxGridView::setCurrentIndex(int index)
QFxItem *QFxGridView::currentItem()
{
Q_D(QFxGridView);
- if (!d->currentItem) {
- // Always return something valid
- if (!d->tmpCurrent)
- d->tmpCurrent = new QFxItem(viewport());
- return d->tmpCurrent;
- }
+ if (!d->currentItem)
+ return 0;
return d->currentItem->item;
}
diff --git a/src/declarative/fx/qfxlistview.cpp b/src/declarative/fx/qfxlistview.cpp
index 1247021..5afd881 100644
--- a/src/declarative/fx/qfxlistview.cpp
+++ b/src/declarative/fx/qfxlistview.cpp
@@ -170,15 +170,15 @@ class QFxListViewPrivate : public QFxFlickablePrivate
public:
QFxListViewPrivate()
- : model(0), currentItem(0), tmpCurrent(0), orient(Qt::Vertical)
+ : model(0), currentItem(0), orient(Qt::Vertical)
, visiblePos(0), visibleIndex(0)
, averageSize(100.0), currentIndex(-1), requestedIndex(-1)
, highlightRangeStart(0), highlightRangeEnd(0)
, highlightComponent(0), highlight(0), trackedItem(0)
, moveReason(Other), buffer(0), highlightPosAnimator(0), highlightSizeAnimator(0), spacing(0.0)
+ , highlightMoveSpeed(400), highlightResizeSpeed(400)
, ownModel(false), wrap(false), autoHighlight(true)
, haveHighlightRange(false), strictHighlightRange(false)
- , highlightMoveSpeed(400), highlightResizeSpeed(400)
{}
void init();
@@ -371,7 +371,6 @@ public:
QList<FxListItem*> visibleItems;
QHash<QFxItem*,int> unrequestedItems;
FxListItem *currentItem;
- QFxItem *tmpCurrent;
Qt::Orientation orient;
int visiblePos;
int visibleIndex;
@@ -752,10 +751,6 @@ void QFxListViewPrivate::updateCurrent(int modelIndex)
return;
}
- if (tmpCurrent) {
- delete tmpCurrent;
- tmpCurrent = 0;
- }
FxListItem *oldCurrentItem = currentItem;
currentIndex = modelIndex;
currentItem = createItem(modelIndex);
@@ -991,14 +986,8 @@ void QFxListView::setCurrentIndex(int index)
QFxItem *QFxListView::currentItem()
{
Q_D(QFxListView);
- if (!d->currentItem) {
- // Always return something valid
- if (!d->tmpCurrent) {
- d->tmpCurrent = new QFxItem;
- d->tmpCurrent->setParent(viewport());
- }
- return d->tmpCurrent;
- }
+ if (!d->currentItem)
+ return 0;
return d->currentItem->item;
}
diff --git a/src/declarative/fx/qfxvisualitemmodel.cpp b/src/declarative/fx/qfxvisualitemmodel.cpp
index b7248ea..943f909 100644
--- a/src/declarative/fx/qfxvisualitemmodel.cpp
+++ b/src/declarative/fx/qfxvisualitemmodel.cpp
@@ -239,6 +239,10 @@ class QFxVisualDataModelPrivate : public QObjectPrivate
public:
QFxVisualDataModelPrivate(QmlContext *);
+ static QFxVisualDataModelPrivate *get(QFxVisualDataModel *m) {
+ return static_cast<QFxVisualDataModelPrivate *>(QObjectPrivate::get(m));
+ }
+
QGuard<QListModelInterface> m_listModelInterface;
QGuard<QAbstractItemModel> m_abstractItemModel;
QGuard<QFxVisualDataModel> m_visualItemModel;
@@ -363,7 +367,8 @@ class QFxVisualDataModelData : public QObject
{
Q_OBJECT
public:
- QFxVisualDataModelData(int index, QFxVisualDataModelPrivate *model);
+ QFxVisualDataModelData(int index, QFxVisualDataModel *model);
+ ~QFxVisualDataModelData();
Q_PROPERTY(int index READ index NOTIFY indexChanged)
int index() const;
@@ -379,7 +384,7 @@ Q_SIGNALS:
private:
friend class QFxVisualDataModelDataMetaObject;
int m_index;
- QFxVisualDataModelPrivate *m_model;
+ QGuard<QFxVisualDataModel> m_model;
QFxVisualDataModelDataMetaObject *m_meta;
};
@@ -404,15 +409,19 @@ int QFxVisualDataModelDataMetaObject::createProperty(const char *name, const cha
QFxVisualDataModelData *data =
static_cast<QFxVisualDataModelData *>(object());
- if ((!data->m_model->m_listModelInterface || !data->m_model->m_abstractItemModel)
- && data->m_model->m_listAccessor) {
- data->m_model->ensureRoles();
- if (data->m_model->m_roleNames.contains(QLatin1String(name)))
+ if (!data->m_model)
+ return -1;
+
+ QFxVisualDataModelPrivate *model = QFxVisualDataModelPrivate::get(data->m_model);
+
+ if ((!model->m_listModelInterface || !model->m_abstractItemModel) && model->m_listAccessor) {
+ model->ensureRoles();
+ if (model->m_roleNames.contains(QLatin1String(name)))
return QmlOpenMetaObject::createProperty(name, type);
} else {
- data->m_model->ensureRoles();
+ model->ensureRoles();
const QLatin1String sname(name);
- if (data->m_model->m_roleNames.contains(sname))
+ if (model->m_roleNames.contains(sname))
return QmlOpenMetaObject::createProperty(name, type);
}
return -1;
@@ -425,45 +434,48 @@ QFxVisualDataModelDataMetaObject::propertyCreated(int, QMetaPropertyBuilder &pro
QFxVisualDataModelData *data =
static_cast<QFxVisualDataModelData *>(object());
+
+ Q_ASSERT(data->m_model);
+ QFxVisualDataModelPrivate *model = QFxVisualDataModelPrivate::get(data->m_model);
+
QString name = QLatin1String(prop.name());
- if ((!data->m_model->m_listModelInterface || !data->m_model->m_abstractItemModel)
- && data->m_model->m_listAccessor) {
+ if ((!model->m_listModelInterface || !model->m_abstractItemModel) && model->m_listAccessor) {
if (name == QLatin1String("modelData")) {
- if (data->m_model->m_listAccessor->type() == QmlListAccessor::Instance) {
- QObject *object = data->m_model->m_listAccessor->at(0).value<QObject*>();
+ if (model->m_listAccessor->type() == QmlListAccessor::Instance) {
+ QObject *object = model->m_listAccessor->at(0).value<QObject*>();
return object->metaObject()->property(1).read(object); // the first property after objectName
}
- return data->m_model->m_listAccessor->at(data->m_index);
+ return model->m_listAccessor->at(data->m_index);
} else {
// return any property of a single object instance.
- QObject *object = data->m_model->m_listAccessor->at(0).value<QObject*>();
+ QObject *object = model->m_listAccessor->at(0).value<QObject*>();
return object->property(prop.name());
}
- } else if (data->m_model->m_listModelInterface) {
- data->m_model->ensureRoles();
- QHash<QString,int>::const_iterator it = data->m_model->m_roleNames.find(name);
- if (it != data->m_model->m_roleNames.end()) {
+ } else if (model->m_listModelInterface) {
+ model->ensureRoles();
+ QHash<QString,int>::const_iterator it = model->m_roleNames.find(name);
+ if (it != model->m_roleNames.end()) {
roles.append(*it);
- QHash<int,QVariant> values = data->m_model->m_listModelInterface->data(data->m_index, QList<int>() << *it);
+ QHash<int,QVariant> values = model->m_listModelInterface->data(data->m_index, QList<int>() << *it);
if (values.isEmpty())
return QVariant();
else
return values.value(*it);
- } else if (data->m_model->m_roles.count() == 1 && name == QLatin1String("modelData")) {
+ } else if (model->m_roles.count() == 1 && name == QLatin1String("modelData")) {
//for compatability with other lists, assign modelData if there is only a single role
- QHash<int,QVariant> values = data->m_model->m_listModelInterface->data(data->m_index, QList<int>() << data->m_model->m_roles.first());
+ QHash<int,QVariant> values = model->m_listModelInterface->data(data->m_index, QList<int>() << model->m_roles.first());
if (values.isEmpty())
return QVariant();
else
return *values.begin();
}
- } else if (data->m_model->m_abstractItemModel) {
- data->m_model->ensureRoles();
- QHash<QString,int>::const_iterator it = data->m_model->m_roleNames.find(name);
- if (it != data->m_model->m_roleNames.end()) {
+ } else if (model->m_abstractItemModel) {
+ model->ensureRoles();
+ QHash<QString,int>::const_iterator it = model->m_roleNames.find(name);
+ if (it != model->m_roleNames.end()) {
roles.append(*it);
- QModelIndex index = data->m_model->m_abstractItemModel->index(data->m_index, 0);
- return data->m_model->m_abstractItemModel->data(index, *it);
+ QModelIndex index = model->m_abstractItemModel->index(data->m_index, 0);
+ return model->m_abstractItemModel->data(index, *it);
}
}
Q_ASSERT(!"Can never be reached");
@@ -471,12 +483,16 @@ QFxVisualDataModelDataMetaObject::propertyCreated(int, QMetaPropertyBuilder &pro
}
QFxVisualDataModelData::QFxVisualDataModelData(int index,
- QFxVisualDataModelPrivate *model)
+ QFxVisualDataModel *model)
: m_index(index), m_model(model),
m_meta(new QFxVisualDataModelDataMetaObject(this))
{
}
+QFxVisualDataModelData::~QFxVisualDataModelData()
+{
+}
+
int QFxVisualDataModelData::index() const
{
return m_index;
@@ -752,7 +768,7 @@ QFxItem *QFxVisualDataModel::item(int index, const QByteArray &viewId, bool comp
QmlContext *ccontext = d->m_context;
if (!ccontext) ccontext = qmlContext(this);
QmlContext *ctxt = new QmlContext(ccontext);
- QFxVisualDataModelData *data = new QFxVisualDataModelData(index, d);
+ QFxVisualDataModelData *data = new QFxVisualDataModelData(index, this);
ctxt->setContextProperty(QLatin1String("model"), data);
ctxt->addDefaultObject(data);
nobj = d->m_delegate->beginCreate(ctxt);
@@ -821,7 +837,7 @@ QVariant QFxVisualDataModel::evaluate(int index, const QString &expression, QObj
QmlContext *ccontext = d->m_context;
if (!ccontext) ccontext = qmlContext(this);
QmlContext *ctxt = new QmlContext(ccontext);
- QFxVisualDataModelData *data = new QFxVisualDataModelData(index, d);
+ QFxVisualDataModelData *data = new QFxVisualDataModelData(index, this);
ctxt->addDefaultObject(data);
QmlExpression e(ctxt, expression, objectContext);
e.setTrackChange(false);
diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri
index 8349e29..a2e2050 100644
--- a/src/declarative/qml/qml.pri
+++ b/src/declarative/qml/qml.pri
@@ -34,7 +34,16 @@ SOURCES += qml/qmlparser.cpp \
qml/qmlxmlhttprequest.cpp \
qml/qmlsqldatabase.cpp \
qml/qmetaobjectbuilder.cpp \
- qml/qmlwatcher.cpp
+ qml/qmlwatcher.cpp \
+ qml/qmlscript.cpp \
+ qml/qmlpropertycache.cpp \
+ qml/qmlintegercache.cpp \
+ qml/qmltypenamecache.cpp \
+ qml/qmlobjectscriptclass.cpp \
+ qml/qmlcontextscriptclass.cpp \
+ qml/qmlglobalscriptclass.cpp \
+ qml/qmlvaluetypescriptclass.cpp \
+ qml/qmltypenamescriptclass.cpp
HEADERS += qml/qmlparser_p.h \
qml/qmlinstruction_p.h \
@@ -86,7 +95,15 @@ HEADERS += qml/qmlparser_p.h \
qml/qmlxmlhttprequest_p.h \
qml/qmlsqldatabase_p.h \
qml/qmetaobjectbuilder_p.h \
- qml/qmlwatcher_p.h
+ qml/qmlwatcher_p.h \
+ qml/qmlpropertycache_p.h \
+ qml/qmlintegercache_p.h \
+ qml/qmltypenamecache_p.h \
+ qml/qmlobjectscriptclass_p.h \
+ qml/qmlcontextscriptclass_p.h \
+ qml/qmlglobalscriptclass_p.h \
+ qml/qmlvaluetypescriptclass_p.h \
+ qml/qmltypenamescriptclass_p.h
# for qtscript debugger
contains(QT_CONFIG, scripttools):QT += scripttools
diff --git a/src/declarative/qml/qmlbinding.cpp b/src/declarative/qml/qmlbinding.cpp
index 454369b..3a34f46 100644
--- a/src/declarative/qml/qmlbinding.cpp
+++ b/src/declarative/qml/qmlbinding.cpp
@@ -57,11 +57,16 @@ QT_BEGIN_NAMESPACE
QML_DEFINE_NOCREATE_TYPE(QmlBinding);
-QmlBindingPrivate::QmlBindingPrivate()
+QmlBindingData::QmlBindingData()
: updating(false), enabled(false)
{
}
+QmlBindingPrivate::QmlBindingPrivate()
+: QmlExpressionPrivate(new QmlBindingData)
+{
+}
+
QmlBinding::QmlBinding(void *data, QmlRefCount *rc, QObject *obj, QmlContext *ctxt, QObject *parent)
: QmlExpression(ctxt, data, rc, obj, *new QmlBindingPrivate)
{
@@ -81,7 +86,7 @@ QmlBinding::~QmlBinding()
void QmlBinding::setTarget(const QmlMetaProperty &prop)
{
Q_D(QmlBinding);
- d->property = prop;
+ d->bindingData()->property = prop;
update();
}
@@ -89,7 +94,7 @@ void QmlBinding::setTarget(const QmlMetaProperty &prop)
QmlMetaProperty QmlBinding::property() const
{
Q_D(const QmlBinding);
- return d->property;
+ return d->bindingData()->property;
}
void QmlBinding::update()
@@ -99,45 +104,41 @@ void QmlBinding::update()
#ifdef Q_ENABLE_PERFORMANCE_LOG
QFxPerfTimer<QFxPerf::BindableValueUpdate> bu;
#endif
- if (!d->enabled)
+ QmlBindingData *data = d->bindingData();
+
+ if (!data->enabled)
return;
- if (!d->updating) {
- d->updating = true;
+ data->addref();
- if (d->property.propertyCategory() == QmlMetaProperty::Bindable) {
+ if (!data->updating) {
+ data->updating = true;
- int idx = d->property.coreIndex();
+ if (data->property.propertyCategory() == QmlMetaProperty::Bindable) {
+
+ int idx = data->property.coreIndex();
Q_ASSERT(idx != -1);
void *a[1];
QmlBinding *t = this;
a[0] = (void *)&t;
- QMetaObject::metacall(d->property.object(),
+ QMetaObject::metacall(data->property.object(),
QMetaObject::WriteProperty,
idx, a);
} else {
QVariant value = this->value();
- if (value.type() == QVariant::String) {
- QmlMetaType::StringConverter con = QmlMetaType::customStringConverter(d->property.propertyType());
- if (con)
- value = con(value.toString());
- }
-
- if (d->property.propertyType() == QVariant::Vector3D &&
- value.type() == QVariant::String) {
- value = qVariantFromValue(QmlStringConverters::vector3DFromString(value.toString()));
- }
-
- d->property.write(value, QmlMetaProperty::Binding);
+ data->property.write(value, QmlMetaProperty::Binding);
}
- d->updating = false;
+ data->updating = false;
} else {
- qmlInfo(d->property.object()) << "Binding loop detected for property" << d->property.name();
+ qmlInfo(data->property.object()) << "Binding loop detected for property"
+ << data->property.name();
}
+
+ data->release();
}
void QmlBinding::valueChanged()
@@ -148,30 +149,30 @@ void QmlBinding::valueChanged()
void QmlBinding::setEnabled(bool e)
{
Q_D(QmlBinding);
- d->enabled = e;
+ d->bindingData()->enabled = e;
setTrackChange(e);
+ QmlAbstractBinding::setEnabled(e);
+
if (e) {
- addToObject(d->property.object());
+ addToObject(d->bindingData()->property.object());
update();
} else {
removeFromObject();
}
-
- QmlAbstractBinding::setEnabled(e);
}
int QmlBinding::propertyIndex()
{
Q_D(QmlBinding);
- return d->property.coreIndex();
+ return d->bindingData()->property.coreIndex();
}
bool QmlBinding::enabled() const
{
Q_D(const QmlBinding);
- return d->enabled;
+ return d->bindingData()->enabled;
}
QString QmlBinding::expression() const
diff --git a/src/declarative/qml/qmlbinding.h b/src/declarative/qml/qmlbinding.h
index 675917d..e3a297c 100644
--- a/src/declarative/qml/qmlbinding.h
+++ b/src/declarative/qml/qmlbinding.h
@@ -73,6 +73,7 @@ public:
private:
friend class QmlDeclarativeData;
friend class QmlMetaProperty;
+ friend class QmlMetaPropertyPrivate;
friend class QmlVME;
QObject *m_object;
diff --git a/src/declarative/qml/qmlbinding_p.h b/src/declarative/qml/qmlbinding_p.h
index 963e2c1..2c0c6b9 100644
--- a/src/declarative/qml/qmlbinding_p.h
+++ b/src/declarative/qml/qmlbinding_p.h
@@ -59,11 +59,10 @@
QT_BEGIN_NAMESPACE
-class QmlBindingPrivate : public QmlExpressionPrivate
+class QmlBindingData : public QmlExpressionData
{
- Q_DECLARE_PUBLIC(QmlBinding)
public:
- QmlBindingPrivate();
+ QmlBindingData();
bool updating:1;
bool enabled:1;
@@ -71,6 +70,16 @@ public:
QmlMetaProperty property;
};
+class QmlBindingPrivate : public QmlExpressionPrivate
+{
+ Q_DECLARE_PUBLIC(QmlBinding)
+public:
+ QmlBindingPrivate();
+
+ QmlBindingData *bindingData() { return static_cast<QmlBindingData *>(data); }
+ const QmlBindingData *bindingData() const { return static_cast<const QmlBindingData *>(data); }
+};
+
QT_END_NAMESPACE
#endif // QMLBINDING_P_H
diff --git a/src/declarative/qml/qmlcompileddata.cpp b/src/declarative/qml/qmlcompileddata.cpp
index b2e2d40..8c3c355 100644
--- a/src/declarative/qml/qmlcompileddata.cpp
+++ b/src/declarative/qml/qmlcompileddata.cpp
@@ -150,6 +150,7 @@ int QmlCompiledData::indexForLocation(const QmlParser::LocationSpan &l)
}
QmlCompiledData::QmlCompiledData()
+: importCache(0)
{
}
@@ -159,6 +160,14 @@ QmlCompiledData::~QmlCompiledData()
if (types.at(ii).ref)
types.at(ii).ref->release();
}
+
+ for (int ii = 0; ii < propertyCaches.count(); ++ii)
+ propertyCaches.at(ii)->release();
+
+ if (importCache)
+ importCache->release();
+
+ qDeleteAll(programs);
}
QObject *QmlCompiledData::TypeReference::createInstance(QmlContext *ctxt, const QBitField &bindings) const
diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp
index 02cd813..12e8101 100644
--- a/src/declarative/qml/qmlcompiler.cpp
+++ b/src/declarative/qml/qmlcompiler.cpp
@@ -633,7 +633,7 @@ void QmlCompiler::compileTree(Object *tree)
init.line = 0;
init.init.bindingsSize = compileState.bindings.count();
init.init.parserStatusSize = compileState.parserStatusCount;
- init.init.idSize = compileState.ids.count();
+ init.init.contextCache = genContextCache();
output->bytecode << init;
genObject(tree);
@@ -644,10 +644,11 @@ void QmlCompiler::compileTree(Object *tree)
output->bytecode << def;
output->imports = unit->imports;
+ output->importCache = output->imports.cache(engine);
Q_ASSERT(tree->metatype);
static_cast<QMetaObject &>(output->root) = *tree->metaObject();
- if (!tree->metadata.isEmpty())
+ if (!tree->metadata.isEmpty())
QmlEnginePrivate::get(engine)->registerCompositeType(output);
}
@@ -668,7 +669,11 @@ bool QmlCompiler::buildObject(Object *obj, const BindingContext &ctxt)
if (obj->metatype == &QmlComponent::staticMetaObject) {
COMPILE_CHECK(buildComponent(obj, ctxt));
return true;
- }
+ }
+
+ // Build any script blocks for this type
+ for (int ii = 0; ii < obj->scriptBlockObjects.count(); ++ii)
+ COMPILE_CHECK(buildScript(obj, obj->scriptBlockObjects.at(ii)));
// Object instantiations reset the binding context
BindingContext objCtxt(obj);
@@ -807,7 +812,9 @@ void QmlCompiler::genObject(QmlParser::Object *obj)
meta.line = -1;
meta.storeMeta.data = output->indexForByteArray(obj->metadata);
meta.storeMeta.aliasData = output->indexForByteArray(obj->synthdata);
- meta.storeMeta.slotData = -1;
+ meta.storeMeta.propertyCache = output->propertyCaches.count();
+ // ### Surely the creation of this property cache could be more efficient
+ output->propertyCaches << QmlPropertyCache::create(engine, obj->metaObject());
output->bytecode << meta;
}
@@ -821,6 +828,15 @@ void QmlCompiler::genObject(QmlParser::Object *obj)
output->bytecode << id;
}
+ // Set any script blocks
+ for (int ii = 0; ii < obj->scriptBlocks.count(); ++ii) {
+ QmlInstruction script;
+ script.type = QmlInstruction::StoreScript;
+ script.line = -1; // ###
+ script.storeScript.value = output->indexForString(obj->scriptBlocks.at(ii));
+ output->bytecode << script;
+ }
+
// Begin the class
if (obj->parserStatusCast != -1) {
QmlInstruction begin;
@@ -962,7 +978,7 @@ void QmlCompiler::genComponent(QmlParser::Object *obj)
init.type = QmlInstruction::Init;
init.init.bindingsSize = compileState.bindings.count();
init.init.parserStatusSize = compileState.parserStatusCount;
- init.init.idSize = compileState.ids.count();
+ init.init.contextCache = genContextCache();
init.line = obj->location.start.line;
output->bytecode << init;
@@ -997,7 +1013,8 @@ bool QmlCompiler::buildComponent(QmlParser::Object *obj,
// Find, check and set the "id" property (if any)
Property *idProp = 0;
if (obj->properties.count() > 1 ||
- (obj->properties.count() == 1 && obj->properties.begin().key() != "id"))
+ (obj->properties.count() == 1 && obj->properties.begin().key() != "id") ||
+ !obj->scriptBlockObjects.isEmpty())
COMPILE_EXCEPTION(obj, "Invalid component specification");
if (obj->properties.count())
@@ -1034,6 +1051,66 @@ bool QmlCompiler::buildComponent(QmlParser::Object *obj,
return true;
}
+bool QmlCompiler::buildScript(QmlParser::Object *obj, QmlParser::Object *script)
+{
+ QString scriptCode;
+
+ if (script->properties.count() == 1 &&
+ script->properties.begin().key() == QByteArray("source")) {
+
+ Property *source = *script->properties.begin();
+ if (script->defaultProperty)
+ COMPILE_EXCEPTION(source, "Invalid Script block. Specify either the source property or inline script.");
+
+ if (source->value || source->values.count() != 1 ||
+ source->values.at(0)->object || !source->values.at(0)->value.isString())
+ COMPILE_EXCEPTION(source, "Invalid Script source value");
+
+ QString sourceUrl =
+ output->url.resolved(QUrl(source->values.at(0)->value.asString())).toString();
+
+ for (int ii = 0; ii < unit->resources.count(); ++ii) {
+ if (unit->resources.at(ii)->url == sourceUrl) {
+ scriptCode = QString::fromUtf8(unit->resources.at(ii)->data);
+ break;
+ }
+ }
+
+ } else if (!script->properties.isEmpty()) {
+ COMPILE_EXCEPTION(*script->properties.begin(), "Properties cannot be set on Script block");
+ } else if (script->defaultProperty) {
+ QmlParser::Location currentLocation;
+
+ for (int ii = 0; ii < script->defaultProperty->values.count(); ++ii) {
+ Value *v = script->defaultProperty->values.at(ii);
+ if (v->object || !v->value.isString())
+ COMPILE_EXCEPTION(v, "Invalid Script block");
+
+ if (ii == 0) {
+ currentLocation = v->location.start;
+ scriptCode.append(QString(currentLocation.column, QLatin1Char(' ')));
+ }
+
+ while (currentLocation.line < v->location.start.line) {
+ scriptCode.append(QLatin1String("\n"));
+ currentLocation.line++;
+ currentLocation.column = 0;
+ }
+
+ scriptCode.append(QString(v->location.start.column - currentLocation.column, QLatin1Char(' ')));
+
+ scriptCode += v->value.asString();
+ currentLocation = v->location.end;
+ currentLocation.column++;
+ }
+ }
+
+ if (!scriptCode.isEmpty())
+ obj->scriptBlocks.append(scriptCode);
+
+ return true;
+}
+
bool QmlCompiler::buildComponentFromRoot(QmlParser::Object *obj,
const BindingContext &ctxt)
{
@@ -2261,6 +2338,22 @@ void QmlCompiler::genBindingAssignment(QmlParser::Value *binding,
output->bytecode << store;
}
+int QmlCompiler::genContextCache()
+{
+ if (compileState.ids.count() == 0)
+ return -1;
+
+ QmlIntegerCache *cache = new QmlIntegerCache(engine);
+
+ for (QHash<QString, QmlParser::Object *>::ConstIterator iter = compileState.ids.begin();
+ iter != compileState.ids.end();
+ ++iter)
+ cache->add(iter.key(), (*iter)->idIndex);
+
+ output->contextCaches.append(cache);
+ return output->contextCaches.count() - 1;
+}
+
bool QmlCompiler::completeComponentBuild()
{
for (int ii = 0; ii < compileState.aliasingObjects.count(); ++ii) {
@@ -2296,7 +2389,10 @@ bool QmlCompiler::completeComponentBuild()
expression = rewriteBinding(expression);
quint32 length = expression.length();
+ quint32 pc = output->programs.length();
+ output->programs.append(0);
binding.compiledData =
+ QByteArray((const char *)&pc, sizeof(quint32)) +
QByteArray((const char *)&length, sizeof(quint32)) +
QByteArray((const char *)expression.constData(),
expression.length() * sizeof(QChar));
diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h
index 00637e3..1d27342 100644
--- a/src/declarative/qml/qmlcompiler_p.h
+++ b/src/declarative/qml/qmlcompiler_p.h
@@ -62,6 +62,9 @@
#include <private/qmlparser_p.h>
#include <private/qmlengine_p.h>
#include <private/qbitfield_p.h>
+#include <private/qmlpropertycache_p.h>
+#include <private/qmlintegercache_p.h>
+#include <private/qmltypenamecache_p.h>
QT_BEGIN_NAMESPACE
@@ -69,6 +72,7 @@ class QmlEngine;
class QmlComponent;
class QmlContext;
+class QScriptProgram;
class QmlCompiledData : public QmlRefCount
{
public:
@@ -78,6 +82,7 @@ public:
QByteArray name;
QUrl url;
QmlEnginePrivate::Imports imports;
+ QmlTypeNameCache *importCache;
struct TypeReference
{
@@ -98,6 +103,7 @@ public:
int index;
int type;
};
+
QAbstractDynamicMetaObject root;
QList<QString> primitives;
QList<float> floatData;
@@ -106,6 +112,9 @@ public:
QList<QByteArray> datas;
QList<QmlParser::Location> locations;
QList<QmlInstruction> bytecode;
+ QList<QScriptProgram *> programs;
+ QList<QmlPropertyCache *> propertyCaches;
+ QList<QmlIntegerCache *> contextCaches;
void dumpInstructions();
private:
@@ -162,6 +171,7 @@ private:
bool buildObject(QmlParser::Object *obj, const BindingContext &);
+ bool buildScript(QmlParser::Object *obj, QmlParser::Object *script);
bool buildComponent(QmlParser::Object *obj, const BindingContext &);
bool buildSubObject(QmlParser::Object *obj, const BindingContext &);
bool buildSignal(QmlParser::Property *prop, QmlParser::Object *obj,
@@ -227,7 +237,7 @@ private:
QmlParser::Property *prop,
QmlParser::Object *obj,
QmlParser::Property *valueTypeProperty = 0);
-
+ int genContextCache();
int componentTypeRef();
@@ -253,12 +263,10 @@ private:
struct ComponentCompileState
{
ComponentCompileState()
- : parserStatusCount(0), savedObjects(0),
- pushedProperties(0), root(0) {}
+ : parserStatusCount(0), pushedProperties(0), root(0) {}
QHash<QString, QmlParser::Object *> ids;
QHash<int, QmlParser::Object *> idIndexes;
int parserStatusCount;
- int savedObjects;
int pushedProperties;
QHash<QmlParser::Value *, BindingReference> bindings;
diff --git a/src/declarative/qml/qmlcomponent.cpp b/src/declarative/qml/qmlcomponent.cpp
index fedc2da..5b1cbeb 100644
--- a/src/declarative/qml/qmlcomponent.cpp
+++ b/src/declarative/qml/qmlcomponent.cpp
@@ -517,7 +517,8 @@ QmlComponentPrivate::beginCreate(QmlContext *context, const QBitField &bindings)
static_cast<QmlContextPrivate *>(QObjectPrivate::get(context));
QmlContext *ctxt = new QmlContext(context, 0, true);
static_cast<QmlContextPrivate*>(ctxt->d_func())->url = cc->url;
- static_cast<QmlContextPrivate*>(ctxt->d_func())->imports = cc->imports;
+ static_cast<QmlContextPrivate*>(ctxt->d_func())->imports = cc->importCache;
+ cc->importCache->addref();
QmlVME vme;
QObject *rv = vme.run(ctxt, cc, start, count, bindings);
diff --git a/src/declarative/qml/qmlcomponentjs_p.h b/src/declarative/qml/qmlcomponentjs_p.h
index 0f56766..3213929 100644
--- a/src/declarative/qml/qmlcomponentjs_p.h
+++ b/src/declarative/qml/qmlcomponentjs_p.h
@@ -69,14 +69,14 @@ class Q_DECLARATIVE_EXPORT QmlComponentJS : public QmlComponent
{
Q_OBJECT
Q_DECLARE_PRIVATE(QmlComponentJS)
- friend class QmlEngine;
-public:
- QmlComponentJS(QmlEngine *, const QUrl &url, QObject *parent = 0);
- QmlComponentJS(QmlEngine *, QObject *parent=0);
Q_PROPERTY(bool isNull READ isNull NOTIFY isNullChanged)
Q_PROPERTY(bool isReady READ isReady NOTIFY isReadyChanged)
Q_PROPERTY(bool isError READ isError NOTIFY isErrorChanged)
Q_PROPERTY(bool isLoading READ isLoading NOTIFY isLoadingChanged)
+ friend class QmlEngine;
+public:
+ QmlComponentJS(QmlEngine *, const QUrl &url, QObject *parent = 0);
+ QmlComponentJS(QmlEngine *, QObject *parent=0);
Q_INVOKABLE QScriptValue createObject();
Q_INVOKABLE QString errorsString() const;
diff --git a/src/declarative/qml/qmlcompositetypedata_p.h b/src/declarative/qml/qmlcompositetypedata_p.h
index 48c6c2b..fa11137 100644
--- a/src/declarative/qml/qmlcompositetypedata_p.h
+++ b/src/declarative/qml/qmlcompositetypedata_p.h
@@ -58,6 +58,7 @@
QT_BEGIN_NAMESPACE
+class QmlCompositeTypeResource;
class QmlCompositeTypeData : public QmlRefCount
{
public:
@@ -101,6 +102,7 @@ public:
};
QList<TypeReference> types;
+ QList<QmlCompositeTypeResource *> resources;
// Add or remove p as a waiter. When the QmlCompositeTypeData becomes
// ready, the QmlComponentPrivate::typeDataReady() method will be invoked on
@@ -122,5 +124,25 @@ private:
QmlCompiledData *compiledComponent;
};
+class QmlCompositeTypeResource : public QmlRefCount
+{
+public:
+ QmlCompositeTypeResource();
+ virtual ~QmlCompositeTypeResource();
+
+ enum Status {
+ Invalid,
+ Complete,
+ Error,
+ Waiting
+ };
+ Status status;
+
+ QList<QmlCompositeTypeData *> dependants;
+
+ QString url;
+ QByteArray data;
+};
+
#endif // QMLCOMPOSITETYPEDATA_P_H
diff --git a/src/declarative/qml/qmlcompositetypemanager.cpp b/src/declarative/qml/qmlcompositetypemanager.cpp
index a99cff0..71b4ef0 100644
--- a/src/declarative/qml/qmlcompositetypemanager.cpp
+++ b/src/declarative/qml/qmlcompositetypemanager.cpp
@@ -63,6 +63,9 @@ QmlCompositeTypeData::~QmlCompositeTypeData()
for (int ii = 0; ii < dependants.count(); ++ii)
dependants.at(ii)->release();
+ for (int ii = 0; ii < resources.count(); ++ii)
+ resources.at(ii)->release();
+
if (compiledComponent)
compiledComponent->release();
@@ -70,6 +73,16 @@ QmlCompositeTypeData::~QmlCompositeTypeData()
delete component;
}
+QmlCompositeTypeResource::QmlCompositeTypeResource()
+{
+}
+
+QmlCompositeTypeResource::~QmlCompositeTypeResource()
+{
+ for (int ii = 0; ii < dependants.count(); ++ii)
+ dependants.at(ii)->release();
+}
+
void QmlCompositeTypeData::addWaiter(QmlComponentPrivate *p)
{
waiters << p;
@@ -142,6 +155,10 @@ QmlCompositeTypeManager::~QmlCompositeTypeManager()
(*iter)->release();
iter = components.erase(iter);
}
+ for (Resources::Iterator iter = resources.begin(); iter != resources.end();) {
+ (*iter)->release();
+ iter = resources.erase(iter);
+ }
}
QmlCompositeTypeData *QmlCompositeTypeManager::get(const QUrl &url)
@@ -181,8 +198,16 @@ void QmlCompositeTypeManager::clearCache()
++iter;
}
}
-}
+ for (Resources::Iterator iter = resources.begin(); iter != resources.end();) {
+ if ((*iter)->status != QmlCompositeTypeResource::Waiting) {
+ (*iter)->release();
+ iter = resources.erase(iter);
+ } else {
+ ++iter;
+ }
+ }
+}
void QmlCompositeTypeManager::replyFinished()
{
@@ -215,6 +240,52 @@ void QmlCompositeTypeManager::replyFinished()
reply->deleteLater();
}
+void QmlCompositeTypeManager::resourceReplyFinished()
+{
+ QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
+
+ QmlCompositeTypeResource *resource = resources.value(reply->url().toString());
+ Q_ASSERT(resource);
+
+ if (reply->error() != QNetworkReply::NoError) {
+
+ resource->status = QmlCompositeTypeResource::Error;
+
+ } else {
+
+ resource->status = QmlCompositeTypeResource::Complete;
+ resource->data = reply->readAll();
+
+ }
+
+ doComplete(resource);
+ reply->deleteLater();
+}
+
+void QmlCompositeTypeManager::loadResource(QmlCompositeTypeResource *resource)
+{
+ QUrl url(resource->url);
+
+ if (url.scheme() == QLatin1String("file")) {
+
+ QFile file(url.toLocalFile());
+ if (file.open(QFile::ReadOnly)) {
+ resource->data = file.readAll();
+ resource->status = QmlCompositeTypeResource::Complete;
+ } else {
+ resource->status = QmlCompositeTypeResource::Error;
+ }
+
+ } else {
+
+ QNetworkReply *reply =
+ engine->networkAccessManager()->get(QNetworkRequest(url));
+ QObject::connect(reply, SIGNAL(finished()),
+ this, SLOT(resourceReplyFinished()));
+
+ }
+}
+
void QmlCompositeTypeManager::loadSource(QmlCompositeTypeData *unit)
{
QUrl url(unit->imports.baseUrl());
@@ -308,6 +379,15 @@ void QmlCompositeTypeManager::doComplete(QmlCompositeTypeData *unit)
}
}
+void QmlCompositeTypeManager::doComplete(QmlCompositeTypeResource *resource)
+{
+ for (int ii = 0; ii < resource->dependants.count(); ++ii) {
+ checkComplete(resource->dependants.at(ii));
+ resource->dependants.at(ii)->release();
+ }
+ resource->dependants.clear();
+}
+
void QmlCompositeTypeManager::checkComplete(QmlCompositeTypeData *unit)
{
if (unit->status != QmlCompositeTypeData::Waiting)
@@ -329,12 +409,33 @@ void QmlCompositeTypeManager::checkComplete(QmlCompositeTypeData *unit)
waiting++;
}
}
+ for (int ii = 0; ii < unit->resources.count(); ++ii) {
+ QmlCompositeTypeResource *r = unit->resources.at(ii);
+
+ if (!r)
+ continue;
+
+ if (r->status == QmlCompositeTypeResource::Error) {
+ unit->status = QmlCompositeTypeData::Error;
+ QmlError error;
+ error.setUrl(unit->imports.baseUrl());
+ error.setDescription(QLatin1String("Resource ") + r->url +
+ QLatin1String(" unavailable"));
+ unit->errors << error;
+ doComplete(unit);
+ return;
+ } else if (r->status == QmlCompositeTypeData::Waiting) {
+ waiting++;
+ }
+ }
+
if (!waiting) {
unit->status = QmlCompositeTypeData::Complete;
doComplete(unit);
}
}
+// ### Check ref counting in here
void QmlCompositeTypeManager::compile(QmlCompositeTypeData *unit)
{
QList<QmlScriptParser::TypeReference*> types = unit->data.referencedTypes();
@@ -346,12 +447,6 @@ void QmlCompositeTypeManager::compile(QmlCompositeTypeData *unit)
QmlCompositeTypeData::TypeReference ref;
- if (typeName == QByteArray("Property") ||
- typeName == QByteArray("Signal")) {
- unit->types << ref;
- continue;
- }
-
QUrl url;
int majorVersion;
int minorVersion;
@@ -431,6 +526,49 @@ void QmlCompositeTypeManager::compile(QmlCompositeTypeData *unit)
unit->types << ref;
}
+ QList<QUrl> resourceList = unit->data.referencedResources();
+ for (int ii = 0; ii < resourceList.count(); ++ii) {
+ QUrl url = unit->imports.baseUrl().resolved(resourceList.at(ii));
+
+ QmlCompositeTypeResource *resource = resources.value(url.toString());
+
+ if (!resource) {
+ resource = new QmlCompositeTypeResource;
+ resource->status = QmlCompositeTypeResource::Waiting;
+ resource->url = url.toString();
+ resources.insert(resource->url, resource);
+
+ loadResource(resource);
+ }
+
+ switch(resource->status) {
+ case QmlCompositeTypeResource::Invalid:
+ case QmlCompositeTypeResource::Error:
+ unit->status = QmlCompositeTypeData::Error;
+ {
+ QmlError error;
+ error.setUrl(unit->imports.baseUrl());
+ error.setDescription(QLatin1String("Resource ") + resource->url +
+ QLatin1String(" unavailable"));
+ unit->errors << error;
+ }
+ doComplete(unit);
+ return;
+
+ case QmlCompositeTypeData::Complete:
+ break;
+
+ case QmlCompositeTypeData::Waiting:
+ unit->addref();
+ resource->dependants << unit;
+ waiting++;
+ break;
+ }
+
+ resource->addref();
+ unit->resources << resource;
+ }
+
if (waiting) {
unit->status = QmlCompositeTypeData::Waiting;
} else {
diff --git a/src/declarative/qml/qmlcompositetypemanager_p.h b/src/declarative/qml/qmlcompositetypemanager_p.h
index 8f16998..843a9cf 100644
--- a/src/declarative/qml/qmlcompositetypemanager_p.h
+++ b/src/declarative/qml/qmlcompositetypemanager_p.h
@@ -67,6 +67,7 @@ class QmlComponent;
class QmlDomDocument;
class QmlCompositeTypeData;
+class QmlCompositeTypeResource;
class QmlCompositeTypeManager : public QObject
{
@@ -88,19 +89,24 @@ public:
private Q_SLOTS:
void replyFinished();
+ void resourceReplyFinished();
void requestProgress(qint64 received, qint64 total);
private:
void loadSource(QmlCompositeTypeData *);
+ void loadResource(QmlCompositeTypeResource *);
void compile(QmlCompositeTypeData *);
void setData(QmlCompositeTypeData *, const QByteArray &, const QUrl &);
void doComplete(QmlCompositeTypeData *);
+ void doComplete(QmlCompositeTypeResource *);
void checkComplete(QmlCompositeTypeData *);
QmlEngine *engine;
typedef QHash<QString, QmlCompositeTypeData *> Components;
Components components;
+ typedef QHash<QString, QmlCompositeTypeResource *> Resources;
+ Resources resources;
};
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp
index 0632ef7..f6795aa 100644
--- a/src/declarative/qml/qmlcontext.cpp
+++ b/src/declarative/qml/qmlcontext.cpp
@@ -48,6 +48,7 @@
#include <QtCore/qvarlengtharray.h>
#include <QtCore/qdebug.h>
#include <private/qmlbindingoptimizations_p.h>
+#include <QtDeclarative/qmlinfo.h>
// 6-bits
#define MAXIMUM_DEFAULT_OBJECTS 63
@@ -55,11 +56,49 @@
QT_BEGIN_NAMESPACE
QmlContextPrivate::QmlContextPrivate()
-: parent(0), engine(0), isInternal(false), notifyIndex(-1),
- highPriorityCount(0), expressions(0), idValues(0), idValueCount(0)
+: parent(0), engine(0), isInternal(false), propertyNames(0), notifyIndex(-1),
+ highPriorityCount(0), imports(0), expressions(0), idValues(0), idValueCount(0)
{
}
+void QmlContextPrivate::addScript(const QString &script, QObject *scopeObject)
+{
+ if (!engine)
+ return;
+
+ QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine);
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+
+ QScriptContext *scriptContext = scriptEngine->pushCleanContext();
+ scriptContext->pushScope(scriptValue);
+
+ if (scopeObject)
+ scriptContext->pushScope(enginePriv->objectClass->newQObject(scopeObject));
+
+ QScriptValue scope = scriptEngine->newObject();
+ scriptContext->setActivationObject(scope);
+
+ QScriptValue val = scriptEngine->evaluate(script);
+
+ if (scriptEngine->hasUncaughtException()) {
+ if (scriptEngine->uncaughtException().isError()){
+ QScriptValue exception = scriptEngine->uncaughtException();
+ if (!exception.property(QLatin1String("fileName")).toString().isEmpty()){
+ qWarning() << exception.property(QLatin1String("fileName")).toString()
+ << scriptEngine->uncaughtExceptionLineNumber()
+ << exception.toString();
+
+ } else {
+ qmlInfo(scopeObject) << exception.toString();
+ }
+ }
+ }
+
+ scriptEngine->popContext();
+
+ scripts.append(scope);
+}
+
void QmlContextPrivate::dump()
{
dump(0);
@@ -103,16 +142,7 @@ void QmlContextPrivate::init()
//set scope chain
QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
- QScriptValue scopeObj =
- scriptEngine->newObject(QmlEnginePrivate::get(engine)->contextClass, scriptEngine->newVariant(QVariant::fromValue((QObject*)q)));
- //### no longer need to push global object once we switch to JSC (test with objects added to globalObject)
- //if (parent)
- // scopeChain = parent->d_func()->scopeChain;
- if (!parent)
- scopeChain.append(scriptEngine->globalObject());
- else
- scopeChain = parent->d_func()->scopeChain;
- scopeChain.prepend(scopeObj);
+ scriptValue = QmlEnginePrivate::get(engine)->contextClass->newContext(q);
}
void QmlContextPrivate::addDefaultObject(QObject *object, Priority priority)
@@ -304,6 +334,12 @@ QmlContext::~QmlContext()
d->contextObjects.clear();
delete [] d->idValues;
+
+ if (d->propertyNames)
+ d->propertyNames->release();
+
+ if (d->imports)
+ d->imports->release();
}
void QmlContextPrivate::invalidateEngines()
@@ -361,13 +397,16 @@ void QmlContext::setContextProperty(const QString &name, const QVariant &value)
QObject *o = QmlMetaType::toQObject(value);
setContextProperty(name, o);
} else {
- QHash<QString, int>::ConstIterator iter = d->propertyNames.find(name);
- if(iter == d->propertyNames.end()) {
- d->propertyNames.insert(name, d->idValueCount + d->propertyValues.count());
+
+ if (!d->propertyNames) d->propertyNames = new QmlIntegerCache(d->engine);
+
+ int idx = d->propertyNames->value(name);
+ if (idx == -1) {
+ d->propertyNames->add(name, d->idValueCount + d->propertyValues.count());
d->propertyValues.append(value);
} else {
- d->propertyValues[*iter] = value;
- QMetaObject::activate(this, *iter + d->notifyIndex, 0);
+ d->propertyValues[idx] = value;
+ QMetaObject::activate(this, idx + d->notifyIndex, 0);
}
}
}
@@ -380,15 +419,18 @@ void QmlContextPrivate::setIdProperty(const QString &name, int idx,
notifyIndex = q->metaObject()->methodCount();
}
- propertyNames.insert(name, idx);
idValues[idx].priv = this;
idValues[idx] = obj;
}
-void QmlContextPrivate::setIdPropertyCount(int count)
+void QmlContextPrivate::setIdPropertyData(QmlIntegerCache *data)
{
- idValues = new ContextGuard[count];
- idValueCount = count;
+ Q_ASSERT(!propertyNames);
+ propertyNames = data;
+ propertyNames->addref();
+
+ idValueCount = data->count();
+ idValues = new ContextGuard[idValueCount];
}
/*!
@@ -402,14 +444,15 @@ void QmlContext::setContextProperty(const QString &name, QObject *value)
if (d->notifyIndex == -1)
d->notifyIndex = this->metaObject()->methodCount();
- QHash<QString, int>::ConstIterator iter = d->propertyNames.find(name);
- if(iter == d->propertyNames.end()) {
- d->propertyNames.insert(name, d->idValueCount + d->propertyValues.count());
+ if (!d->propertyNames) d->propertyNames = new QmlIntegerCache(d->engine);
+ int idx = d->propertyNames->value(name);
+
+ if (idx == -1) {
+ d->propertyNames->add(name, d->idValueCount + d->propertyValues.count());
d->propertyValues.append(QVariant::fromValue(value));
} else {
- int idx = *iter;
- d->propertyValues[*iter] = QVariant::fromValue(value);
- QMetaObject::activate(this, *iter + d->notifyIndex, 0);
+ d->propertyValues[idx] = QVariant::fromValue(value);
+ QMetaObject::activate(this, idx + d->notifyIndex, 0);
}
}
diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h
index b305408..d18bfda 100644
--- a/src/declarative/qml/qmlcontext_p.h
+++ b/src/declarative/qml/qmlcontext_p.h
@@ -61,6 +61,8 @@
#include <QtCore/qset.h>
#include <private/qguard_p.h>
#include <private/qmlengine_p.h>
+#include <private/qmlintegercache_p.h>
+#include <private/qmltypenamecache_p.h>
QT_BEGIN_NAMESPACE
@@ -82,17 +84,21 @@ public:
QmlEngine *engine;
bool isInternal;
- QHash<QString, int> propertyNames;
+ QmlIntegerCache *propertyNames;
QList<QVariant> propertyValues;
int notifyIndex;
QObjectList defaultObjects;
int highPriorityCount;
- QScriptValueList scopeChain;
+ QScriptValue scriptValue;
+
+ QList<QScriptValue> scripts;
+ void addScript(const QString &script, QObject *scope);
QUrl url;
- QmlEnginePrivate::Imports imports;
+
+ QmlTypeNameCache *imports;
void init();
@@ -125,9 +131,13 @@ public:
ContextGuard *idValues;
int idValueCount;
void setIdProperty(const QString &, int, QObject *);
- void setIdPropertyCount(int);
+ void setIdPropertyData(QmlIntegerCache *);
void destroyed(ContextGuard *);
+ static QmlContextPrivate *get(QmlContext *context) {
+ return static_cast<QmlContextPrivate *>(QObjectPrivate::get(context));
+ }
+
// Only used for debugging
QList<QPointer<QObject> > instances;
};
diff --git a/src/declarative/qml/qmlcontextscriptclass.cpp b/src/declarative/qml/qmlcontextscriptclass.cpp
new file mode 100644
index 0000000..6d2c58c
--- /dev/null
+++ b/src/declarative/qml/qmlcontextscriptclass.cpp
@@ -0,0 +1,211 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlcontextscriptclass_p.h"
+#include <private/qmlengine_p.h>
+#include <private/qmlcontext_p.h>
+#include <private/qmltypenamescriptclass_p.h>
+
+QT_BEGIN_NAMESPACE
+
+struct ContextData : public QScriptDeclarativeClass::Object {
+ ContextData(QmlContext *c) : context(c) {}
+ QGuard<QmlContext> context;
+};
+
+/*
+ The QmlContextScriptClass handles property access for a QmlContext
+ via QtScript.
+ */
+QmlContextScriptClass::QmlContextScriptClass(QmlEngine *bindEngine)
+: QScriptDeclarativeClass(QmlEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine),
+ lastData(0), lastPropertyIndex(-1), lastDefaultObject(-1)
+{
+}
+
+QmlContextScriptClass::~QmlContextScriptClass()
+{
+}
+
+QScriptValue QmlContextScriptClass::newContext(QmlContext *context)
+{
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+
+ return newObject(scriptEngine, this, new ContextData(context));
+}
+
+QmlContext *QmlContextScriptClass::contextFromValue(const QScriptValue &v)
+{
+ if (scriptClass(v) != this)
+ return 0;
+
+ ContextData *data = (ContextData *)object(v);
+ return data->context;
+}
+
+#include <QDebug>
+QScriptClass::QueryFlags
+QmlContextScriptClass::queryProperty(Object *object, const Identifier &name,
+ QScriptClass::QueryFlags flags)
+{
+ Q_UNUSED(flags);
+
+ lastContext = 0;
+ lastData = 0;
+ lastPropertyIndex = -1;
+ lastDefaultObject = -1;
+
+ QmlContext *bindContext = ((ContextData *)object)->context.data();
+ if (!bindContext)
+ return 0;
+
+ while (bindContext) {
+ QScriptClass::QueryFlags rv = queryProperty(bindContext, name, flags);
+ if (rv) return rv;
+ bindContext = bindContext->parentContext();
+ }
+
+ return 0;
+}
+
+QScriptClass::QueryFlags
+QmlContextScriptClass::queryProperty(QmlContext *bindContext, const Identifier &name,
+ QScriptClass::QueryFlags flags)
+{
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
+ QmlContextPrivate *cp = QmlContextPrivate::get(bindContext);
+
+ lastPropertyIndex = cp->propertyNames?cp->propertyNames->value(name):-1;
+ if (lastPropertyIndex != -1) {
+ lastContext = bindContext;
+ return QScriptClass::HandlesReadAccess;
+ }
+
+ if (cp->imports) {
+ QmlTypeNameCache::Data *data = cp->imports->data(name);
+
+ if (data) {
+ lastData = data;
+ lastContext = bindContext;
+ return QScriptClass::HandlesReadAccess;
+ }
+ }
+
+ for (int ii = 0; ii < cp->defaultObjects.count(); ++ii) {
+ QScriptClass::QueryFlags rv =
+ ep->objectClass->queryProperty(cp->defaultObjects.at(ii), name, flags, 0);
+
+ if (rv) {
+ lastDefaultObject = ii;
+ lastContext = bindContext;
+ return rv;
+ }
+ }
+
+ for (int ii = 0; ii < cp->scripts.count(); ++ii) {
+ lastFunction = QScriptDeclarativeClass::function(cp->scripts.at(ii), name);
+ if (lastFunction.isValid()) {
+ lastContext = bindContext;
+ return QScriptClass::HandlesReadAccess;
+ }
+ }
+ return 0;
+}
+
+QScriptValue QmlContextScriptClass::property(Object *object, const Identifier &name)
+{
+ Q_UNUSED(object);
+
+ QmlContext *bindContext = lastContext;
+ Q_ASSERT(bindContext);
+
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
+ QmlContextPrivate *cp = QmlContextPrivate::get(bindContext);
+
+
+ if (lastData) {
+
+ if (lastData->type)
+ return ep->typeNameClass->newObject(cp->defaultObjects.at(0), lastData->type);
+ else
+ return ep->typeNameClass->newObject(cp->defaultObjects.at(0), lastData->typeNamespace);
+
+ } else if (lastPropertyIndex != -1) {
+
+ QScriptValue rv;
+ if (lastPropertyIndex < cp->idValueCount) {
+ rv = ep->objectClass->newQObject(cp->idValues[lastPropertyIndex].data());
+ } else {
+ QVariant value = cp->propertyValues.at(lastPropertyIndex);
+ rv = ep->scriptValueFromVariant(value);
+ }
+
+ ep->capturedProperties <<
+ QmlEnginePrivate::CapturedProperty(bindContext, -1, lastPropertyIndex + cp->notifyIndex);
+
+ return rv;
+ } else if(lastDefaultObject != -1) {
+
+ // Default object property
+ return ep->objectClass->property(cp->defaultObjects.at(lastDefaultObject), name);
+
+ } else {
+
+ return lastFunction;
+
+ }
+}
+
+void QmlContextScriptClass::setProperty(Object *object, const Identifier &name,
+ const QScriptValue &value)
+{
+ Q_ASSERT(lastDefaultObject != -1);
+
+ QmlContext *bindContext = lastContext;
+ Q_ASSERT(bindContext);
+
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
+ QmlContextPrivate *cp = QmlContextPrivate::get(bindContext);
+
+ ep->objectClass->setProperty(cp->defaultObjects.at(lastDefaultObject), name, value);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcontextscriptclass_p.h b/src/declarative/qml/qmlcontextscriptclass_p.h
new file mode 100644
index 0000000..761a115
--- /dev/null
+++ b/src/declarative/qml/qmlcontextscriptclass_p.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLCONTEXTSCRIPTCLASS_P_H
+#define QMLCONTEXTSCRIPTCLASS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtScript/qscriptclass.h>
+#include <private/qscriptdeclarativeclass_p.h>
+#include <private/qmltypenamecache_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlEngine;
+class QmlContext;
+class QmlContextScriptClass : public QScriptDeclarativeClass
+{
+public:
+ QmlContextScriptClass(QmlEngine *);
+ ~QmlContextScriptClass();
+
+ QScriptValue newContext(QmlContext *);
+
+ QmlContext *contextFromValue(const QScriptValue &);
+
+protected:
+ virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &,
+ QScriptClass::QueryFlags flags);
+ virtual QScriptValue property(Object *, const Identifier &);
+ virtual void setProperty(Object *, const Identifier &name, const QScriptValue &);
+
+private:
+ QScriptClass::QueryFlags queryProperty(QmlContext *, const Identifier &,
+ QScriptClass::QueryFlags flags);
+
+ QmlEngine *engine;
+
+ QmlContext *lastContext;
+ QmlTypeNameCache::Data *lastData;
+ int lastPropertyIndex;
+ int lastDefaultObject;
+ QScriptValue lastFunction;
+
+ uint m_id;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLCONTEXTSCRIPTCLASS_P_H
+
diff --git a/src/declarative/qml/qmldeclarativedata_p.h b/src/declarative/qml/qmldeclarativedata_p.h
index ade961f..f6ecc3d 100644
--- a/src/declarative/qml/qmldeclarativedata_p.h
+++ b/src/declarative/qml/qmldeclarativedata_p.h
@@ -54,12 +54,14 @@
//
#include <private/qobject_p.h>
+#include <QtScript/qscriptvalue.h>
QT_BEGIN_NAMESPACE
class QmlCompiledData;
class QmlAbstractBinding;
class QmlContext;
+class QmlPropertyCache;
class QmlDeclarativeData : public QDeclarativeData
{
public:
@@ -85,6 +87,9 @@ public:
QHash<int, QObject *> *attachedProperties;
+ QScriptValue scriptValue;
+ QmlPropertyCache *propertyCache;
+
static QmlDeclarativeData *get(const QObject *object, bool create = false) {
QObjectPrivate *priv =
QObjectPrivate::get(const_cast<QObject *>(object));
diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp
index f34d790..ccdf6cf 100644
--- a/src/declarative/qml/qmlengine.cpp
+++ b/src/declarative/qml/qmlengine.cpp
@@ -41,11 +41,13 @@
#undef QT3_SUPPORT // don't want it here - it just causes bugs (which is why we removed it)
-#include <QMetaProperty>
+#include <QtCore/qmetaobject.h>
#include <private/qmlengine_p.h>
#include <private/qmlcontext_p.h>
#include <private/qobject_p.h>
#include <private/qmlcompiler_p.h>
+#include <private/qscriptdeclarativeclass_p.h>
+#include <private/qmlglobalscriptclass_p.h>
#ifdef QT_SCRIPTTOOLS_LIB
#include <QScriptEngineDebugger>
@@ -83,6 +85,7 @@
#include <private/qmlstringconverters_p.h>
#include <private/qmlxmlhttprequest_p.h>
#include <private/qmlsqldatabase_p.h>
+#include <private/qmltypenamescriptclass_p.h>
#ifdef Q_OS_WIN // for %APPDATA%
#include "qt_windows.h"
@@ -121,7 +124,7 @@ static QString userLocalDataPath(const QString& app)
QmlEnginePrivate::QmlEnginePrivate(QmlEngine *e)
: rootContext(0), currentExpression(0),
- isDebugging(false), contextClass(0), objectClass(0), valueTypeClass(0),
+ isDebugging(false), contextClass(0), objectClass(0), valueTypeClass(0), globalClass(0),
nodeListClass(0), namedNodeMapClass(0), sqlQueryClass(0), scriptEngine(this), rootComponent(0),
networkAccessManager(0), typeManager(e), uniqueId(1)
{
@@ -148,6 +151,14 @@ QmlEnginePrivate::QmlEnginePrivate(QmlEngine *e)
qtObject.setProperty(QLatin1String("lighter"), scriptEngine.newFunction(QmlEnginePrivate::lighter, 1));
qtObject.setProperty(QLatin1String("darker"), scriptEngine.newFunction(QmlEnginePrivate::darker, 1));
qtObject.setProperty(QLatin1String("tint"), scriptEngine.newFunction(QmlEnginePrivate::tint, 2));
+
+ scriptEngine.globalObject().setProperty(QLatin1String("createQmlObject"),
+ scriptEngine.newFunction(QmlEnginePrivate::createQmlObject, 1));
+ scriptEngine.globalObject().setProperty(QLatin1String("createComponent"),
+ scriptEngine.newFunction(QmlEnginePrivate::createComponent, 1));
+
+ //scriptEngine.globalObject().setScriptClass(new QmlGlobalScriptClass(&scriptEngine));
+ globalClass = new QmlGlobalScriptClass(&scriptEngine);
}
QmlEnginePrivate::~QmlEnginePrivate()
@@ -177,6 +188,9 @@ QmlEnginePrivate::~QmlEnginePrivate()
clear(parserStatus[ii]);
for(QHash<int, QmlCompiledData*>::ConstIterator iter = m_compositeTypes.constBegin(); iter != m_compositeTypes.constEnd(); ++iter)
(*iter)->release();
+ for(QHash<const QMetaObject *, QmlPropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
+ (*iter)->release();
+
}
void QmlEnginePrivate::clear(SimpleList<QmlAbstractBinding> &bvs)
@@ -212,11 +226,6 @@ void QmlEnginePrivate::init()
}
#endif
- scriptEngine.globalObject().setProperty(QLatin1String("createQmlObject"),
- scriptEngine.newFunction(QmlEnginePrivate::createQmlObject, 1));
- scriptEngine.globalObject().setProperty(QLatin1String("createComponent"),
- scriptEngine.newFunction(QmlEnginePrivate::createComponent, 1));
-
if (QCoreApplication::instance()->thread() == q->thread() &&
QmlEngineDebugServer::isDebuggingEnabled()) {
qmlEngineDebugServer();
@@ -232,203 +241,6 @@ QmlEnginePrivate::CapturedProperty::CapturedProperty(const QmlMetaProperty &p)
{
}
-struct QmlTypeNameBridge
-{
- QObject *object;
- QmlType *type;
- QmlEnginePrivate::ImportedNamespace *ns;
-};
-Q_DECLARE_METATYPE(QmlTypeNameBridge);
-
-struct QmlValueTypeReference {
- QmlValueType *type;
- QGuard<QObject> object;
- int property;
-};
-Q_DECLARE_METATYPE(QmlValueTypeReference);
-
-////////////////////////////////////////////////////////////////////
-QScriptClass::QueryFlags
-QmlEnginePrivate::queryContext(const QString &propName, uint *id,
- QmlContext *bindContext)
-{
- resolveData.safetyCheckId++;
- *id = resolveData.safetyCheckId;
- resolveData.clear();
-
- QHash<QString, int>::Iterator contextProperty =
- bindContext->d_func()->propertyNames.find(propName);
-
- if (contextProperty != bindContext->d_func()->propertyNames.end()) {
-
- resolveData.context = bindContext;
- resolveData.contextIndex = *contextProperty;
-
- return QScriptClass::HandlesReadAccess;
- }
-
- QmlType *type = 0; ImportedNamespace *ns = 0;
- if (currentExpression && bindContext == currentExpression->context() &&
- propName.at(0).isUpper() && resolveType(bindContext->d_func()->imports, propName.toUtf8(), &type, 0, 0, 0, &ns)) {
-
- if (type || ns) {
- // Must be either an attached property, or an enum
- resolveData.object = bindContext->d_func()->defaultObjects.first();
- resolveData.type = type;
- resolveData.ns = ns;
- return QScriptClass::HandlesReadAccess;
- }
-
- }
-
- QScriptClass::QueryFlags rv = 0;
- for (int ii = 0; !rv && ii < bindContext->d_func()->defaultObjects.count(); ++ii) {
- rv = queryObject(propName, id,
- bindContext->d_func()->defaultObjects.at(ii));
- }
-
- return rv;
-}
-
-QScriptValue QmlEnginePrivate::propertyContext(const QScriptString &name, uint id)
-{
- Q_ASSERT(id == resolveData.safetyCheckId);
-
- if (resolveData.type || resolveData.ns) {
- QmlTypeNameBridge tnb = {
- resolveData.object,
- resolveData.type,
- resolveData.ns
- };
- return scriptEngine.newObject(typeNameClass, scriptEngine.newVariant(qVariantFromValue(tnb)));
- } else if (resolveData.context) {
- QmlContext *bindContext = resolveData.context;
- QmlContextPrivate *contextPrivate = bindContext->d_func();
- int index = resolveData.contextIndex;
-
- QScriptValue rv;
- if (index < contextPrivate->idValueCount) {
- rv = scriptEngine.newObject(objectClass, scriptEngine.newVariant(QVariant::fromValue(contextPrivate->idValues[index].data())));
- } else {
- QVariant value = contextPrivate->propertyValues.at(index);
- if (QmlMetaType::isObject(value.userType())) {
- rv = scriptEngine.newObject(objectClass, scriptEngine.newVariant(value));
- } else {
- rv = scriptEngine.newVariant(value);
- }
- }
- capturedProperties << QmlEnginePrivate::CapturedProperty(bindContext, -1, index + contextPrivate->notifyIndex);
- return rv;
-
- } else {
-
- return propertyObject(name, resolveData.object, id);
-
- }
-
- return QScriptValue();
-}
-
-void QmlEnginePrivate::setPropertyContext(const QScriptValue &value, uint id)
-{
- // As context properties cannot be written, we can assume that the
- // write is a object property write
- setPropertyObject(value, id);
-}
-
-void QmlEnginePrivate::setPropertyObject(const QScriptValue &value, uint id)
-{
- Q_ASSERT(id == resolveData.safetyCheckId);
- Q_Q(QmlEngine);
-
- resolveData.property.write(QmlScriptClass::toVariant(q, value));
-}
-
-QScriptClass::QueryFlags
-QmlEnginePrivate::queryObject(const QString &propName,
- uint *id, QObject *obj)
-{
- resolveData.safetyCheckId++;
- *id = resolveData.safetyCheckId;
- resolveData.clear();
-
- QScriptClass::QueryFlags rv = 0;
-
- QmlContext *ctxt = QmlEngine::contextForObject(obj);
- if (!ctxt)
- ctxt = rootContext;
- QmlMetaProperty prop(obj, propName, ctxt);
-
- if (prop.type() == QmlMetaProperty::Invalid) {
- QPair<const QMetaObject *, QString> key =
- qMakePair(obj->metaObject(), propName);
- bool isFunction = false;
- if (functionCache.contains(key)) {
- isFunction = functionCache.value(key);
- } else {
- QScriptValue sobj = scriptEngine.newQObject(obj);
- QScriptValue func = sobj.property(propName);
- isFunction = func.isFunction();
- functionCache.insert(key, isFunction);
- }
-
- if (isFunction) {
- resolveData.object = obj;
- resolveData.isFunction = true;
- rv |= QScriptClass::HandlesReadAccess;
- }
- } else {
- resolveData.object = obj;
- resolveData.property = prop;
-
- rv |= QScriptClass::HandlesReadAccess;
- if (prop.isWritable())
- rv |= QScriptClass::HandlesWriteAccess;
- }
-
- return rv;
-}
-
-QScriptValue QmlEnginePrivate::propertyObject(const QScriptString &propName,
- QObject *obj, uint id)
-{
- Q_ASSERT(id == resolveData.safetyCheckId);
- Q_ASSERT(resolveData.object);
-
- if (resolveData.isFunction) {
- // ### Optimize
- QScriptValue sobj = scriptEngine.newQObject(obj);
- QScriptValue func = sobj.property(propName);
- return func;
- } else {
- const QmlMetaProperty &prop = resolveData.property;
-
- if (prop.needsChangedNotifier())
- capturedProperties << CapturedProperty(prop);
-
- int propType = prop.propertyType();
- if (propType < QVariant::UserType && valueTypes[propType]) {
- QmlValueTypeReference ref;
- ref.type = valueTypes[propType];
- ref.object = obj;
- ref.property = prop.coreIndex();
- return scriptEngine.newObject(valueTypeClass, scriptEngine.newVariant(QVariant::fromValue(ref)));
- }
-
- QVariant var = prop.read();
- QObject *varobj = (propType < QVariant::UserType)?0:QmlMetaType::toQObject(var);
- if (!varobj)
- varobj = qvariant_cast<QObject *>(var);
- if (varobj) {
- return scriptEngine.newObject(objectClass, scriptEngine.newVariant(QVariant::fromValue(varobj)));
- } else {
- return qScriptValueFromValue(&scriptEngine, var);
- }
- }
-
- return QScriptValue();
-}
-
/*!
\class QmlEngine
\brief The QmlEngine class provides an environment for instantiating QML components.
@@ -666,7 +478,7 @@ QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool cre
QmlDeclarativeData::QmlDeclarativeData(QmlContext *ctxt)
: context(ctxt), bindings(0), bindingBitsSize(0), bindingBits(0),
outerContext(0), lineNumber(0), columnNumber(0), deferredComponent(0),
- deferredIdx(0), attachedProperties(0)
+ deferredIdx(0), attachedProperties(0), propertyCache(0)
{
}
@@ -691,6 +503,9 @@ void QmlDeclarativeData::destroyed(QObject *object)
if (bindingBits)
free(bindingBits);
+ if (propertyCache)
+ propertyCache->release();
+
delete this;
}
@@ -719,9 +534,10 @@ void QmlDeclarativeData::setBindingBit(QObject *obj, int bit)
bindingBits = (quint32 *)realloc(bindingBits,
arraySize * sizeof(quint32));
+
memset(bindingBits + oldArraySize,
- sizeof(quint32) * (arraySize - oldArraySize),
- 0x00);
+ 0x00,
+ sizeof(quint32) * (arraySize - oldArraySize));
bindingBitsSize = arraySize * 32;
}
@@ -740,8 +556,8 @@ void QmlDeclarativeData::setBindingBit(QObject *obj, int bit)
QScriptValue QmlEnginePrivate::qmlScriptObject(QObject* object,
QmlEngine* engine)
{
- QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
- return scriptEngine->newObject(engine->d_func()->objectClass, scriptEngine->newQObject(object, QScriptEngine::AutoOwnership));
+ QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine);
+ return enginePriv->objectClass->newQObject(object);
}
/*!
@@ -857,7 +673,7 @@ QScriptValue QmlEnginePrivate::createQmlObject(QScriptContext *ctxt, QScriptEngi
QUrl url;
if(ctxt->argumentCount() > 2)
url = QUrl(ctxt->argument(2).toString());
- QObject *parentArg = ctxt->argument(1).data().toQObject();
+ QObject *parentArg = activeEnginePriv->objectClass->toQObject(ctxt->argument(1));
QmlContext *qmlCtxt = qmlContext(parentArg);
url = qmlCtxt->resolvedUrl(url);
QmlComponent component(activeEngine, qml.toUtf8(), url);
@@ -1083,346 +899,63 @@ QScriptValue QmlEnginePrivate::tint(QScriptContext *ctxt, QScriptEngine *engine)
return qScriptValueFromValue(engine, qVariantFromValue(finalColor));
}
-QmlScriptClass::QmlScriptClass(QmlEngine *bindengine)
-: QScriptClass(QmlEnginePrivate::getScriptEngine(bindengine)),
- engine(bindengine)
+
+QScriptValue QmlEnginePrivate::scriptValueFromVariant(const QVariant &val)
{
+ if (QmlMetaType::isObject(val.userType())) {
+ QObject *rv = *(QObject **)val.constData();
+ return objectClass->newQObject(rv);
+ } else {
+ return qScriptValueFromValue(&scriptEngine, val);
+ }
}
-QVariant QmlScriptClass::toVariant(QmlEngine *engine, const QScriptValue &val)
+QVariant QmlEnginePrivate::scriptValueToVariant(const QScriptValue &val)
{
- QmlEnginePrivate *ep =
- static_cast<QmlEnginePrivate *>(QObjectPrivate::get(engine));
+ QScriptDeclarativeClass *dc = QScriptDeclarativeClass::scriptClass(val);
+ if (dc == objectClass)
+ return QVariant::fromValue(objectClass->toQObject(val));
+ else if (dc == contextClass)
+ return QVariant();
QScriptClass *sc = val.scriptClass();
if (!sc) {
return val.toVariant();
- } else if (sc == ep->contextClass) {
+ } else if (sc == valueTypeClass) {
+ return valueTypeClass->toVariant(val);
+ } else {
return QVariant();
- } else if (sc == ep->objectClass) {
- return QVariant::fromValue(val.data().toQObject());
- } else if (sc == ep->valueTypeClass) {
- QmlValueTypeReference ref =
- qvariant_cast<QmlValueTypeReference>(val.data().toVariant());
-
- if (!ref.object)
- return QVariant();
-
- QMetaProperty p = ref.object->metaObject()->property(ref.property);
- return p.read(ref.object);
}
-
- return QVariant();
-}
-
-/////////////////////////////////////////////////////////////
-/*
- The QmlContextScriptClass handles property access for a QmlContext
- via QtScript.
- */
-QmlContextScriptClass::QmlContextScriptClass(QmlEngine *bindEngine)
- : QmlScriptClass(bindEngine)
-{
-}
-
-QmlContextScriptClass::~QmlContextScriptClass()
-{
}
-QScriptClass::QueryFlags
-QmlContextScriptClass::queryProperty(const QScriptValue &object,
- const QScriptString &name,
- QueryFlags flags, uint *id)
-{
- Q_UNUSED(flags);
- QmlContext *bindContext =
- static_cast<QmlContext*>(object.data().toQObject());
-
- QString propName = name.toString();
-
- QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
- return ep->queryContext(propName, id, bindContext);
-}
-
-QScriptValue QmlContextScriptClass::property(const QScriptValue &object,
- const QScriptString &name,
- uint id)
-{
- Q_UNUSED(object);
-
- QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
- return ep->propertyContext(name, id);
-}
-
-void QmlContextScriptClass::setProperty(QScriptValue &object,
- const QScriptString &name,
- uint id,
- const QScriptValue &value)
-{
- Q_UNUSED(object);
- Q_UNUSED(name);
-
- QmlEnginePrivate::get(engine)->setPropertyContext(value, id);
-}
-
-/////////////////////////////////////////////////////////////
-QmlTypeNameScriptClass::QmlTypeNameScriptClass(QmlEngine *engine)
-: QmlScriptClass(engine), object(0), type(0)
-{
-}
-
-QmlTypeNameScriptClass::~QmlTypeNameScriptClass()
+QmlScriptClass::QmlScriptClass(QmlEngine *bindengine)
+: QScriptClass(QmlEnginePrivate::getScriptEngine(bindengine)),
+ engine(bindengine)
{
}
-QmlTypeNameScriptClass::QueryFlags
-QmlTypeNameScriptClass::queryProperty(const QScriptValue &scriptObject,
- const QScriptString &name,
- QueryFlags flags, uint *id)
+QVariant QmlScriptClass::toVariant(QmlEngine *engine, const QScriptValue &val)
{
- Q_UNUSED(flags);
-
- QmlTypeNameBridge bridge =
- qvariant_cast<QmlTypeNameBridge>(scriptObject.data().toVariant());
-
- object = 0;
- type = 0;
- QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
-
- if (bridge.ns) {
- QmlType *type = 0;
- ep->resolveTypeInNamespace(bridge.ns, name.toString().toUtf8(),
- &type, 0, 0, 0);
- if (type) {
- object = bridge.object;
- this->type = type;
- return HandlesReadAccess;
- } else {
- return 0;
- }
+ QmlEnginePrivate *ep =
+ static_cast<QmlEnginePrivate *>(QObjectPrivate::get(engine));
- } else {
- Q_ASSERT(bridge.type);
- QString strName = name.toString();
- if (strName.at(0).isUpper()) {
- // Must be an enum
- // ### Optimize
- const char *enumName = strName.toUtf8().constData();
- const QMetaObject *metaObject = bridge.type->baseMetaObject();
- for (int ii = metaObject->enumeratorCount() - 1; ii >= 0; --ii) {
- QMetaEnum e = metaObject->enumerator(ii);
- int value = e.keyToValue(enumName);
- if (value != -1) {
- enumValue = value;
- return HandlesReadAccess;
- }
- }
- return 0;
- } else {
- // Must be an attached property
- this->object = qmlAttachedPropertiesObjectById(bridge.type->index(), bridge.object);
- if (!this->object)
- return 0;
- return ep->queryObject(strName, id, this->object);
- }
- }
-}
+ QScriptDeclarativeClass *dc = QScriptDeclarativeClass::scriptClass(val);
+ if (dc == ep->objectClass)
+ return QVariant::fromValue(ep->objectClass->toQObject(val));
+ else if (dc == ep->contextClass)
+ return QVariant();
-QScriptValue QmlTypeNameScriptClass::property(const QScriptValue &,
- const QScriptString &propName,
- uint id)
-{
- QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
- if (type) {
- QmlTypeNameBridge tnb = { object, type, 0 };
- return ep->scriptEngine.newObject(ep->typeNameClass, ep->scriptEngine.newVariant(qVariantFromValue(tnb)));
- } else if (object) {
- return ep->propertyObject(propName, object, id);
- } else {
- return QScriptValue(enumValue);
+ QScriptClass *sc = val.scriptClass();
+ if (!sc) {
+ return val.toVariant();
+ } else if (sc == ep->valueTypeClass) {
+ return ep->valueTypeClass->toVariant(val);
}
-}
-
-/////////////////////////////////////////////////////////////
-QmlValueTypeScriptClass::QmlValueTypeScriptClass(QmlEngine *bindEngine)
-: QmlScriptClass(bindEngine)
-{
-}
-
-QmlValueTypeScriptClass::~QmlValueTypeScriptClass()
-{
-}
-
-QmlValueTypeScriptClass::QueryFlags
-QmlValueTypeScriptClass::queryProperty(const QScriptValue &object,
- const QScriptString &name,
- QueryFlags flags, uint *id)
-{
- Q_UNUSED(flags);
- QmlValueTypeReference ref =
- qvariant_cast<QmlValueTypeReference>(object.data().toVariant());
-
- if (!ref.object)
- return 0;
- QByteArray propName = name.toString().toUtf8();
-
- int idx = ref.type->metaObject()->indexOfProperty(propName.constData());
- if (idx == -1)
- return 0;
- *id = idx;
-
- QMetaProperty prop = ref.object->metaObject()->property(idx);
-
- QmlValueTypeScriptClass::QueryFlags rv =
- QmlValueTypeScriptClass::HandlesReadAccess;
- if (prop.isWritable())
- rv |= QmlValueTypeScriptClass::HandlesWriteAccess;
-
- return rv;
-}
-
-QScriptValue QmlValueTypeScriptClass::property(const QScriptValue &object,
- const QScriptString &name,
- uint id)
-{
- Q_UNUSED(name);
- QmlValueTypeReference ref =
- qvariant_cast<QmlValueTypeReference>(object.data().toVariant());
-
- if (!ref.object)
- return QScriptValue();
-
- ref.type->read(ref.object, ref.property);
-
- QMetaProperty p = ref.type->metaObject()->property(id);
- QVariant rv = p.read(ref.type);
-
- return static_cast<QmlEnginePrivate *>(QObjectPrivate::get(engine))->scriptEngine.newVariant(rv);
-}
-
-void QmlValueTypeScriptClass::setProperty(QScriptValue &object,
- const QScriptString &name,
- uint id,
- const QScriptValue &value)
-{
- Q_UNUSED(name);
- QmlValueTypeReference ref =
- qvariant_cast<QmlValueTypeReference>(object.data().toVariant());
-
- if (!ref.object)
- return;
-
- QVariant v = QmlScriptClass::toVariant(engine, value);
-
- ref.type->read(ref.object, ref.property);
- QMetaProperty p = ref.type->metaObject()->property(id);
- p.write(ref.type, v);
- ref.type->write(ref.object, ref.property);
+ return QVariant();
}
/////////////////////////////////////////////////////////////
-/*
- The QmlObjectScriptClass handles property access for QObjects
- via QtScript. It is also used to provide a more useful API in
- QtScript for QML.
- */
-
-QScriptValue QmlObjectToString(QScriptContext *context, QScriptEngine *engine)
-{
- QObject* obj = context->thisObject().data().toQObject();
- QString ret = QLatin1String("Qml Object, ");
- if(obj){
- //###Should this be designer or developer details? Dev for now.
- //TODO: Can we print the id too?
- ret += QLatin1String("\"");
- ret += obj->objectName();
- ret += QLatin1String("\" ");
- ret += QLatin1String(obj->metaObject()->className());
- ret += QLatin1String("(0x");
- ret += QString::number((quintptr)obj,16);
- ret += QLatin1String(")");
- }else{
- ret += QLatin1String("null");
- }
- return engine->newVariant(ret);
-}
-
-QScriptValue QmlObjectDestroy(QScriptContext *context, QScriptEngine *engine)
-{
- QObject* obj = context->thisObject().data().toQObject();
- if(obj){
- int delay = 0;
- if(context->argumentCount() > 0)
- delay = context->argument(0).toInt32();
- QTimer::singleShot(delay, obj, SLOT(deleteLater()));
- //### Should this be delayed as well?
- context->thisObject().setData(QScriptValue(engine, 0));
- }
- return engine->nullValue();
-}
-
-QmlObjectScriptClass::QmlObjectScriptClass(QmlEngine *bindEngine)
- : QmlScriptClass(bindEngine)
-{
- engine = bindEngine;
- QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(bindEngine);
- prototypeObject = scriptEngine->newObject();
- prototypeObject.setProperty(QLatin1String("toStr"),//TODO: Why won't toString work?
- scriptEngine->newFunction(QmlObjectToString));
- prototypeObject.setProperty(QLatin1String("destroy"),
- scriptEngine->newFunction(QmlObjectDestroy));
-}
-
-QmlObjectScriptClass::~QmlObjectScriptClass()
-{
-}
-
-QScriptValue QmlObjectScriptClass::prototype() const
-{
- return prototypeObject;
-}
-
-QScriptClass::QueryFlags QmlObjectScriptClass::queryProperty(const QScriptValue &object,
- const QScriptString &name,
- QueryFlags flags, uint *id)
-{
- Q_UNUSED(flags);
- QObject *obj = object.data().toQObject();
- QueryFlags rv = 0;
- QString propName = name.toString();
-
- if (obj)
- rv = QmlEnginePrivate::get(engine)->queryObject(propName, id, obj);
-
- return rv;
-}
-
-QScriptValue QmlObjectScriptClass::property(const QScriptValue &object,
- const QScriptString &name,
- uint id)
-{
- QObject *obj = object.data().toQObject();
-
- QScriptValue rv =
- QmlEnginePrivate::get(engine)->propertyObject(name, obj, id);
- if (rv.isValid())
- return rv;
-
- return QScriptValue();
-}
-
-void QmlObjectScriptClass::setProperty(QScriptValue &object,
- const QScriptString &name,
- uint id,
- const QScriptValue &value)
-{
- Q_UNUSED(name);
- Q_UNUSED(object);
- QmlEnginePrivate::get(engine)->setPropertyObject(value, id);
-}
-
-
struct QmlEnginePrivate::ImportedNamespace {
QStringList urls;
QList<int> majversions;
@@ -1589,6 +1122,7 @@ public:
int ref;
private:
+ friend class QmlEnginePrivate::Imports;
QmlEnginePrivate::ImportedNamespace unqualifiedset;
QHash<QString,QmlEnginePrivate::ImportedNamespace* > set;
};
@@ -1619,6 +1153,80 @@ QmlEnginePrivate::Imports::~Imports()
delete d;
}
+#include <QtDeclarative/qmlmetatype.h>
+#include <private/qmltypenamecache_p.h>
+static QmlTypeNameCache *cacheForNamespace(QmlEngine *engine, const QmlEnginePrivate::ImportedNamespace &set, QmlTypeNameCache *cache)
+{
+ if (!cache)
+ cache = new QmlTypeNameCache(engine);
+
+ QList<QmlType *> types = QmlMetaType::qmlTypes();
+
+ for (int ii = 0; ii < set.urls.count(); ++ii) {
+ if (!set.isBuiltin.at(ii))
+ continue;
+
+ QByteArray base = set.urls.at(ii).toUtf8() + "/";
+ int major = set.majversions.at(ii);
+ int minor = set.minversions.at(ii);
+
+ foreach (QmlType *type, types) {
+ if (type->qmlTypeName().startsWith(base) &&
+ type->qmlTypeName().lastIndexOf('/') == (base.length() - 1) &&
+ type->majorVersion() == major && type->minMinorVersion() <= minor &&
+ type->maxMinorVersion() >= minor) {
+
+ QString name = QString::fromUtf8(type->qmlTypeName().mid(base.length()));
+
+ cache->add(name, type);
+ }
+ }
+ }
+
+ return cache;
+}
+
+QmlTypeNameCache *QmlEnginePrivate::Imports::cache(QmlEngine *engine) const
+{
+ const QmlEnginePrivate::ImportedNamespace &set = d->unqualifiedset;
+
+ QmlTypeNameCache *cache = new QmlTypeNameCache(engine);
+
+ for (QHash<QString,QmlEnginePrivate::ImportedNamespace* >::ConstIterator iter = d->set.begin();
+ iter != d->set.end(); ++iter) {
+
+ QmlTypeNameCache::Data *d = cache->data(iter.key());
+ if (d) {
+ if (!d->typeNamespace)
+ cacheForNamespace(engine, *(*iter), d->typeNamespace);
+ } else {
+ QmlTypeNameCache *nc = cacheForNamespace(engine, *(*iter), 0);
+ cache->add(iter.key(), nc);
+ nc->release();
+ }
+ }
+
+ cacheForNamespace(engine, set, cache);
+
+ return cache;
+}
+
+/*
+QStringList QmlEnginePrivate::Imports::unqualifiedSet() const
+{
+ QStringList rv;
+
+ const QmlEnginePrivate::ImportedNamespace &set = d->unqualifiedset;
+
+ for (int ii = 0; ii < set.urls.count(); ++ii) {
+ if (set.isBuiltin.at(ii))
+ rv << set.urls.at(ii);
+ }
+
+ return rv;
+}
+*/
+
/*!
Sets the base URL to be used for all relative file imports added.
*/
diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h
index 74e24d4..7978023 100644
--- a/src/declarative/qml/qmlengine_p.h
+++ b/src/declarative/qml/qmlengine_p.h
@@ -72,6 +72,10 @@
#include <QtDeclarative/qmlexpression.h>
#include <QtScript/qscriptengine.h>
#include <private/qmlmetaproperty_p.h>
+#include <private/qmlpropertycache_p.h>
+#include <private/qmlobjectscriptclass_p.h>
+#include <private/qmlcontextscriptclass_p.h>
+#include <private/qmlvaluetypescriptclass_p.h>
QT_BEGIN_NAMESPACE
@@ -88,6 +92,9 @@ class QScriptEngineDebugger;
class QNetworkReply;
class QNetworkAccessManager;
class QmlAbstractBinding;
+class QScriptDeclarativeClass;
+class QmlTypeNameScriptClass;
+class QmlTypeNameCache;
class QmlEnginePrivate : public QObjectPrivate
{
@@ -98,17 +105,6 @@ public:
void init();
- QScriptClass::QueryFlags queryContext(const QString &name, uint *id,
- QmlContext *);
- QScriptValue propertyContext(const QScriptString &propName, uint id);
- void setPropertyContext(const QScriptValue &, uint id);
- QScriptClass::QueryFlags queryObject(const QString &name, uint *id,
- QObject *);
- QScriptValue propertyObject(const QScriptString &propName, QObject *,
- uint id = 0);
- void setPropertyObject(const QScriptValue &, uint id);
-
-
struct CapturedProperty {
CapturedProperty(QObject *o, int c, int n)
: object(o), coreIndex(c), notifyIndex(n) {}
@@ -128,29 +124,12 @@ public:
#endif
struct ImportedNamespace;
- struct ResolveData {
- ResolveData() : safetyCheckId(0) {}
- int safetyCheckId;
-
- void clear() {
- object = 0; context = 0;
- type = 0; ns = 0;
- contextIndex = -1; isFunction = false;
- }
- QObject *object;
- QmlContext *context;
-
- QmlType *type;
- QmlEnginePrivate::ImportedNamespace *ns;
-
- int contextIndex;
- bool isFunction;
- QmlMetaProperty property;
- } resolveData;
QmlContextScriptClass *contextClass;
QmlObjectScriptClass *objectClass;
QmlValueTypeScriptClass *valueTypeClass;
QmlTypeNameScriptClass *typeNameClass;
+ // Global script class
+ QScriptClass *globalClass;
// Used by DOM Core 3 API
QScriptClass *nodeListClass;
QScriptClass *namedNodeMapClass;
@@ -209,15 +188,21 @@ public:
}
QmlValueTypeFactory valueTypes;
- // ### Fixme
- typedef QHash<QPair<const QMetaObject *, QString>, bool> FunctionCache;
- FunctionCache functionCache;
- QHash<const QMetaObject *, QmlMetaObjectCache> propertyCache;
- static QmlMetaObjectCache *cache(QmlEnginePrivate *priv, QObject *obj) {
- if (!priv || !obj || QObjectPrivate::get(obj)->metaObject) return 0;
- return &priv->propertyCache[obj->metaObject()];
+
+ QHash<const QMetaObject *, QmlPropertyCache *> propertyCache;
+ QmlPropertyCache *cache(QObject *obj) {
+ Q_Q(QmlEngine);
+ if (!obj || QObjectPrivate::get(obj)->metaObject) return 0;
+ const QMetaObject *mo = obj->metaObject();
+ QmlPropertyCache *rv = propertyCache.value(mo);
+ if (!rv) {
+ rv = QmlPropertyCache::create(q, mo);
+ propertyCache.insert(mo, rv);
+ }
+ return rv;
}
+ // ### This whole class is embarrassing
struct Imports {
Imports();
~Imports();
@@ -227,6 +212,8 @@ public:
void setBaseUrl(const QUrl& url);
QUrl baseUrl() const;
+ QmlTypeNameCache *cache(QmlEngine *) const;
+
private:
friend class QmlEnginePrivate;
QmlImportsPrivate *d;
@@ -251,6 +238,9 @@ public:
QHash<int, int> m_qmlLists;
QHash<int, QmlCompiledData *> m_compositeTypes;
+ QScriptValue scriptValueFromVariant(const QVariant &);
+ QVariant scriptValueToVariant(const QScriptValue &);
+
static QScriptValue qmlScriptObject(QObject*, QmlEngine*);
static QScriptValue createComponent(QScriptContext*, QScriptEngine*);
static QScriptValue createQmlObject(QScriptContext*, QScriptEngine*);
@@ -275,19 +265,6 @@ public:
class QmlScriptClass : public QScriptClass
{
public:
- enum ClassId
- {
- InvalidId = -1,
-
- FunctionId = 0x80000000,
- VariantPropertyId = 0x40000000,
- PropertyId = 0x00000000,
-
- ClassIdMask = 0xC0000000,
-
- ClassIdSelectorMask = 0x3F000000,
- };
-
QmlScriptClass(QmlEngine *);
static QVariant toVariant(QmlEngine *, const QScriptValue &);
@@ -295,82 +272,6 @@ protected:
QmlEngine *engine;
};
-class QmlContextScriptClass : public QmlScriptClass
-{
-public:
- QmlContextScriptClass(QmlEngine *);
- ~QmlContextScriptClass();
-
- virtual QueryFlags queryProperty(const QScriptValue &object,
- const QScriptString &name,
- QueryFlags flags, uint *id);
- virtual QScriptValue property(const QScriptValue &object,
- const QScriptString &name,
- uint id);
- virtual void setProperty(QScriptValue &object,
- const QScriptString &name,
- uint id,
- const QScriptValue &value);
-};
-
-class QmlObjectScriptClass : public QmlScriptClass
-{
-public:
- QmlObjectScriptClass(QmlEngine *);
- ~QmlObjectScriptClass();
-
- virtual QScriptValue prototype () const;
- QScriptValue prototypeObject;
-
- virtual QueryFlags queryProperty(const QScriptValue &object,
- const QScriptString &name,
- QueryFlags flags, uint *id);
- virtual QScriptValue property(const QScriptValue &object,
- const QScriptString &name,
- uint id);
- virtual void setProperty(QScriptValue &object,
- const QScriptString &name,
- uint id,
- const QScriptValue &value);
-};
-
-class QmlTypeNameScriptClass : public QmlScriptClass
-{
-public:
- QmlTypeNameScriptClass(QmlEngine *);
- ~QmlTypeNameScriptClass();
-
- virtual QueryFlags queryProperty(const QScriptValue &object,
- const QScriptString &name,
- QueryFlags flags, uint *id);
- virtual QScriptValue property(const QScriptValue &object,
- const QScriptString &name,
- uint id);
-
-private:
- QObject *object;
- QmlType *type;
- quint32 enumValue;
-};
-
-class QmlValueTypeScriptClass : public QmlScriptClass
-{
-public:
- QmlValueTypeScriptClass(QmlEngine *);
- ~QmlValueTypeScriptClass();
-
- virtual QueryFlags queryProperty(const QScriptValue &object,
- const QScriptString &name,
- QueryFlags flags, uint *id);
- virtual QScriptValue property(const QScriptValue &object,
- const QScriptString &name,
- uint id);
- virtual void setProperty(QScriptValue &object,
- const QScriptString &name,
- uint id,
- const QScriptValue &value);
-};
-
QT_END_NAMESPACE
#endif // QMLENGINE_P_H
diff --git a/src/declarative/qml/qmlexpression.cpp b/src/declarative/qml/qmlexpression.cpp
index db9d39f..23e1700 100644
--- a/src/declarative/qml/qmlexpression.cpp
+++ b/src/declarative/qml/qmlexpression.cpp
@@ -45,46 +45,85 @@
#include "qmlcontext_p.h"
#include "qmlrewrite_p.h"
#include "QtCore/qdebug.h"
+#include "qmlcompiler_p.h"
Q_DECLARE_METATYPE(QList<QObject *>);
QT_BEGIN_NAMESPACE
-QmlExpressionPrivate::QmlExpressionPrivate()
+QmlExpressionData::QmlExpressionData()
: expressionFunctionValid(false), expressionRewritten(false), me(0),
trackChange(true), line(-1), guardList(0), guardListLength(0)
{
}
+QmlExpressionData::~QmlExpressionData()
+{
+ if (guardList) { delete [] guardList; guardList = 0; }
+}
+
+QmlExpressionPrivate::QmlExpressionPrivate()
+: data(new QmlExpressionData)
+{
+ data->q = this;
+}
+
+QmlExpressionPrivate::QmlExpressionPrivate(QmlExpressionData *d)
+: data(d)
+{
+ data->q = this;
+}
+
+QmlExpressionPrivate::~QmlExpressionPrivate()
+{
+ if (data) { data->q = 0; data->release(); data = 0; }
+}
+
void QmlExpressionPrivate::init(QmlContext *ctxt, const QString &expr,
QObject *me)
{
- expression = expr;
+ data->expression = expr;
- QmlAbstractExpression::setContext(ctxt);
- this->me = me;
+ data->QmlAbstractExpression::setContext(ctxt);
+ data->me = me;
}
void QmlExpressionPrivate::init(QmlContext *ctxt, void *expr, QmlRefCount *rc,
QObject *me)
{
- quint32 *data = (quint32 *)expr;
- Q_ASSERT(*data == BasicScriptEngineData ||
- *data == PreTransformedQtScriptData);
- if (*data == BasicScriptEngineData) {
- sse.load((const char *)(data + 1), rc);
+ quint32 *exprData = (quint32 *)expr;
+ Q_ASSERT(*exprData == BasicScriptEngineData ||
+ *exprData == PreTransformedQtScriptData);
+ if (*exprData == BasicScriptEngineData) {
+ data->sse.load((const char *)(exprData + 1), rc);
} else {
- expression = QString::fromRawData((QChar *)(data + 2), data[1]);
- expressionRewritten = true;
- }
+ QmlCompiledData *dd = (QmlCompiledData *)rc;
- QmlAbstractExpression::setContext(ctxt);
- this->me = me;
-}
+ data->expressionRewritten = true;
+ data->expression = QString::fromRawData((QChar *)(exprData + 3), exprData[2]);
-QmlExpressionPrivate::~QmlExpressionPrivate()
-{
- if (guardList) { delete [] guardList; guardList = 0; }
+ int progIdx = *(exprData + 1);
+ QmlEngine *engine = ctxt->engine();
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+ if (!dd->programs.at(progIdx)) {
+ dd->programs[progIdx] = new QScriptProgram(scriptEngine->compile(data->expression));
+ }
+
+ QmlContextPrivate *ctxtPriv = ctxt->d_func();
+ QScriptContext *scriptContext = scriptEngine->pushCleanContext();
+ scriptContext->pushScope(ctxtPriv->scriptValue);
+ if (me)
+ scriptContext->pushScope(ep->objectClass->newQObject(me));
+
+ data->expressionFunction = scriptEngine->evaluate(*dd->programs[progIdx]);
+
+ data->expressionFunctionValid = true;
+ scriptEngine->popContext();
+ }
+
+ data->QmlAbstractExpression::setContext(ctxt);
+ data->me = me;
}
/*!
@@ -151,7 +190,7 @@ QmlExpression::~QmlExpression()
QmlEngine *QmlExpression::engine() const
{
Q_D(const QmlExpression);
- return d->context()?d->context()->engine():0;
+ return d->data->context()?d->data->context()->engine():0;
}
/*!
@@ -161,7 +200,7 @@ QmlEngine *QmlExpression::engine() const
QmlContext *QmlExpression::context() const
{
Q_D(const QmlExpression);
- return d->context();
+ return d->data->context();
}
/*!
@@ -170,10 +209,10 @@ QmlContext *QmlExpression::context() const
QString QmlExpression::expression() const
{
Q_D(const QmlExpression);
- if (d->sse.isValid())
- return QLatin1String(d->sse.expression());
+ if (d->data->sse.isValid())
+ return QLatin1String(d->data->sse.expression());
else
- return d->expression;
+ return d->data->expression;
}
/*!
@@ -193,12 +232,12 @@ void QmlExpression::setExpression(const QString &expression)
d->clearGuards();
- d->expression = expression;
- d->expressionFunctionValid = false;
- d->expressionRewritten = false;
- d->expressionFunction = QScriptValue();
+ d->data->expression = expression;
+ d->data->expressionFunctionValid = false;
+ d->data->expressionRewritten = false;
+ d->data->expressionFunction = QScriptValue();
- d->sse.clear();
+ d->data->sse.clear();
}
QVariant QmlExpressionPrivate::evalSSE()
@@ -207,7 +246,7 @@ QVariant QmlExpressionPrivate::evalSSE()
QFxPerfTimer<QFxPerf::BindValueSSE> perfsse;
#endif
- QVariant rv = sse.run(context(), me);
+ QVariant rv = data->sse.run(data->context(), data->me);
return rv;
}
@@ -218,37 +257,39 @@ QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope)
QFxPerfTimer<QFxPerf::BindValueQt> perfqt;
#endif
- QmlContextPrivate *ctxtPriv = context()->d_func();
- QmlEngine *engine = context()->engine();
+ QmlContextPrivate *ctxtPriv = data->context()->d_func();
+ QmlEngine *engine = data->context()->engine();
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
- if (me)
- ctxtPriv->defaultObjects.insert(ctxtPriv->highPriorityCount, me);
if (secondaryScope)
ctxtPriv->defaultObjects.insert(ctxtPriv->highPriorityCount,
secondaryScope);
QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
- if (!expressionFunctionValid) {
+ if (!data->expressionFunctionValid) {
+
+ QScriptContext *scriptContext = scriptEngine->pushCleanContext();
+ scriptContext->pushScope(ctxtPriv->scriptValue);
- QScriptContext *scriptContext = scriptEngine->pushContext();
- for (int i = ctxtPriv->scopeChain.size() - 1; i > -1; --i)
- scriptContext->pushScope(ctxtPriv->scopeChain.at(i));
+ if (data->me)
+ scriptContext->pushScope(ep->objectClass->newQObject(data->me));
- if (expressionRewritten) {
- expressionFunction = scriptEngine->evaluate(expression, fileName, line);
+ if (data->expressionRewritten) {
+ data->expressionFunction = scriptEngine->evaluate(data->expression,
+ data->fileName, data->line);
} else {
QmlRewrite::RewriteBinding rewriteBinding;
- const QString code = rewriteBinding(expression);
- expressionFunction = scriptEngine->evaluate(code, fileName, line);
+ const QString code = rewriteBinding(data->expression);
+ data->expressionFunction = scriptEngine->evaluate(code, data->fileName, data->line);
}
scriptEngine->popContext();
- expressionFunctionValid = true;
+ data->expressionFunctionValid = true;
}
- QScriptValue svalue = expressionFunction.call();
+ QScriptValue svalue = data->expressionFunction.call();
if (scriptEngine->hasUncaughtException()) {
if (scriptEngine->uncaughtException().isError()){
@@ -264,8 +305,6 @@ QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope)
}
}
- if (me)
- ctxtPriv->defaultObjects.removeAt(ctxtPriv->highPriorityCount);
if (secondaryScope)
ctxtPriv->defaultObjects.removeAt(ctxtPriv->highPriorityCount);
@@ -277,13 +316,8 @@ QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope)
QList<QObject *> list;
for (int ii = 0; ii < length; ++ii) {
QScriptValue arrayItem = svalue.property(ii);
- QObject *d =
- qvariant_cast<QObject *>(arrayItem.data().toVariant());
- if (d) {
- list << d;
- } else {
- list << 0;
- }
+ QObject *d = arrayItem.toQObject();
+ list << d;
}
rv = QVariant::fromValue(list);
}
@@ -297,13 +331,10 @@ QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope)
!svalue.isQMetaObject() &&
!svalue.isQObject() &&
!svalue.isRegExp()) {
- QScriptValue objValue = svalue.data();
- if (objValue.isValid()) {
- QVariant var = objValue.toVariant();
- if (var.userType() >= (int)QVariant::UserType &&
- QmlMetaType::isObject(var.userType()))
- rv = var;
- }
+
+ QObject *o = svalue.toQObject();
+ if (o)
+ return qVariantFromValue(o);
}
if (rv.isNull())
rv = svalue.toVariant();
@@ -316,7 +347,7 @@ QVariant QmlExpressionPrivate::value(QObject *secondaryScope)
Q_Q(QmlExpression);
QVariant rv;
- if (!q->engine() || (!sse.isValid() && expression.isEmpty()))
+ if (!q->engine() || (!data->sse.isValid() && data->expression.isEmpty()))
return rv;
#ifdef Q_ENABLE_PERFORMANCE_LOG
@@ -331,7 +362,11 @@ QVariant QmlExpressionPrivate::value(QObject *secondaryScope)
ep->currentExpression = q;
- if (sse.isValid()) {
+ // This object might be deleted during the eval
+ QmlExpressionData *localData = data;
+ localData->addref();
+
+ if (data->sse.isValid()) {
rv = evalSSE();
} else {
rv = evalQtScript(secondaryScope);
@@ -339,12 +374,17 @@ QVariant QmlExpressionPrivate::value(QObject *secondaryScope)
ep->currentExpression = lastCurrentExpression;
- if ((!q->trackChange() || !ep->capturedProperties.count()) && guardList) {
- clearGuards();
- } else if(q->trackChange()) {
- updateGuards(ep->capturedProperties);
+ // Check if we were deleted
+ if (localData->q) {
+ if ((!data->trackChange || !ep->capturedProperties.count()) && data->guardList) {
+ clearGuards();
+ } else if(data->trackChange) {
+ updateGuards(ep->capturedProperties);
+ }
}
+ localData->release();
+
lastCapturedProperties.copyAndClear(ep->capturedProperties);
return rv;
@@ -368,7 +408,7 @@ QVariant QmlExpression::value()
bool QmlExpression::isConstant() const
{
Q_D(const QmlExpression);
- return !d->guardList;
+ return !d->data->guardList;
}
/*!
@@ -377,7 +417,7 @@ bool QmlExpression::isConstant() const
bool QmlExpression::trackChange() const
{
Q_D(const QmlExpression);
- return d->trackChange;
+ return d->data->trackChange;
}
/*!
@@ -398,7 +438,7 @@ bool QmlExpression::trackChange() const
void QmlExpression::setTrackChange(bool trackChange)
{
Q_D(QmlExpression);
- d->trackChange = trackChange;
+ d->data->trackChange = trackChange;
}
/*!
@@ -408,8 +448,8 @@ void QmlExpression::setTrackChange(bool trackChange)
void QmlExpression::setSourceLocation(const QUrl &fileName, int line)
{
Q_D(QmlExpression);
- d->fileName = fileName.toString();
- d->line = line;
+ d->data->fileName = fileName.toString();
+ d->data->line = line;
}
/*!
@@ -421,7 +461,7 @@ void QmlExpression::setSourceLocation(const QUrl &fileName, int line)
QObject *QmlExpression::scopeObject() const
{
Q_D(const QmlExpression);
- return d->me;
+ return d->data->me;
}
/*! \internal */
@@ -439,16 +479,16 @@ void QmlExpressionPrivate::clearGuards()
notifyIdx =
QmlExpression::staticMetaObject.indexOfMethod("__q_notify()");
- for (int ii = 0; ii < guardListLength; ++ii) {
- if (guardList[ii].data()) {
- QMetaObject::disconnect(guardList[ii].data(),
- guardList[ii].notifyIndex,
+ for (int ii = 0; ii < data->guardListLength; ++ii) {
+ if (data->guardList[ii].data()) {
+ QMetaObject::disconnect(data->guardList[ii].data(),
+ data->guardList[ii].notifyIndex,
q, notifyIdx);
}
}
- delete [] guardList; guardList = 0;
- guardListLength = 0;
+ delete [] data->guardList; data->guardList = 0;
+ data->guardListLength = 0;
}
void QmlExpressionPrivate::updateGuards(const QPODVector<QmlEnginePrivate::CapturedProperty> &properties)
@@ -461,10 +501,10 @@ void QmlExpressionPrivate::updateGuards(const QPODVector<QmlEnginePrivate::Captu
notifyIdx =
QmlExpression::staticMetaObject.indexOfMethod("__q_notify()");
- SignalGuard *newGuardList = 0;
+ QmlExpressionData::SignalGuard *newGuardList = 0;
- if (properties.count() != guardListLength)
- newGuardList = new SignalGuard[properties.count()];
+ if (properties.count() != data->guardListLength)
+ newGuardList = new QmlExpressionData::SignalGuard[properties.count()];
bool outputWarningHeader = false;
int hit = 0;
@@ -472,20 +512,20 @@ void QmlExpressionPrivate::updateGuards(const QPODVector<QmlEnginePrivate::Captu
const QmlEnginePrivate::CapturedProperty &property = properties.at(ii);
bool needGuard = true;
- if (ii >= guardListLength) {
+ if (ii >= data->guardListLength) {
// New guard
- } else if(guardList[ii].data() == property.object &&
- guardList[ii].notifyIndex == property.notifyIndex) {
+ } else if(data->guardList[ii].data() == property.object &&
+ data->guardList[ii].notifyIndex == property.notifyIndex) {
// Cache hit
- if (!guardList[ii].isDuplicate ||
- (guardList[ii].isDuplicate && hit == ii)) {
+ if (!data->guardList[ii].isDuplicate ||
+ (data->guardList[ii].isDuplicate && hit == ii)) {
needGuard = false;
++hit;
}
- } else if(guardList[ii].data() && !guardList[ii].isDuplicate) {
+ } else if(data->guardList[ii].data() && !data->guardList[ii].isDuplicate) {
// Cache miss
- QMetaObject::disconnect(guardList[ii].data(),
- guardList[ii].notifyIndex,
+ QMetaObject::disconnect(data->guardList[ii].data(),
+ data->guardList[ii].notifyIndex,
q, notifyIdx);
}
/* else {
@@ -494,9 +534,9 @@ void QmlExpressionPrivate::updateGuards(const QPODVector<QmlEnginePrivate::Captu
if (needGuard) {
if (!newGuardList) {
- newGuardList = new SignalGuard[properties.count()];
+ newGuardList = new QmlExpressionData::SignalGuard[properties.count()];
for (int jj = 0; jj < ii; ++jj)
- newGuardList[jj] = guardList[jj];
+ newGuardList[jj] = data->guardList[jj];
}
if (property.notifyIndex != -1) {
@@ -526,22 +566,22 @@ void QmlExpressionPrivate::updateGuards(const QPODVector<QmlEnginePrivate::Captu
<< "::" << metaProp.name();
}
} else if (newGuardList) {
- newGuardList[ii] = guardList[ii];
+ newGuardList[ii] = data->guardList[ii];
}
}
- for (int ii = properties.count(); ii < guardListLength; ++ii) {
- if (guardList[ii].data() && !guardList[ii].isDuplicate) {
- QMetaObject::disconnect(guardList[ii].data(),
- guardList[ii].notifyIndex,
+ for (int ii = properties.count(); ii < data->guardListLength; ++ii) {
+ if (data->guardList[ii].data() && !data->guardList[ii].isDuplicate) {
+ QMetaObject::disconnect(data->guardList[ii].data(),
+ data->guardList[ii].notifyIndex,
q, notifyIdx);
}
}
if (newGuardList) {
- if (guardList) delete [] guardList;
- guardList = newGuardList;
- guardListLength = properties.count();
+ if (data->guardList) delete [] data->guardList;
+ data->guardList = newGuardList;
+ data->guardListLength = properties.count();
}
}
diff --git a/src/declarative/qml/qmlexpression_p.h b/src/declarative/qml/qmlexpression_p.h
index 501e5d8..33016e6 100644
--- a/src/declarative/qml/qmlexpression_p.h
+++ b/src/declarative/qml/qmlexpression_p.h
@@ -79,23 +79,13 @@ private:
QmlAbstractExpression *m_nextExpression;
};
-class QmlExpression;
-class QString;
-class QmlExpressionPrivate : public QObjectPrivate, public QmlAbstractExpression
+class QmlExpressionData : public QmlAbstractExpression, public QmlRefCount
{
- Q_DECLARE_PUBLIC(QmlExpression)
public:
- QmlExpressionPrivate();
- ~QmlExpressionPrivate();
-
- enum CompiledDataType {
- BasicScriptEngineData = 1,
- PreTransformedQtScriptData = 2
- };
+ QmlExpressionData();
+ ~QmlExpressionData();
-
- void init(QmlContext *, const QString &, QObject *);
- void init(QmlContext *, void *, QmlRefCount *, QObject *);
+ QmlExpressionPrivate *q;
QString expression;
bool expressionFunctionValid:1;
@@ -109,10 +99,6 @@ public:
QString fileName;
int line;
- QVariant value(QObject *secondaryScope = 0);
- QVariant evalSSE();
- QVariant evalQtScript(QObject *secondaryScope);
-
struct SignalGuard : public QGuard<QObject> {
SignalGuard() : isDuplicate(false), notifyIndex(-1) {}
@@ -132,6 +118,32 @@ public:
};
SignalGuard *guardList;
int guardListLength;
+};
+
+class QmlExpression;
+class QString;
+class QmlExpressionPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlExpression)
+public:
+ QmlExpressionPrivate();
+ QmlExpressionPrivate(QmlExpressionData *);
+ ~QmlExpressionPrivate();
+
+ enum CompiledDataType {
+ BasicScriptEngineData = 1,
+ PreTransformedQtScriptData = 2
+ };
+
+ void init(QmlContext *, const QString &, QObject *);
+ void init(QmlContext *, void *, QmlRefCount *, QObject *);
+
+ QmlExpressionData *data;
+
+ QVariant value(QObject *secondaryScope = 0);
+ QVariant evalSSE();
+ QVariant evalQtScript(QObject *secondaryScope);
+
void updateGuards(const QPODVector<QmlEnginePrivate::CapturedProperty> &properties);
void clearGuards();
diff --git a/src/declarative/qml/qmlglobalscriptclass.cpp b/src/declarative/qml/qmlglobalscriptclass.cpp
new file mode 100644
index 0000000..0ade5ee
--- /dev/null
+++ b/src/declarative/qml/qmlglobalscriptclass.cpp
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlglobalscriptclass_p.h"
+#include <QtScript/qscriptstring.h>
+#include <QtScript/qscriptengine.h>
+#include <QtScript/qscriptvalueiterator.h>
+
+QT_BEGIN_NAMESPACE
+
+/*
+ Used to prevent any writes to the global object.
+*/
+QmlGlobalScriptClass::QmlGlobalScriptClass(QScriptEngine *engine)
+: QScriptClass(engine)
+{
+ QScriptValue v = engine->newObject();
+ globalObject = engine->globalObject();
+
+ QScriptValueIterator iter(globalObject);
+ while (iter.hasNext()) {
+ iter.next();
+ v.setProperty(iter.scriptName(), iter.value());
+ }
+
+ v.setScriptClass(this);
+ engine->setGlobalObject(v);
+}
+
+QScriptClass::QueryFlags
+QmlGlobalScriptClass::queryProperty(const QScriptValue &object,
+ const QScriptString &name,
+ QueryFlags flags, uint *id)
+{
+ return HandlesReadAccess | HandlesWriteAccess;
+}
+
+QScriptValue
+QmlGlobalScriptClass::property(const QScriptValue &object,
+ const QScriptString &name,
+ uint id)
+{
+ return engine()->undefinedValue();
+}
+
+void QmlGlobalScriptClass::setProperty(QScriptValue &object,
+ const QScriptString &name,
+ uint id, const QScriptValue &value)
+{
+ QString error = QLatin1String("Invalid write to global property \"") +
+ name.toString() + QLatin1String("\"");
+ engine()->currentContext()->throwError(error);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/declarative/util/qmlscript.h b/src/declarative/qml/qmlglobalscriptclass_p.h
index 4ba4f6b..1b58f1e 100644
--- a/src/declarative/util/qmlscript.h
+++ b/src/declarative/qml/qmlglobalscriptclass_p.h
@@ -39,46 +39,43 @@
**
****************************************************************************/
-#ifndef QMLSCRIPT_H
-#define QMLSCRIPT_H
+#ifndef QMLGLOBALSCRIPTCLASS_P_H
+#define QMLGLOBALSCRIPTCLASS_P_H
-#include <QtDeclarative/qfxglobal.h>
-#include <QtCore/qobject.h>
-#include <QtDeclarative/qml.h>
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
-QT_BEGIN_HEADER
+#include <QtScript/qscriptclass.h>
QT_BEGIN_NAMESPACE
-QT_MODULE(Declarative)
-
-class QmlScriptPrivate;
-class Q_DECLARATIVE_EXPORT QmlScript : public QObject
+class QmlGlobalScriptClass : public QScriptClass
{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QmlScript)
-
- Q_PROPERTY(QString script READ script WRITE setScript)
- Q_PROPERTY(QUrl source READ source WRITE setSource)
- Q_CLASSINFO("DefaultProperty", "script")
-
public:
- QmlScript(QObject *parent=0);
+ QmlGlobalScriptClass(QScriptEngine *);
- QString script() const;
- void setScript(const QString &);
+ virtual QueryFlags queryProperty(const QScriptValue &object,
+ const QScriptString &name,
+ QueryFlags flags, uint *id);
- QUrl source() const;
- void setSource(const QUrl &);
+ virtual QScriptValue property(const QScriptValue &object,
+ const QScriptString &name, uint id);
-private Q_SLOTS:
- void replyFinished();
+ virtual void setProperty(QScriptValue &object, const QScriptString &name,
+ uint id, const QScriptValue &value);
+
+private:
+ QScriptValue globalObject;
};
QT_END_NAMESPACE
-QML_DECLARE_TYPE(QmlScript)
-
-QT_END_HEADER
-
-#endif
+#endif // QMLGLOBALSCRIPTCLASS_P_H
diff --git a/src/declarative/qml/qmlinstruction.cpp b/src/declarative/qml/qmlinstruction.cpp
index b71c6e3..18439f4 100644
--- a/src/declarative/qml/qmlinstruction.cpp
+++ b/src/declarative/qml/qmlinstruction.cpp
@@ -69,7 +69,7 @@ void QmlCompiledData::dump(QmlInstruction *instr, int idx)
qWarning() << idx << "\t" << line << "\t" << "CREATE_COMPONENT\t" << instr->createComponent.count;
break;
case QmlInstruction::StoreMetaObject:
- qWarning() << idx << "\t" << line << "\t" << "STORE_META\t\t" << instr->storeMeta.data << "\t" << instr->storeMeta.slotData;
+ qWarning() << idx << "\t" << line << "\t" << "STORE_META\t\t" << instr->storeMeta.data << "\t";
break;
case QmlInstruction::StoreFloat:
qWarning() << idx << "\t" << line << "\t" << "STORE_FLOAT\t\t" << instr->storeFloat.propertyIndex << "\t" << instr->storeFloat.value;
diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h
index 2c9ceac..1dcdace 100644
--- a/src/declarative/qml/qmlinstruction_p.h
+++ b/src/declarative/qml/qmlinstruction_p.h
@@ -118,6 +118,7 @@ public:
StoreInterface, /* storeObject */
StoreSignal, /* storeSignal */
+ StoreScript, /* storeScript */
//
// Unresolved single assignment
@@ -165,7 +166,7 @@ public:
struct {
int bindingsSize;
int parserStatusSize;
- int idSize;
+ int contextCache;
} init;
struct {
int type;
@@ -175,8 +176,8 @@ public:
} create;
struct {
int data;
- int slotData;
int aliasData;
+ int propertyCache;
} storeMeta;
struct {
int value;
@@ -238,6 +239,9 @@ public:
int value;
} storeString;
struct {
+ int value;
+ } storeScript;
+ struct {
int propertyIndex;
int value;
} storeUrl;
diff --git a/src/declarative/qml/qmlintegercache.cpp b/src/declarative/qml/qmlintegercache.cpp
new file mode 100644
index 0000000..564faaa
--- /dev/null
+++ b/src/declarative/qml/qmlintegercache.cpp
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlintegercache_p.h"
+#include <private/qmlengine_p.h>
+#include <QtDeclarative/qmlmetatype.h>
+
+QT_BEGIN_NAMESPACE
+
+QmlIntegerCache::QmlIntegerCache(QmlEngine *e)
+: engine(e)
+{
+}
+
+QmlIntegerCache::~QmlIntegerCache()
+{
+ qDeleteAll(stringCache);
+}
+
+void QmlIntegerCache::add(const QString &id, int value)
+{
+ Q_ASSERT(!stringCache.contains(id));
+
+ QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine);
+
+ // ### use contextClass
+ Data *d = new Data(enginePriv->objectClass->createPersistentIdentifier(id), value);
+
+ stringCache.insert(id, d);
+ identifierCache.insert(d->identifier, d);
+}
+
+int QmlIntegerCache::value(const QString &id)
+{
+ Data *d = stringCache.value(id);
+ return d?d->value:-1;
+}
+
+QmlIntegerCache *QmlIntegerCache::createForEnums(QmlType *type, QmlEngine *engine)
+{
+ Q_ASSERT(type);
+ Q_ASSERT(engine);
+
+ QmlIntegerCache *cache = new QmlIntegerCache(engine);
+
+ const QMetaObject *mo = type->metaObject();
+
+ for (int ii = mo->enumeratorCount() - 1; ii >= 0; --ii) {
+ QMetaEnum enumerator = mo->enumerator(ii);
+
+ for (int jj = 0; jj < enumerator.keyCount(); ++jj) {
+ QString name = QLatin1String(enumerator.key(jj));
+ int value = enumerator.value(jj);
+
+ if (!name.at(0).isUpper())
+ continue;
+
+ if (cache->stringCache.contains(name))
+ continue;
+
+ cache->add(name, value);
+ }
+ }
+
+ return cache;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlintegercache_p.h b/src/declarative/qml/qmlintegercache_p.h
new file mode 100644
index 0000000..e11e0be
--- /dev/null
+++ b/src/declarative/qml/qmlintegercache_p.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLINTEGERCACHE_P_H
+#define QMLINTEGERCACHE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qmlrefcount_p.h>
+#include <private/qscriptdeclarativeclass_p.h>
+#include <QtCore/qhash.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlType;
+class QmlEngine;
+class QmlIntegerCache : public QmlRefCount
+{
+public:
+ QmlIntegerCache(QmlEngine *);
+ virtual ~QmlIntegerCache();
+
+ inline int count() const;
+ void add(const QString &, int);
+ int value(const QString &);
+ inline int value(const QScriptDeclarativeClass::Identifier &id) const;
+
+ static QmlIntegerCache *createForEnums(QmlType *, QmlEngine *);
+private:
+ struct Data : public QScriptDeclarativeClass::PersistentIdentifier {
+ Data(const QScriptDeclarativeClass::PersistentIdentifier &i, int v)
+ : QScriptDeclarativeClass::PersistentIdentifier(i), value(v) {}
+
+ int value;
+ };
+
+ typedef QHash<QString, Data *> StringCache;
+ typedef QHash<QScriptDeclarativeClass::Identifier, Data *> IdentifierCache;
+
+ StringCache stringCache;
+ IdentifierCache identifierCache;
+ QmlEngine *engine;
+};
+
+int QmlIntegerCache::value(const QScriptDeclarativeClass::Identifier &id) const
+{
+ Data *d = identifierCache.value(id);
+ return d?d->value:-1;
+}
+
+int QmlIntegerCache::count() const
+{
+ return stringCache.count();
+}
+
+QT_END_NAMESPACE
+
+#endif // QMLINTEGERCACHE_P_H
+
diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp
index efc4a2b..302ce8c 100644
--- a/src/declarative/qml/qmlmetaproperty.cpp
+++ b/src/declarative/qml/qmlmetaproperty.cpp
@@ -58,56 +58,6 @@ Q_DECLARE_METATYPE(QList<QObject *>);
QT_BEGIN_NAMESPACE
-QmlMetaObjectCache::QmlMetaObjectCache()
-: propertyCache(0)
-{
-}
-
-void QmlMetaObjectCache::init(const QMetaObject *metaObject)
-{
- if (propertyCache || !metaObject)
- return;
-
- int propCount = metaObject->propertyCount();
-
- propertyCache = new Data[propCount];
- for (int ii = 0; ii < propCount; ++ii) {
- QMetaProperty p = metaObject->property(ii);
- propertyCache[ii].propType = p.userType();
- propertyCache[ii].coreIndex = ii;
- propertyCache[ii].name = QLatin1String(p.name());
-
- propertyNameCache.insert(propertyCache[ii].name, ii);
- }
-}
-
-QmlMetaObjectCache::~QmlMetaObjectCache()
-{
- delete [] propertyCache;
-}
-
-QmlMetaObjectCache::Data *
-QmlMetaObjectCache::property(int index, const QMetaObject *metaObject)
-{
- init(metaObject);
-
- return propertyCache + index;
-}
-
-QmlMetaObjectCache::Data *
-QmlMetaObjectCache::property(const QString &name, const QMetaObject *metaObject)
-{
- init(metaObject);
-
- QHash<QString, int>::ConstIterator iter = propertyNameCache.find(name);
-
- if (iter != propertyNameCache.end()) {
- return propertyCache + *iter;
- } else {
- return 0;
- }
-}
-
/*!
\class QmlMetaProperty
\brief The QmlMetaProperty class abstracts accessing QML properties.
@@ -122,9 +72,7 @@ QmlMetaProperty::QmlMetaProperty()
d->q = this;
}
-/*!
- The destructor deletes its heap data.
- */
+/*! \internal */
QmlMetaProperty::~QmlMetaProperty()
{
delete d; d = 0;
@@ -164,11 +112,9 @@ void QmlMetaPropertyPrivate::initDefault(QObject *obj)
object = obj;
QMetaProperty p = QmlMetaType::defaultProperty(obj);
- name = QLatin1String(p.name());
- propType = p.userType();;
- coreIdx = p.propertyIndex();
- if (!name.isEmpty())
- type = QmlMetaProperty::Property | QmlMetaProperty::Default;
+ core.load(p);
+ if (core.isValid())
+ isDefaultProperty = true;
}
/*!
@@ -179,15 +125,12 @@ void QmlMetaPropertyPrivate::initDefault(QObject *obj)
QmlMetaProperty::QmlMetaProperty(QObject *obj, int idx, QmlContext *ctxt)
: d(new QmlMetaPropertyPrivate)
{
+ Q_ASSERT(obj);
+
d->q = this;
d->context = ctxt;
d->object = obj;
- d->type = Property;
- QMetaProperty p = obj->metaObject()->property(idx);
- d->propType = p.userType();
- d->coreIdx = idx;
- if (p.name() != 0)
- d->name = QLatin1String(p.name());
+ d->core.load(obj->metaObject()->property(idx));
}
/*!
@@ -218,7 +161,6 @@ void QmlMetaPropertyPrivate::initProperty(QObject *obj, const QString &name)
if (context && context->engine())
enginePrivate = QmlEnginePrivate::get(context->engine());
- this->name = name;
object = obj;
if (name.isEmpty() || !obj)
@@ -235,8 +177,6 @@ void QmlMetaPropertyPrivate::initProperty(QObject *obj, const QString &name)
enginePrivate->resolveType(typeData->imports, name.toLatin1(), &t, 0, 0, 0, 0);
if (t && t->attachedPropertiesFunction()) {
attachedFunc = t->index();
- if (attachedFunc != -1)
- type = QmlMetaProperty::Property | QmlMetaProperty::Attached;
}
typeData->release();
}
@@ -250,30 +190,31 @@ void QmlMetaPropertyPrivate::initProperty(QObject *obj, const QString &name)
QString signalName = name.mid(2);
signalName[0] = signalName.at(0).toLower();
- findSignalInt(obj, signalName);
- if (signal.signature() != 0) {
- type = QmlMetaProperty::SignalProperty;
+ QMetaMethod method = findSignal(obj, signalName);
+ if (method.signature()) {
+ core.load(method);
return;
}
}
// Property
- QmlMetaObjectCache *cache = QmlEnginePrivate::cache(enginePrivate, obj);
+ QmlPropertyCache *cache = 0;
+ QmlDeclarativeData *ddata = QmlDeclarativeData::get(obj);
+ if (ddata)
+ cache = ddata->propertyCache;
+ if (!cache)
+ cache = enginePrivate?enginePrivate->cache(obj):0;
+
if (cache) {
- QmlMetaObjectCache::Data *data =
- cache->property(name, obj->metaObject());
- if (data) {
- type = QmlMetaProperty::Property;
- propType = data->propType;
- coreIdx = data->coreIndex;
- }
+ QmlPropertyCache::Data *data = cache->property(name);
+
+ if (data && !(data->flags & QmlPropertyCache::Data::IsFunction))
+ core = *data;
+
} else {
- // Can't cache
+ // No cache available
QMetaProperty p = QmlMetaType::property(obj, name.toUtf8().constData());
- propType = p.userType();
- coreIdx = p.propertyIndex();
- if (p.name())
- type = QmlMetaProperty::Property;
+ core.load(p);
}
}
@@ -323,33 +264,31 @@ QmlMetaProperty::PropertyCategory QmlMetaProperty::propertyCategory() const
QmlMetaProperty::PropertyCategory
QmlMetaPropertyPrivate::propertyCategory() const
{
- if (category == QmlMetaProperty::Unknown) {
+ uint type = q->type();
+
+ if (type & QmlMetaProperty::ValueTypeProperty) {
+ return QmlMetaProperty::Normal;
+ } else if (type & QmlMetaProperty::Attached) {
+ return QmlMetaProperty::Object;
+ } else if (type & QmlMetaProperty::Property) {
int type = propertyType();
- if (type == QmlMetaProperty::Invalid)
- category = QmlMetaProperty::InvalidProperty;
- else if (type < QVariant::UserType)
- category = QmlMetaProperty::Normal;
+ if (type == QVariant::Invalid)
+ return QmlMetaProperty::InvalidProperty;
+ else if ((uint)type < QVariant::UserType)
+ return QmlMetaProperty::Normal;
else if (type == qMetaTypeId<QmlBinding *>())
- category = QmlMetaProperty::Bindable;
- else {
- QmlMetaType::TypeCategory tc = QmlMetaType::typeCategory(type);
- switch(tc) {
- case QmlMetaType::Object:
- category = QmlMetaProperty::Object;
- break;
- case QmlMetaType::QmlList:
- category = QmlMetaProperty::QmlList;
- break;
- case QmlMetaType::List:
- category = QmlMetaProperty::List;
- break;
- case QmlMetaType::Unknown:
- category = QmlMetaProperty::Normal;
- break;
- }
- }
+ return QmlMetaProperty::Bindable;
+ else if (core.flags & QmlPropertyCache::Data::IsQObjectDerived)
+ return QmlMetaProperty::Object;
+ else if (core.flags & QmlPropertyCache::Data::IsQmlList)
+ return QmlMetaProperty::QmlList;
+ else if (core.flags & QmlPropertyCache::Data::IsQList)
+ return QmlMetaProperty::List;
+ else
+ return QmlMetaProperty::Normal;
+ } else {
+ return QmlMetaProperty::InvalidProperty;
}
- return category;
}
/*!
@@ -358,8 +297,21 @@ QmlMetaPropertyPrivate::propertyCategory() const
*/
const char *QmlMetaProperty::propertyTypeName() const
{
- if (!d->name.isEmpty() && d->object) {
- return d->object->metaObject()->property(d->coreIdx).typeName();
+ if (type() & ValueTypeProperty) {
+
+ QmlEnginePrivate *ep = d->context?QmlEnginePrivate::get(d->context->engine()):0;
+ QmlValueType *valueType = 0;
+ if (ep) valueType = ep->valueTypes[d->core.propType];
+ else valueType = QmlValueTypeFactory::valueType(d->core.propType);
+ Q_ASSERT(valueType);
+
+ const char *rv = valueType->metaObject()->property(d->valueTypeCoreIdx).typeName();
+
+ if (!ep) delete valueType;
+
+ return rv;
+ } else if (d->object && type() & Property && d->core.isValid()) {
+ return d->object->metaObject()->property(d->core.coreIndex).typeName();
} else {
return 0;
}
@@ -371,10 +323,13 @@ const char *QmlMetaProperty::propertyTypeName() const
*/
bool QmlMetaProperty::operator==(const QmlMetaProperty &other) const
{
- return d->name == other.d->name &&
- d->signal.signature() == other.d->signal.signature() &&
- d->type == other.d->type &&
- d->object == other.d->object;
+ // category is intentially omitted here as it is generated
+ // from the other members
+ return d->object == other.d->object &&
+ d->core == other.d->core &&
+ d->valueTypeCoreIdx == other.d->valueTypeCoreIdx &&
+ d->valueTypePropType == other.d->valueTypePropType &&
+ d->attachedFunc == other.d->attachedFunc;
}
/*!
@@ -388,18 +343,19 @@ int QmlMetaProperty::propertyType() const
int QmlMetaPropertyPrivate::propertyType() const
{
- int rv = QVariant::Invalid;
-
- if (!name.isEmpty()) {
- if (propType == (int)QVariant::LastType)
- rv = qMetaTypeId<QVariant>();
+ uint type = q->type();
+ if (type & QmlMetaProperty::ValueTypeProperty) {
+ return valueTypePropType;
+ } else if (type & QmlMetaProperty::Attached) {
+ return qMetaTypeId<QObject *>();
+ } else if (type & QmlMetaProperty::Property) {
+ if (core.propType == (int)QVariant::LastType)
+ return qMetaTypeId<QVariant>();
else
- rv = propType;
- } else if (attachedFunc) {
- rv = qMetaTypeId<QObject *>();
- }
-
- return rv;
+ return core.propType;
+ } else {
+ return QVariant::Invalid;
+ }
}
/*!
@@ -407,7 +363,16 @@ int QmlMetaPropertyPrivate::propertyType() const
*/
QmlMetaProperty::Type QmlMetaProperty::type() const
{
- return (Type)d->type;
+ if (d->core.flags & QmlPropertyCache::Data::IsFunction)
+ return SignalProperty;
+ else if (d->attachedFunc != -1)
+ return Attached;
+ else if (d->valueTypeCoreIdx != -1)
+ return (Type)(Property | ValueTypeProperty);
+ else if (d->core.isValid())
+ return (Type)(Property | ((d->isDefaultProperty)?Default:0));
+ else
+ return Invalid;
}
/*!
@@ -439,17 +404,16 @@ QObject *QmlMetaProperty::object() const
*/
QmlMetaProperty &QmlMetaProperty::operator=(const QmlMetaProperty &other)
{
- d->name = other.d->name;
- d->signal = other.d->signal;
d->context = other.d->context;
- d->coreIdx = other.d->coreIdx;
- d->valueTypeIdx = other.d->valueTypeIdx;
- d->valueTypeId = other.d->valueTypeId;
- d->type = other.d->type;
- d->attachedFunc = other.d->attachedFunc;
d->object = other.d->object;
- d->propType = other.d->propType;
- d->category = other.d->category;
+
+ d->isDefaultProperty = other.d->isDefaultProperty;
+ d->core = other.d->core;
+
+ d->valueTypeCoreIdx = other.d->valueTypeCoreIdx;
+ d->valueTypePropType = other.d->valueTypePropType;
+
+ d->attachedFunc = other.d->attachedFunc;
return *this;
}
@@ -458,12 +422,14 @@ QmlMetaProperty &QmlMetaProperty::operator=(const QmlMetaProperty &other)
*/
bool QmlMetaProperty::isWritable() const
{
- if (propertyCategory() == List || propertyCategory() == QmlList)
+ QmlMetaProperty::PropertyCategory category = propertyCategory();
+
+ if (category == List || category == QmlList)
return true;
else if (type() & SignalProperty)
return true;
- else if (!d->name.isEmpty() && d->object)
- return d->object->metaObject()->property(d->coreIdx).isWritable();
+ else if (d->core.isValid() && d->object)
+ return d->object->metaObject()->property(d->core.coreIndex).isWritable();
else
return false;
}
@@ -473,8 +439,8 @@ bool QmlMetaProperty::isWritable() const
*/
bool QmlMetaProperty::isDesignable() const
{
- if (!d->name.isEmpty() && d->object)
- return d->object->metaObject()->property(d->coreIdx).isDesignable();
+ if (type() & Property && d->core.isValid() && d->object)
+ return d->object->metaObject()->property(d->core.coreIndex).isDesignable();
else
return false;
}
@@ -493,6 +459,7 @@ bool QmlMetaProperty::isValid() const
*/
QStringList QmlMetaProperty::properties(QObject *obj)
{
+ // ### What is this used for?
if (!obj)
return QStringList();
@@ -511,7 +478,23 @@ QStringList QmlMetaProperty::properties(QObject *obj)
*/
QString QmlMetaProperty::name() const
{
- return d->name;
+ if (type() & ValueTypeProperty) {
+ QString rv = d->core.name + QLatin1String(".");
+
+ QmlEnginePrivate *ep = d->context?QmlEnginePrivate::get(d->context->engine()):0;
+ QmlValueType *valueType = 0;
+ if (ep) valueType = ep->valueTypes[d->core.propType];
+ else valueType = QmlValueTypeFactory::valueType(d->core.propType);
+ Q_ASSERT(valueType);
+
+ rv += QLatin1String(valueType->metaObject()->property(d->valueTypeCoreIdx).name());
+
+ if (!ep) delete valueType;
+
+ return rv;
+ } else {
+ return d->core.name;
+ }
}
/*!
@@ -520,13 +503,26 @@ QString QmlMetaProperty::name() const
*/
QMetaProperty QmlMetaProperty::property() const
{
- if (d->object)
- return d->object->metaObject()->property(d->coreIdx);
+ if (type() & Property && d->core.isValid() && d->object)
+ return d->object->metaObject()->property(d->core.coreIndex);
else
return QMetaProperty();
}
/*!
+ Return the QMetaMethod for this property if it is a SignalProperty,
+ otherwise returns an invalid QMetaMethod.
+*/
+QMetaMethod QmlMetaProperty::method() const
+{
+ if (type() & SignalProperty && d->object)
+ return d->object->metaObject()->method(d->core.coreIndex);
+ else
+ return QMetaMethod();
+}
+
+
+/*!
Returns the binding associated with this property, or 0 if no binding
exists.
*/
@@ -539,13 +535,13 @@ QmlAbstractBinding *QmlMetaProperty::binding() const
if (!data)
return 0;
- if (!data->hasBindingBit(d->coreIdx))
+ if (!data->hasBindingBit(d->core.coreIndex))
return 0;
QmlAbstractBinding *binding = data->bindings;
while (binding) {
// ### This wont work for value types
- if (binding->propertyIndex() == d->coreIdx)
+ if (binding->propertyIndex() == d->core.coreIndex)
return binding;
binding = binding->m_nextBinding;
}
@@ -568,14 +564,20 @@ QmlMetaProperty::setBinding(QmlAbstractBinding *newBinding) const
if (!isProperty() || (type() & Attached) || !d->object)
return 0;
- QmlDeclarativeData *data =
- QmlDeclarativeData::get(d->object, 0 != newBinding);
+ return d->setBinding(d->object, d->core, newBinding);
+}
+
+QmlAbstractBinding *
+QmlMetaPropertyPrivate::setBinding(QObject *object, const QmlPropertyCache::Data &core,
+ QmlAbstractBinding *newBinding)
+{
+ QmlDeclarativeData *data = QmlDeclarativeData::get(object, 0 != newBinding);
- if (data && data->hasBindingBit(d->coreIdx)) {
+ if (data && data->hasBindingBit(core.coreIndex)) {
QmlAbstractBinding *binding = data->bindings;
while (binding) {
// ### This wont work for value types
- if (binding->propertyIndex() == d->coreIdx) {
+ if (binding->propertyIndex() == core.coreIndex) {
binding->setEnabled(false);
if (newBinding)
@@ -638,15 +640,14 @@ QmlExpression *QmlMetaProperty::setSignalExpression(QmlExpression *expr) const
}
if (expr) {
- QmlBoundSignal *signal = new QmlBoundSignal(d->object, d->signal,
- d->object);
+ QmlBoundSignal *signal = new QmlBoundSignal(d->object, method(), d->object);
return signal->setExpression(expr);
} else {
return 0;
}
}
-void QmlMetaPropertyPrivate::findSignalInt(QObject *obj, const QString &name)
+QMetaMethod QmlMetaPropertyPrivate::findSignal(QObject *obj, const QString &name)
{
const QMetaObject *mo = obj->metaObject();
@@ -657,12 +658,10 @@ void QmlMetaPropertyPrivate::findSignalInt(QObject *obj, const QString &name)
int idx = methodName.indexOf(QLatin1Char('('));
methodName = methodName.left(idx);
- if (methodName == name) {
- signal = method;
- coreIdx = ii;
- return;
- }
+ if (methodName == name)
+ return method;
}
+ return QMetaMethod();
}
QObject *QmlMetaPropertyPrivate::attachedObject() const
@@ -687,31 +686,14 @@ QVariant QmlMetaProperty::read() const
for (int ii = 0; ii < children.count(); ++ii) {
QmlBoundSignal *sig = QmlBoundSignal::cast(children.at(ii));
- if (sig && sig->index() == d->coreIdx)
+ if (sig && sig->index() == d->core.coreIndex)
return sig->expression()->expression();
}
+
} else if (type() & Property) {
- if (type() & Attached) {
- return QVariant::fromValue(d->attachedObject());
- } else if(type() & ValueTypeProperty) {
- QmlEnginePrivate *ep = d->context?static_cast<QmlEnginePrivate *>(QObjectPrivate::get(d->context->engine())):0;
- QmlValueType *valueType = 0;
- if (ep)
- valueType = ep->valueTypes[d->valueTypeId];
- else
- valueType = QmlValueTypeFactory::valueType(d->valueTypeId);
- Q_ASSERT(valueType);
-
- valueType->read(object(), d->coreIdx);
- QVariant rv =
- valueType->metaObject()->property(d->valueTypeIdx).read(valueType);
- if (!ep)
- delete valueType;
- return rv;
- } else {
- return d->object->metaObject()->property(d->coreIdx).read(object());
- }
+ return d->readValueProperty();
+
}
return QVariant();
}
@@ -723,7 +705,7 @@ void QmlMetaPropertyPrivate::writeSignalProperty(const QVariant &value)
for (int ii = 0; ii < children.count(); ++ii) {
QmlBoundSignal *sig = QmlBoundSignal::cast(children.at(ii));
- if (sig && sig->index() == coreIdx) {
+ if (sig && sig->index() == core.coreIndex) {
if (expr.isEmpty()) {
sig->disconnect();
sig->deleteLater();
@@ -736,47 +718,86 @@ void QmlMetaPropertyPrivate::writeSignalProperty(const QVariant &value)
if (!expr.isEmpty()) {
// XXX scope
- (void *)new QmlBoundSignal(qmlContext(object), expr, object, signal, object);
+ (void *)new QmlBoundSignal(qmlContext(object), expr, object, q->method(), object);
+ }
+}
+
+QVariant QmlMetaPropertyPrivate::readValueProperty()
+{
+ uint type = q->type();
+ if (type & QmlMetaProperty::Attached) {
+
+ return QVariant::fromValue(attachedObject());
+
+ } else if(type & QmlMetaProperty::ValueTypeProperty) {
+
+ QmlEnginePrivate *ep = context?QmlEnginePrivate::get(context->engine()):0;
+ QmlValueType *valueType = 0;
+ if (ep) valueType = ep->valueTypes[core.propType];
+ else valueType = QmlValueTypeFactory::valueType(core.propType);
+ Q_ASSERT(valueType);
+
+ valueType->read(object, core.coreIndex);
+
+ QVariant rv =
+ valueType->metaObject()->property(valueTypeCoreIdx).read(valueType);
+
+ if (!ep) delete valueType;
+ return rv;
+
+ } else {
+
+ return object->metaObject()->property(core.coreIndex).read(object.data());
+
}
}
void QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value,
QmlMetaProperty::WriteSource source)
{
- QObject *object = this->object;
- int coreIdx = this->coreIdx;
-
- QmlValueType *writeBack = 0;
- QObject *writeBackObj = 0;
- int writeBackIdx = -1;
- bool deleteWriteBack = false;
-
// Remove any existing bindings on this property
if (source != QmlMetaProperty::Binding)
delete q->setBinding(0);
+ uint type = q->type();
if (type & QmlMetaProperty::ValueTypeProperty) {
- QmlEnginePrivate *ep = context?static_cast<QmlEnginePrivate *>(QObjectPrivate::get(context->engine())):0;
+ QmlEnginePrivate *ep =
+ context?static_cast<QmlEnginePrivate *>(QObjectPrivate::get(context->engine())):0;
+ QmlValueType *writeBack = 0;
if (ep) {
- writeBack = ep->valueTypes[valueTypeId];
+ writeBack = ep->valueTypes[core.propType];
} else {
- writeBack = QmlValueTypeFactory::valueType(valueTypeId);
- deleteWriteBack = true;
+ writeBack = QmlValueTypeFactory::valueType(core.propType);
}
- writeBackObj = this->object;
- writeBackIdx = this->coreIdx;
- writeBack->read(writeBackObj, writeBackIdx);
- object = writeBack;
- coreIdx = valueTypeIdx;
+ writeBack->read(object, core.coreIndex);
+
+ QmlPropertyCache::Data data = core;
+ data.coreIndex = valueTypeCoreIdx;
+ data.propType = valueTypePropType;
+ write(writeBack, data, value, context);
+
+ writeBack->write(object, core.coreIndex);
+ if (!ep) delete writeBack;
+
+ } else {
+
+ write(object, core, value, context);
+
}
+}
- QMetaProperty prop = object->metaObject()->property(coreIdx);
+void QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data &property,
+ const QVariant &value, QmlContext *context)
+{
+ int coreIdx = property.coreIndex;
- if (prop.isEnumType()) {
+ if (property.flags & QmlPropertyCache::Data::IsEnumType) {
+ QMetaProperty prop = object->metaObject()->property(property.coreIndex);
QVariant v = value;
- if (value.type() == QVariant::Double) { //enum values come through the script engine as doubles
+ // Enum values come through the script engine as doubles
+ if (value.type() == QVariant::Double) {
double integral;
double fractional = modf(value.toDouble(), &integral);
if (qFuzzyCompare(fractional, (double)0.0))
@@ -784,19 +805,36 @@ void QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value,
}
prop.write(object, v);
- if (writeBack) {
- writeBack->write(writeBackObj, writeBackIdx);
- if (deleteWriteBack) delete writeBack;
- }
return;
}
- int t = propertyType();
+ int t = property.propType;
int vt = value.userType();
- int category = propertyCategory();
- if (vt == t
- && t != QVariant::Url) { // always resolve relative urls
+ if (t == QVariant::Url) {
+
+ QUrl u;
+ bool found = false;
+ if (vt == QVariant::Url) {
+ u = value.toUrl();
+ found = true;
+ } else if (vt == QVariant::ByteArray) {
+ u = QUrl(QLatin1String(value.toByteArray()));
+ found = true;
+ } else if (vt == QVariant::String) {
+ u = QUrl(value.toString());
+ found = true;
+ }
+
+ if (found) {
+ if (context && u.isRelative() && !u.isEmpty())
+ u = context->baseUrl().resolved(u);
+ void *a[1];
+ a[0] = &u;
+ QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a);
+ }
+
+ } else if (vt == t) {
void *a[1];
a[0] = (void *)value.constData();
@@ -804,9 +842,11 @@ void QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value,
} else if (qMetaTypeId<QVariant>() == t) {
- prop.write(object, value);
+ void *a[1];
+ a[0] = (void *)&value;
+ QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a);
- } else if (category == QmlMetaProperty::Object) {
+ } else if (property.flags & QmlPropertyCache::Data::IsQObjectDerived) {
QObject *o = QmlMetaType::toQObject(value);
@@ -833,9 +873,10 @@ void QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value,
}
- } else if (category == QmlMetaProperty::List) {
+ } else if (property.flags & QmlPropertyCache::Data::IsQList) {
int listType = QmlMetaType::listType(t);
+ QMetaProperty prop = object->metaObject()->property(property.coreIndex);
if (value.userType() == qMetaTypeId<QList<QObject *> >()) {
const QList<QObject *> &list =
@@ -853,9 +894,11 @@ void QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value,
QmlMetaType::clear(listVar);
QmlMetaType::append(listVar, value);
}
- } else if (category == QmlMetaProperty::QmlList) {
+
+ } else if (property.flags & QmlPropertyCache::Data::IsQmlList) {
// XXX - optimize!
+ QMetaProperty prop = object->metaObject()->property(property.coreIndex);
QVariant list = prop.read(object);
QmlPrivate::ListInterface *li =
*(QmlPrivate::ListInterface **)list.constData();
@@ -885,118 +928,25 @@ void QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value,
void *d = (void *)&obj;
li->append(d);
}
- } else if (category == QmlMetaProperty::Normal) {
-
- bool found = false;
- switch(t) {
- case QVariant::Double:
- {
- double d;
- if (vt == QVariant::Int) {
- d = value.toInt();
- found = true;
- } else if (vt == QVariant::UInt) {
- d = value.toUInt();
- found = true;
- }
-
- if (found) {
- void *a[1];
- a[0] = &d;
- QMetaObject::metacall(object,
- QMetaObject::WriteProperty,
- coreIdx, a);
- }
- }
- break;
-
- case QVariant::Int:
- {
- int i;
- if (vt == QVariant::Double) {
- i = (int)value.toDouble();
- found = true;
- } else if (vt == QVariant::UInt) {
- i = (int)value.toUInt();
- found = true;
- }
-
- if (found) {
- void *a[1];
- a[0] = &i;
- QMetaObject::metacall(object,
- QMetaObject::WriteProperty,
- coreIdx, a);
- }
- }
- break;
-
- case QVariant::String:
- {
- QString s;
- if (vt == QVariant::ByteArray) {
- s = QLatin1String(value.toByteArray());
- found = true;
- }
-
- if (found) {
- void *a[1];
- a[0] = &s;
- QMetaObject::metacall(object,
- QMetaObject::WriteProperty,
- coreIdx, a);
- }
- }
- break;
-
- case QVariant::Url:
- {
- QUrl u;
- if (vt == QVariant::Url) {
- u = value.toUrl();
- found = true;
- } else if (vt == QVariant::ByteArray) {
- u = QUrl(QLatin1String(value.toByteArray()));
- found = true;
- } else if (vt == QVariant::String) {
- u = QUrl(value.toString());
- found = true;
- }
+ } else {
+ Q_ASSERT(vt != t);
- if (found) {
- if (context && u.isRelative() && !u.isEmpty())
- u = context->baseUrl().resolved(u);
+ QVariant v = value;
+ if (v.convert((QVariant::Type)t)) {
+ void *a[1];
+ a[0] = (void *)v.constData();
+ QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a);
+ } else if ((uint)t >= QVariant::UserType && vt == QVariant::String) {
+ QmlMetaType::StringConverter con = QmlMetaType::customStringConverter(t);
+ if (con) {
+ QVariant v = con(value.toString());
+ if (v.userType() == t) {
void *a[1];
- a[0] = &u;
- QMetaObject::metacall(object,
- QMetaObject::WriteProperty,
- coreIdx, a);
- }
-
- }
- break;
-
-
- default:
- {
- if ((uint)t >= QVariant::UserType && vt == QVariant::String) {
- QmlMetaType::StringConverter con = QmlMetaType::customStringConverter(t);
- if (con) {
- QVariant v = con(value.toString());
- prop.write(object, v);
- found = true;
- }
+ a[0] = (void *)v.constData();
+ QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a);
}
}
- break;
}
- if (!found)
- prop.write(object, value);
- }
-
- if (writeBack) {
- writeBack->write(writeBackObj, writeBackIdx);
- if (deleteWriteBack) delete writeBack;
}
}
@@ -1017,7 +967,7 @@ void QmlMetaProperty::write(const QVariant &value, WriteSource source) const
d->writeSignalProperty(value);
- } else if (d->coreIdx != -1) {
+ } else if (d->core.isValid()) {
d->writeValueProperty(value, source);
@@ -1030,7 +980,7 @@ void QmlMetaProperty::write(const QVariant &value, WriteSource source) const
bool QmlMetaProperty::hasChangedNotifier() const
{
if (type() & Property && !(type() & Attached) && d->object) {
- return d->object->metaObject()->property(d->coreIdx).hasNotifySignal();
+ return d->object->metaObject()->property(d->core.coreIndex).hasNotifySignal();
}
return false;
}
@@ -1061,7 +1011,7 @@ bool QmlMetaProperty::connectNotifier(QObject *dest, int method) const
if (!(type() & Property) || (type() & Attached) || !d->object)
return false;
- QMetaProperty prop = d->object->metaObject()->property(d->coreIdx);
+ QMetaProperty prop = d->object->metaObject()->property(d->core.coreIndex);
if (prop.hasNotifySignal()) {
return QMetaObject::connect(d->object, prop.notifySignalIndex(), dest, method, Qt::DirectConnection);
} else {
@@ -1082,7 +1032,7 @@ bool QmlMetaProperty::connectNotifier(QObject *dest, const char *slot) const
if (!(type() & Property) || (type() & Attached) || !d->object)
return false;
- QMetaProperty prop = d->object->metaObject()->property(d->coreIdx);
+ QMetaProperty prop = d->object->metaObject()->property(d->core.coreIndex);
if (prop.hasNotifySignal()) {
QByteArray signal(QByteArray("2") + prop.notifySignal().signature());
return QObject::connect(d->object, signal.constData(), dest, slot);
@@ -1096,7 +1046,7 @@ bool QmlMetaProperty::connectNotifier(QObject *dest, const char *slot) const
*/
int QmlMetaProperty::coreIndex() const
{
- return d->coreIdx;
+ return d->core.coreIndex;
}
Q_GLOBAL_STATIC(QmlValueTypeFactory, qmlValueTypes);
@@ -1111,17 +1061,17 @@ quint32 QmlMetaProperty::save() const
if (type() & Attached) {
rv = d->attachedFunc;
} else if (type() != Invalid) {
- rv = d->coreIdx;
+ rv = d->core.coreIndex;
}
Q_ASSERT(rv <= 0x7FF);
Q_ASSERT(type() <= 0x3F);
- Q_ASSERT(d->valueTypeIdx <= 0x7F);
+ Q_ASSERT(d->valueTypeCoreIdx <= 0x7F);
rv |= (type() << 18);
if (type() & ValueTypeProperty)
- rv |= (d->valueTypeIdx << 11);
+ rv |= (d->valueTypeCoreIdx << 11);
return rv;
}
@@ -1162,12 +1112,12 @@ void QmlMetaProperty::restore(quint32 id, QObject *obj, QmlContext *ctxt)
d->context = ctxt;
id &= 0xFFFFFF;
- d->type = id >> 18;
+ uint type = id >> 18;
id &= 0xFFFF;
- if (d->type & Attached) {
+ if (type & Attached) {
d->attachedFunc = id;
- } else if (d->type & ValueTypeProperty) {
+ } else if (type & ValueTypeProperty) {
int coreIdx = id & 0x7FF;
int valueTypeIdx = id >> 11;
@@ -1178,47 +1128,31 @@ void QmlMetaProperty::restore(quint32 id, QObject *obj, QmlContext *ctxt)
QMetaProperty p2(valueType->metaObject()->property(valueTypeIdx));
- d->name = QLatin1String(p2.name());
- d->propType = p2.userType();
- d->coreIdx = coreIdx;
- d->valueTypeIdx = valueTypeIdx;
- d->valueTypeId = p.type();
-
- } else if (d->type & Property) {
+ d->core.load(p);
+ d->valueTypeCoreIdx = valueTypeIdx;
+ d->valueTypePropType = p2.userType();
+ } else if (type & Property) {
- QmlMetaObjectCache *cache = QmlEnginePrivate::cache(enginePrivate, obj);
-
- d->coreIdx = id;
+ QmlPropertyCache *cache = enginePrivate?enginePrivate->cache(obj):0;
if (cache) {
- QmlMetaObjectCache::Data *data =
- cache->property(id, obj->metaObject());
- d->propType = data->propType;
- d->name = data->name;
+ QmlPropertyCache::Data *data = cache->property(id);
+ if (data) d->core = *data;
} else {
QMetaProperty p(obj->metaObject()->property(id));
- d->name = QLatin1String(p.name());
- d->propType = p.userType();
+ d->core.load(p);
}
- } else if (d->type & SignalProperty) {
- d->signal = obj->metaObject()->method(id);
- d->coreIdx = id;
+ } else if (type & SignalProperty) {
+
+ QMetaMethod method = obj->metaObject()->method(id);
+ d->core.load(method);
} else {
*this = QmlMetaProperty();
}
}
/*!
- Return the QMetaMethod for this property if it is a SignalProperty,
- otherwise returns an invalid QMetaMethod.
-*/
-QMetaMethod QmlMetaProperty::method() const
-{
- return d->signal;
-}
-
-/*!
\internal
Creates a QmlMetaProperty for the property \a name of \a obj. Unlike
@@ -1245,17 +1179,11 @@ QmlMetaProperty QmlMetaProperty::createProperty(QObject *obj,
int idx = typeObject->metaObject()->indexOfProperty(path.last().toUtf8().constData());
if (idx == -1)
return QmlMetaProperty();
+ QMetaProperty vtProp = typeObject->metaObject()->property(idx);
- QmlMetaProperty p;
- p.d->name = pathName + QLatin1String(".") + path.last();
- p.d->context = 0;
- p.d->coreIdx = prop.coreIndex();
- p.d->valueTypeIdx = idx;
- p.d->valueTypeId = prop.propertyType();
- p.d->type = QmlMetaProperty::ValueTypeProperty |
- QmlMetaProperty::Property;
- p.d->object = obj;
- p.d->propType = typeObject->metaObject()->property(idx).userType();
+ QmlMetaProperty p = prop;
+ p.d->valueTypeCoreIdx = idx;
+ p.d->valueTypePropType = vtProp.userType();
return p;
}
diff --git a/src/declarative/qml/qmlmetaproperty_p.h b/src/declarative/qml/qmlmetaproperty_p.h
index 1ccf913..00b9c3a 100644
--- a/src/declarative/qml/qmlmetaproperty_p.h
+++ b/src/declarative/qml/qmlmetaproperty_p.h
@@ -54,73 +54,54 @@
//
#include "qmlmetaproperty.h"
-#include "private/qobject_p.h"
+#include <private/qobject_p.h>
+#include <private/qmlpropertycache_p.h>
QT_BEGIN_NAMESPACE
-class QmlMetaObjectCache
-{
-public:
- QmlMetaObjectCache();
- ~QmlMetaObjectCache();
-
- struct Data {
- int propType;
- int coreIndex;
- QString name;
- };
-
- Data *property(const QString &, const QMetaObject *);
- Data *property(int, const QMetaObject *);
-
-private:
- void init(const QMetaObject *);
-
- Data *propertyCache;
- QHash<QString, int> propertyNameCache;
-};
-
class QmlContext;
class QmlMetaPropertyPrivate
{
public:
QmlMetaPropertyPrivate()
- : q(0), context(0), coreIdx(-1), valueTypeIdx(-1), valueTypeId(0),
- type(QmlMetaProperty::Invalid), attachedFunc(-1),
- object(0), propType(-1), category(QmlMetaProperty::Unknown) {}
+ : q(0), context(0), object(0), isDefaultProperty(false), valueTypeCoreIdx(-1),
+ valueTypePropType(0), attachedFunc(-1) {}
+
QmlMetaPropertyPrivate(const QmlMetaPropertyPrivate &other)
- : q(0), name(other.name), signal(other.signal), context(other.context),
- coreIdx(other.coreIdx), valueTypeIdx(other.valueTypeIdx),
- valueTypeId(other.valueTypeId), type(other.type),
- attachedFunc(other.attachedFunc), object(other.object),
- propType(other.propType), category(other.category) {}
+ : q(0), context(other.context), object(other.object),
+ isDefaultProperty(other.isDefaultProperty), core(other.core),
+ valueTypeCoreIdx(other.valueTypeCoreIdx),
+ valueTypePropType(other.valueTypePropType), attachedFunc(other.attachedFunc) {}
QmlMetaProperty *q;
-
- QString name;
- QMetaMethod signal;
QmlContext *context;
- int coreIdx;
- int valueTypeIdx;
- int valueTypeId;
- uint type;
- int attachedFunc;
QGuard<QObject> object;
- int propType;
- mutable QmlMetaProperty::PropertyCategory category;
+ bool isDefaultProperty;
+ QmlPropertyCache::Data core;
+
+ // Describes the "virtual" value-type sub-property.
+ int valueTypeCoreIdx; // The prop index of the access property on the value type wrapper
+ int valueTypePropType; // The QVariant::Type of access property on the value type wrapper
+
+ // The attached property accessor
+ int attachedFunc;
void initProperty(QObject *obj, const QString &name);
void initDefault(QObject *obj);
QObject *attachedObject() const;
- void findSignalInt(QObject *, const QString &);
+ QMetaMethod findSignal(QObject *, const QString &);
int propertyType() const;
QmlMetaProperty::PropertyCategory propertyCategory() const;
void writeSignalProperty(const QVariant &);
+
+ QVariant readValueProperty();
void writeValueProperty(const QVariant &, QmlMetaProperty::WriteSource);
+ static void write(QObject *, const QmlPropertyCache::Data &, const QVariant &, QmlContext *);
+ static QmlAbstractBinding *setBinding(QObject *, const QmlPropertyCache::Data &, QmlAbstractBinding *);
static quint32 saveValueType(int, int);
static quint32 saveProperty(int);
diff --git a/src/declarative/qml/qmlmetatype.cpp b/src/declarative/qml/qmlmetatype.cpp
index 14d85ff..c40232f 100644
--- a/src/declarative/qml/qmlmetatype.cpp
+++ b/src/declarative/qml/qmlmetatype.cpp
@@ -929,6 +929,30 @@ QList<QmlType*> QmlMetaType::qmlTypes()
return data->nameToType.values();
}
+#include <QtGui/qfont.h>
+#include <QtGui/qpixmap.h>
+#include <QtGui/qbrush.h>
+#include <QtGui/qcolor.h>
+#include <QtGui/qpalette.h>
+#include <QtGui/qicon.h>
+#include <QtGui/qimage.h>
+#include <QtGui/qpolygon.h>
+#include <QtGui/qregion.h>
+#include <QtGui/qbitmap.h>
+#include <QtGui/qcursor.h>
+#include <QtGui/qsizepolicy.h>
+#include <QtGui/qkeysequence.h>
+#include <QtGui/qpen.h>
+//#include <QtGui/qtextlength.h>
+#include <QtGui/qtextformat.h>
+#include <QtGui/qmatrix.h>
+#include <QtGui/qtransform.h>
+#include <QtGui/qmatrix4x4.h>
+#include <QtGui/qvector2d.h>
+#include <QtGui/qvector3d.h>
+#include <QtGui/qvector4d.h>
+#include <QtGui/qquaternion.h>
+
/*!
Copies \a copy into \a data, assuming they both are of type \a type. If
\a copy is zero, a default type is copied. Returns true if the copy was
@@ -988,7 +1012,6 @@ bool QmlMetaType::copy(int type, void *data, const void *copy)
case QMetaType::QChar:
*static_cast<NS(QChar) *>(data) = *static_cast<const NS(QChar)*>(copy);
return true;
-#ifndef QT_BOOTSTRAPPED
case QMetaType::QVariantMap:
*static_cast<NS(QVariantMap) *>(data) = *static_cast<const NS(QVariantMap)*>(copy);
return true;
@@ -998,7 +1021,6 @@ bool QmlMetaType::copy(int type, void *data, const void *copy)
case QMetaType::QVariantList:
*static_cast<NS(QVariantList) *>(data) = *static_cast<const NS(QVariantList)*>(copy);
return true;
-#endif
case QMetaType::QByteArray:
*static_cast<NS(QByteArray) *>(data) = *static_cast<const NS(QByteArray)*>(copy);
return true;
@@ -1008,11 +1030,9 @@ bool QmlMetaType::copy(int type, void *data, const void *copy)
case QMetaType::QStringList:
*static_cast<NS(QStringList) *>(data) = *static_cast<const NS(QStringList)*>(copy);
return true;
-#ifndef QT_BOOTSTRAPPED
case QMetaType::QBitArray:
*static_cast<NS(QBitArray) *>(data) = *static_cast<const NS(QBitArray)*>(copy);
return true;
-#endif
case QMetaType::QDate:
*static_cast<NS(QDate) *>(data) = *static_cast<const NS(QDate)*>(copy);
return true;
@@ -1022,15 +1042,12 @@ bool QmlMetaType::copy(int type, void *data, const void *copy)
case QMetaType::QDateTime:
*static_cast<NS(QDateTime) *>(data) = *static_cast<const NS(QDateTime)*>(copy);
return true;
-#ifndef QT_BOOTSTRAPPED
case QMetaType::QUrl:
*static_cast<NS(QUrl) *>(data) = *static_cast<const NS(QUrl)*>(copy);
return true;
-#endif
case QMetaType::QLocale:
*static_cast<NS(QLocale) *>(data) = *static_cast<const NS(QLocale)*>(copy);
return true;
-#ifndef QT_NO_GEOM_VARIANT
case QMetaType::QRect:
*static_cast<NS(QRect) *>(data) = *static_cast<const NS(QRect)*>(copy);
return true;
@@ -1058,7 +1075,6 @@ bool QmlMetaType::copy(int type, void *data, const void *copy)
case QMetaType::QVector3D:
*static_cast<NS(QVector3D) *>(data) = *static_cast<const NS(QVector3D)*>(copy);
return true;
-#endif
#ifndef QT_NO_REGEXP
case QMetaType::QRegExp:
*static_cast<NS(QRegExp) *>(data) = *static_cast<const NS(QRegExp)*>(copy);
@@ -1066,8 +1082,90 @@ bool QmlMetaType::copy(int type, void *data, const void *copy)
#endif
case QMetaType::Void:
return true;
+
+
+#ifdef QT3_SUPPORT
+ case QMetaType::QColorGroup:
+ *static_cast<NS(QColorGroup) *>(data) = *static_cast<const NS(QColorGroup)*>(copy);
+ return true;
+#endif
+
+ case QMetaType::QFont:
+ *static_cast<NS(QFont) *>(data) = *static_cast<const NS(QFont)*>(copy);
+ return true;
+ case QMetaType::QPixmap:
+ *static_cast<NS(QPixmap) *>(data) = *static_cast<const NS(QPixmap)*>(copy);
+ return true;
+ case QMetaType::QBrush:
+ *static_cast<NS(QBrush) *>(data) = *static_cast<const NS(QBrush)*>(copy);
+ return true;
+ case QMetaType::QColor:
+ *static_cast<NS(QColor) *>(data) = *static_cast<const NS(QColor)*>(copy);
+ return true;
+ case QMetaType::QPalette:
+ *static_cast<NS(QPalette) *>(data) = *static_cast<const NS(QPalette)*>(copy);
+ return true;
+ case QMetaType::QIcon:
+ *static_cast<NS(QIcon) *>(data) = *static_cast<const NS(QIcon)*>(copy);
+ return true;
+ case QMetaType::QImage:
+ *static_cast<NS(QImage) *>(data) = *static_cast<const NS(QImage)*>(copy);
+ return true;
+ case QMetaType::QPolygon:
+ *static_cast<NS(QPolygon) *>(data) = *static_cast<const NS(QPolygon)*>(copy);
+ return true;
+ case QMetaType::QRegion:
+ *static_cast<NS(QRegion) *>(data) = *static_cast<const NS(QRegion)*>(copy);
+ return true;
+ case QMetaType::QBitmap:
+ *static_cast<NS(QBitmap) *>(data) = *static_cast<const NS(QBitmap)*>(copy);
+ return true;
+ case QMetaType::QCursor:
+ *static_cast<NS(QCursor) *>(data) = *static_cast<const NS(QCursor)*>(copy);
+ return true;
+ case QMetaType::QSizePolicy:
+ *static_cast<NS(QSizePolicy) *>(data) = *static_cast<const NS(QSizePolicy)*>(copy);
+ return true;
+ case QMetaType::QKeySequence:
+ *static_cast<NS(QKeySequence) *>(data) = *static_cast<const NS(QKeySequence)*>(copy);
+ return true;
+ case QMetaType::QPen:
+ *static_cast<NS(QPen) *>(data) = *static_cast<const NS(QPen)*>(copy);
+ return true;
+ case QMetaType::QTextLength:
+ *static_cast<NS(QTextLength) *>(data) = *static_cast<const NS(QTextLength)*>(copy);
+ return true;
+ case QMetaType::QTextFormat:
+ *static_cast<NS(QTextFormat) *>(data) = *static_cast<const NS(QTextFormat)*>(copy);
+ return true;
+ case QMetaType::QMatrix:
+ *static_cast<NS(QMatrix) *>(data) = *static_cast<const NS(QMatrix)*>(copy);
+ return true;
+ case QMetaType::QTransform:
+ *static_cast<NS(QTransform) *>(data) = *static_cast<const NS(QTransform)*>(copy);
+ return true;
+ case QMetaType::QMatrix4x4:
+ *static_cast<NS(QMatrix4x4) *>(data) = *static_cast<const NS(QMatrix4x4)*>(copy);
+ return true;
+ case QMetaType::QVector2D:
+ *static_cast<NS(QVector2D) *>(data) = *static_cast<const NS(QVector2D)*>(copy);
+ return true;
+ case QMetaType::QVector4D:
+ *static_cast<NS(QVector4D) *>(data) = *static_cast<const NS(QVector4D)*>(copy);
+ return true;
+ case QMetaType::QQuaternion:
+ *static_cast<NS(QQuaternion) *>(data) = *static_cast<const NS(QQuaternion)*>(copy);
+ return true;
+
default:
- ;
+ if (type == qMetaTypeId<QVariant>()) {
+ *static_cast<NS(QVariant) *>(data) = *static_cast<const NS(QVariant)*>(copy);
+ return true;
+ } else if (typeCategory(type) != Unknown) {
+ *static_cast<void **>(data) = *static_cast<void* const *>(copy);
+ return true;
+ }
+ break;
}
} else {
switch(type) {
@@ -1118,7 +1216,6 @@ bool QmlMetaType::copy(int type, void *data, const void *copy)
case QMetaType::QChar:
*static_cast<NS(QChar) *>(data) = NS(QChar)();
return true;
-#ifndef QT_BOOTSTRAPPED
case QMetaType::QVariantMap:
*static_cast<NS(QVariantMap) *>(data) = NS(QVariantMap)();
return true;
@@ -1128,7 +1225,6 @@ bool QmlMetaType::copy(int type, void *data, const void *copy)
case QMetaType::QVariantList:
*static_cast<NS(QVariantList) *>(data) = NS(QVariantList)();
return true;
-#endif
case QMetaType::QByteArray:
*static_cast<NS(QByteArray) *>(data) = NS(QByteArray)();
return true;
@@ -1138,11 +1234,9 @@ bool QmlMetaType::copy(int type, void *data, const void *copy)
case QMetaType::QStringList:
*static_cast<NS(QStringList) *>(data) = NS(QStringList)();
return true;
-#ifndef QT_BOOTSTRAPPED
case QMetaType::QBitArray:
*static_cast<NS(QBitArray) *>(data) = NS(QBitArray)();
return true;
-#endif
case QMetaType::QDate:
*static_cast<NS(QDate) *>(data) = NS(QDate)();
return true;
@@ -1152,15 +1246,12 @@ bool QmlMetaType::copy(int type, void *data, const void *copy)
case QMetaType::QDateTime:
*static_cast<NS(QDateTime) *>(data) = NS(QDateTime)();
return true;
-#ifndef QT_BOOTSTRAPPED
case QMetaType::QUrl:
*static_cast<NS(QUrl) *>(data) = NS(QUrl)();
return true;
-#endif
case QMetaType::QLocale:
*static_cast<NS(QLocale) *>(data) = NS(QLocale)();
return true;
-#ifndef QT_NO_GEOM_VARIANT
case QMetaType::QRect:
*static_cast<NS(QRect) *>(data) = NS(QRect)();
return true;
@@ -1188,7 +1279,6 @@ bool QmlMetaType::copy(int type, void *data, const void *copy)
case QMetaType::QVector3D:
*static_cast<NS(QVector3D) *>(data) = NS(QVector3D)();
return true;
-#endif
#ifndef QT_NO_REGEXP
case QMetaType::QRegExp:
*static_cast<NS(QRegExp) *>(data) = NS(QRegExp)();
@@ -1196,8 +1286,88 @@ bool QmlMetaType::copy(int type, void *data, const void *copy)
#endif
case QMetaType::Void:
return true;
+
+#ifdef QT3_SUPPORT
+ case QMetaType::QColorGroup:
+ *static_cast<NS(QColorGroup) *>(data) = NS(QColorGroup)();
+ return true;
+#endif
+
+ case QMetaType::QFont:
+ *static_cast<NS(QFont) *>(data) = NS(QFont)();
+ return true;
+ case QMetaType::QPixmap:
+ *static_cast<NS(QPixmap) *>(data) = NS(QPixmap)();
+ return true;
+ case QMetaType::QBrush:
+ *static_cast<NS(QBrush) *>(data) = NS(QBrush)();
+ return true;
+ case QMetaType::QColor:
+ *static_cast<NS(QColor) *>(data) = NS(QColor)();
+ return true;
+ case QMetaType::QPalette:
+ *static_cast<NS(QPalette) *>(data) = NS(QPalette)();
+ return true;
+ case QMetaType::QIcon:
+ *static_cast<NS(QIcon) *>(data) = NS(QIcon)();
+ return true;
+ case QMetaType::QImage:
+ *static_cast<NS(QImage) *>(data) = NS(QImage)();
+ return true;
+ case QMetaType::QPolygon:
+ *static_cast<NS(QPolygon) *>(data) = NS(QPolygon)();
+ return true;
+ case QMetaType::QRegion:
+ *static_cast<NS(QRegion) *>(data) = NS(QRegion)();
+ return true;
+ case QMetaType::QBitmap:
+ *static_cast<NS(QBitmap) *>(data) = NS(QBitmap)();
+ return true;
+ case QMetaType::QCursor:
+ *static_cast<NS(QCursor) *>(data) = NS(QCursor)();
+ return true;
+ case QMetaType::QSizePolicy:
+ *static_cast<NS(QSizePolicy) *>(data) = NS(QSizePolicy)();
+ return true;
+ case QMetaType::QKeySequence:
+ *static_cast<NS(QKeySequence) *>(data) = NS(QKeySequence)();
+ return true;
+ case QMetaType::QPen:
+ *static_cast<NS(QPen) *>(data) = NS(QPen)();
+ return true;
+ case QMetaType::QTextLength:
+ *static_cast<NS(QTextLength) *>(data) = NS(QTextLength)();
+ return true;
+ case QMetaType::QTextFormat:
+ *static_cast<NS(QTextFormat) *>(data) = NS(QTextFormat)();
+ return true;
+ case QMetaType::QMatrix:
+ *static_cast<NS(QMatrix) *>(data) = NS(QMatrix)();
+ return true;
+ case QMetaType::QTransform:
+ *static_cast<NS(QTransform) *>(data) = NS(QTransform)();
+ return true;
+ case QMetaType::QMatrix4x4:
+ *static_cast<NS(QMatrix4x4) *>(data) = NS(QMatrix4x4)();
+ return true;
+ case QMetaType::QVector2D:
+ *static_cast<NS(QVector2D) *>(data) = NS(QVector2D)();
+ return true;
+ case QMetaType::QVector4D:
+ *static_cast<NS(QVector4D) *>(data) = NS(QVector4D)();
+ return true;
+ case QMetaType::QQuaternion:
+ *static_cast<NS(QQuaternion) *>(data) = NS(QQuaternion)();
+ return true;
default:
- ;
+ if (type == qMetaTypeId<QVariant>()) {
+ *static_cast<NS(QVariant) *>(data) = NS(QVariant)();
+ return true;
+ } else if (typeCategory(type) != Unknown) {
+ *static_cast<void **>(data) = 0;
+ return true;
+ }
+ break;
}
}
diff --git a/src/declarative/qml/qmlobjectscriptclass.cpp b/src/declarative/qml/qmlobjectscriptclass.cpp
new file mode 100644
index 0000000..41573a2
--- /dev/null
+++ b/src/declarative/qml/qmlobjectscriptclass.cpp
@@ -0,0 +1,303 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlobjectscriptclass_p.h"
+#include <private/qmlengine_p.h>
+#include <private/qguard_p.h>
+#include <private/qmlcontext_p.h>
+#include <private/qmldeclarativedata_p.h>
+#include <private/qmltypenamescriptclass_p.h>
+#include <QtDeclarative/qmlbinding.h>
+#include <QtCore/qtimer.h>
+
+QT_BEGIN_NAMESPACE
+
+struct ObjectData : public QScriptDeclarativeClass::Object {
+ ObjectData(QObject *o) : object(o) {}
+ QGuard<QObject> object;
+};
+
+/*
+ The QmlObjectScriptClass handles property access for QObjects
+ via QtScript. It is also used to provide a more useful API in
+ QtScript for QML.
+ */
+QmlObjectScriptClass::QmlObjectScriptClass(QmlEngine *bindEngine)
+: QScriptDeclarativeClass(QmlEnginePrivate::getScriptEngine(bindEngine)), lastData(0),
+ engine(bindEngine)
+{
+ engine = bindEngine;
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(bindEngine);
+
+ m_destroy = scriptEngine->newFunction(destroy);
+ m_destroyId = createPersistentIdentifier(QLatin1String("destroy"));
+ m_toString = scriptEngine->newFunction(tostring);
+ m_toStringId = createPersistentIdentifier(QLatin1String("toString"));
+}
+
+QmlObjectScriptClass::~QmlObjectScriptClass()
+{
+}
+
+QScriptValue QmlObjectScriptClass::newQObject(QObject *object)
+{
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+
+ if (!object)
+ return newObject(scriptEngine, this, new ObjectData(object));
+
+ QmlDeclarativeData *ddata = QmlDeclarativeData::get(object, true);
+
+ if (!ddata->scriptValue.isValid()) {
+ ddata->scriptValue = newObject(scriptEngine, this, new ObjectData(object));
+ return ddata->scriptValue;
+ } else if (ddata->scriptValue.engine() == QmlEnginePrivate::getScriptEngine(engine)) {
+ return ddata->scriptValue;
+ } else {
+ return newObject(scriptEngine, this, new ObjectData(object));
+ }
+}
+
+QObject *QmlObjectScriptClass::toQObject(const QScriptValue &value) const
+{
+ return value.toQObject();
+}
+
+QScriptClass::QueryFlags
+QmlObjectScriptClass::queryProperty(Object *object, const Identifier &name,
+ QScriptClass::QueryFlags flags)
+{
+ return queryProperty(toQObject(object), name, flags, 0);
+}
+
+QScriptClass::QueryFlags
+QmlObjectScriptClass::queryProperty(QObject *obj, const Identifier &name,
+ QScriptClass::QueryFlags flags, QmlContext *evalContext)
+{
+ Q_UNUSED(flags);
+ lastData = 0;
+ lastTNData = 0;
+
+ if (name == m_destroyId.identifier ||
+ name == m_toStringId.identifier)
+ return QScriptClass::HandlesReadAccess;
+
+ if (!obj)
+ return 0;
+
+ QmlEnginePrivate *enginePrivate = QmlEnginePrivate::get(engine);
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+
+ QmlPropertyCache *cache = 0;
+ QmlDeclarativeData *ddata = QmlDeclarativeData::get(obj);
+ if (ddata)
+ cache = ddata->propertyCache;
+ if (!cache) {
+ cache = enginePrivate->cache(obj);
+ if (cache && ddata) { cache->addref(); ddata->propertyCache = cache; }
+ }
+
+ if (cache) {
+ lastData = cache->property(name);
+ } else {
+ local = QmlPropertyCache::create(obj->metaObject(), toString(name));
+ if (local.isValid())
+ lastData = &local;
+ }
+
+ if (lastData) {
+ QScriptClass::QueryFlags rv = QScriptClass::HandlesReadAccess;
+ if (lastData->flags & QmlPropertyCache::Data::IsWritable)
+ rv |= QScriptClass::HandlesWriteAccess;
+ return rv;
+ }
+
+ if (!evalContext && context()) {
+ // Global object, QScriptContext activation object, QmlContext object
+ QScriptValue scopeNode = scopeChainValue(context(), -3);
+ Q_ASSERT(scopeNode.isValid());
+ Q_ASSERT(scriptClass(scopeNode) == enginePrivate->contextClass);
+
+ evalContext = enginePrivate->contextClass->contextFromValue(scopeNode);
+ }
+
+ if (evalContext) {
+ QmlContextPrivate *cp = QmlContextPrivate::get(evalContext);
+
+ if (cp->imports) {
+ QmlTypeNameCache::Data *data = cp->imports->data(name);
+ if (data) {
+ lastTNData = data;
+ return QScriptClass::HandlesReadAccess;
+ }
+ }
+ }
+
+ return 0;
+}
+
+QScriptValue QmlObjectScriptClass::property(Object *object, const Identifier &name)
+{
+ return property(toQObject(object), name);
+}
+
+QScriptValue QmlObjectScriptClass::property(QObject *obj, const Identifier &name)
+{
+ if (name == m_destroyId.identifier)
+ return m_destroy;
+ else if (name == m_toStringId.identifier)
+ return m_toString;
+
+ Q_ASSERT(obj);
+
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+ QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine);
+
+ if (lastTNData) {
+
+ if (lastTNData->type)
+ return enginePriv->typeNameClass->newObject(obj, lastTNData->type);
+ else
+ return enginePriv->typeNameClass->newObject(obj, lastTNData->typeNamespace);
+
+ } else if (lastData->flags & QmlPropertyCache::Data::IsFunction) {
+ // ### Optimize
+ QScriptValue sobj = scriptEngine->newQObject(obj);
+ return sobj.property(toString(name));
+ } else {
+ if (!(lastData->flags & QmlPropertyCache::Data::IsConstant)) {
+ enginePriv->capturedProperties <<
+ QmlEnginePrivate::CapturedProperty(obj, lastData->coreIndex, lastData->notifyIndex);
+ }
+
+ if ((uint)lastData->propType < QVariant::UserType) {
+ QmlValueType *valueType = enginePriv->valueTypes[lastData->propType];
+ if (valueType)
+ return enginePriv->valueTypeClass->newObject(obj, lastData->coreIndex, valueType);
+ }
+
+ if (lastData->flags & QmlPropertyCache::Data::IsQObjectDerived) {
+ QObject *rv = 0;
+ void *args[] = { &rv, 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
+ return newQObject(rv);
+ } else {
+ QVariant var = obj->metaObject()->property(lastData->coreIndex).read(obj);
+ return enginePriv->scriptValueFromVariant(var);
+ }
+
+ }
+}
+
+void QmlObjectScriptClass::setProperty(Object *object,
+ const Identifier &name,
+ const QScriptValue &value)
+{
+ return setProperty(toQObject(object), name, value);
+}
+
+void QmlObjectScriptClass::setProperty(QObject *obj,
+ const Identifier &name,
+ const QScriptValue &value)
+{
+ Q_UNUSED(name);
+
+ Q_ASSERT(obj);
+ Q_ASSERT(lastData);
+
+ QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine);
+
+ // ### Can well known types be optimized?
+ QVariant v = QmlScriptClass::toVariant(engine, value);
+ delete QmlMetaPropertyPrivate::setBinding(obj, *lastData, 0);
+ QmlMetaPropertyPrivate::write(obj, *lastData, v, enginePriv->currentExpression->context());
+}
+
+QObject *QmlObjectScriptClass::toQObject(Object *object, bool *ok)
+{
+ if (ok) *ok = true;
+
+ ObjectData *data = (ObjectData*)object;
+ return data->object.data();
+}
+
+QScriptValue QmlObjectScriptClass::tostring(QScriptContext *context, QScriptEngine *)
+{
+ QObject* obj = context->thisObject().toQObject();
+
+ QString ret;
+ if(obj){
+ QString objectName = obj->objectName();
+
+ ret += QLatin1String(obj->metaObject()->className());
+ ret += QLatin1String("(0x");
+ ret += QString::number((quintptr)obj,16);
+
+ if (!objectName.isEmpty()) {
+ ret += QLatin1String(", \"");
+ ret += objectName;
+ ret += QLatin1String("\"");
+ }
+
+ ret += QLatin1String(")");
+ }else{
+ ret += QLatin1String("null");
+ }
+ return QScriptValue(ret);
+}
+
+QScriptValue QmlObjectScriptClass::destroy(QScriptContext *context, QScriptEngine *engine)
+{
+ QObject* obj = context->thisObject().toQObject();
+ if(obj){
+ int delay = 0;
+ if(context->argumentCount() > 0)
+ delay = context->argument(0).toInt32();
+ if (delay > 0)
+ QTimer::singleShot(delay, obj, SLOT(deleteLater()));
+ else
+ obj->deleteLater();
+ }
+ return engine->nullValue();
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/declarative/qml/qmlobjectscriptclass_p.h b/src/declarative/qml/qmlobjectscriptclass_p.h
new file mode 100644
index 0000000..3fcf009
--- /dev/null
+++ b/src/declarative/qml/qmlobjectscriptclass_p.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLOBJECTSCRIPTCLASS_P_H
+#define QMLOBJECTSCRIPTCLASS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtScript/qscriptclass.h>
+#include <private/qscriptdeclarativeclass_p.h>
+#include <private/qmlpropertycache_p.h>
+#include <private/qmltypenamecache_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlEngine;
+class QScriptContext;
+class QScriptEngine;
+class QmlContext;
+class QmlObjectScriptClass : public QScriptDeclarativeClass
+{
+public:
+ QmlObjectScriptClass(QmlEngine *);
+ ~QmlObjectScriptClass();
+
+ QScriptValue newQObject(QObject *);
+ QObject *toQObject(const QScriptValue &) const;
+
+ enum QueryMode { IncludeAttachedProperties, SkipAttachedProperties };
+
+ QScriptClass::QueryFlags queryProperty(QObject *, const Identifier &,
+ QScriptClass::QueryFlags flags,
+ QmlContext *evalContext);
+ QScriptValue property(QObject *, const Identifier &);
+ void setProperty(QObject *, const Identifier &name, const QScriptValue &);
+
+protected:
+ virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &,
+ QScriptClass::QueryFlags flags);
+
+ virtual QScriptValue property(Object *, const Identifier &);
+ virtual void setProperty(Object *, const Identifier &name, const QScriptValue &);
+ virtual QObject *toQObject(Object *, bool *ok = 0);
+
+private:
+ QmlTypeNameCache::Data *lastTNData;
+ QmlPropertyCache::Data *lastData;
+ QmlPropertyCache::Data local;
+
+ PersistentIdentifier m_destroyId;
+ PersistentIdentifier m_toStringId;
+ QScriptValue m_destroy;
+ QScriptValue m_toString;
+
+ static QScriptValue tostring(QScriptContext *context, QScriptEngine *engine);
+ static QScriptValue destroy(QScriptContext *context, QScriptEngine *engine);
+
+ QmlEngine *engine;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLOBJECTSCRIPTCLASS_P_H
+
diff --git a/src/declarative/qml/qmlparser.cpp b/src/declarative/qml/qmlparser.cpp
index 39fe1e2..8c46939 100644
--- a/src/declarative/qml/qmlparser.cpp
+++ b/src/declarative/qml/qmlparser.cpp
@@ -82,6 +82,8 @@ QmlParser::Object::~Object()
prop->release();
foreach(const DynamicProperty &prop, dynamicProperties)
if (prop.defaultValue) prop.defaultValue->release();
+ foreach(Object *obj, scriptBlockObjects)
+ obj->release();
}
void Object::setBindingBit(int b)
diff --git a/src/declarative/qml/qmlparser_p.h b/src/declarative/qml/qmlparser_p.h
index e0579b0..16862eb 100644
--- a/src/declarative/qml/qmlparser_p.h
+++ b/src/declarative/qml/qmlparser_p.h
@@ -151,6 +151,8 @@ namespace QmlParser
Property *defaultProperty;
QHash<QByteArray, Property *> properties;
+ QList<Object *> scriptBlockObjects;
+
// Output of the compilation phase (these properties continue to exist
// in either the defaultProperty or properties members too)
void addValueProperty(Property *);
@@ -164,6 +166,9 @@ namespace QmlParser
QList<Property *> groupedProperties;
QList<Property *> valueTypeProperties;
+ // Script blocks that were nested under this object
+ QStringList scriptBlocks;
+
// The bytes to cast instances by to get to the QmlParserStatus
// interface. -1 indicates the type doesn't support this interface.
// Set by the QmlCompiler.
diff --git a/src/declarative/qml/qmlpropertycache.cpp b/src/declarative/qml/qmlpropertycache.cpp
new file mode 100644
index 0000000..63ce00c
--- /dev/null
+++ b/src/declarative/qml/qmlpropertycache.cpp
@@ -0,0 +1,213 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlpropertycache_p.h"
+#include <private/qmlengine_p.h>
+#include <QtDeclarative/qmlbinding.h>
+
+QT_BEGIN_NAMESPACE
+
+void QmlPropertyCache::Data::load(const QMetaProperty &p)
+{
+ propType = p.userType();
+ if (propType == QVariant::LastType)
+ propType = qMetaTypeId<QVariant>();
+ coreIndex = p.propertyIndex();
+ notifyIndex = p.notifySignalIndex();
+ name = QLatin1String(p.name());
+
+ if (p.isConstant())
+ flags |= Data::IsConstant;
+ if (p.isWritable())
+ flags |= Data::IsWritable;
+
+ if (propType == qMetaTypeId<QmlBinding *>()) {
+ flags |= Data::IsQmlBinding;
+ } else if (p.isEnumType()) {
+ flags |= Data::IsEnumType;
+ } else {
+ QmlMetaType::TypeCategory cat = QmlMetaType::typeCategory(propType);
+ if (cat == QmlMetaType::Object)
+ flags |= Data::IsQObjectDerived;
+ else if (cat == QmlMetaType::List)
+ flags |= Data::IsQList;
+ else if (cat == QmlMetaType::QmlList)
+ flags |= Data::IsQmlList;
+ }
+}
+
+void QmlPropertyCache::Data::load(const QMetaMethod &m)
+{
+ name = QLatin1String(m.signature());
+ int parenIdx = name.indexOf(QLatin1Char('('));
+ Q_ASSERT(parenIdx != -1);
+ name = name.left(parenIdx);
+
+ coreIndex = m.methodIndex();
+ flags |= Data::IsFunction;
+}
+
+
+QmlPropertyCache::QmlPropertyCache()
+{
+}
+
+QmlPropertyCache::~QmlPropertyCache()
+{
+ for (int ii = 0; ii < indexCache.count(); ++ii)
+ indexCache.at(ii)->release();
+
+ for (StringCache::ConstIterator iter = stringCache.begin();
+ iter != stringCache.end(); ++iter)
+ (*iter)->release();
+
+ for (IdentifierCache::ConstIterator iter = identifierCache.begin();
+ iter != identifierCache.end(); ++iter)
+ (*iter)->release();
+}
+
+QmlPropertyCache::Data QmlPropertyCache::create(const QMetaObject *metaObject,
+ const QString &property)
+{
+ Q_ASSERT(metaObject);
+
+ QmlPropertyCache::Data rv;
+
+ int idx = metaObject->indexOfProperty(property.toUtf8());
+ if (idx != -1) {
+ rv.load(metaObject->property(idx));
+ return rv;
+ }
+
+ int methodCount = metaObject->methodCount();
+ for (int ii = methodCount - 1; ii >= 0; --ii) {
+ QMetaMethod m = metaObject->method(ii);
+ QString methodName = QLatin1String(m.signature());
+
+ int parenIdx = methodName.indexOf(QLatin1Char('('));
+ Q_ASSERT(parenIdx != -1);
+ methodName = methodName.left(parenIdx);
+
+ if (methodName == property) {
+ rv.load(m);
+ return rv;
+ }
+ }
+
+ return rv;
+}
+
+// ### Optimize - check engine for the parent meta object etc.
+QmlPropertyCache *QmlPropertyCache::create(QmlEngine *engine, const QMetaObject *metaObject)
+{
+ Q_ASSERT(engine);
+ Q_ASSERT(metaObject);
+
+ QmlPropertyCache *cache = new QmlPropertyCache;
+
+ QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine);
+
+ // ### The properties/methods should probably be spliced on a per-metaobject basis
+ int propCount = metaObject->propertyCount();
+
+ cache->indexCache.resize(propCount);
+ for (int ii = propCount - 1; ii >= 0; --ii) {
+ QMetaProperty p = metaObject->property(ii);
+ QString propName = QLatin1String(p.name());
+
+ RData *data = new RData;
+ data->identifier = enginePriv->objectClass->createPersistentIdentifier(propName);
+
+ data->load(p);
+
+ cache->indexCache[ii] = data;
+
+ if (cache->stringCache.contains(propName))
+ continue;
+
+ cache->stringCache.insert(propName, data);
+ cache->identifierCache.insert(data->identifier.identifier, data);
+ data->addref();
+ data->addref();
+ }
+
+ int methodCount = metaObject->methodCount();
+ for (int ii = methodCount - 1; ii >= 0; --ii) {
+ QMetaMethod m = metaObject->method(ii);
+ QString methodName = QLatin1String(m.signature());
+
+ int parenIdx = methodName.indexOf(QLatin1Char('('));
+ Q_ASSERT(parenIdx != -1);
+ methodName = methodName.left(parenIdx);
+
+ if (cache->stringCache.contains(methodName))
+ continue;
+
+ RData *data = new RData;
+ data->identifier = enginePriv->objectClass->createPersistentIdentifier(methodName);
+
+ data->load(m);
+
+ cache->stringCache.insert(methodName, data);
+ cache->identifierCache.insert(data->identifier.identifier, data);
+ data->addref();
+ data->addref();
+ }
+
+ return cache;
+}
+
+QmlPropertyCache::Data *
+QmlPropertyCache::property(int index) const
+{
+ if (index < 0 || index >= indexCache.count())
+ return 0;
+
+ return indexCache.at(index);
+}
+
+QmlPropertyCache::Data *
+QmlPropertyCache::property(const QString &str) const
+{
+ return stringCache.value(str);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlpropertycache_p.h b/src/declarative/qml/qmlpropertycache_p.h
new file mode 100644
index 0000000..f1b1219
--- /dev/null
+++ b/src/declarative/qml/qmlpropertycache_p.h
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLPROPERTYCACHE_P_H
+#define QMLPROPERTYCACHE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qmlrefcount_p.h>
+#include <private/qscriptdeclarativeclass_p.h>
+#include <QtCore/qvector.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlEngine;
+class QMetaProperty;
+class QmlPropertyCache : public QmlRefCount
+{
+public:
+ QmlPropertyCache();
+ virtual ~QmlPropertyCache();
+
+ struct Data {
+ inline Data();
+ inline bool operator==(const Data &);
+
+ enum Flag {
+ // Can apply to all properties, except IsFunction
+ IsConstant = 0x00000001,
+ IsWritable = 0x00000002,
+
+ // These are mutually exclusive
+ IsFunction = 0x00000004,
+ IsQObjectDerived = 0x00000008,
+ IsEnumType = 0x00000010,
+ IsQmlList = 0x00000020,
+ IsQList = 0x00000040,
+ IsQmlBinding = 0x00000080
+ };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ bool isValid() const { return coreIndex != -1; }
+
+ Flags flags;
+ int propType;
+ int coreIndex;
+ int notifyIndex;
+ QString name;
+
+ void load(const QMetaProperty &);
+ void load(const QMetaMethod &);
+ };
+
+#if 0
+ struct ValueTypeData {
+ int valueTypeCoreIdx; // The prop index of the access property on the value type wrapper
+ int valueTypePropType; // The QVariant::Type of access property on the value type wrapper
+ };
+#endif
+
+ static QmlPropertyCache *create(QmlEngine *, const QMetaObject *);
+ static Data create(const QMetaObject *, const QString &);
+
+ inline Data *property(const QScriptDeclarativeClass::Identifier &id) const;
+ Data *property(const QString &) const;
+ Data *property(int) const;
+
+private:
+ struct RData : public Data, public QmlRefCount {
+ QScriptDeclarativeClass::PersistentIdentifier identifier;
+ };
+
+ typedef QVector<RData *> IndexCache;
+ typedef QHash<QString, RData *> StringCache;
+ typedef QHash<QScriptDeclarativeClass::Identifier, RData *> IdentifierCache;
+
+ IndexCache indexCache;
+ StringCache stringCache;
+ IdentifierCache identifierCache;
+};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QmlPropertyCache::Data::Flags);
+
+QmlPropertyCache::Data::Data()
+: flags(0), propType(0), coreIndex(-1), notifyIndex(-1)
+{
+}
+
+bool QmlPropertyCache::Data::operator==(const QmlPropertyCache::Data::Data &other)
+{
+ return flags == other.flags &&
+ propType == other.propType &&
+ coreIndex == other.coreIndex &&
+ notifyIndex == other.notifyIndex &&
+ name == other.name;
+}
+
+QmlPropertyCache::Data *
+QmlPropertyCache::property(const QScriptDeclarativeClass::Identifier &id) const
+{
+ return identifierCache.value(id);
+}
+
+QT_END_NAMESPACE
+
+#endif // QMLPROPERTYCACHE_P_H
diff --git a/src/declarative/qml/qmlscript.cpp b/src/declarative/qml/qmlscript.cpp
new file mode 100644
index 0000000..307d72f
--- /dev/null
+++ b/src/declarative/qml/qmlscript.cpp
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// This is just a dummy file to include the documentation
+
+/*!
+ \qmlclass Script QmlScript
+ \brief The Script element adds JavaScript snippets.
+ \ingroup group_utility
+
+ QmlScript is used to add convenient JavaScript "glue" methods to
+ your Qt Declarative application or component. While you can have any JavaScript code
+ within a QmlScript, it is best to limit yourself to defining functions.
+
+ \qml
+ Script {
+ function debugMyComponent() {
+ print(text.text);
+ print(otherinterestingitem.property);
+ }
+ }
+ MouseRegion { onClicked: debugMyComponent() }
+ \endqml
+
+ \note QmlScript executes JavaScript as soon as it is specified.
+ When defining a component, this may be before the execution context is
+ fully specified. As a result some properties or items may not be
+ accessible. By limiting your JavaScript to defining functions that are
+ only executed later once the context is fully defined, this problem is
+ avoided.
+*/
+
+/*!
+ \qmlproperty string Script::script
+ \default
+ JavaScript code to execute.
+*/
+
+/*!
+ \qmlproperty url Script::source
+
+ Setting this property causes the Script element to read JavaScript code from
+ the file specified.
+*/
diff --git a/src/declarative/qml/qmlscriptparser.cpp b/src/declarative/qml/qmlscriptparser.cpp
index c126830..1c7bf83 100644
--- a/src/declarative/qml/qmlscriptparser.cpp
+++ b/src/declarative/qml/qmlscriptparser.cpp
@@ -289,12 +289,26 @@ ProcessAST::defineObjectBinding_helper(AST::UiQualifiedId *propertyName,
if (lastTypeDot >= 0)
resolvableObjectType.replace(QLatin1Char('.'),QLatin1Char('/'));
- QmlScriptParser::TypeReference *typeRef = _parser->findOrCreateType(resolvableObjectType);
+ bool isScript = resolvableObjectType == QLatin1String("Script");
+
+ if (isScript) {
+ if (_stateStack.isEmpty() || _stateStack.top().property) {
+ QmlError error;
+ error.setDescription(QLatin1String("Invalid use of Script block"));
+ error.setLine(typeLocation.startLine);
+ error.setColumn(typeLocation.startColumn);
+ _parser->_errors << error;
+ }
+ }
Object *obj = new Object;
- obj->type = typeRef->id;
- typeRef->refObjects.append(obj);
+ if (!isScript) {
+ QmlScriptParser::TypeReference *typeRef = _parser->findOrCreateType(resolvableObjectType);
+ obj->type = typeRef->id;
+
+ typeRef->refObjects.append(obj);
+ }
// XXX this doesn't do anything (_scope never builds up)
_scope.append(resolvableObjectType);
@@ -303,7 +317,11 @@ ProcessAST::defineObjectBinding_helper(AST::UiQualifiedId *propertyName,
obj->location = location;
- if (propertyCount) {
+ if (isScript) {
+
+ _stateStack.top().object->scriptBlockObjects.append(obj);
+
+ } else if (propertyCount) {
Property *prop = currentProperty();
Value *v = new Value;
@@ -385,6 +403,26 @@ Object *ProcessAST::defineObjectBinding(AST::UiQualifiedId *qualifiedId,
_stateStack.pop(); // object
return obj;
+ } else if (objectType == QLatin1String("Script")) {
+
+ AST::UiObjectMemberList *it = initializer->members;
+ for (; it; it = it->next) {
+ AST::UiScriptBinding *scriptBinding = AST::cast<AST::UiScriptBinding *>(it->member);
+ if (! scriptBinding)
+ continue;
+
+ QString propertyName = asString(scriptBinding->qualifiedId);
+ if (propertyName == QLatin1String("source")) {
+ if (AST::ExpressionStatement *stmt = AST::cast<AST::ExpressionStatement *>(scriptBinding->statement)) {
+ AST::StringLiteral *string = AST::cast<AST::StringLiteral *>(stmt->expression);
+ if (string) {
+ // We need to add this as a resource
+ _parser->_refUrls << QUrl(string->value->asString());
+ }
+ }
+ }
+ }
+
}
return defineObjectBinding_helper(qualifiedId, objectType, typeLocation, location, initializer);
@@ -867,6 +905,11 @@ QList<QmlScriptParser::TypeReference*> QmlScriptParser::referencedTypes() const
return _refTypes;
}
+QList<QUrl> QmlScriptParser::referencedResources() const
+{
+ return _refUrls;
+}
+
Object *QmlScriptParser::tree() const
{
return root;
diff --git a/src/declarative/qml/qmlscriptparser_p.h b/src/declarative/qml/qmlscriptparser_p.h
index d489610..b25d6bf 100644
--- a/src/declarative/qml/qmlscriptparser_p.h
+++ b/src/declarative/qml/qmlscriptparser_p.h
@@ -102,6 +102,7 @@ public:
bool parse(const QByteArray &data, const QUrl &url = QUrl());
QList<TypeReference*> referencedTypes() const;
+ QList<QUrl> referencedResources() const;
QmlParser::Object *tree() const;
QList<Import> imports() const;
@@ -123,6 +124,7 @@ public:
QmlParser::Object *root;
QList<Import> _imports;
QList<TypeReference*> _refTypes;
+ QList<QUrl> _refUrls;
QString _scriptFile;
QmlScriptParserJsASTData *data;
};
diff --git a/src/declarative/qml/qmltypenamecache.cpp b/src/declarative/qml/qmltypenamecache.cpp
new file mode 100644
index 0000000..aa1c938
--- /dev/null
+++ b/src/declarative/qml/qmltypenamecache.cpp
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmltypenamecache_p.h"
+#include <private/qmlengine_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QmlTypeNameCache::QmlTypeNameCache(QmlEngine *e)
+: engine(e)
+{
+}
+
+QmlTypeNameCache::~QmlTypeNameCache()
+{
+ qDeleteAll(stringCache);
+}
+
+void QmlTypeNameCache::add(const QString &name, QmlType *type)
+{
+ if (stringCache.contains(name))
+ return;
+
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
+
+ RData *data = new RData;
+ // ### Use typename class
+ data->identifier = ep->objectClass->createPersistentIdentifier(name);
+ data->type = type;
+ stringCache.insert(name, data);
+ identifierCache.insert(data->identifier.identifier, data);
+}
+
+void QmlTypeNameCache::add(const QString &name, QmlTypeNameCache *typeNamespace)
+{
+ if (stringCache.contains(name))
+ return;
+
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
+
+ RData *data = new RData;
+ // ### Use typename class
+ data->identifier = ep->objectClass->createPersistentIdentifier(name);
+ data->typeNamespace = typeNamespace;
+ stringCache.insert(name, data);
+ identifierCache.insert(data->identifier.identifier, data);
+ typeNamespace->addref();
+}
+
+QmlTypeNameCache::Data *QmlTypeNameCache::data(const QString &id) const
+{
+ return stringCache.value(id);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/declarative/qml/qmltypenamecache_p.h b/src/declarative/qml/qmltypenamecache_p.h
new file mode 100644
index 0000000..f11fe68
--- /dev/null
+++ b/src/declarative/qml/qmltypenamecache_p.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLTYPENAMECACHE_P_H
+#define QMLTYPENAMECACHE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qmlrefcount_p.h>
+#include <private/qscriptdeclarativeclass_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlType;
+class QmlEngine;
+class QmlTypeNameCache : public QmlRefCount
+{
+public:
+ QmlTypeNameCache(QmlEngine *);
+ virtual ~QmlTypeNameCache();
+
+ struct Data {
+ inline Data();
+ inline ~Data();
+ QmlType *type;
+ QmlTypeNameCache *typeNamespace;
+ };
+
+ void add(const QString &, QmlType *);
+ void add(const QString &, QmlTypeNameCache *);
+
+ Data *data(const QString &) const;
+ inline Data *data(const QScriptDeclarativeClass::Identifier &id) const;
+
+private:
+ struct RData : public Data {
+ QScriptDeclarativeClass::PersistentIdentifier identifier;
+ };
+ typedef QHash<QString, RData *> StringCache;
+ typedef QHash<QScriptDeclarativeClass::Identifier, RData *> IdentifierCache;
+
+ StringCache stringCache;
+ IdentifierCache identifierCache;
+ QmlEngine *engine;
+};
+
+QmlTypeNameCache::Data::Data()
+: type(0), typeNamespace(0)
+{
+}
+
+QmlTypeNameCache::Data::~Data()
+{
+ if (typeNamespace) typeNamespace->release();
+}
+
+QmlTypeNameCache::Data *QmlTypeNameCache::data(const QScriptDeclarativeClass::Identifier &id) const
+{
+ return identifierCache.value(id);
+}
+
+QT_END_NAMESPACE
+
+#endif // QMLTYPENAMECACHE_P_H
+
diff --git a/src/declarative/qml/qmltypenamescriptclass.cpp b/src/declarative/qml/qmltypenamescriptclass.cpp
new file mode 100644
index 0000000..c0613d1
--- /dev/null
+++ b/src/declarative/qml/qmltypenamescriptclass.cpp
@@ -0,0 +1,163 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmltypenamescriptclass_p.h"
+#include <private/qmlengine_p.h>
+#include <private/qmltypenamecache_p.h>
+
+QT_BEGIN_NAMESPACE
+
+struct TypeNameData : public QScriptDeclarativeClass::Object {
+ TypeNameData(QObject *o, QmlType *t, QmlTypeNameScriptClass::TypeNameMode m) : object(o), type(t), typeNamespace(0), mode(m) {}
+ TypeNameData(QObject *o, QmlTypeNameCache *n, QmlTypeNameScriptClass::TypeNameMode m) : object(o), type(0), typeNamespace(n), mode(m) {
+ if (typeNamespace) typeNamespace->addref();
+ }
+ ~TypeNameData() {
+ if (typeNamespace) typeNamespace->release();
+ }
+
+ QObject *object;
+ QmlType *type;
+ QmlTypeNameCache *typeNamespace;
+ QmlTypeNameScriptClass::TypeNameMode mode;
+};
+
+QmlTypeNameScriptClass::QmlTypeNameScriptClass(QmlEngine *bindEngine)
+: QScriptDeclarativeClass(QmlEnginePrivate::getScriptEngine(bindEngine)),
+ engine(bindEngine), object(0), type(0)
+{
+}
+
+QmlTypeNameScriptClass::~QmlTypeNameScriptClass()
+{
+}
+
+QScriptValue QmlTypeNameScriptClass::newObject(QObject *object, QmlType *type, TypeNameMode mode)
+{
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+
+ return QScriptDeclarativeClass::newObject(scriptEngine, this, new TypeNameData(object, type, mode));
+}
+
+QScriptValue QmlTypeNameScriptClass::newObject(QObject *object, QmlTypeNameCache *ns, TypeNameMode mode)
+{
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+
+ return QScriptDeclarativeClass::newObject(scriptEngine, this, new TypeNameData(object, ns, mode));
+}
+
+QScriptClass::QueryFlags
+QmlTypeNameScriptClass::queryProperty(Object *obj, const Identifier &name,
+ QScriptClass::QueryFlags flags)
+{
+ Q_UNUSED(flags);
+
+ TypeNameData *data = (TypeNameData *)obj;
+
+ object = 0;
+ type = 0;
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
+
+ if (data->typeNamespace) {
+
+ QmlTypeNameCache::Data *d = data->typeNamespace->data(name);
+ if (d && d->type) {
+ type = d->type;
+ return QScriptClass::HandlesReadAccess;
+ } else {
+ return 0;
+ }
+
+ } else {
+ Q_ASSERT(data->type);
+
+ QString strName = toString(name);
+
+ if (strName.at(0).isUpper()) {
+ // Must be an enum
+ if (data->mode == IncludeEnums) {
+ // ### Optimize
+ const char *enumName = strName.toUtf8().constData();
+ const QMetaObject *metaObject = data->type->baseMetaObject();
+ for (int ii = metaObject->enumeratorCount() - 1; ii >= 0; --ii) {
+ QMetaEnum e = metaObject->enumerator(ii);
+ int value = e.keyToValue(enumName);
+ if (value != -1) {
+ enumValue = value;
+ return QScriptClass::HandlesReadAccess;
+ }
+ }
+ }
+ return 0;
+ } else if (data->object) {
+ // Must be an attached property
+ object = qmlAttachedPropertiesObjectById(data->type->index(), data->object);
+ if (!object) return 0;
+ return ep->objectClass->queryProperty(object, name, flags, 0);
+ }
+ }
+
+ return 0;
+}
+
+QScriptValue QmlTypeNameScriptClass::property(Object *obj, const Identifier &name)
+{
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
+ if (type) {
+ return newObject(((TypeNameData *)obj)->object, type, ((TypeNameData *)obj)->mode);
+ } else if (object) {
+ return ep->objectClass->property(object, name);
+ } else {
+ return QScriptValue(enumValue);
+ }
+}
+
+void QmlTypeNameScriptClass::setProperty(Object *o, const Identifier &n, const QScriptValue &v)
+{
+ Q_ASSERT(object);
+ Q_ASSERT(!type);
+
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
+ ep->objectClass->setProperty(((TypeNameData *)o)->object, n, v);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/declarative/qml/qmltypenamescriptclass_p.h b/src/declarative/qml/qmltypenamescriptclass_p.h
new file mode 100644
index 0000000..d8112d2
--- /dev/null
+++ b/src/declarative/qml/qmltypenamescriptclass_p.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLTYPENAMESCRIPTCLASS_P_H
+#define QMLTYPENAMESCRIPTCLASS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+#include <QtScript/qscriptclass.h>
+#include <private/qscriptdeclarativeclass_p.h>
+#include <private/qmlengine_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlEngine;
+class QmlType;
+class QmlTypeNameCache;
+class QmlTypeNameScriptClass : public QScriptDeclarativeClass
+{
+public:
+ QmlTypeNameScriptClass(QmlEngine *);
+ ~QmlTypeNameScriptClass();
+
+ enum TypeNameMode { IncludeEnums, ExcludeEnums };
+ QScriptValue newObject(QObject *, QmlType *, TypeNameMode = IncludeEnums);
+ QScriptValue newObject(QObject *, QmlTypeNameCache *, TypeNameMode = IncludeEnums);
+
+protected:
+ virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &,
+ QScriptClass::QueryFlags flags);
+
+ virtual QScriptValue property(Object *, const Identifier &);
+ virtual void setProperty(Object *, const Identifier &name, const QScriptValue &);
+
+private:
+ QmlEngine *engine;
+ QObject *object;
+ QmlType *type;
+ quint32 enumValue;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLTYPENAMESCRIPTCLASS_P_H
+
diff --git a/src/declarative/qml/qmlvaluetypescriptclass.cpp b/src/declarative/qml/qmlvaluetypescriptclass.cpp
new file mode 100644
index 0000000..6fd674a
--- /dev/null
+++ b/src/declarative/qml/qmlvaluetypescriptclass.cpp
@@ -0,0 +1,151 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlvaluetypescriptclass_p.h"
+#include <private/qmlengine_p.h>
+
+QT_BEGIN_NAMESPACE
+
+struct QmlValueTypeReference {
+ QmlValueType *type;
+ QGuard<QObject> object;
+ int property;
+};
+Q_DECLARE_METATYPE(QmlValueTypeReference);
+
+QmlValueTypeScriptClass::QmlValueTypeScriptClass(QmlEngine *bindEngine)
+: QScriptClass(QmlEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine)
+{
+}
+
+QmlValueTypeScriptClass::~QmlValueTypeScriptClass()
+{
+}
+
+QScriptValue QmlValueTypeScriptClass::newObject(QObject *object, int coreIndex, QmlValueType *type)
+{
+ QmlValueTypeReference ref = { type, object, coreIndex };
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+ return scriptEngine->newObject(this, scriptEngine->newVariant(qVariantFromValue(ref)));
+}
+
+QmlValueTypeScriptClass::QueryFlags
+QmlValueTypeScriptClass::queryProperty(const QScriptValue &object,
+ const QScriptString &name,
+ QueryFlags flags, uint *id)
+{
+ Q_UNUSED(flags);
+ QmlValueTypeReference ref =
+ qvariant_cast<QmlValueTypeReference>(object.data().toVariant());
+
+ if (!ref.object)
+ return 0;
+
+ QByteArray propName = name.toString().toUtf8();
+
+ int idx = ref.type->metaObject()->indexOfProperty(propName.constData());
+ if (idx == -1)
+ return 0;
+ *id = idx;
+
+ QMetaProperty prop = ref.object->metaObject()->property(idx);
+
+ QmlValueTypeScriptClass::QueryFlags rv =
+ QmlValueTypeScriptClass::HandlesReadAccess;
+ if (prop.isWritable())
+ rv |= QmlValueTypeScriptClass::HandlesWriteAccess;
+
+ return rv;
+}
+
+QScriptValue QmlValueTypeScriptClass::property(const QScriptValue &object,
+ const QScriptString &name,
+ uint id)
+{
+ Q_UNUSED(name);
+ QmlValueTypeReference ref =
+ qvariant_cast<QmlValueTypeReference>(object.data().toVariant());
+
+ if (!ref.object)
+ return QScriptValue();
+
+ ref.type->read(ref.object, ref.property);
+
+ QMetaProperty p = ref.type->metaObject()->property(id);
+ QVariant rv = p.read(ref.type);
+
+ return static_cast<QmlEnginePrivate *>(QObjectPrivate::get(engine))->scriptValueFromVariant(rv);
+}
+
+void QmlValueTypeScriptClass::setProperty(QScriptValue &object,
+ const QScriptString &name,
+ uint id,
+ const QScriptValue &value)
+{
+ Q_UNUSED(name);
+ QmlValueTypeReference ref =
+ qvariant_cast<QmlValueTypeReference>(object.data().toVariant());
+
+ if (!ref.object)
+ return;
+
+ QVariant v = QmlScriptClass::toVariant(engine, value);
+
+ ref.type->read(ref.object, ref.property);
+ QMetaProperty p = ref.type->metaObject()->property(id);
+ p.write(ref.type, v);
+ ref.type->write(ref.object, ref.property);
+}
+
+QVariant QmlValueTypeScriptClass::toVariant(const QScriptValue &val)
+{
+ QmlValueTypeReference ref =
+ qvariant_cast<QmlValueTypeReference>(val.data().toVariant());
+
+ if (!ref.object)
+ return QVariant();
+
+ QMetaProperty p = ref.object->metaObject()->property(ref.property);
+ return p.read(ref.object);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/declarative/qml/qmlvaluetypescriptclass_p.h b/src/declarative/qml/qmlvaluetypescriptclass_p.h
new file mode 100644
index 0000000..d656a22
--- /dev/null
+++ b/src/declarative/qml/qmlvaluetypescriptclass_p.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMLVALUETYPESCRIPTCLASS_P_H
+#define QMLVALUETYPESCRIPTCLASS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+#include <QtScript/qscriptclass.h>
+#include <private/qscriptdeclarativeclass_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlEngine;
+class QmlValueType;
+class QmlValueTypeScriptClass : public QScriptClass
+{
+public:
+ QmlValueTypeScriptClass(QmlEngine *);
+ ~QmlValueTypeScriptClass();
+
+ QScriptValue newObject(QObject *object, int coreIndex, QmlValueType *);
+
+ virtual QueryFlags queryProperty(const QScriptValue &object,
+ const QScriptString &name,
+ QueryFlags flags, uint *id);
+ virtual QScriptValue property(const QScriptValue &object,
+ const QScriptString &name,
+ uint id);
+ virtual void setProperty(QScriptValue &object,
+ const QScriptString &name,
+ uint id,
+ const QScriptValue &value);
+
+ QVariant toVariant(const QScriptValue &);
+private:
+ QmlEngine *engine;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLVALUETYPESCRIPTCLASS_P_H
+
diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp
index 44b17e6..e4eef64 100644
--- a/src/declarative/qml/qmlvme.cpp
+++ b/src/declarative/qml/qmlvme.cpp
@@ -143,6 +143,7 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt,
const QList<QmlCompiledData::CustomTypeData> &customTypeData = comp->customTypeData;
const QList<int> &intData = comp->intData;
const QList<float> &floatData = comp->floatData;
+ const QList<QmlPropertyCache *> &propertyCaches = comp->propertyCaches;
QmlEnginePrivate::SimpleList<QmlAbstractBinding> bindValues;
@@ -165,8 +166,8 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt,
if (instr.init.parserStatusSize)
parserStatus = QmlEnginePrivate::SimpleList<QmlParserStatus>(instr.init.parserStatusSize);
- if (instr.init.idSize)
- cp->setIdPropertyCount(instr.init.idSize);
+ if (instr.init.contextCache != -1)
+ cp->setIdPropertyData(comp->contextCaches.at(instr.init.contextCache));
}
break;
@@ -259,9 +260,15 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt,
const QByteArray &metadata = datas.at(instr.storeMeta.data);
QMetaObjectBuilder::fromRelocatableData(&mo, 0, metadata);
- const QmlVMEMetaData *data = (const QmlVMEMetaData *)datas.at(instr.storeMeta.aliasData).constData();
+ const QmlVMEMetaData *data =
+ (const QmlVMEMetaData *)datas.at(instr.storeMeta.aliasData).constData();
(void)new QmlVMEMetaObject(target, &mo, data, comp);
+
+ QmlDeclarativeData *ddata = QmlDeclarativeData::get(target, true);
+ if (ddata->propertyCache) ddata->propertyCache->release();
+ ddata->propertyCache = propertyCaches.at(instr.storeMeta.propertyCache);
+ ddata->propertyCache->addref();
}
break;
@@ -557,6 +564,13 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt,
}
break;
+ case QmlInstruction::StoreScript:
+ {
+ QObject *target = stack.top();
+ cp->addScript(primitives.at(instr.storeScript.value), target);
+ }
+ break;
+
case QmlInstruction::BeginObject:
{
QObject *target = stack.top();
diff --git a/src/declarative/qml/qmlxmlhttprequest.cpp b/src/declarative/qml/qmlxmlhttprequest.cpp
index 65c5b16..0bc927c 100644
--- a/src/declarative/qml/qmlxmlhttprequest.cpp
+++ b/src/declarative/qml/qmlxmlhttprequest.cpp
@@ -1190,7 +1190,7 @@ static QScriptValue qmlxmlhttprequest_open(QScriptContext *context, QScriptEngin
if (!request) return context->throwError(QScriptContext::ReferenceError, QLatin1String("Not an XMLHttpRequest object"));
if (context->argumentCount() < 2 || context->argumentCount() > 5)
- return context->throwError(QScriptContext::SyntaxError, "Incorrect argument count");
+ return context->throwError(QScriptContext::SyntaxError, QLatin1String("Incorrect argument count"));
// Argument 0 - Method
QString method = context->argument(0).toString().toUpper();
@@ -1198,7 +1198,7 @@ static QScriptValue qmlxmlhttprequest_open(QScriptContext *context, QScriptEngin
method != QLatin1String("PUT") &&
method != QLatin1String("HEAD") &&
method != QLatin1String("POST"))
- return context->throwError(QScriptContext::SyntaxError, "Unsupported method");
+ return context->throwError(QScriptContext::SyntaxError, QLatin1String("Unsupported method"));
// Argument 1 - URL
@@ -1209,12 +1209,12 @@ static QScriptValue qmlxmlhttprequest_open(QScriptContext *context, QScriptEngin
if (ctxt)
url = ctxt->resolvedUrl(url);
else
- return context->throwError(QScriptContext::SyntaxError, "Relative URLs not supported");
+ return context->throwError(QScriptContext::SyntaxError, QLatin1String("Relative URLs not supported"));
}
// Argument 2 - async (optional)
if (context->argumentCount() > 2 && !context->argument(2).toBoolean())
- return context->throwError(QScriptContext::SyntaxError, "Synchronous call not supported");
+ return context->throwError(QScriptContext::SyntaxError, QLatin1String("Synchronous call not supported"));
// Argument 3/4 - user/pass (optional)
@@ -1242,12 +1242,12 @@ static QScriptValue qmlxmlhttprequest_setRequestHeader(QScriptContext *context,
if (!request) return context->throwError(QScriptContext::ReferenceError, QLatin1String("Not an XMLHttpRequest object"));
if (context->argumentCount() != 2)
- return context->throwError(QScriptContext::SyntaxError, "Incorrect argument count");
+ return context->throwError(QScriptContext::SyntaxError, QLatin1String("Incorrect argument count"));
if (request->readyState() != QmlXMLHttpRequest::Opened ||
request->sendFlag())
- return context->throwError(INVALID_STATE_ERR, "Invalid state");
+ return context->throwError(INVALID_STATE_ERR, QLatin1String("Invalid state"));
QString name = context->argument(0).toString();
@@ -1289,10 +1289,10 @@ static QScriptValue qmlxmlhttprequest_send(QScriptContext *context, QScriptEngin
if (!request) return context->throwError(QScriptContext::ReferenceError, QLatin1String("Not an XMLHttpRequest object"));
if (request->readyState() != QmlXMLHttpRequest::Opened)
- return context->throwError(INVALID_STATE_ERR, "Invalid state");
+ return context->throwError(INVALID_STATE_ERR, QLatin1String("Invalid state"));
if (request->sendFlag())
- return context->throwError(INVALID_STATE_ERR, "Invalid state");
+ return context->throwError(INVALID_STATE_ERR, QLatin1String("Invalid state"));
QByteArray data;
if (context->argumentCount() > 0)
@@ -1324,7 +1324,7 @@ static QScriptValue qmlxmlhttprequest_getResponseHeader(QScriptContext *context,
if (request->readyState() != QmlXMLHttpRequest::Loading &&
request->readyState() != QmlXMLHttpRequest::Done &&
request->readyState() != QmlXMLHttpRequest::HeadersReceived)
- return context->throwError(INVALID_STATE_ERR, "Invalid state");
+ return context->throwError(INVALID_STATE_ERR, QLatin1String("Invalid state"));
QString headerName = context->argument(0).toString();
@@ -1342,7 +1342,7 @@ static QScriptValue qmlxmlhttprequest_getAllResponseHeaders(QScriptContext *cont
if (request->readyState() != QmlXMLHttpRequest::Loading &&
request->readyState() != QmlXMLHttpRequest::Done &&
request->readyState() != QmlXMLHttpRequest::HeadersReceived)
- return context->throwError(INVALID_STATE_ERR, "Invalid state");
+ return context->throwError(INVALID_STATE_ERR, QLatin1String("Invalid state"));
return QScriptValue(request->headers());
}
@@ -1363,7 +1363,7 @@ static QScriptValue qmlxmlhttprequest_status(QScriptContext *context, QScriptEng
if (request->readyState() == QmlXMLHttpRequest::Unsent ||
request->readyState() == QmlXMLHttpRequest::Opened)
- return context->throwError(INVALID_STATE_ERR, "Invalid state");
+ return context->throwError(INVALID_STATE_ERR, QLatin1String("Invalid state"));
if (request->errorFlag())
return QScriptValue(0);
@@ -1378,7 +1378,7 @@ static QScriptValue qmlxmlhttprequest_statusText(QScriptContext *context, QScrip
if (request->readyState() == QmlXMLHttpRequest::Unsent ||
request->readyState() == QmlXMLHttpRequest::Opened)
- return context->throwError(INVALID_STATE_ERR, "Invalid state");
+ return context->throwError(INVALID_STATE_ERR, QLatin1String("Invalid state"));
if (request->errorFlag())
return QScriptValue(0);
diff --git a/src/declarative/util/qmlpackage.cpp b/src/declarative/util/qmlpackage.cpp
index 912bb6b..7df8453 100644
--- a/src/declarative/util/qmlpackage.cpp
+++ b/src/declarative/util/qmlpackage.cpp
@@ -55,11 +55,11 @@ public:
class QmlPackageAttached : public QObject
{
Q_OBJECT
+Q_PROPERTY(QString name READ name WRITE setName)
public:
QmlPackageAttached(QObject *parent);
virtual ~QmlPackageAttached();
- Q_PROPERTY(QString name READ name WRITE setName)
QString name() const;
void setName(const QString &n);
diff --git a/src/declarative/util/qmlscript.cpp b/src/declarative/util/qmlscript.cpp
deleted file mode 100644
index de2128d..0000000
--- a/src/declarative/util/qmlscript.cpp
+++ /dev/null
@@ -1,205 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Qt Software Information (qt-info@nokia.com)
-**
-** This file is part of the QtDeclarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at qt-sales@nokia.com.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtDeclarative/qmlengine.h>
-#include <QtDeclarative/qmlcontext.h>
-#include <private/qobject_p.h>
-#include <QtCore/qfile.h>
-#include <QtCore/qdebug.h>
-#include <QtScript/qscriptvalue.h>
-#include <QtScript/qscriptcontext.h>
-#include <QtScript/qscriptengine.h>
-#include <private/qmlnullablevalue_p.h>
-#include <private/qmlengine_p.h>
-#include <private/qmlcontext_p.h>
-#include "qmlscript.h"
-#include <QNetworkReply>
-#include <QNetworkRequest>
-#include <QtDeclarative/qmlinfo.h>
-#include <private/qfxperf_p.h>
-
-QT_BEGIN_NAMESPACE
-
-class QmlScriptPrivate : public QObjectPrivate
-{
- Q_DECLARE_PUBLIC(QmlScript);
-
-public:
- QmlScriptPrivate() : reply(0) {}
-
- void addScriptToEngine(const QString &, const QString &source=QString());
-
- QString script;
- QNetworkReply *reply;
- QUrl url;
-};
-
-/*!
- \qmlclass Script QmlScript
- \brief The Script element adds JavaScript snippets.
- \ingroup group_utility
-
- QmlScript is used to add convenient JavaScript "glue" methods to
- your Qt Declarative application or component. While you can have any JavaScript code
- within a QmlScript, it is best to limit yourself to defining functions.
-
- \qml
- Script {
- function debugMyComponent() {
- print(text.text);
- print(otherinterestingitem.property);
- }
- }
- MouseRegion { onClicked: debugMyComponent() }
- \endqml
-
- \note QmlScript executes JavaScript as soon as it is specified.
- When defining a component, this may be before the execution context is
- fully specified. As a result some properties or items may not be
- accessible. By limiting your JavaScript to defining functions that are
- only executed later once the context is fully defined, this problem is
- avoided.
-*/
-
-QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,Script,QmlScript)
-QmlScript::QmlScript(QObject *parent) : QObject(*(new QmlScriptPrivate), parent)
-{
-}
-
-/*!
- \qmlproperty string Script::script
- \default
- JavaScript code to execute.
-*/
-QString QmlScript::script() const
-{
- Q_D(const QmlScript);
- return d->script;
-}
-
-void QmlScript::setScript(const QString &script)
-{
- Q_D(QmlScript);
- d->script = script;
- d->addScriptToEngine(d->script);
-}
-
-/*!
- \qmlproperty url Script::source
-
- Setting this property causes the Script element to read JavaScript code from
- the file specified.
-*/
-QUrl QmlScript::source() const
-{
- Q_D(const QmlScript);
- return d->url;
-}
-
-void QmlScript::setSource(const QUrl &source)
-{
- Q_D(QmlScript);
- if (d->url == source)
- return;
- d->url = qmlContext(this)->resolvedUrl(source);
-
-#ifndef QT_NO_LOCALFILE_OPTIMIZED_QML
- if (d->url.scheme() == QLatin1String("file")) {
- QFile file(d->url.toLocalFile());
- file.open(QIODevice::ReadOnly);
- QByteArray ba = file.readAll();
- d->addScriptToEngine(QString::fromUtf8(ba), file.fileName());
- } else
-#endif
- {
- QNetworkRequest req(d->url);
- d->reply = qmlEngine(this)->networkAccessManager()->get(req);
- QObject::connect(d->reply, SIGNAL(finished()),
- this, SLOT(replyFinished()));
- }
-}
-
-void QmlScript::replyFinished()
-{
- Q_D(QmlScript);
- if (!d->reply->error()) {
- QByteArray ba = d->reply->readAll();
- d->addScriptToEngine(QString::fromUtf8(ba), d->url.toString());
- }
- d->reply->deleteLater();
- d->reply = 0;
-}
-
-void QmlScriptPrivate::addScriptToEngine(const QString &script, const QString &source)
-{
-#ifdef Q_ENABLE_PERFORMANCE_LOG
- QFxPerfTimer<QFxPerf::AddScript> pt;
-#endif
- Q_Q(QmlScript);
- QmlEngine *engine = qmlEngine(q);
- QmlContext *context = qmlContext(q);
- QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
-
- QScriptContext *scriptContext = scriptEngine->pushContext();
- for (int i = context->d_func()->scopeChain.size() - 1; i > -1; --i) {
- scriptContext->pushScope(context->d_func()->scopeChain.at(i));
- }
- scriptContext->setActivationObject(context->d_func()->scopeChain.at(0));
-
- QScriptValue val = scriptEngine->evaluate(script, source);
- if (scriptEngine->hasUncaughtException()) {
- if (scriptEngine->uncaughtException().isError()){
- QScriptValue exception = scriptEngine->uncaughtException();
- if (!exception.property(QLatin1String("fileName")).toString().isEmpty()){
- qWarning() << exception.property(QLatin1String("fileName")).toString()
- << scriptEngine->uncaughtExceptionLineNumber()
- << exception.toString();
-
- } else {
- qmlInfo(q) << exception.toString();
- }
- }
- }
-
- scriptEngine->popContext();
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/util/util.pri b/src/declarative/util/util.pri
index 41c9019..ec9967c 100644
--- a/src/declarative/util/util.pri
+++ b/src/declarative/util/util.pri
@@ -4,7 +4,6 @@ SOURCES += \
util/qperformancelog.cpp \
util/qmlconnection.cpp \
util/qmlpackage.cpp \
- util/qmlscript.cpp \
util/qmlanimation.cpp \
util/qmlsystempalette.cpp \
util/qmlspringfollow.cpp \
@@ -29,7 +28,6 @@ HEADERS += \
util/qperformancelog_p.h \
util/qmlconnection.h \
util/qmlpackage.h \
- util/qmlscript.h \
util/qmlanimation.h \
util/qmlanimation_p.h \
util/qmlsystempalette.h \
diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp
index b1f36be..029d3a5 100644
--- a/src/script/api/qscriptengine.cpp
+++ b/src/script/api/qscriptengine.cpp
@@ -340,6 +340,25 @@ public:
JSC::JSValue prototype;
};
+class QScriptProgramPrivate
+{
+public:
+ QScriptProgramPrivate() : refcount(1), hasException(false) { }
+ ~QScriptProgramPrivate() { if (evalNode) evalNode->destroyData(); }
+
+ void addref() { ++refcount; }
+ void release() { if (--refcount) delete this; }
+
+ int refcount;
+
+ bool hasException;
+ QScriptValue exception;
+
+ JSC::SourceCode source;
+ WTF::RefPtr<JSC::EvalNode> evalNode;
+};
+
+
namespace QScript
{
@@ -2113,7 +2132,121 @@ QScriptSyntaxCheckResult QScriptEnginePrivate::checkSyntax(const QString &progra
return QScriptSyntaxCheckResult(p);
}
+QScriptProgram QScriptEngine::compile(const QString &program, const QString &fileName, int lineNumber)
+{
+ Q_D(QScriptEngine);
+
+ QScriptProgram rv;
+ rv.d = new QScriptProgramPrivate;
+
+ JSC::JSLock lock(false); // ### hmmm
+ QBoolBlocker inEval(d->inEval, true);
+ currentContext()->activationObject(); //force the creation of a context for native function;
+
+ JSC::Debugger* debugger = d->originalGlobalObject()->debugger();
+
+ JSC::UString jscProgram = program;
+ JSC::UString jscFileName = fileName;
+ JSC::ExecState* exec = d->currentFrame;
+ WTF::PassRefPtr<QScript::UStringSourceProviderWithFeedback> provider
+ = QScript::UStringSourceProviderWithFeedback::create(jscProgram, jscFileName, lineNumber, d);
+ intptr_t sourceId = provider->asID();
+ JSC::SourceCode &source = rv.d->source;
+ source = JSC::SourceCode(provider, lineNumber); //after construction of SourceCode provider variable will be null.
+
+ if (debugger)
+ debugger->evaluateStart(sourceId);
+
+ exec->clearException();
+ JSC::DynamicGlobalObjectScope dynamicGlobalObjectScope(exec, exec->scopeChain()->globalObject());
+
+ int errorLine;
+ JSC::UString errorMessage;
+ WTF::RefPtr<JSC::EvalNode> &evalNode = rv.d->evalNode;
+ evalNode = exec->globalData().parser->parse<JSC::EvalNode>(&exec->globalData(), exec->lexicalGlobalObject()->debugger(), exec, source, &errorLine, &errorMessage);
+ if (!evalNode) {
+ JSC::JSValue exceptionValue = JSC::Error::create(exec, JSC::SyntaxError, errorMessage, errorLine, source.provider()->asID(), source.provider()->url());
+ exec->setException(exceptionValue);
+
+ if (debugger) {
+ debugger->exceptionThrow(JSC::DebuggerCallFrame(exec, exceptionValue), sourceId, false);
+ debugger->evaluateStop(exceptionValue, sourceId);
+ }
+
+ rv.d->hasException = true;
+ rv.d->exception = d->scriptValueFromJSCValue(exceptionValue);
+ } else if (debugger) {
+ debugger->evaluateStop(JSC::JSValue(), sourceId);
+ }
+
+ return rv;
+}
+
+QScriptValue QScriptEngine::evaluate(const QScriptProgram &program)
+{
+ Q_D(QScriptEngine);
+
+ if (0 == program.d)
+ return QScriptValue();
+ else if (program.d->hasException)
+ return program.d->exception;
+ else if (!program.d->evalNode)
+ return QScriptValue();
+
+ JSC::JSLock lock(false); // ### hmmm
+ QBoolBlocker inEval(d->inEval, true);
+ currentContext()->activationObject(); //force the creation of a context for native function;
+
+ JSC::Debugger* debugger = d->originalGlobalObject()->debugger();
+
+ JSC::ExecState* exec = d->currentFrame;
+
+ intptr_t sourceId = program.d->source.provider()->asID();
+
+ if (debugger)
+ debugger->evaluateStart(sourceId);
+
+ exec->clearException();
+ JSC::DynamicGlobalObjectScope dynamicGlobalObjectScope(exec, exec->scopeChain()->globalObject());
+
+ WTF::RefPtr<JSC::EvalNode> &evalNode = program.d->evalNode;
+
+ JSC::EvalExecutable executable(exec, program.d->source);
+ executable.compile(exec, evalNode, exec->scopeChain());
+ JSC::JSValue thisValue = d->thisForContext(exec);
+ JSC::JSObject* thisObject = (!thisValue || thisValue.isUndefinedOrNull()) ? exec->dynamicGlobalObject() : thisValue.toObject(exec);
+ JSC::JSValue exceptionValue;
+ d->timeoutChecker()->setShouldAbort(false);
+ if (d->processEventsInterval > 0)
+ d->timeoutChecker()->reset();
+ JSC::JSValue result = exec->interpreter()->execute(&executable, exec, thisObject, exec->scopeChain(), &exceptionValue);
+
+ if (d->timeoutChecker()->shouldAbort()) {
+ if (d->abortResult.isError())
+ exec->setException(d->scriptValueToJSCValue(d->abortResult));
+
+ if (debugger)
+ debugger->evaluateStop(d->scriptValueToJSCValue(d->abortResult), sourceId);
+
+ return d->abortResult;
+ }
+
+ if (exceptionValue) {
+ exec->setException(exceptionValue);
+
+ if (debugger)
+ debugger->evaluateStop(exceptionValue, sourceId);
+
+ return d->scriptValueFromJSCValue(exceptionValue);
+ }
+
+ if (debugger)
+ debugger->evaluateStop(result, sourceId);
+
+ Q_ASSERT(!exec->hadException());
+ return d->scriptValueFromJSCValue(result);
+}
/*!
Evaluates \a program, using \a lineNumber as the base line number,
@@ -2266,6 +2399,35 @@ QScriptContext *QScriptEngine::pushContext()
return d->contextForFrame(newFrame);
}
+/*!
+ Enters a new execution context and returns the associated
+ QScriptContext object.
+
+ Once you are done with the context, you should call popContext() to
+ restore the old context.
+
+ By default, the `this' object of the new context is the Global Object.
+ The context's \l{QScriptContext::callee()}{callee}() will be invalid.
+
+ Unlike pushContext(), the default scope chain is reset to include
+ only the global object and the QScriptContext's activation object.
+
+ \sa popContext()
+*/
+QScriptContext *QScriptEngine::pushCleanContext()
+{
+ Q_D(QScriptEngine);
+
+ JSC::CallFrame* newFrame = d->pushContext(d->currentFrame, d->currentFrame->globalData().dynamicGlobalObject,
+ JSC::ArgList(), /*callee = */0, false, true);
+
+ if (agent())
+ agent()->contextPush();
+
+ return d->contextForFrame(newFrame);
+}
+
+
/*! \internal
push a context for a native function.
JSC native function doesn't have different stackframe or context. so we need to create one.
@@ -2277,7 +2439,8 @@ QScriptContext *QScriptEngine::pushContext()
return the new top frame. (might be the same as exec if a new stackframe was not needed) or 0 if stack overflow
*/
JSC::CallFrame *QScriptEnginePrivate::pushContext(JSC::CallFrame *exec, JSC::JSValue _thisObject,
- const JSC::ArgList& args, JSC::JSObject *callee, bool calledAsConstructor)
+ const JSC::ArgList& args, JSC::JSObject *callee, bool calledAsConstructor,
+ bool clearScopeChain)
{
JSC::JSValue thisObject = _thisObject;
if (calledAsConstructor) {
@@ -2311,7 +2474,14 @@ JSC::CallFrame *QScriptEnginePrivate::pushContext(JSC::CallFrame *exec, JSC::JSV
for (it = args.begin(); it != args.end(); ++it)
newCallFrame[++dst] = *it;
newCallFrame += argc + JSC::RegisterFile::CallFrameHeaderSize;
- newCallFrame->init(0, /*vPC=*/0, exec->scopeChain(), exec, flags | ShouldRestoreCallFrame, argc, callee);
+
+ if (!clearScopeChain) {
+ newCallFrame->init(0, /*vPC=*/0, exec->scopeChain(), exec, flags | ShouldRestoreCallFrame, argc, callee);
+ } else {
+ JSC::JSObject *jscObject = originalGlobalObject();
+ JSC::ScopeChainNode *scn = new JSC::ScopeChainNode(0, jscObject, &exec->globalData(), jscObject);
+ newCallFrame->init(0, /*vPC=*/0, scn, exec, flags | ShouldRestoreCallFrame, argc, callee);
+ }
} else {
setContextFlags(newCallFrame, flags);
#if ENABLE(JIT)
@@ -3707,6 +3877,9 @@ QScriptValue QScriptEngine::objectById(qint64 id) const
return const_cast<QScriptEnginePrivate*>(d)->scriptValueFromJSCValue((JSC::JSCell*)id);
}
+
+
+
/*!
\since 4.5
\class QScriptSyntaxCheckResult
@@ -3835,4 +4008,51 @@ Q_AUTOTEST_EXPORT bool qt_script_isJITEnabled()
}
#endif
+QScriptProgram::QScriptProgram()
+: d(0)
+{
+}
+
+QScriptProgram::~QScriptProgram()
+{
+ if (d) d->release();
+}
+
+QScriptProgram::QScriptProgram(const QScriptProgram &c)
+: d(c.d)
+{
+ if (d) d->addref();
+}
+
+QScriptProgram &QScriptProgram::operator=(const QScriptProgram &c)
+{
+ if (c.d) c.d->addref();
+ if (d) d->release();
+ d = c.d;
+ return *this;
+}
+
+bool QScriptProgram::isNull() const
+{
+ return d == 0;
+}
+
+bool QScriptProgram::hasSyntaxError() const
+{
+ if (d) return d->hasException;
+ else return false;
+}
+
+QScriptValue QScriptProgram::syntaxError() const
+{
+ if (d) return d->exception;
+ else return QScriptValue();
+}
+
+QString QScriptProgram::programSource() const
+{
+ if (d) return d->source.toString();
+ else return QString();
+}
+
QT_END_NAMESPACE
diff --git a/src/script/api/qscriptengine.h b/src/script/api/qscriptengine.h
index 701f9c6..cd86aca 100644
--- a/src/script/api/qscriptengine.h
+++ b/src/script/api/qscriptengine.h
@@ -120,6 +120,29 @@ private:
friend class QScriptEnginePrivate;
};
+class QScriptProgramPrivate;
+class Q_SCRIPT_EXPORT QScriptProgram
+{
+public:
+ QScriptProgram();
+ QScriptProgram(const QScriptProgram &);
+ ~QScriptProgram();
+
+ QScriptProgram &operator=(const QScriptProgram &);
+
+ bool isNull() const;
+
+ bool hasSyntaxError() const;
+ QScriptValue syntaxError() const;
+
+ QString programSource() const;
+
+private:
+ friend class QScriptEngine;
+ QScriptProgramPrivate *d;
+};
+
+class QScriptCode;
class Q_SCRIPT_EXPORT QScriptEngine
#ifndef QT_NO_QOBJECT
: public QObject
@@ -159,11 +182,15 @@ public:
QScriptContext *currentContext() const;
QScriptContext *pushContext();
+ QScriptContext *pushCleanContext();
void popContext();
bool canEvaluate(const QString &program) const;
static QScriptSyntaxCheckResult checkSyntax(const QString &program);
+ QScriptProgram compile(const QString &program, const QString &fileName = QString(), int lineNumber = 1);
+ QScriptValue evaluate(const QScriptProgram &);
+
QScriptValue evaluate(const QString &program, const QString &fileName = QString(), int lineNumber = 1);
bool isEvaluating() const;
diff --git a/src/script/api/qscriptengine_p.h b/src/script/api/qscriptengine_p.h
index 5f31054..7218ee1 100644
--- a/src/script/api/qscriptengine_p.h
+++ b/src/script/api/qscriptengine_p.h
@@ -162,7 +162,7 @@ public:
static JSC::Register *thisRegisterForFrame(JSC::ExecState *frame);
JSC::CallFrame *pushContext(JSC::CallFrame *exec, JSC::JSValue thisObject, const JSC::ArgList& args,
- JSC::JSObject *callee, bool calledAsConstructor = false);
+ JSC::JSObject *callee, bool calledAsConstructor = false, bool clearScopeChain = false);
void popContext();
void mark(JSC::MarkStack& markStack);
diff --git a/src/script/api/qscriptvalue.cpp b/src/script/api/qscriptvalue.cpp
index 92c987c..7136a85 100644
--- a/src/script/api/qscriptvalue.cpp
+++ b/src/script/api/qscriptvalue.cpp
@@ -71,6 +71,7 @@
#include "bridge/qscriptclassobject_p.h"
#include "bridge/qscriptvariant_p.h"
#include "bridge/qscriptqobject_p.h"
+#include "bridge/qscriptdeclarativeclass_p.h"
/*!
\since 4.3
@@ -1529,6 +1530,8 @@ QVariant QScriptValue::toVariant() const
#endif
else if (isArray())
return QScriptEnginePrivate::variantListFromArray(*this);
+ else if (QScriptDeclarativeClass *dc = QScriptDeclarativeClass::scriptClass(*this))
+ return dc->toVariant(QScriptDeclarativeClass::object(*this));
// try to convert to primitive
JSC::ExecState *exec = d->engine->currentFrame;
JSC::JSValue savedException;
@@ -1619,6 +1622,8 @@ QObject *QScriptValue::toQObject() const
if (isQObject()) {
QScriptObject *object = static_cast<QScriptObject*>(JSC::asObject(d->jscValue));
return static_cast<QScript::QObjectDelegate*>(object->delegate())->value();
+ } else if (QScriptDeclarativeClass *dc = QScriptDeclarativeClass::scriptClass(*this)) {
+ return dc->toQObject(QScriptDeclarativeClass::object(*this));
} else if (isVariant()) {
QVariant var = toVariant();
int type = var.userType();
diff --git a/src/script/bridge/bridge.pri b/src/script/bridge/bridge.pri
index 666a07e..09e2dfb 100644
--- a/src/script/bridge/bridge.pri
+++ b/src/script/bridge/bridge.pri
@@ -5,7 +5,9 @@ SOURCES += \
$$PWD/qscriptvariant.cpp \
$$PWD/qscriptqobject.cpp \
$$PWD/qscriptglobalobject.cpp \
- $$PWD/qscriptactivationobject.cpp
+ $$PWD/qscriptactivationobject.cpp \
+ $$PWD/qscriptdeclarativeobject.cpp \
+ $$PWD/qscriptdeclarativeclass.cpp
HEADERS += \
$$PWD/qscriptfunction_p.h \
@@ -14,4 +16,6 @@ HEADERS += \
$$PWD/qscriptvariant_p.h \
$$PWD/qscriptqobject_p.h \
$$PWD/qscriptglobalobject_p.h \
- $$PWD/qscriptactivationobject_p.h
+ $$PWD/qscriptactivationobject_p.h \
+ $$PWD/qscriptdeclarativeobject_p.h \
+ $$PWD/qscriptdeclarativeclass_p.h
diff --git a/src/script/bridge/qscriptdeclarativeclass.cpp b/src/script/bridge/qscriptdeclarativeclass.cpp
new file mode 100644
index 0000000..d019839
--- /dev/null
+++ b/src/script/bridge/qscriptdeclarativeclass.cpp
@@ -0,0 +1,316 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qscriptdeclarativeclass_p.h"
+#include "qscriptdeclarativeobject_p.h"
+#include "qscriptobject_p.h"
+#include <QtScript/qscriptstring.h>
+#include <QtScript/qscriptengine.h>
+#include <private/qscriptengine_p.h>
+#include <private/qscriptvalue_p.h>
+#include <private/qscriptqobject_p.h>
+#include <private/qscriptactivationobject_p.h>
+#include <QtCore/qstringlist.h>
+
+QT_BEGIN_NAMESPACE
+
+QScriptDeclarativeClass::PersistentIdentifier::PersistentIdentifier()
+{
+ new (&d) JSC::Identifier();
+}
+
+QScriptDeclarativeClass::PersistentIdentifier::~PersistentIdentifier()
+{
+ ((JSC::Identifier &)d).JSC::Identifier::~Identifier();
+}
+
+QScriptDeclarativeClass::PersistentIdentifier::PersistentIdentifier(const PersistentIdentifier &other)
+{
+ identifier = other.identifier;
+ new (&d) JSC::Identifier((JSC::Identifier &)(other.d));
+}
+
+QScriptDeclarativeClass::PersistentIdentifier &
+QScriptDeclarativeClass::PersistentIdentifier::operator=(const PersistentIdentifier &other)
+{
+ identifier = other.identifier;
+ ((JSC::Identifier &)d) = (JSC::Identifier &)(other.d);
+ return *this;
+}
+
+QScriptDeclarativeClass::QScriptDeclarativeClass(QScriptEngine *engine)
+: d_ptr(new QScriptDeclarativeClassPrivate)
+{
+ Q_ASSERT(sizeof(void*) == sizeof(JSC::Identifier));
+ d_ptr->q_ptr = this;
+ d_ptr->engine = engine;
+}
+
+QScriptValue QScriptDeclarativeClass::newObject(QScriptEngine *engine,
+ QScriptDeclarativeClass *scriptClass,
+ Object *object)
+{
+ Q_ASSERT(engine);
+ Q_ASSERT(scriptClass);
+
+ QScriptEnginePrivate *p = static_cast<QScriptEnginePrivate *>(QObjectPrivate::get(engine));
+
+ JSC::ExecState* exec = p->currentFrame;
+ QScriptObject *result = new (exec) QScriptObject(p->scriptObjectStructure);
+ result->setDelegate(new QScript::DeclarativeObjectDelegate(scriptClass, object));
+ return p->scriptValueFromJSCValue(result);
+}
+
+QScriptDeclarativeClass *QScriptDeclarativeClass::scriptClass(const QScriptValue &v)
+{
+ QScriptValuePrivate *d = QScriptValuePrivate::get(v);
+ if (!d || !d->isJSC() || !d->jscValue.inherits(&QScriptObject::info))
+ return 0;
+ QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(d->jscValue));
+ QScriptObjectDelegate *delegate = scriptObject->delegate();
+ if (!delegate || (delegate->type() != QScriptObjectDelegate::DeclarativeClassObject))
+ return 0;
+ return static_cast<QScript::DeclarativeObjectDelegate*>(delegate)->scriptClass();
+}
+
+QScriptDeclarativeClass::Object *QScriptDeclarativeClass::object(const QScriptValue &v)
+{
+ QScriptValuePrivate *d = QScriptValuePrivate::get(v);
+ if (!d || !d->isJSC() || !d->jscValue.inherits(&QScriptObject::info))
+ return 0;
+ QScriptObject *scriptObject = static_cast<QScriptObject*>(JSC::asObject(d->jscValue));
+ QScriptObjectDelegate *delegate = scriptObject->delegate();
+ if (!delegate || (delegate->type() != QScriptObjectDelegate::DeclarativeClassObject))
+ return 0;
+ return static_cast<QScript::DeclarativeObjectDelegate*>(delegate)->object();
+}
+
+QScriptValue QScriptDeclarativeClass::function(const QScriptValue &v, const Identifier &name)
+{
+ QScriptValuePrivate *d = QScriptValuePrivate::get(v);
+
+ if (!d->isObject())
+ return QScriptValue();
+
+ JSC::ExecState *exec = d->engine->currentFrame;
+ JSC::JSObject *object = d->jscValue.getObject();
+ JSC::PropertySlot slot(const_cast<JSC::JSObject*>(object));
+ JSC::JSValue result;
+
+ JSC::Identifier id(exec, (JSC::UString::Rep *)name);
+
+ if (const_cast<JSC::JSObject*>(object)->getOwnPropertySlot(exec, id, slot)) {
+ result = slot.getValue(exec, id);
+ if (QScript::isFunction(result))
+ return d->engine->scriptValueFromJSCValue(result);
+ }
+
+ return QScriptValue();
+}
+
+QScriptValue QScriptDeclarativeClass::property(const QScriptValue &v, const Identifier &name)
+{
+ QScriptValuePrivate *d = QScriptValuePrivate::get(v);
+
+ if (!d->isObject())
+ return QScriptValue();
+
+ JSC::ExecState *exec = d->engine->currentFrame;
+ JSC::JSObject *object = d->jscValue.getObject();
+ JSC::PropertySlot slot(const_cast<JSC::JSObject*>(object));
+ JSC::JSValue result;
+
+ JSC::Identifier id(exec, (JSC::UString::Rep *)name);
+
+ if (const_cast<JSC::JSObject*>(object)->getOwnPropertySlot(exec, id, slot)) {
+ result = slot.getValue(exec, id);
+ return d->engine->scriptValueFromJSCValue(result);
+ }
+
+ return QScriptValue();
+}
+
+/*
+Returns the scope chain entry at \a index. If index is less than 0, returns
+entries starting at the end. For example, scopeChainValue(context, -1) will return
+the value last in the scope chain.
+*/
+QScriptValue QScriptDeclarativeClass::scopeChainValue(QScriptContext *context, int index)
+{
+ context->activationObject(); //ensure the creation of the normal scope for native context
+ const JSC::CallFrame *frame = QScriptEnginePrivate::frameForContext(context);
+ QScriptEnginePrivate *engine = QScript::scriptEngineFromExec(frame);
+
+ JSC::ScopeChainNode *node = frame->scopeChain();
+ JSC::ScopeChainIterator it(node);
+
+ if (index < 0) {
+ int count = 0;
+ for (it = node->begin(); it != node->end(); ++it)
+ ++count;
+
+ index = qAbs(index);
+ if (index > count)
+ return QScriptValue();
+ else
+ index = count - index;
+ }
+
+ for (it = node->begin(); it != node->end(); ++it) {
+
+ if (index == 0) {
+
+ JSC::JSObject *object = *it;
+ if (!object) return QScriptValue();
+
+ if (object->inherits(&QScript::QScriptActivationObject::info)
+ && (static_cast<QScript::QScriptActivationObject*>(object)->delegate() != 0)) {
+ // Return the object that property access is being delegated to
+ object = static_cast<QScript::QScriptActivationObject*>(object)->delegate();
+ }
+ return engine->scriptValueFromJSCValue(object);
+
+ } else {
+ --index;
+ }
+
+ }
+
+ return QScriptValue();
+}
+
+QScriptDeclarativeClass::~QScriptDeclarativeClass()
+{
+}
+
+QScriptEngine *QScriptDeclarativeClass::engine() const
+{
+ return d_ptr->engine;
+}
+
+QScriptDeclarativeClass::PersistentIdentifier
+QScriptDeclarativeClass::createPersistentIdentifier(const QString &str)
+{
+ QScriptEnginePrivate *p =
+ static_cast<QScriptEnginePrivate *>(QObjectPrivate::get(d_ptr->engine));
+ JSC::ExecState* exec = p->currentFrame;
+
+ PersistentIdentifier rv(true);
+ new (&rv.d) JSC::Identifier(exec, (UChar *)str.constData(), str.size());
+ rv.identifier = (void *)((JSC::Identifier &)rv.d).ustring().rep();
+ return rv;
+}
+
+QScriptDeclarativeClass::PersistentIdentifier
+QScriptDeclarativeClass::createPersistentIdentifier(const Identifier &id)
+{
+ QScriptEnginePrivate *p =
+ static_cast<QScriptEnginePrivate *>(QObjectPrivate::get(d_ptr->engine));
+ JSC::ExecState* exec = p->currentFrame;
+
+ PersistentIdentifier rv(true);
+ new (&rv.d) JSC::Identifier(exec, (JSC::UString::Rep *)id);
+ rv.identifier = (void *)((JSC::Identifier &)rv.d).ustring().rep();
+ return rv;
+}
+
+QString QScriptDeclarativeClass::toString(const Identifier &identifier)
+{
+ JSC::UString::Rep *r = (JSC::UString::Rep *)identifier;
+ return QString((QChar *)r->data(), r->size());
+}
+
+QScriptClass::QueryFlags
+QScriptDeclarativeClass::queryProperty(Object *object, const Identifier &name,
+ QScriptClass::QueryFlags flags)
+{
+ Q_UNUSED(object);
+ Q_UNUSED(name);
+ Q_UNUSED(flags);
+ return 0;
+}
+
+QScriptValue QScriptDeclarativeClass::property(Object *object, const Identifier &name)
+{
+ Q_UNUSED(object);
+ Q_UNUSED(name);
+ return QScriptValue();
+}
+
+void QScriptDeclarativeClass::setProperty(Object *object, const Identifier &name,
+ const QScriptValue &value)
+{
+ Q_UNUSED(object);
+ Q_UNUSED(name);
+ Q_UNUSED(value);
+}
+
+QScriptValue::PropertyFlags
+QScriptDeclarativeClass::propertyFlags(Object *object, const Identifier &name)
+{
+ Q_UNUSED(object);
+ Q_UNUSED(name);
+ return 0;
+}
+
+QStringList QScriptDeclarativeClass::propertyNames(Object *object)
+{
+ Q_UNUSED(object);
+ return QStringList();
+}
+
+QObject *QScriptDeclarativeClass::toQObject(Object *, bool *ok)
+{
+ if (ok) *ok = false;
+ return 0;
+}
+
+QVariant QScriptDeclarativeClass::toVariant(Object *, bool *ok)
+{
+ if (ok) *ok = false;
+ return QVariant();
+}
+
+QScriptContext *QScriptDeclarativeClass::context() const
+{
+ return d_ptr->context;
+}
+
diff --git a/src/script/bridge/qscriptdeclarativeclass_p.h b/src/script/bridge/qscriptdeclarativeclass_p.h
new file mode 100644
index 0000000..b28209a
--- /dev/null
+++ b/src/script/bridge/qscriptdeclarativeclass_p.h
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCRIPTDECLARATIVECLASS_P_H
+#define QSCRIPTDECLARATIVECLASS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qobjectdefs.h>
+#include <QtScript/qscriptvalue.h>
+#include <QtScript/qscriptclass.h>
+
+QT_BEGIN_NAMESPACE
+
+class QScriptDeclarativeClassPrivate;
+class PersistentIdentifierPrivate;
+class QScriptContext;
+class Q_SCRIPT_EXPORT QScriptDeclarativeClass
+{
+public:
+ typedef void* Identifier;
+
+ struct Object { virtual ~Object() {} };
+
+ static QScriptValue newObject(QScriptEngine *, QScriptDeclarativeClass *, Object *);
+ static QScriptDeclarativeClass *scriptClass(const QScriptValue &);
+ static Object *object(const QScriptValue &);
+
+ static QScriptValue function(const QScriptValue &, const Identifier &);
+ static QScriptValue property(const QScriptValue &, const Identifier &);
+
+ static QScriptValue scopeChainValue(QScriptContext *, int index);
+
+ class Q_SCRIPT_EXPORT PersistentIdentifier
+ {
+ public:
+ Identifier identifier;
+
+ PersistentIdentifier();
+ ~PersistentIdentifier();
+ PersistentIdentifier(const PersistentIdentifier &other);
+ PersistentIdentifier &operator=(const PersistentIdentifier &other);
+
+ private:
+ friend class QScriptDeclarativeClass;
+ PersistentIdentifier(bool) : identifier(0), d(0) {}
+ void *d;
+ };
+
+ QScriptDeclarativeClass(QScriptEngine *engine);
+ virtual ~QScriptDeclarativeClass();
+
+ QScriptEngine *engine() const;
+
+ PersistentIdentifier createPersistentIdentifier(const QString &);
+ PersistentIdentifier createPersistentIdentifier(const Identifier &);
+
+ QString toString(const Identifier &);
+
+ virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &,
+ QScriptClass::QueryFlags flags);
+
+ virtual QScriptValue property(Object *, const Identifier &);
+ virtual void setProperty(Object *, const Identifier &name, const QScriptValue &);
+ virtual QScriptValue::PropertyFlags propertyFlags(Object *, const Identifier &);
+
+ virtual QStringList propertyNames(Object *);
+
+ virtual QObject *toQObject(Object *, bool *ok = 0);
+ virtual QVariant toVariant(Object *, bool *ok = 0);
+
+ QScriptContext *context() const;
+protected:
+ friend class QScriptDeclarativeClassPrivate;
+ QScopedPointer<QScriptDeclarativeClassPrivate> d_ptr;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/script/bridge/qscriptdeclarativeobject.cpp b/src/script/bridge/qscriptdeclarativeobject.cpp
new file mode 100644
index 0000000..76c2eb0
--- /dev/null
+++ b/src/script/bridge/qscriptdeclarativeobject.cpp
@@ -0,0 +1,192 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "config.h"
+#include "qscriptdeclarativeobject_p.h"
+
+#include "../api/qscriptengine.h"
+#include "../api/qscriptengine_p.h"
+#include "../api/qscriptcontext.h"
+#include "../api/qscriptcontext_p.h"
+#include "../api/qscriptclass.h"
+#include "../api/qscriptclasspropertyiterator.h"
+
+#include "Error.h"
+#include "PropertyNameArray.h"
+
+#include <QtCore/qstringlist.h>
+
+Q_DECLARE_METATYPE(QScriptContext*)
+Q_DECLARE_METATYPE(QScriptValue)
+Q_DECLARE_METATYPE(QScriptValueList)
+
+QT_BEGIN_NAMESPACE
+
+namespace QScript
+{
+
+DeclarativeObjectDelegate::DeclarativeObjectDelegate(QScriptDeclarativeClass *c,
+ QScriptDeclarativeClass::Object *o)
+: m_class(c), m_object(o)
+{
+}
+
+DeclarativeObjectDelegate::~DeclarativeObjectDelegate()
+{
+ delete m_object;
+}
+
+QScriptObjectDelegate::Type DeclarativeObjectDelegate::type() const
+{
+ return DeclarativeClassObject;
+}
+
+bool DeclarativeObjectDelegate::getOwnPropertySlot(QScriptObject* object,
+ JSC::ExecState *exec,
+ const JSC::Identifier &propertyName,
+ JSC::PropertySlot &slot)
+{
+ QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
+ QScriptDeclarativeClass::Identifier identifier = (void *)propertyName.ustring().rep();
+
+ QScriptDeclarativeClassPrivate *p = QScriptDeclarativeClassPrivate::get(m_class);
+ p->context = reinterpret_cast<QScriptContext *>(exec);
+ QScriptClass::QueryFlags flags =
+ m_class->queryProperty(m_object, identifier, QScriptClass::HandlesReadAccess);
+ if (flags & QScriptClass::HandlesReadAccess) {
+ QScriptValue value = m_class->property(m_object, identifier);
+ p->context = 0;
+ slot.setValue(engine->scriptValueToJSCValue(value));
+ return true;
+ }
+ p->context = 0;
+
+ return QScriptObjectDelegate::getOwnPropertySlot(object, exec, propertyName, slot);
+}
+
+void DeclarativeObjectDelegate::put(QScriptObject* object, JSC::ExecState *exec,
+ const JSC::Identifier &propertyName,
+ JSC::JSValue value, JSC::PutPropertySlot &slot)
+{
+ QScriptEnginePrivate *engine = scriptEngineFromExec(exec);
+ QScriptDeclarativeClass::Identifier identifier = (void *)propertyName.ustring().rep();
+
+ QScriptDeclarativeClassPrivate *p = QScriptDeclarativeClassPrivate::get(m_class);
+ p->context = reinterpret_cast<QScriptContext *>(exec);
+ QScriptClass::QueryFlags flags =
+ m_class->queryProperty(m_object, identifier, QScriptClass::HandlesWriteAccess);
+ if (flags & QScriptClass::HandlesWriteAccess) {
+ m_class->setProperty(m_object, identifier, engine->scriptValueFromJSCValue(value));
+ p->context = 0;
+ return;
+ }
+ p->context = 0;
+
+ QScriptObjectDelegate::put(object, exec, propertyName, value, slot);
+}
+
+bool DeclarativeObjectDelegate::deleteProperty(QScriptObject* object, JSC::ExecState *exec,
+ const JSC::Identifier &propertyName,
+ bool checkDontDelete)
+{
+ return QScriptObjectDelegate::deleteProperty(object, exec, propertyName, checkDontDelete);
+}
+
+bool DeclarativeObjectDelegate::getPropertyAttributes(const QScriptObject* object,
+ JSC::ExecState *exec,
+ const JSC::Identifier &propertyName,
+ unsigned &attribs) const
+{
+ QScriptDeclarativeClass::Identifier identifier = (void *)propertyName.ustring().rep();
+
+ QScriptClass::QueryFlags flags =
+ m_class->queryProperty(m_object, identifier, QScriptClass::HandlesReadAccess);
+ if (flags & QScriptClass::HandlesReadAccess) {
+ QScriptValue::PropertyFlags flags = m_class->propertyFlags(m_object, identifier);
+ attribs = 0;
+ if (flags & QScriptValue::ReadOnly)
+ attribs |= JSC::ReadOnly;
+ if (flags & QScriptValue::SkipInEnumeration)
+ attribs |= JSC::DontEnum;
+ if (flags & QScriptValue::Undeletable)
+ attribs |= JSC::DontDelete;
+ if (flags & QScriptValue::PropertyGetter)
+ attribs |= JSC::Getter;
+ if (flags & QScriptValue::PropertySetter)
+ attribs |= JSC::Setter;
+ attribs |= flags & QScriptValue::UserRange;
+ return true;
+ }
+ return QScriptObjectDelegate::getPropertyAttributes(object, exec, propertyName, attribs);
+}
+
+void DeclarativeObjectDelegate::getOwnPropertyNames(QScriptObject* object, JSC::ExecState *exec,
+ JSC::PropertyNameArray &propertyNames,
+ bool includeNonEnumerable)
+{
+ QStringList properties = m_class->propertyNames(m_object);
+ for (int ii = 0; ii < properties.count(); ++ii) {
+ const QString &name = properties.at(ii);
+ propertyNames.add(JSC::Identifier(exec, name));
+ }
+
+ QScriptObjectDelegate::getOwnPropertyNames(object, exec, propertyNames, includeNonEnumerable);
+}
+
+JSC::CallType DeclarativeObjectDelegate::getCallData(QScriptObject *object, JSC::CallData &callData)
+{
+ return QScriptObjectDelegate::getCallData(object, callData);
+}
+
+JSC::ConstructType DeclarativeObjectDelegate::getConstructData(QScriptObject* object, JSC::ConstructData &constructData)
+{
+ return QScriptObjectDelegate::getConstructData(object, constructData);
+}
+
+bool DeclarativeObjectDelegate::hasInstance(QScriptObject* object, JSC::ExecState *exec,
+ JSC::JSValue value, JSC::JSValue proto)
+{
+ return QScriptObjectDelegate::hasInstance(object, exec, value, proto);
+}
+
+} // namespace QScript
+
+QT_END_NAMESPACE
diff --git a/src/script/bridge/qscriptdeclarativeobject_p.h b/src/script/bridge/qscriptdeclarativeobject_p.h
new file mode 100644
index 0000000..c6dfb83
--- /dev/null
+++ b/src/script/bridge/qscriptdeclarativeobject_p.h
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCRIPTDECLARATIVEOBJECT_P_H
+#define QSCRIPTDECLARATIVEOBJECT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qobjectdefs.h>
+
+#include "config.h"
+#include "qscriptobject_p.h"
+#include "qscriptdeclarativeclass_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QScriptClass;
+
+class QScriptDeclarativeClassPrivate
+{
+public:
+ QScriptDeclarativeClassPrivate() : engine(0), q_ptr(0), context(0) {}
+
+ QScriptEngine *engine;
+ QScriptDeclarativeClass *q_ptr;
+ QScriptContext *context;
+
+ static QScriptDeclarativeClassPrivate *get(QScriptDeclarativeClass *c) {
+ return c->d_ptr.data();
+ }
+};
+
+namespace QScript
+{
+
+class DeclarativeObjectDelegate : public QScriptObjectDelegate
+{
+public:
+ DeclarativeObjectDelegate(QScriptDeclarativeClass *c, QScriptDeclarativeClass::Object *o);
+ ~DeclarativeObjectDelegate();
+
+ virtual Type type() const;
+
+ QScriptDeclarativeClass *scriptClass() const { return m_class; }
+ QScriptDeclarativeClass::Object *object() const { return m_object; }
+
+ virtual bool getOwnPropertySlot(QScriptObject*, JSC::ExecState*,
+ const JSC::Identifier& propertyName,
+ JSC::PropertySlot&);
+ virtual void put(QScriptObject*, JSC::ExecState* exec,
+ const JSC::Identifier& propertyName,
+ JSC::JSValue, JSC::PutPropertySlot&);
+ virtual bool deleteProperty(QScriptObject*, JSC::ExecState*,
+ const JSC::Identifier& propertyName,
+ bool checkDontDelete = true);
+ virtual bool getPropertyAttributes(const QScriptObject*, JSC::ExecState*,
+ const JSC::Identifier&,
+ unsigned&) const;
+ virtual void getOwnPropertyNames(QScriptObject*, JSC::ExecState*,
+ JSC::PropertyNameArray&,
+ bool includeNonEnumerable = false);
+
+ virtual JSC::CallType getCallData(QScriptObject*, JSC::CallData&);
+ virtual JSC::ConstructType getConstructData(QScriptObject*, JSC::ConstructData&);
+
+ virtual bool hasInstance(QScriptObject*, JSC::ExecState*,
+ JSC::JSValue value, JSC::JSValue proto);
+
+private:
+ QScriptDeclarativeClass *m_class;
+ QScriptDeclarativeClass::Object *m_object;
+};
+
+} // namespace QScript
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/script/bridge/qscriptobject_p.h b/src/script/bridge/qscriptobject_p.h
index c1cee31..a5858ac 100644
--- a/src/script/bridge/qscriptobject_p.h
+++ b/src/script/bridge/qscriptobject_p.h
@@ -127,7 +127,8 @@ public:
enum Type {
QtObject,
Variant,
- ClassObject
+ ClassObject,
+ DeclarativeClassObject
};
QScriptObjectDelegate();
diff --git a/tests/auto/declarative/qmlecmascript/data/ScopeObject.qml b/tests/auto/declarative/qmlecmascript/data/ScopeObject.qml
new file mode 100644
index 0000000..b7bec63
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/ScopeObject.qml
@@ -0,0 +1,14 @@
+import Qt 4.6
+
+Item {
+ property int a: 3
+ property int binding: myFunction();
+ property int binding2: myCompFunction();
+
+ Script {
+ function myCompFunction() {
+ return a;
+ }
+ }
+}
+
diff --git a/tests/auto/declarative/qmlecmascript/data/attachedProperty.qml b/tests/auto/declarative/qmlecmascript/data/attachedProperty.qml
new file mode 100644
index 0000000..c5088e3
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/attachedProperty.qml
@@ -0,0 +1,11 @@
+import Qt.test 1.0
+import Qt.test 1.0 as Namespace
+
+MyQmlObject {
+ id: Me
+ property int a: MyQmlObject.value
+ property int b: Namespace.MyQmlObject.value
+ property int c: Me.Namespace.MyQmlObject.value
+ property int d: Me.Namespace.MyQmlObject.value
+}
+
diff --git a/tests/auto/declarative/qmlecmascript/data/extendedObjectPropertyLookup.qml b/tests/auto/declarative/qmlecmascript/data/extendedObjectPropertyLookup.qml
new file mode 100644
index 0000000..8ff3aeb
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/extendedObjectPropertyLookup.qml
@@ -0,0 +1,8 @@
+import Qt.test 1.0
+import Qt 4.6
+
+Object {
+ property MyExtendedObject a;
+ a: MyExtendedObject { id: Root }
+ property int b: Math.max(Root.extendedProperty, 0)
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/objectsCompareAsEqual.qml b/tests/auto/declarative/qmlecmascript/data/objectsCompareAsEqual.qml
new file mode 100644
index 0000000..2526576
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/objectsCompareAsEqual.qml
@@ -0,0 +1,15 @@
+import Qt 4.6
+
+Item {
+ id: Root
+
+ property var item: Child
+ Item { id: Child }
+
+ property bool test1: Child == Child
+ property bool test2: Child.parent == Root
+ property bool test3: Root != Child
+ property bool test4: item == Child
+ property bool test5: item != Root
+}
+
diff --git a/tests/auto/declarative/qmlecmascript/data/scope.qml b/tests/auto/declarative/qmlecmascript/data/scope.qml
new file mode 100644
index 0000000..80222c8
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/scope.qml
@@ -0,0 +1,48 @@
+import Qt 4.6
+
+Item {
+ id: Root
+
+ property int a: 1
+ property int binding: a
+ property string binding2: a + "Test"
+ property int binding3: myFunction()
+ property int binding4: myNestedFunction()
+
+ Script {
+ function myFunction() {
+ return a;
+ }
+ }
+
+ Item {
+ id: NestedObject
+
+ Script {
+ function myNestedFunction() {
+ return a;
+ }
+ }
+
+ property int a: 2
+ property int binding: a
+ property string binding2: a + "Test"
+ property int binding3: myFunction()
+ property int binding4: myNestedFunction()
+ }
+
+ ScopeObject {
+ id: CompObject
+ }
+
+ property alias test1: Root.binding
+ property alias test2: NestedObject.binding
+ property alias test3: Root.binding2
+ property alias test4: NestedObject.binding2
+ property alias test5: Root.binding3
+ property alias test6: NestedObject.binding3
+ property alias test7: Root.binding4
+ property alias test8: NestedObject.binding4
+ property alias test9: CompObject.binding
+ property alias test10: CompObject.binding2
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/scriptAccess.js b/tests/auto/declarative/qmlecmascript/data/scriptAccess.js
new file mode 100644
index 0000000..c00d285
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/scriptAccess.js
@@ -0,0 +1,7 @@
+var extVariable = 19;
+
+function extMethod()
+{
+ return extVariable;
+}
+
diff --git a/tests/auto/declarative/qmlecmascript/data/scriptAccess.qml b/tests/auto/declarative/qmlecmascript/data/scriptAccess.qml
new file mode 100644
index 0000000..feb6d16
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/scriptAccess.qml
@@ -0,0 +1,17 @@
+import Qt 4.6
+
+Item {
+ Script {
+ function method() {
+ return 10;
+ }
+ }
+
+ Script {
+ source: "scriptAccess.js"
+ }
+
+ property int test1: method()
+ property int test2: extMethod()
+ property int test3: extVariable
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/selfDeletingBinding.2.qml b/tests/auto/declarative/qmlecmascript/data/selfDeletingBinding.2.qml
new file mode 100644
index 0000000..58cf805
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/selfDeletingBinding.2.qml
@@ -0,0 +1,17 @@
+import Qt.test 1.0
+
+MyQmlContainer {
+ property bool triggerDelete: false
+
+ children: [
+ MyQmlObject {
+ // Will trigger deletion on binding assignment
+ deleteOnSet: Math.max(0, 1)
+ },
+
+ MyQmlObject {
+ // Will trigger deletion on binding assignment, but after component creation
+ deleteOnSet: if (triggerDelete) 1; else 0;
+ }
+ ]
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/selfDeletingBinding.qml b/tests/auto/declarative/qmlecmascript/data/selfDeletingBinding.qml
new file mode 100644
index 0000000..074851a
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/selfDeletingBinding.qml
@@ -0,0 +1,18 @@
+import Qt.test 1.0
+
+MyQmlContainer {
+ property bool triggerDelete: false
+
+ children: [
+ MyQmlObject {
+ // Will trigger deletion during binding evaluation
+ stringProperty: {deleteMe(), "Hello"}
+ },
+
+ MyQmlObject {
+ // Will trigger deletion during binding evaluation, but after component creation
+ stringProperty: if (triggerDelete) { deleteMe(), "Hello" } else { "World" }
+ }
+
+ ]
+}
diff --git a/tests/auto/declarative/qmlecmascript/data/signalParameterTypes.qml b/tests/auto/declarative/qmlecmascript/data/signalParameterTypes.qml
new file mode 100644
index 0000000..42d26a1
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/signalParameterTypes.qml
@@ -0,0 +1,16 @@
+import Qt.test 1.0
+
+MyQmlObject
+{
+ id: Root
+ property int intProperty
+ property real realProperty
+ property color colorProperty
+ property var variantProperty
+
+ signal mySignal(int a, real b, color c, var d)
+
+ onMySignal: { intProperty = a; realProperty = b; colorProperty = c; variantProperty = d; }
+
+ onBasicSignal: Root.mySignal(10, 19.2, Qt.rgba(1, 1, 0, 1), Qt.rgba(1, 0, 1, 1))
+}
diff --git a/tests/auto/declarative/qmlecmascript/testtypes.h b/tests/auto/declarative/qmlecmascript/testtypes.h
index ffc8fec..e6c2c20 100644
--- a/tests/auto/declarative/qmlecmascript/testtypes.h
+++ b/tests/auto/declarative/qmlecmascript/testtypes.h
@@ -23,6 +23,7 @@ class MyQmlObject : public QObject
Q_OBJECT
Q_ENUMS(MyEnum)
Q_ENUMS(MyEnum2)
+ Q_PROPERTY(int deleteOnSet READ deleteOnSet WRITE setDeleteOnSet);
Q_PROPERTY(bool trueProperty READ trueProperty CONSTANT)
Q_PROPERTY(bool falseProperty READ falseProperty CONSTANT)
Q_PROPERTY(QString stringProperty READ stringProperty WRITE setStringProperty NOTIFY stringChanged)
@@ -61,6 +62,9 @@ public:
static MyQmlAttachedObject *qmlAttachedProperties(QObject *o) {
return new MyQmlAttachedObject(o);
}
+
+ int deleteOnSet() const { return 1; }
+ void setDeleteOnSet(int v) { if(v) delete this; }
signals:
void basicSignal();
void argumentSignal(int a, QString b, qreal c);
@@ -68,6 +72,7 @@ signals:
void objectChanged();
public slots:
+ void deleteMe() { delete this; }
void method() { m_methodCalled = true; }
void method(int a) { if(a == 163) m_methodIntCalled = true; }
void setString(const QString &s) { m_string = s; }
diff --git a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp
index 3f01192..dde3bb7 100644
--- a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp
+++ b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp
@@ -45,15 +45,22 @@ private slots:
void objectPropertiesTriggerReeval();
void deferredProperties();
void extensionObjects();
+ void attachedProperties();
void enums();
void valueTypeFunctions();
void constantsOverrideBindings();
void outerBindingOverridesInnerBinding();
void aliasPropertyAndBinding();
void nonExistantAttachedObject();
+ void scope();
+ void signalParameterTypes();
+ void objectsCompareAsEqual();
+ void scriptAccess();
void dynamicCreation();
void dynamicDestruction();
void objectToString();
+ void selfDeletingBinding();
+ void extendedObjectPropertyLookup();
private:
QmlEngine engine;
@@ -383,6 +390,19 @@ void tst_qmlecmascript::extensionObjects()
QCOMPARE(object->baseProperty(), 92);
}
+void tst_qmlecmascript::attachedProperties()
+{
+ QmlComponent component(&engine, TEST_FILE("attachedProperty.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ QCOMPARE(object->property("a").toInt(), 19);
+ QCOMPARE(object->property("b").toInt(), 19);
+ QCOMPARE(object->property("c").toInt(), 19);
+ QCOMPARE(object->property("d").toInt(), 19);
+
+ // ### Need to test attached property assignment
+}
+
void tst_qmlecmascript::enums()
{
// Existant enums
@@ -515,6 +535,58 @@ void tst_qmlecmascript::nonExistantAttachedObject()
QVERIFY(object != 0);
}
+void tst_qmlecmascript::scope()
+{
+ QmlComponent component(&engine, TEST_FILE("scope.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("test1").toInt(), 1);
+ QCOMPARE(object->property("test2").toInt(), 2);
+ QCOMPARE(object->property("test3").toString(), QString("1Test"));
+ QCOMPARE(object->property("test4").toString(), QString("2Test"));
+ QCOMPARE(object->property("test5").toInt(), 1);
+ QCOMPARE(object->property("test6").toInt(), 1);
+ QCOMPARE(object->property("test7").toInt(), 2);
+ QCOMPARE(object->property("test8").toInt(), 2);
+ QCOMPARE(object->property("test9").toInt(), 1);
+ QCOMPARE(object->property("test10").toInt(), 3);
+}
+
+/*
+Tests that "any" type passes through a synthesized signal parameter. This
+is essentially a test of QmlMetaType::copy()
+*/
+void tst_qmlecmascript::signalParameterTypes()
+{
+ QmlComponent component(&engine, TEST_FILE("signalParameterTypes.qml"));
+ MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+ QVERIFY(object != 0);
+
+ emit object->basicSignal();
+
+ QCOMPARE(object->property("intProperty").toInt(), 10);
+ QCOMPARE(object->property("realProperty").toReal(), 19.2);
+ QVERIFY(object->property("colorProperty").value<QColor>() == QColor(255, 255, 0, 255));
+ QVERIFY(object->property("variantProperty") == QVariant::fromValue(QColor(255, 0, 255, 255)));
+}
+
+/*
+Test that two JS objects for the same QObject compare as equal.
+*/
+void tst_qmlecmascript::objectsCompareAsEqual()
+{
+ QmlComponent component(&engine, TEST_FILE("objectsCompareAsEqual.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("test1").toBool(), true);
+ QCOMPARE(object->property("test2").toBool(), true);
+ QCOMPARE(object->property("test3").toBool(), true);
+ QCOMPARE(object->property("test4").toBool(), true);
+ QCOMPARE(object->property("test5").toBool(), true);
+}
+
/*
Confirm bindings and alias properties can coexist.
@@ -536,8 +608,22 @@ void tst_qmlecmascript::aliasPropertyAndBinding()
}
/*
- Test using createQmlObject to dynamically generate an item
- Also using createComponent is tested.
+Tests that only methods of Script {} blocks are exposed.
+*/
+void tst_qmlecmascript::scriptAccess()
+{
+ QmlComponent component(&engine, TEST_FILE("scriptAccess.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("test1").toInt(), 10);
+ QCOMPARE(object->property("test2").toInt(), 19);
+ QCOMPARE(object->property("test3").toInt(), 0);
+}
+
+/*
+Test using createQmlObject to dynamically generate an item
+Also using createComponent is tested.
*/
void tst_qmlecmascript::dynamicCreation()
{
@@ -576,13 +662,16 @@ void tst_qmlecmascript::dynamicDestruction()
QMetaObject::invokeMethod(object, "killOther");
QVERIFY(createdQmlObject);
QTest::qWait(0);
+ QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
QVERIFY(createdQmlObject);
QTest::qWait(100);
+ QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
QVERIFY(!createdQmlObject);
QMetaObject::invokeMethod(object, "killMe");
QVERIFY(object);
QTest::qWait(0);
+ QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
QVERIFY(!object);
}
@@ -595,7 +684,44 @@ void tst_qmlecmascript::objectToString()
MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
QVERIFY(object != 0);
QMetaObject::invokeMethod(object, "testToString");
- QVERIFY(object->stringProperty().startsWith("Qml Object, \"objName\" MyQmlObject_QML_15"));
+ QVERIFY(object->stringProperty().startsWith("MyQmlObject_QML_"));
+ QVERIFY(object->stringProperty().endsWith(", \"objName\")"));
+}
+
+/*
+Tests bindings that indirectly cause their own deletion work.
+
+This test is best run under valgrind to ensure no invalid memory access occur.
+*/
+void tst_qmlecmascript::selfDeletingBinding()
+{
+ {
+ QmlComponent component(&engine, TEST_FILE("selfDeletingBinding.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ object->setProperty("triggerDelete", true);
+ }
+
+ {
+ QmlComponent component(&engine, TEST_FILE("selfDeletingBinding.2.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ object->setProperty("triggerDelete", true);
+ }
+}
+
+/*
+Test that extended object properties can be accessed.
+
+This test a regression where this used to crash. The issue was specificially
+for extended objects that did not include a synthesized meta object (so non-root
+and no synthesiszed properties).
+*/
+void tst_qmlecmascript::extendedObjectPropertyLookup()
+{
+ QmlComponent component(&engine, TEST_FILE("extendedObjectPropertyLookup.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
}
QTEST_MAIN(tst_qmlecmascript)
diff --git a/tests/auto/declarative/qmllanguage/data/dynamicObjectProperties.qml b/tests/auto/declarative/qmllanguage/data/dynamicObjectProperties.qml
new file mode 100644
index 0000000..e69ccee
--- /dev/null
+++ b/tests/auto/declarative/qmllanguage/data/dynamicObjectProperties.qml
@@ -0,0 +1,13 @@
+import Test 1.0
+import Qt 4.6
+import Qt 4.6 as Qt
+
+Object {
+ property Object objectProperty
+ property Object objectProperty2
+ objectProperty2: Object {}
+
+ property MyComponent myComponentProperty
+ property MyComponent myComponentProperty2
+ myComponentProperty2: MyComponent {}
+}
diff --git a/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp b/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp
index 1bf98df..3825b62 100644
--- a/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp
+++ b/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp
@@ -45,6 +45,7 @@ private slots:
void idProperty();
void assignSignal();
void dynamicProperties();
+ void dynamicObjectProperties();
void dynamicSignalsAndSlots();
void simpleBindings();
void autoComponentCreation();
@@ -404,6 +405,19 @@ void tst_qmllanguage::dynamicProperties()
QCOMPARE(object->property("variantProperty"), QVariant(12));
}
+// Tests the creation and assignment of dynamic object properties
+// ### Not complete
+void tst_qmllanguage::dynamicObjectProperties()
+{
+ QmlComponent component(&engine, TEST_FILE("dynamicObjectProperties.qml"));
+ VERIFY_ERRORS(0);
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QVERIFY(object->property("objectProperty") == qVariantFromValue((QObject*)0));
+ QVERIFY(object->property("objectProperty2") != qVariantFromValue((QObject*)0));
+}
+
// Tests the declaration of dynamic signals and slots
void tst_qmllanguage::dynamicSignalsAndSlots()
{
diff --git a/tools/qmlviewer/qfxtester.cpp b/tools/qmlviewer/qfxtester.cpp
index 8005b0e..0ccc9c0 100644
--- a/tools/qmlviewer/qfxtester.cpp
+++ b/tools/qmlviewer/qfxtester.cpp
@@ -118,12 +118,14 @@ void QFxTester::imagefailure()
void QFxTester::complete()
{
+ if (options & QmlViewer::ExitOnComplete)
+ QApplication::exit(hasFailed?-1:0);
+
if (hasCompleted)
return;
hasCompleted = true;
- if (options & QmlViewer::ExitOnComplete)
- QApplication::exit(hasFailed?-1:0);
- else if (options & QmlViewer::Play)
+
+ if (options & QmlViewer::Play)
qWarning("Script playback complete");
}