summaryrefslogtreecommitdiffstats
path: root/src/declarative/qml
diff options
context:
space:
mode:
Diffstat (limited to 'src/declarative/qml')
-rw-r--r--src/declarative/qml/parser/parser.pri22
-rw-r--r--src/declarative/qml/parser/qmljs.g3069
-rw-r--r--src/declarative/qml/parser/qmljsast.cpp955
-rw-r--r--src/declarative/qml/parser/qmljsast_p.h2677
-rw-r--r--src/declarative/qml/parser/qmljsastfwd_p.h188
-rw-r--r--src/declarative/qml/parser/qmljsastvisitor.cpp58
-rw-r--r--src/declarative/qml/parser/qmljsastvisitor_p.h335
-rw-r--r--src/declarative/qml/parser/qmljsengine_p.cpp210
-rw-r--r--src/declarative/qml/parser/qmljsengine_p.h173
-rw-r--r--src/declarative/qml/parser/qmljsglobal_p.h14
-rw-r--r--src/declarative/qml/parser/qmljsgrammar.cpp960
-rw-r--r--src/declarative/qml/parser/qmljsgrammar_p.h207
-rw-r--r--src/declarative/qml/parser/qmljslexer.cpp1160
-rw-r--r--src/declarative/qml/parser/qmljslexer_p.h249
-rw-r--r--src/declarative/qml/parser/qmljsmemorypool_p.h132
-rw-r--r--src/declarative/qml/parser/qmljsnodepool_p.h139
-rw-r--r--src/declarative/qml/parser/qmljsparser.cpp1825
-rw-r--r--src/declarative/qml/parser/qmljsparser_p.h242
-rw-r--r--src/declarative/qml/qbitfield_p.h165
-rw-r--r--src/declarative/qml/qmetaobjectbuilder.cpp2573
-rw-r--r--src/declarative/qml/qmetaobjectbuilder_p.h321
-rw-r--r--src/declarative/qml/qml.h155
-rw-r--r--src/declarative/qml/qml.pri121
-rw-r--r--src/declarative/qml/qmlbasicscript.cpp763
-rw-r--r--src/declarative/qml/qmlbasicscript_p.h116
-rw-r--r--src/declarative/qml/qmlbinding.cpp251
-rw-r--r--src/declarative/qml/qmlbinding.h127
-rw-r--r--src/declarative/qml/qmlbinding_p.h85
-rw-r--r--src/declarative/qml/qmlbindingoptimizations.cpp205
-rw-r--r--src/declarative/qml/qmlbindingoptimizations_p.h120
-rw-r--r--src/declarative/qml/qmlboundsignal.cpp259
-rw-r--r--src/declarative/qml/qmlboundsignal_p.h96
-rw-r--r--src/declarative/qml/qmlclassfactory.cpp50
-rw-r--r--src/declarative/qml/qmlclassfactory_p.h74
-rw-r--r--src/declarative/qml/qmlcleanup.cpp82
-rw-r--r--src/declarative/qml/qmlcleanup_p.h79
-rw-r--r--src/declarative/qml/qmlcompileddata.cpp209
-rw-r--r--src/declarative/qml/qmlcompiler.cpp2565
-rw-r--r--src/declarative/qml/qmlcompiler_p.h294
-rw-r--r--src/declarative/qml/qmlcomponent.cpp682
-rw-r--r--src/declarative/qml/qmlcomponent.h125
-rw-r--r--src/declarative/qml/qmlcomponent_p.h134
-rw-r--r--src/declarative/qml/qmlcomponentjs.cpp131
-rw-r--r--src/declarative/qml/qmlcomponentjs_p.h98
-rw-r--r--src/declarative/qml/qmlcomponentjs_p_p.h77
-rw-r--r--src/declarative/qml/qmlcompositetypedata_p.h148
-rw-r--r--src/declarative/qml/qmlcompositetypemanager.cpp590
-rw-r--r--src/declarative/qml/qmlcompositetypemanager_p.h115
-rw-r--r--src/declarative/qml/qmlcontext.cpp502
-rw-r--r--src/declarative/qml/qmlcontext.h104
-rw-r--r--src/declarative/qml/qmlcontext_p.h146
-rw-r--r--src/declarative/qml/qmlcontextscriptclass.cpp238
-rw-r--r--src/declarative/qml/qmlcontextscriptclass_p.h101
-rw-r--r--src/declarative/qml/qmlcustomparser.cpp276
-rw-r--r--src/declarative/qml/qmlcustomparser_p.h146
-rw-r--r--src/declarative/qml/qmlcustomparser_p_p.h87
-rw-r--r--src/declarative/qml/qmldeclarativedata_p.h109
-rw-r--r--src/declarative/qml/qmldom.cpp1770
-rw-r--r--src/declarative/qml/qmldom.h325
-rw-r--r--src/declarative/qml/qmldom_p.h150
-rw-r--r--src/declarative/qml/qmlengine.cpp1510
-rw-r--r--src/declarative/qml/qmlengine.h100
-rw-r--r--src/declarative/qml/qmlengine_p.h288
-rw-r--r--src/declarative/qml/qmlenginedebug.cpp401
-rw-r--r--src/declarative/qml/qmlenginedebug_p.h120
-rw-r--r--src/declarative/qml/qmlerror.cpp234
-rw-r--r--src/declarative/qml/qmlerror.h84
-rw-r--r--src/declarative/qml/qmlexpression.cpp686
-rw-r--r--src/declarative/qml/qmlexpression.h111
-rw-r--r--src/declarative/qml/qmlexpression_p.h159
-rw-r--r--src/declarative/qml/qmlglobalscriptclass.cpp94
-rw-r--r--src/declarative/qml/qmlglobalscriptclass_p.h81
-rw-r--r--src/declarative/qml/qmlinfo.cpp102
-rw-r--r--src/declarative/qml/qmlinfo.h59
-rw-r--r--src/declarative/qml/qmlinstruction.cpp200
-rw-r--r--src/declarative/qml/qmlinstruction_p.h323
-rw-r--r--src/declarative/qml/qmlintegercache.cpp114
-rw-r--r--src/declarative/qml/qmlintegercache_p.h111
-rw-r--r--src/declarative/qml/qmllist.h126
-rw-r--r--src/declarative/qml/qmllistscriptclass.cpp141
-rw-r--r--src/declarative/qml/qmllistscriptclass_p.h85
-rw-r--r--src/declarative/qml/qmlmetaproperty.cpp1254
-rw-r--r--src/declarative/qml/qmlmetaproperty.h151
-rw-r--r--src/declarative/qml/qmlmetaproperty_p.h116
-rw-r--r--src/declarative/qml/qmlmetatype.cpp1399
-rw-r--r--src/declarative/qml/qmlmetatype.h309
-rw-r--r--src/declarative/qml/qmlobjectscriptclass.cpp330
-rw-r--r--src/declarative/qml/qmlobjectscriptclass_p.h113
-rw-r--r--src/declarative/qml/qmlparser.cpp424
-rw-r--r--src/declarative/qml/qmlparser_p.h356
-rw-r--r--src/declarative/qml/qmlparserstatus.cpp80
-rw-r--r--src/declarative/qml/qmlparserstatus.h75
-rw-r--r--src/declarative/qml/qmlprivate.cpp48
-rw-r--r--src/declarative/qml/qmlprivate.h416
-rw-r--r--src/declarative/qml/qmlpropertycache.cpp223
-rw-r--r--src/declarative/qml/qmlpropertycache_p.h156
-rw-r--r--src/declarative/qml/qmlpropertyvalueinterceptor.cpp78
-rw-r--r--src/declarative/qml/qmlpropertyvalueinterceptor.h68
-rw-r--r--src/declarative/qml/qmlpropertyvaluesource.cpp70
-rw-r--r--src/declarative/qml/qmlpropertyvaluesource.h67
-rw-r--r--src/declarative/qml/qmlproxymetaobject.cpp138
-rw-r--r--src/declarative/qml/qmlproxymetaobject_p.h98
-rw-r--r--src/declarative/qml/qmlrefcount.cpp70
-rw-r--r--src/declarative/qml/qmlrefcount_p.h80
-rw-r--r--src/declarative/qml/qmlrewrite.cpp191
-rw-r--r--src/declarative/qml/qmlrewrite_p.h110
-rw-r--r--src/declarative/qml/qmlscript.cpp82
-rw-r--r--src/declarative/qml/qmlscriptparser.cpp941
-rw-r--r--src/declarative/qml/qmlscriptparser_p.h136
-rw-r--r--src/declarative/qml/qmlscriptstring.cpp154
-rw-r--r--src/declarative/qml/qmlscriptstring.h87
-rw-r--r--src/declarative/qml/qmlsqldatabase.cpp369
-rw-r--r--src/declarative/qml/qmlsqldatabase_p.h60
-rw-r--r--src/declarative/qml/qmlstringconverters.cpp241
-rw-r--r--src/declarative/qml/qmlstringconverters_p.h81
-rw-r--r--src/declarative/qml/qmltypenamecache.cpp102
-rw-r--r--src/declarative/qml/qmltypenamecache_p.h116
-rw-r--r--src/declarative/qml/qmltypenamescriptclass.cpp163
-rw-r--r--src/declarative/qml/qmltypenamescriptclass_p.h91
-rw-r--r--src/declarative/qml/qmlvaluetype.cpp569
-rw-r--r--src/declarative/qml/qmlvaluetype_p.h300
-rw-r--r--src/declarative/qml/qmlvaluetypescriptclass.cpp151
-rw-r--r--src/declarative/qml/qmlvaluetypescriptclass_p.h89
-rw-r--r--src/declarative/qml/qmlvme.cpp905
-rw-r--r--src/declarative/qml/qmlvme_p.h90
-rw-r--r--src/declarative/qml/qmlvmemetaobject.cpp311
-rw-r--r--src/declarative/qml/qmlvmemetaobject_p.h161
-rw-r--r--src/declarative/qml/qmlwatcher.cpp183
-rw-r--r--src/declarative/qml/qmlwatcher_p.h93
-rw-r--r--src/declarative/qml/qmlxmlhttprequest.cpp1463
-rw-r--r--src/declarative/qml/qmlxmlhttprequest_p.h60
-rw-r--r--src/declarative/qml/qpodvector_p.h147
-rw-r--r--src/declarative/qml/rewriter/rewriter.cpp101
-rw-r--r--src/declarative/qml/rewriter/rewriter.pri11
-rw-r--r--src/declarative/qml/rewriter/rewriter_p.h152
-rw-r--r--src/declarative/qml/rewriter/textwriter.cpp217
-rw-r--r--src/declarative/qml/rewriter/textwriter_p.h101
137 files changed, 46655 insertions, 0 deletions
diff --git a/src/declarative/qml/parser/parser.pri b/src/declarative/qml/parser/parser.pri
new file mode 100644
index 0000000..986b146
--- /dev/null
+++ b/src/declarative/qml/parser/parser.pri
@@ -0,0 +1,22 @@
+
+INCLUDEPATH += $$PWD
+DEPENDPATH += $$PWD
+
+HEADERS += $$PWD/qmljsast_p.h \
+ $$PWD/qmljsastfwd_p.h \
+ $$PWD/qmljsastvisitor_p.h \
+ $$PWD/qmljsengine_p.h \
+ $$PWD/qmljsgrammar_p.h \
+ $$PWD/qmljslexer_p.h \
+ $$PWD/qmljsmemorypool_p.h \
+ $$PWD/qmljsnodepool_p.h \
+ $$PWD/qmljsparser_p.h \
+ $$PWD/qmljsglobal_p.h
+
+SOURCES += $$PWD/qmljsast.cpp \
+ $$PWD/qmljsastvisitor.cpp \
+ $$PWD/qmljsengine_p.cpp \
+ $$PWD/qmljsgrammar.cpp \
+ $$PWD/qmljslexer.cpp \
+ $$PWD/qmljsparser.cpp
+
diff --git a/src/declarative/qml/parser/qmljs.g b/src/declarative/qml/parser/qmljs.g
new file mode 100644
index 0000000..eb9a8ab
--- /dev/null
+++ b/src/declarative/qml/parser/qmljs.g
@@ -0,0 +1,3069 @@
+----------------------------------------------------------------------------
+--
+-- 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 file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+-- WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+--
+----------------------------------------------------------------------------
+
+%parser QmlJSGrammar
+%decl qmljsparser_p.h
+%impl qmljsparser.cpp
+%expect 2
+%expect-rr 2
+
+%token T_AND "&" T_AND_AND "&&" T_AND_EQ "&="
+%token T_BREAK "break" T_CASE "case" T_CATCH "catch"
+%token T_COLON ":" T_COMMA ";" T_CONTINUE "continue"
+%token T_DEFAULT "default" T_DELETE "delete" T_DIVIDE_ "/"
+%token T_DIVIDE_EQ "/=" T_DO "do" T_DOT "."
+%token T_ELSE "else" T_EQ "=" T_EQ_EQ "=="
+%token T_EQ_EQ_EQ "===" T_FINALLY "finally" T_FOR "for"
+%token T_FUNCTION "function" T_GE ">=" T_GT ">"
+%token T_GT_GT ">>" T_GT_GT_EQ ">>=" T_GT_GT_GT ">>>"
+%token T_GT_GT_GT_EQ ">>>=" T_IDENTIFIER "identifier" T_IF "if"
+%token T_IN "in" T_INSTANCEOF "instanceof" T_LBRACE "{"
+%token T_LBRACKET "[" T_LE "<=" T_LPAREN "("
+%token T_LT "<" T_LT_LT "<<" T_LT_LT_EQ "<<="
+%token T_MINUS "-" T_MINUS_EQ "-=" T_MINUS_MINUS "--"
+%token T_NEW "new" T_NOT "!" T_NOT_EQ "!="
+%token T_NOT_EQ_EQ "!==" T_NUMERIC_LITERAL "numeric literal" T_OR "|"
+%token T_OR_EQ "|=" T_OR_OR "||" T_PLUS "+"
+%token T_PLUS_EQ "+=" T_PLUS_PLUS "++" T_QUESTION "?"
+%token T_RBRACE "}" T_RBRACKET "]" T_REMAINDER "%"
+%token T_REMAINDER_EQ "%=" T_RETURN "return" T_RPAREN ")"
+%token T_SEMICOLON ";" T_AUTOMATIC_SEMICOLON T_STAR "*"
+%token T_STAR_EQ "*=" T_STRING_LITERAL "string literal"
+%token T_PROPERTY "property" T_SIGNAL "signal" T_READONLY "readonly"
+%token T_SWITCH "switch" T_THIS "this" T_THROW "throw"
+%token T_TILDE "~" T_TRY "try" T_TYPEOF "typeof"
+%token T_VAR "var" T_VOID "void" T_WHILE "while"
+%token T_WITH "with" T_XOR "^" T_XOR_EQ "^="
+%token T_NULL "null" T_TRUE "true" T_FALSE "false"
+%token T_CONST "const"
+%token T_DEBUGGER "debugger"
+%token T_RESERVED_WORD "reserved word"
+%token T_MULTILINE_STRING_LITERAL "multiline string literal"
+%token T_COMMENT "comment"
+
+--- context keywords.
+%token T_PUBLIC "public"
+%token T_IMPORT "import"
+%token T_AS "as"
+
+--- feed tokens
+%token T_FEED_UI_PROGRAM
+%token T_FEED_UI_OBJECT_MEMBER
+%token T_FEED_JS_STATEMENT
+%token T_FEED_JS_EXPRESSION
+
+%nonassoc SHIFT_THERE
+%nonassoc T_IDENTIFIER T_COLON T_SIGNAL T_PROPERTY T_READONLY
+%nonassoc REDUCE_HERE
+
+%start TopLevel
+
+/.
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 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 <QtCore/QtDebug>
+#include <QtGui/QApplication>
+
+#include <string.h>
+
+#include "qmljsengine_p.h"
+#include "qmljslexer_p.h"
+#include "qmljsast_p.h"
+#include "qmljsnodepool_p.h"
+
+./
+
+/:
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 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$
+**
+****************************************************************************/
+
+//
+// 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.
+//
+
+//
+// This file is automatically generated from qmljs.g.
+// Changes will be lost.
+//
+
+#ifndef QMLJSPARSER_P_H
+#define QMLJSPARSER_P_H
+
+#include "qmljsglobal_p.h"
+#include "qmljsgrammar_p.h"
+#include "qmljsast_p.h"
+#include "qmljsengine_p.h"
+
+#include <QtCore/QList>
+#include <QtCore/QString>
+
+QT_QML_BEGIN_NAMESPACE
+
+namespace QmlJS {
+
+class Engine;
+class NameId;
+
+class Parser: protected $table
+{
+public:
+ union Value {
+ int ival;
+ double dval;
+ NameId *sval;
+ AST::ArgumentList *ArgumentList;
+ AST::CaseBlock *CaseBlock;
+ AST::CaseClause *CaseClause;
+ AST::CaseClauses *CaseClauses;
+ AST::Catch *Catch;
+ AST::DefaultClause *DefaultClause;
+ AST::ElementList *ElementList;
+ AST::Elision *Elision;
+ AST::ExpressionNode *Expression;
+ AST::Finally *Finally;
+ AST::FormalParameterList *FormalParameterList;
+ AST::FunctionBody *FunctionBody;
+ AST::FunctionDeclaration *FunctionDeclaration;
+ AST::Node *Node;
+ AST::PropertyName *PropertyName;
+ AST::PropertyNameAndValueList *PropertyNameAndValueList;
+ AST::SourceElement *SourceElement;
+ AST::SourceElements *SourceElements;
+ AST::Statement *Statement;
+ AST::StatementList *StatementList;
+ AST::Block *Block;
+ AST::VariableDeclaration *VariableDeclaration;
+ AST::VariableDeclarationList *VariableDeclarationList;
+
+ AST::UiProgram *UiProgram;
+ AST::UiImportList *UiImportList;
+ AST::UiImport *UiImport;
+ AST::UiParameterList *UiParameterList;
+ AST::UiPublicMember *UiPublicMember;
+ AST::UiObjectDefinition *UiObjectDefinition;
+ AST::UiObjectInitializer *UiObjectInitializer;
+ AST::UiObjectBinding *UiObjectBinding;
+ AST::UiScriptBinding *UiScriptBinding;
+ AST::UiArrayBinding *UiArrayBinding;
+ AST::UiObjectMember *UiObjectMember;
+ AST::UiObjectMemberList *UiObjectMemberList;
+ AST::UiArrayMemberList *UiArrayMemberList;
+ AST::UiQualifiedId *UiQualifiedId;
+ AST::UiSignature *UiSignature;
+ AST::UiFormalList *UiFormalList;
+ AST::UiFormal *UiFormal;
+ };
+
+public:
+ Parser(Engine *engine);
+ ~Parser();
+
+ // parse a UI program
+ bool parse() { return parse(T_FEED_UI_PROGRAM); }
+ bool parseStatement() { return parse(T_FEED_JS_STATEMENT); }
+ bool parseExpression() { return parse(T_FEED_JS_EXPRESSION); }
+ bool parseUiObjectMember() { return parse(T_FEED_UI_OBJECT_MEMBER); }
+
+ AST::UiProgram *ast() const
+ { return AST::cast<AST::UiProgram *>(program); }
+
+ AST::Statement *statement() const
+ {
+ if (! program)
+ return 0;
+
+ return program->statementCast();
+ }
+
+ AST::ExpressionNode *expression() const
+ {
+ if (! program)
+ return 0;
+
+ return program->expressionCast();
+ }
+
+ AST::UiObjectMember *uiObjectMember() const
+ {
+ if (! program)
+ return 0;
+
+ return program->uiObjectMemberCast();
+ }
+
+ QList<DiagnosticMessage> diagnosticMessages() const
+ { return diagnostic_messages; }
+
+ inline DiagnosticMessage diagnosticMessage() const
+ {
+ foreach (const DiagnosticMessage &d, diagnostic_messages) {
+ if (! d.kind == DiagnosticMessage::Warning)
+ return d;
+ }
+
+ return DiagnosticMessage();
+ }
+
+ inline QString errorMessage() const
+ { return diagnosticMessage().message; }
+
+ inline int errorLineNumber() const
+ { return diagnosticMessage().loc.startLine; }
+
+ inline int errorColumnNumber() const
+ { return diagnosticMessage().loc.startColumn; }
+
+protected:
+ bool parse(int startToken);
+
+ void reallocateStack();
+
+ inline Value &sym(int index)
+ { return sym_stack [tos + index - 1]; }
+
+ inline AST::SourceLocation &loc(int index)
+ { return location_stack [tos + index - 1]; }
+
+ AST::UiQualifiedId *reparseAsQualifiedId(AST::ExpressionNode *expr);
+
+protected:
+ Engine *driver;
+ int tos;
+ int stack_size;
+ Value *sym_stack;
+ int *state_stack;
+ AST::SourceLocation *location_stack;
+
+ AST::Node *program;
+
+ // error recovery
+ enum { TOKEN_BUFFER_SIZE = 3 };
+
+ struct SavedToken {
+ int token;
+ double dval;
+ AST::SourceLocation loc;
+ };
+
+ double yylval;
+ AST::SourceLocation yylloc;
+ AST::SourceLocation yyprevlloc;
+
+ SavedToken token_buffer[TOKEN_BUFFER_SIZE];
+ SavedToken *first_token;
+ SavedToken *last_token;
+
+ QList<DiagnosticMessage> diagnostic_messages;
+};
+
+} // end of namespace QmlJS
+
+
+:/
+
+
+/.
+
+#include "qmljsparser_p.h"
+#include <QVarLengthArray>
+
+//
+// This file is automatically generated from qmljs.g.
+// Changes will be lost.
+//
+
+using namespace QmlJS;
+
+QT_QML_BEGIN_NAMESPACE
+
+void Parser::reallocateStack()
+{
+ if (! stack_size)
+ stack_size = 128;
+ else
+ stack_size <<= 1;
+
+ sym_stack = reinterpret_cast<Value*> (qRealloc(sym_stack, stack_size * sizeof(Value)));
+ state_stack = reinterpret_cast<int*> (qRealloc(state_stack, stack_size * sizeof(int)));
+ location_stack = reinterpret_cast<AST::SourceLocation*> (qRealloc(location_stack, stack_size * sizeof(AST::SourceLocation)));
+}
+
+inline static bool automatic(Engine *driver, int token)
+{
+ return token == $table::T_RBRACE
+ || token == 0
+ || driver->lexer()->prevTerminator();
+}
+
+
+Parser::Parser(Engine *engine):
+ driver(engine),
+ tos(0),
+ stack_size(0),
+ sym_stack(0),
+ state_stack(0),
+ location_stack(0),
+ first_token(0),
+ last_token(0)
+{
+}
+
+Parser::~Parser()
+{
+ if (stack_size) {
+ qFree(sym_stack);
+ qFree(state_stack);
+ qFree(location_stack);
+ }
+}
+
+static inline AST::SourceLocation location(Lexer *lexer)
+{
+ AST::SourceLocation loc;
+ loc.offset = lexer->tokenOffset();
+ loc.length = lexer->tokenLength();
+ loc.startLine = lexer->startLineNo();
+ loc.startColumn = lexer->startColumnNo();
+ return loc;
+}
+
+AST::UiQualifiedId *Parser::reparseAsQualifiedId(AST::ExpressionNode *expr)
+{
+ QVarLengthArray<NameId *, 4> nameIds;
+ QVarLengthArray<AST::SourceLocation, 4> locations;
+
+ AST::ExpressionNode *it = expr;
+ while (AST::FieldMemberExpression *m = AST::cast<AST::FieldMemberExpression *>(it)) {
+ nameIds.append(m->name);
+ locations.append(m->identifierToken);
+ it = m->base;
+ }
+
+ if (AST::IdentifierExpression *idExpr = AST::cast<AST::IdentifierExpression *>(it)) {
+ AST::UiQualifiedId *q = makeAstNode<AST::UiQualifiedId>(driver->nodePool(), idExpr->name);
+ q->identifierToken = idExpr->identifierToken;
+
+ AST::UiQualifiedId *currentId = q;
+ for (int i = nameIds.size() - 1; i != -1; --i) {
+ currentId = makeAstNode<AST::UiQualifiedId>(driver->nodePool(), currentId, nameIds[i]);
+ currentId->identifierToken = locations[i];
+ }
+
+ return currentId->finish();
+ }
+
+ return 0;
+}
+
+bool Parser::parse(int startToken)
+{
+ Lexer *lexer = driver->lexer();
+ bool hadErrors = false;
+ int yytoken = -1;
+ int action = 0;
+
+ token_buffer[0].token = startToken;
+ first_token = &token_buffer[0];
+ last_token = &token_buffer[1];
+
+ tos = -1;
+ program = 0;
+
+ do {
+ if (++tos == stack_size)
+ reallocateStack();
+
+ state_stack[tos] = action;
+
+ _Lcheck_token:
+ if (yytoken == -1 && -TERMINAL_COUNT != action_index[action]) {
+ yyprevlloc = yylloc;
+
+ if (first_token == last_token) {
+ yytoken = lexer->lex();
+ yylval = lexer->dval();
+ yylloc = location(lexer);
+ } else {
+ yytoken = first_token->token;
+ yylval = first_token->dval;
+ yylloc = first_token->loc;
+ ++first_token;
+ }
+ }
+
+ action = t_action(action, yytoken);
+ if (action > 0) {
+ if (action != ACCEPT_STATE) {
+ yytoken = -1;
+ sym(1).dval = yylval;
+ loc(1) = yylloc;
+ } else {
+ --tos;
+ return ! hadErrors;
+ }
+ } else if (action < 0) {
+ const int r = -action - 1;
+ tos -= rhs[r];
+
+ switch (r) {
+./
+
+--------------------------------------------------------------------------------------------------------
+-- Declarative UI
+--------------------------------------------------------------------------------------------------------
+
+TopLevel: T_FEED_UI_PROGRAM UiProgram ;
+/.
+case $rule_number: {
+ sym(1).Node = sym(2).Node;
+ program = sym(1).Node;
+} break;
+./
+
+TopLevel: T_FEED_JS_STATEMENT Statement ;
+/.
+case $rule_number: {
+ sym(1).Node = sym(2).Node;
+ program = sym(1).Node;
+} break;
+./
+
+TopLevel: T_FEED_JS_EXPRESSION Expression ;
+/.
+case $rule_number: {
+ sym(1).Node = sym(2).Node;
+ program = sym(1).Node;
+} break;
+./
+
+TopLevel: T_FEED_UI_OBJECT_MEMBER UiObjectMember ;
+/.
+case $rule_number: {
+ sym(1).Node = sym(2).Node;
+ program = sym(1).Node;
+} break;
+./
+
+UiProgram: UiImportListOpt UiRootMember ;
+/.
+case $rule_number: {
+ sym(1).UiProgram = makeAstNode<AST::UiProgram> (driver->nodePool(), sym(1).UiImportList,
+ sym(2).UiObjectMemberList->finish());
+} break;
+./
+
+UiImportListOpt: Empty ;
+UiImportListOpt: UiImportList ;
+/.
+case $rule_number: {
+ sym(1).Node = sym(1).UiImportList->finish();
+} break;
+./
+
+UiImportList: UiImport ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::UiImportList> (driver->nodePool(), sym(1).UiImport);
+} break;
+./
+
+UiImportList: UiImportList UiImport ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::UiImportList> (driver->nodePool(),
+ sym(1).UiImportList, sym(2).UiImport);
+} break;
+./
+
+ImportId: MemberExpression ;
+
+UiImport: UiImportHead T_AUTOMATIC_SEMICOLON ;
+UiImport: UiImportHead T_SEMICOLON ;
+/.
+case $rule_number: {
+ sym(1).UiImport->semicolonToken = loc(2);
+} break;
+./
+
+UiImport: UiImportHead T_NUMERIC_LITERAL T_AUTOMATIC_SEMICOLON ;
+UiImport: UiImportHead T_NUMERIC_LITERAL T_SEMICOLON ;
+/.
+case $rule_number: {
+ sym(1).UiImport->versionToken = loc(2);
+ sym(1).UiImport->semicolonToken = loc(3);
+} break;
+./
+
+UiImport: UiImportHead T_NUMERIC_LITERAL T_AS JsIdentifier T_AUTOMATIC_SEMICOLON ;
+UiImport: UiImportHead T_NUMERIC_LITERAL T_AS JsIdentifier T_SEMICOLON ;
+/.
+case $rule_number: {
+ sym(1).UiImport->versionToken = loc(2);
+ sym(1).UiImport->asToken = loc(3);
+ sym(1).UiImport->importIdToken = loc(4);
+ sym(1).UiImport->importId = sym(4).sval;
+ sym(1).UiImport->semicolonToken = loc(5);
+} break;
+./
+
+UiImport: UiImportHead T_AS JsIdentifier T_AUTOMATIC_SEMICOLON ;
+UiImport: UiImportHead T_AS JsIdentifier T_SEMICOLON ;
+/.
+case $rule_number: {
+ sym(1).UiImport->asToken = loc(2);
+ sym(1).UiImport->importIdToken = loc(3);
+ sym(1).UiImport->importId = sym(3).sval;
+ sym(1).UiImport->semicolonToken = loc(4);
+} break;
+./
+
+
+UiImportHead: T_IMPORT ImportId ;
+/.
+case $rule_number: {
+ AST::UiImport *node = 0;
+
+ if (AST::StringLiteral *importIdLiteral = AST::cast<AST::StringLiteral *>(sym(2).Expression)) {
+ node = makeAstNode<AST::UiImport>(driver->nodePool(), importIdLiteral->value);
+ node->fileNameToken = loc(2);
+ } else if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(2).Expression)) {
+ QString text;
+ for (AST::UiQualifiedId *q = qualifiedId; q; q = q->next) {
+ text += q->name->asString();
+ if (q->next) text += QLatin1String(".");
+ }
+ node = makeAstNode<AST::UiImport>(driver->nodePool(), qualifiedId);
+ node->fileNameToken = loc(2);
+ }
+
+ sym(1).Node = node;
+
+ if (! node) {
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1),
+ QLatin1String("Expected a qualified name id or a string literal")));
+
+ return false; // ### remove me
+ }
+} break;
+./
+
+Empty: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+UiRootMember: UiObjectDefinition ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::UiObjectMemberList> (driver->nodePool(), sym(1).UiObjectMember);
+} break;
+./
+
+UiObjectMemberList: UiObjectMember ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::UiObjectMemberList> (driver->nodePool(), sym(1).UiObjectMember);
+} break;
+./
+
+UiObjectMemberList: UiObjectMemberList UiObjectMember ;
+/.
+case $rule_number: {
+ AST::UiObjectMemberList *node = makeAstNode<AST:: UiObjectMemberList> (driver->nodePool(),
+ sym(1).UiObjectMemberList, sym(2).UiObjectMember);
+ sym(1).Node = node;
+} break;
+./
+
+UiArrayMemberList: UiObjectDefinition ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::UiArrayMemberList> (driver->nodePool(), sym(1).UiObjectMember);
+} break;
+./
+
+UiArrayMemberList: UiArrayMemberList T_COMMA UiObjectDefinition ;
+/.
+case $rule_number: {
+ AST::UiArrayMemberList *node = makeAstNode<AST::UiArrayMemberList> (driver->nodePool(),
+ sym(1).UiArrayMemberList, sym(3).UiObjectMember);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectInitializer: T_LBRACE T_RBRACE ;
+/.
+case $rule_number: {
+ AST::UiObjectInitializer *node = makeAstNode<AST::UiObjectInitializer> (driver->nodePool(), (AST::UiObjectMemberList*)0);
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectInitializer: T_LBRACE UiObjectMemberList T_RBRACE ;
+/.
+case $rule_number: {
+ AST::UiObjectInitializer *node = makeAstNode<AST::UiObjectInitializer> (driver->nodePool(), sym(2).UiObjectMemberList->finish());
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectDefinition: UiQualifiedId UiObjectInitializer ;
+/.
+case $rule_number: {
+ AST::UiObjectDefinition *node = makeAstNode<AST::UiObjectDefinition> (driver->nodePool(), sym(1).UiQualifiedId,
+ sym(2).UiObjectInitializer);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectMember: UiObjectDefinition ;
+
+UiObjectMember: UiQualifiedId T_COLON T_LBRACKET UiArrayMemberList T_RBRACKET ;
+/.
+case $rule_number: {
+ AST::UiArrayBinding *node = makeAstNode<AST::UiArrayBinding> (driver->nodePool(),
+ sym(1).UiQualifiedId, sym(4).UiArrayMemberList->finish());
+ node->colonToken = loc(2);
+ node->lbracketToken = loc(3);
+ node->rbracketToken = loc(5);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectMember: UiQualifiedId T_COLON UiQualifiedId UiObjectInitializer ;
+/.
+case $rule_number: {
+ AST::UiObjectBinding *node = makeAstNode<AST::UiObjectBinding> (driver->nodePool(),
+ sym(1).UiQualifiedId, sym(3).UiQualifiedId, sym(4).UiObjectInitializer);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectMember: UiQualifiedId T_COLON Block ;
+/.case $rule_number:./
+
+UiObjectMember: UiQualifiedId T_COLON EmptyStatement ;
+/.case $rule_number:./
+
+UiObjectMember: UiQualifiedId T_COLON ExpressionStatement ;
+/.case $rule_number:./
+
+UiObjectMember: UiQualifiedId T_COLON IfStatement ; --- ### do we really want if statement in a binding?
+/.case $rule_number:./
+
+/.
+{
+ AST::UiScriptBinding *node = makeAstNode<AST::UiScriptBinding> (driver->nodePool(),
+ sym(1).UiQualifiedId, sym(3).Statement);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+UiPropertyType: T_VAR ;
+/.
+case $rule_number:
+./
+UiPropertyType: T_RESERVED_WORD ;
+/.
+case $rule_number: {
+ sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount());
+ break;
+}
+./
+
+UiPropertyType: T_IDENTIFIER ;
+
+UiParameterListOpt: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+UiParameterListOpt: UiParameterList ;
+/.
+case $rule_number: {
+ sym(1).Node = sym(1).UiParameterList->finish ();
+} break;
+./
+
+UiParameterList: UiPropertyType JsIdentifier ;
+/.
+case $rule_number: {
+ AST::UiParameterList *node = makeAstNode<AST::UiParameterList> (driver->nodePool(), sym(1).sval, sym(2).sval);
+ node->identifierToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+UiParameterList: UiParameterList T_COMMA UiPropertyType JsIdentifier ;
+/.
+case $rule_number: {
+ AST::UiParameterList *node = makeAstNode<AST::UiParameterList> (driver->nodePool(), sym(1).UiParameterList, sym(3).sval, sym(4).sval);
+ node->commaToken = loc(2);
+ node->identifierToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectMember: T_SIGNAL T_IDENTIFIER T_LPAREN UiParameterListOpt T_RPAREN T_AUTOMATIC_SEMICOLON ;
+UiObjectMember: T_SIGNAL T_IDENTIFIER T_LPAREN UiParameterListOpt T_RPAREN T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), (NameId *)0, sym(2).sval);
+ node->type = AST::UiPublicMember::Signal;
+ node->propertyToken = loc(1);
+ node->typeToken = loc(2);
+ node->identifierToken = loc(2);
+ node->parameters = sym(4).UiParameterList;
+ node->semicolonToken = loc(6);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectMember: T_SIGNAL T_IDENTIFIER T_AUTOMATIC_SEMICOLON ;
+UiObjectMember: T_SIGNAL T_IDENTIFIER T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), (NameId *)0, sym(2).sval);
+ node->type = AST::UiPublicMember::Signal;
+ node->propertyToken = loc(1);
+ node->typeToken = loc(2);
+ node->identifierToken = loc(2);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectMember: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT T_IDENTIFIER T_AUTOMATIC_SEMICOLON ;
+UiObjectMember: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT T_IDENTIFIER T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(4).sval, sym(6).sval);
+ node->typeModifier = sym(2).sval;
+ node->propertyToken = loc(1);
+ node->typeModifierToken = loc(2);
+ node->typeToken = loc(4);
+ node->identifierToken = loc(6);
+ node->semicolonToken = loc(7);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectMember: T_PROPERTY UiPropertyType T_IDENTIFIER T_AUTOMATIC_SEMICOLON ;
+UiObjectMember: T_PROPERTY UiPropertyType T_IDENTIFIER T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(2).sval, sym(3).sval);
+ node->propertyToken = loc(1);
+ node->typeToken = loc(2);
+ node->identifierToken = loc(3);
+ node->semicolonToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType T_IDENTIFIER T_AUTOMATIC_SEMICOLON ;
+UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType T_IDENTIFIER T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(3).sval, sym(4).sval);
+ node->isDefaultMember = true;
+ node->defaultToken = loc(1);
+ node->propertyToken = loc(2);
+ node->typeToken = loc(3);
+ node->identifierToken = loc(4);
+ node->semicolonToken = loc(5);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectMember: T_PROPERTY UiPropertyType T_IDENTIFIER T_COLON Expression T_AUTOMATIC_SEMICOLON ;
+UiObjectMember: T_PROPERTY UiPropertyType T_IDENTIFIER T_COLON Expression T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(2).sval, sym(3).sval,
+ sym(5).Expression);
+ node->propertyToken = loc(1);
+ node->typeToken = loc(2);
+ node->identifierToken = loc(3);
+ node->colonToken = loc(4);
+ node->semicolonToken = loc(6);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectMember: T_READONLY T_PROPERTY UiPropertyType T_IDENTIFIER T_COLON Expression T_AUTOMATIC_SEMICOLON ;
+UiObjectMember: T_READONLY T_PROPERTY UiPropertyType T_IDENTIFIER T_COLON Expression T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(3).sval, sym(4).sval,
+ sym(6).Expression);
+ node->isReadonlyMember = true;
+ node->readonlyToken = loc(1);
+ node->propertyToken = loc(2);
+ node->typeToken = loc(3);
+ node->identifierToken = loc(4);
+ node->colonToken = loc(5);
+ node->semicolonToken = loc(7);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType T_IDENTIFIER T_COLON Expression T_AUTOMATIC_SEMICOLON ;
+UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType T_IDENTIFIER T_COLON Expression T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(3).sval, sym(4).sval,
+ sym(6).Expression);
+ node->isDefaultMember = true;
+ node->defaultToken = loc(1);
+ node->propertyToken = loc(2);
+ node->typeToken = loc(3);
+ node->identifierToken = loc(4);
+ node->colonToken = loc(5);
+ node->semicolonToken = loc(7);
+ sym(1).Node = node;
+} break;
+./
+
+UiObjectMember: FunctionDeclaration ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::UiSourceElement>(driver->nodePool(), sym(1).Node);
+} break;
+./
+
+UiObjectMember: VariableStatement ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::UiSourceElement>(driver->nodePool(), sym(1).Node);
+} break;
+./
+
+JsIdentifier: T_IDENTIFIER;
+
+JsIdentifier: T_PROPERTY ;
+/.
+case $rule_number: {
+ QString s = QLatin1String(QmlJSGrammar::spell[T_PROPERTY]);
+ sym(1).sval = driver->intern(s.constData(), s.length());
+ break;
+}
+./
+
+JsIdentifier: T_SIGNAL ;
+/.
+case $rule_number: {
+ QString s = QLatin1String(QmlJSGrammar::spell[T_SIGNAL]);
+ sym(1).sval = driver->intern(s.constData(), s.length());
+ break;
+}
+./
+
+JsIdentifier: T_READONLY ;
+/.
+case $rule_number: {
+ QString s = QLatin1String(QmlJSGrammar::spell[T_READONLY]);
+ sym(1).sval = driver->intern(s.constData(), s.length());
+ break;
+}
+./
+
+--------------------------------------------------------------------------------------------------------
+-- Expressions
+--------------------------------------------------------------------------------------------------------
+
+PrimaryExpression: T_THIS ;
+/.
+case $rule_number: {
+ AST::ThisExpression *node = makeAstNode<AST::ThisExpression> (driver->nodePool());
+ node->thisToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: JsIdentifier ;
+/.
+case $rule_number: {
+ AST::IdentifierExpression *node = makeAstNode<AST::IdentifierExpression> (driver->nodePool(), sym(1).sval);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_NULL ;
+/.
+case $rule_number: {
+ AST::NullExpression *node = makeAstNode<AST::NullExpression> (driver->nodePool());
+ node->nullToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_TRUE ;
+/.
+case $rule_number: {
+ AST::TrueLiteral *node = makeAstNode<AST::TrueLiteral> (driver->nodePool());
+ node->trueToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_FALSE ;
+/.
+case $rule_number: {
+ AST::FalseLiteral *node = makeAstNode<AST::FalseLiteral> (driver->nodePool());
+ node->falseToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_NUMERIC_LITERAL ;
+/.
+case $rule_number: {
+ AST::NumericLiteral *node = makeAstNode<AST::NumericLiteral> (driver->nodePool(), sym(1).dval);
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_MULTILINE_STRING_LITERAL ;
+/.case $rule_number:./
+
+PrimaryExpression: T_STRING_LITERAL ;
+/.
+case $rule_number: {
+ AST::StringLiteral *node = makeAstNode<AST::StringLiteral> (driver->nodePool(), sym(1).sval);
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_DIVIDE_ ;
+/:
+#define J_SCRIPT_REGEXPLITERAL_RULE1 $rule_number
+:/
+/.
+case $rule_number: {
+ bool rx = lexer->scanRegExp(Lexer::NoPrefix);
+ if (!rx) {
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage()));
+ return false; // ### remove me
+ }
+ AST::RegExpLiteral *node = makeAstNode<AST::RegExpLiteral> (driver->nodePool(), lexer->pattern, lexer->flags);
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_DIVIDE_EQ ;
+/:
+#define J_SCRIPT_REGEXPLITERAL_RULE2 $rule_number
+:/
+/.
+case $rule_number: {
+ bool rx = lexer->scanRegExp(Lexer::EqualPrefix);
+ if (!rx) {
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage()));
+ return false;
+ }
+ AST::RegExpLiteral *node = makeAstNode<AST::RegExpLiteral> (driver->nodePool(), lexer->pattern, lexer->flags);
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_LBRACKET T_RBRACKET ;
+/.
+case $rule_number: {
+ AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), (AST::Elision *) 0);
+ node->lbracketToken = loc(1);
+ node->rbracketToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_LBRACKET Elision T_RBRACKET ;
+/.
+case $rule_number: {
+ AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).Elision->finish());
+ node->lbracketToken = loc(1);
+ node->rbracketToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_LBRACKET ElementList T_RBRACKET ;
+/.
+case $rule_number: {
+ AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).ElementList->finish ());
+ node->lbracketToken = loc(1);
+ node->rbracketToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_LBRACKET ElementList T_COMMA T_RBRACKET ;
+/.
+case $rule_number: {
+ AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).ElementList->finish (),
+ (AST::Elision *) 0);
+ node->lbracketToken = loc(1);
+ node->commaToken = loc(3);
+ node->rbracketToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_LBRACKET ElementList T_COMMA Elision T_RBRACKET ;
+/.
+case $rule_number: {
+ AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).ElementList->finish (),
+ sym(4).Elision->finish());
+ node->lbracketToken = loc(1);
+ node->commaToken = loc(3);
+ node->rbracketToken = loc(5);
+ sym(1).Node = node;
+} break;
+./
+
+-- PrimaryExpression: T_LBRACE T_RBRACE ;
+-- /.
+-- case $rule_number: {
+-- sym(1).Node = makeAstNode<AST::ObjectLiteral> (driver->nodePool());
+-- } break;
+-- ./
+
+PrimaryExpression: T_LBRACE PropertyNameAndValueListOpt T_RBRACE ;
+/.
+case $rule_number: {
+ AST::ObjectLiteral *node = 0;
+ if (sym(2).Node)
+ node = makeAstNode<AST::ObjectLiteral> (driver->nodePool(),
+ sym(2).PropertyNameAndValueList->finish ());
+ else
+ node = makeAstNode<AST::ObjectLiteral> (driver->nodePool());
+ node->lbraceToken = loc(1);
+ node->lbraceToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_LBRACE PropertyNameAndValueList T_COMMA T_RBRACE ;
+/.
+case $rule_number: {
+ AST::ObjectLiteral *node = makeAstNode<AST::ObjectLiteral> (driver->nodePool(),
+ sym(2).PropertyNameAndValueList->finish ());
+ node->lbraceToken = loc(1);
+ node->lbraceToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+PrimaryExpression: T_LPAREN Expression T_RPAREN ;
+/.
+case $rule_number: {
+ AST::NestedExpression *node = makeAstNode<AST::NestedExpression>(driver->nodePool(), sym(2).Expression);
+ node->lparenToken = loc(1);
+ node->rparenToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+UiQualifiedId: MemberExpression ;
+/.
+case $rule_number: {
+ if (AST::ArrayMemberExpression *mem = AST::cast<AST::ArrayMemberExpression *>(sym(1).Expression)) {
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, mem->lbracketToken,
+ QLatin1String("Ignored annotation")));
+
+ sym(1).Expression = mem->base;
+ }
+
+ if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(1).Expression)) {
+ sym(1).UiQualifiedId = qualifiedId;
+ } else {
+ sym(1).UiQualifiedId = 0;
+
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1),
+ QLatin1String("Expected a qualified name id")));
+
+ return false; // ### recover
+ }
+} break;
+./
+
+ElementList: AssignmentExpression ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::ElementList> (driver->nodePool(), (AST::Elision *) 0, sym(1).Expression);
+} break;
+./
+
+ElementList: Elision AssignmentExpression ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).Elision->finish(), sym(2).Expression);
+} break;
+./
+
+ElementList: ElementList T_COMMA AssignmentExpression ;
+/.
+case $rule_number: {
+ AST::ElementList *node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).ElementList,
+ (AST::Elision *) 0, sym(3).Expression);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+ElementList: ElementList T_COMMA Elision AssignmentExpression ;
+/.
+case $rule_number: {
+ AST::ElementList *node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).ElementList, sym(3).Elision->finish(),
+ sym(4).Expression);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+Elision: T_COMMA ;
+/.
+case $rule_number: {
+ AST::Elision *node = makeAstNode<AST::Elision> (driver->nodePool());
+ node->commaToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+Elision: Elision T_COMMA ;
+/.
+case $rule_number: {
+ AST::Elision *node = makeAstNode<AST::Elision> (driver->nodePool(), sym(1).Elision);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+PropertyNameAndValueList: PropertyName T_COLON AssignmentExpression ;
+/.
+case $rule_number: {
+ AST::PropertyNameAndValueList *node = makeAstNode<AST::PropertyNameAndValueList> (driver->nodePool(),
+ sym(1).PropertyName, sym(3).Expression);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+PropertyNameAndValueList: PropertyNameAndValueList T_COMMA PropertyName T_COLON AssignmentExpression ;
+/.
+case $rule_number: {
+ AST::PropertyNameAndValueList *node = makeAstNode<AST::PropertyNameAndValueList> (driver->nodePool(),
+ sym(1).PropertyNameAndValueList, sym(3).PropertyName, sym(5).Expression);
+ node->commaToken = loc(2);
+ node->colonToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+PropertyName: T_IDENTIFIER %prec REDUCE_HERE ;
+/.
+case $rule_number: {
+ AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), sym(1).sval);
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PropertyName: T_SIGNAL ;
+/.case $rule_number:./
+
+PropertyName: T_PROPERTY ;
+/.
+case $rule_number: {
+ AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount()));
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PropertyName: T_STRING_LITERAL ;
+/.
+case $rule_number: {
+ AST::StringLiteralPropertyName *node = makeAstNode<AST::StringLiteralPropertyName> (driver->nodePool(), sym(1).sval);
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PropertyName: T_NUMERIC_LITERAL ;
+/.
+case $rule_number: {
+ AST::NumericLiteralPropertyName *node = makeAstNode<AST::NumericLiteralPropertyName> (driver->nodePool(), sym(1).dval);
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+PropertyName: ReservedIdentifier ;
+/.
+case $rule_number: {
+ AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), sym(1).sval);
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+ReservedIdentifier: T_BREAK ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_CASE ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_CATCH ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_CONTINUE ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_DEFAULT ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_DELETE ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_DO ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_ELSE ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_FALSE ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_FINALLY ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_FOR ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_FUNCTION ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_IF ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_IN ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_INSTANCEOF ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_NEW ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_NULL ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_RETURN ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_SWITCH ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_THIS ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_THROW ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_TRUE ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_TRY ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_TYPEOF ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_VAR ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_VOID ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_WHILE ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_CONST ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_DEBUGGER ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_RESERVED_WORD ;
+/.
+case $rule_number:
+./
+ReservedIdentifier: T_WITH ;
+/.
+case $rule_number:
+{
+ sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount());
+} break;
+./
+
+PropertyIdentifier: JsIdentifier ;
+PropertyIdentifier: ReservedIdentifier ;
+
+MemberExpression: PrimaryExpression ;
+MemberExpression: FunctionExpression ;
+
+MemberExpression: MemberExpression T_LBRACKET Expression T_RBRACKET ;
+/.
+case $rule_number: {
+ AST::ArrayMemberExpression *node = makeAstNode<AST::ArrayMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).Expression);
+ node->lbracketToken = loc(2);
+ node->rbracketToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+MemberExpression: MemberExpression T_DOT PropertyIdentifier ;
+/.
+case $rule_number: {
+ AST::FieldMemberExpression *node = makeAstNode<AST::FieldMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).sval);
+ node->dotToken = loc(2);
+ node->identifierToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+MemberExpression: T_NEW MemberExpression T_LPAREN ArgumentListOpt T_RPAREN ;
+/.
+case $rule_number: {
+ AST::NewMemberExpression *node = makeAstNode<AST::NewMemberExpression> (driver->nodePool(), sym(2).Expression, sym(4).ArgumentList);
+ node->newToken = loc(1);
+ node->lparenToken = loc(3);
+ node->rparenToken = loc(5);
+ sym(1).Node = node;
+} break;
+./
+
+NewExpression: MemberExpression ;
+
+NewExpression: T_NEW NewExpression ;
+/.
+case $rule_number: {
+ AST::NewExpression *node = makeAstNode<AST::NewExpression> (driver->nodePool(), sym(2).Expression);
+ node->newToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+CallExpression: MemberExpression T_LPAREN ArgumentListOpt T_RPAREN ;
+/.
+case $rule_number: {
+ AST::CallExpression *node = makeAstNode<AST::CallExpression> (driver->nodePool(), sym(1).Expression, sym(3).ArgumentList);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+CallExpression: CallExpression T_LPAREN ArgumentListOpt T_RPAREN ;
+/.
+case $rule_number: {
+ AST::CallExpression *node = makeAstNode<AST::CallExpression> (driver->nodePool(), sym(1).Expression, sym(3).ArgumentList);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+CallExpression: CallExpression T_LBRACKET Expression T_RBRACKET ;
+/.
+case $rule_number: {
+ AST::ArrayMemberExpression *node = makeAstNode<AST::ArrayMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).Expression);
+ node->lbracketToken = loc(2);
+ node->rbracketToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+CallExpression: CallExpression T_DOT PropertyIdentifier ;
+/.
+case $rule_number: {
+ AST::FieldMemberExpression *node = makeAstNode<AST::FieldMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).sval);
+ node->dotToken = loc(2);
+ node->identifierToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+ArgumentListOpt: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+ArgumentListOpt: ArgumentList ;
+/.
+case $rule_number: {
+ sym(1).Node = sym(1).ArgumentList->finish();
+} break;
+./
+
+ArgumentList: AssignmentExpression ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::ArgumentList> (driver->nodePool(), sym(1).Expression);
+} break;
+./
+
+ArgumentList: ArgumentList T_COMMA AssignmentExpression ;
+/.
+case $rule_number: {
+ AST::ArgumentList *node = makeAstNode<AST::ArgumentList> (driver->nodePool(), sym(1).ArgumentList, sym(3).Expression);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+LeftHandSideExpression: NewExpression ;
+LeftHandSideExpression: CallExpression ;
+PostfixExpression: LeftHandSideExpression ;
+
+PostfixExpression: LeftHandSideExpression T_PLUS_PLUS ;
+/.
+case $rule_number: {
+ AST::PostIncrementExpression *node = makeAstNode<AST::PostIncrementExpression> (driver->nodePool(), sym(1).Expression);
+ node->incrementToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+PostfixExpression: LeftHandSideExpression T_MINUS_MINUS ;
+/.
+case $rule_number: {
+ AST::PostDecrementExpression *node = makeAstNode<AST::PostDecrementExpression> (driver->nodePool(), sym(1).Expression);
+ node->decrementToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+UnaryExpression: PostfixExpression ;
+
+UnaryExpression: T_DELETE UnaryExpression ;
+/.
+case $rule_number: {
+ AST::DeleteExpression *node = makeAstNode<AST::DeleteExpression> (driver->nodePool(), sym(2).Expression);
+ node->deleteToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+UnaryExpression: T_VOID UnaryExpression ;
+/.
+case $rule_number: {
+ AST::VoidExpression *node = makeAstNode<AST::VoidExpression> (driver->nodePool(), sym(2).Expression);
+ node->voidToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+UnaryExpression: T_TYPEOF UnaryExpression ;
+/.
+case $rule_number: {
+ AST::TypeOfExpression *node = makeAstNode<AST::TypeOfExpression> (driver->nodePool(), sym(2).Expression);
+ node->typeofToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+UnaryExpression: T_PLUS_PLUS UnaryExpression ;
+/.
+case $rule_number: {
+ AST::PreIncrementExpression *node = makeAstNode<AST::PreIncrementExpression> (driver->nodePool(), sym(2).Expression);
+ node->incrementToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+UnaryExpression: T_MINUS_MINUS UnaryExpression ;
+/.
+case $rule_number: {
+ AST::PreDecrementExpression *node = makeAstNode<AST::PreDecrementExpression> (driver->nodePool(), sym(2).Expression);
+ node->decrementToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+UnaryExpression: T_PLUS UnaryExpression ;
+/.
+case $rule_number: {
+ AST::UnaryPlusExpression *node = makeAstNode<AST::UnaryPlusExpression> (driver->nodePool(), sym(2).Expression);
+ node->plusToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+UnaryExpression: T_MINUS UnaryExpression ;
+/.
+case $rule_number: {
+ AST::UnaryMinusExpression *node = makeAstNode<AST::UnaryMinusExpression> (driver->nodePool(), sym(2).Expression);
+ node->minusToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+UnaryExpression: T_TILDE UnaryExpression ;
+/.
+case $rule_number: {
+ AST::TildeExpression *node = makeAstNode<AST::TildeExpression> (driver->nodePool(), sym(2).Expression);
+ node->tildeToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+UnaryExpression: T_NOT UnaryExpression ;
+/.
+case $rule_number: {
+ AST::NotExpression *node = makeAstNode<AST::NotExpression> (driver->nodePool(), sym(2).Expression);
+ node->notToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+MultiplicativeExpression: UnaryExpression ;
+
+MultiplicativeExpression: MultiplicativeExpression T_STAR UnaryExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Mul, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+MultiplicativeExpression: MultiplicativeExpression T_DIVIDE_ UnaryExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Div, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+MultiplicativeExpression: MultiplicativeExpression T_REMAINDER UnaryExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Mod, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+AdditiveExpression: MultiplicativeExpression ;
+
+AdditiveExpression: AdditiveExpression T_PLUS MultiplicativeExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Add, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+AdditiveExpression: AdditiveExpression T_MINUS MultiplicativeExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Sub, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+ShiftExpression: AdditiveExpression ;
+
+ShiftExpression: ShiftExpression T_LT_LT AdditiveExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::LShift, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+ShiftExpression: ShiftExpression T_GT_GT AdditiveExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::RShift, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+ShiftExpression: ShiftExpression T_GT_GT_GT AdditiveExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::URShift, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpression: ShiftExpression ;
+
+RelationalExpression: RelationalExpression T_LT ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Lt, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpression: RelationalExpression T_GT ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Gt, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpression: RelationalExpression T_LE ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Le, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpression: RelationalExpression T_GE ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Ge, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpression: RelationalExpression T_INSTANCEOF ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::InstanceOf, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpression: RelationalExpression T_IN ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::In, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpressionNotIn: ShiftExpression ;
+
+RelationalExpressionNotIn: RelationalExpressionNotIn T_LT ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Lt, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpressionNotIn: RelationalExpressionNotIn T_GT ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Gt, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpressionNotIn: RelationalExpressionNotIn T_LE ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Le, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpressionNotIn: RelationalExpressionNotIn T_GE ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Ge, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+RelationalExpressionNotIn: RelationalExpressionNotIn T_INSTANCEOF ShiftExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::InstanceOf, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+EqualityExpression: RelationalExpression ;
+
+EqualityExpression: EqualityExpression T_EQ_EQ RelationalExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Equal, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+EqualityExpression: EqualityExpression T_NOT_EQ RelationalExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::NotEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+EqualityExpression: EqualityExpression T_EQ_EQ_EQ RelationalExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::StrictEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+EqualityExpression: EqualityExpression T_NOT_EQ_EQ RelationalExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::StrictNotEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+EqualityExpressionNotIn: RelationalExpressionNotIn ;
+
+EqualityExpressionNotIn: EqualityExpressionNotIn T_EQ_EQ RelationalExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Equal, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+EqualityExpressionNotIn: EqualityExpressionNotIn T_NOT_EQ RelationalExpressionNotIn;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::NotEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+EqualityExpressionNotIn: EqualityExpressionNotIn T_EQ_EQ_EQ RelationalExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::StrictEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+EqualityExpressionNotIn: EqualityExpressionNotIn T_NOT_EQ_EQ RelationalExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::StrictNotEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+BitwiseANDExpression: EqualityExpression ;
+
+BitwiseANDExpression: BitwiseANDExpression T_AND EqualityExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitAnd, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+BitwiseANDExpressionNotIn: EqualityExpressionNotIn ;
+
+BitwiseANDExpressionNotIn: BitwiseANDExpressionNotIn T_AND EqualityExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitAnd, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+BitwiseXORExpression: BitwiseANDExpression ;
+
+BitwiseXORExpression: BitwiseXORExpression T_XOR BitwiseANDExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitXor, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+BitwiseXORExpressionNotIn: BitwiseANDExpressionNotIn ;
+
+BitwiseXORExpressionNotIn: BitwiseXORExpressionNotIn T_XOR BitwiseANDExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitXor, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+BitwiseORExpression: BitwiseXORExpression ;
+
+BitwiseORExpression: BitwiseORExpression T_OR BitwiseXORExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitOr, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+BitwiseORExpressionNotIn: BitwiseXORExpressionNotIn ;
+
+BitwiseORExpressionNotIn: BitwiseORExpressionNotIn T_OR BitwiseXORExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitOr, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+LogicalANDExpression: BitwiseORExpression ;
+
+LogicalANDExpression: LogicalANDExpression T_AND_AND BitwiseORExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::And, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+LogicalANDExpressionNotIn: BitwiseORExpressionNotIn ;
+
+LogicalANDExpressionNotIn: LogicalANDExpressionNotIn T_AND_AND BitwiseORExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::And, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+LogicalORExpression: LogicalANDExpression ;
+
+LogicalORExpression: LogicalORExpression T_OR_OR LogicalANDExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Or, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+LogicalORExpressionNotIn: LogicalANDExpressionNotIn ;
+
+LogicalORExpressionNotIn: LogicalORExpressionNotIn T_OR_OR LogicalANDExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Or, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+ConditionalExpression: LogicalORExpression ;
+
+ConditionalExpression: LogicalORExpression T_QUESTION AssignmentExpression T_COLON AssignmentExpression ;
+/.
+case $rule_number: {
+ AST::ConditionalExpression *node = makeAstNode<AST::ConditionalExpression> (driver->nodePool(), sym(1).Expression,
+ sym(3).Expression, sym(5).Expression);
+ node->questionToken = loc(2);
+ node->colonToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+ConditionalExpressionNotIn: LogicalORExpressionNotIn ;
+
+ConditionalExpressionNotIn: LogicalORExpressionNotIn T_QUESTION AssignmentExpressionNotIn T_COLON AssignmentExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::ConditionalExpression *node = makeAstNode<AST::ConditionalExpression> (driver->nodePool(), sym(1).Expression,
+ sym(3).Expression, sym(5).Expression);
+ node->questionToken = loc(2);
+ node->colonToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+AssignmentExpression: ConditionalExpression ;
+
+AssignmentExpression: LeftHandSideExpression AssignmentOperator AssignmentExpression ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ sym(2).ival, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+AssignmentExpressionNotIn: ConditionalExpressionNotIn ;
+
+AssignmentExpressionNotIn: LeftHandSideExpression AssignmentOperator AssignmentExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ sym(2).ival, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+AssignmentOperator: T_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::Assign;
+} break;
+./
+
+AssignmentOperator: T_STAR_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceMul;
+} break;
+./
+
+AssignmentOperator: T_DIVIDE_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceDiv;
+} break;
+./
+
+AssignmentOperator: T_REMAINDER_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceMod;
+} break;
+./
+
+AssignmentOperator: T_PLUS_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceAdd;
+} break;
+./
+
+AssignmentOperator: T_MINUS_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceSub;
+} break;
+./
+
+AssignmentOperator: T_LT_LT_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceLeftShift;
+} break;
+./
+
+AssignmentOperator: T_GT_GT_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceRightShift;
+} break;
+./
+
+AssignmentOperator: T_GT_GT_GT_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceURightShift;
+} break;
+./
+
+AssignmentOperator: T_AND_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceAnd;
+} break;
+./
+
+AssignmentOperator: T_XOR_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceXor;
+} break;
+./
+
+AssignmentOperator: T_OR_EQ ;
+/.
+case $rule_number: {
+ sym(1).ival = QSOperator::InplaceOr;
+} break;
+./
+
+Expression: AssignmentExpression ;
+
+Expression: Expression T_COMMA AssignmentExpression ;
+/.
+case $rule_number: {
+ AST::Expression *node = makeAstNode<AST::Expression> (driver->nodePool(), sym(1).Expression, sym(3).Expression);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+ExpressionOpt: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+ExpressionOpt: Expression ;
+
+ExpressionNotIn: AssignmentExpressionNotIn ;
+
+ExpressionNotIn: ExpressionNotIn T_COMMA AssignmentExpressionNotIn ;
+/.
+case $rule_number: {
+ AST::Expression *node = makeAstNode<AST::Expression> (driver->nodePool(), sym(1).Expression, sym(3).Expression);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+ExpressionNotInOpt: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+ExpressionNotInOpt: ExpressionNotIn ;
+
+Statement: Block ;
+Statement: VariableStatement ;
+Statement: EmptyStatement ;
+Statement: ExpressionStatement ;
+Statement: IfStatement ;
+Statement: IterationStatement ;
+Statement: ContinueStatement ;
+Statement: BreakStatement ;
+Statement: ReturnStatement ;
+Statement: WithStatement ;
+Statement: LabelledStatement ;
+Statement: SwitchStatement ;
+Statement: ThrowStatement ;
+Statement: TryStatement ;
+Statement: DebuggerStatement ;
+
+
+Block: T_LBRACE StatementListOpt T_RBRACE ;
+/.
+case $rule_number: {
+ AST::Block *node = makeAstNode<AST::Block> (driver->nodePool(), sym(2).StatementList);
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+StatementList: Statement ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::StatementList> (driver->nodePool(), sym(1).Statement);
+} break;
+./
+
+StatementList: StatementList Statement ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::StatementList> (driver->nodePool(), sym(1).StatementList, sym(2).Statement);
+} break;
+./
+
+StatementListOpt: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+StatementListOpt: StatementList ;
+/.
+case $rule_number: {
+ sym(1).Node = sym(1).StatementList->finish ();
+} break;
+./
+
+VariableStatement: VariableDeclarationKind VariableDeclarationList T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+VariableStatement: VariableDeclarationKind VariableDeclarationList T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::VariableStatement *node = makeAstNode<AST::VariableStatement> (driver->nodePool(),
+ sym(2).VariableDeclarationList->finish (/*readOnly=*/sym(1).ival == T_CONST));
+ node->declarationKindToken = loc(1);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+VariableDeclarationKind: T_CONST ;
+/.
+case $rule_number: {
+ sym(1).ival = T_CONST;
+} break;
+./
+
+VariableDeclarationKind: T_VAR ;
+/.
+case $rule_number: {
+ sym(1).ival = T_VAR;
+} break;
+./
+
+VariableDeclarationList: VariableDeclaration ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclaration);
+} break;
+./
+
+VariableDeclarationList: VariableDeclarationList T_COMMA VariableDeclaration ;
+/.
+case $rule_number: {
+ AST::VariableDeclarationList *node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(),
+ sym(1).VariableDeclarationList, sym(3).VariableDeclaration);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+VariableDeclarationListNotIn: VariableDeclarationNotIn ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclaration);
+} break;
+./
+
+VariableDeclarationListNotIn: VariableDeclarationListNotIn T_COMMA VariableDeclarationNotIn ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclarationList, sym(3).VariableDeclaration);
+} break;
+./
+
+VariableDeclaration: JsIdentifier InitialiserOpt ;
+/.
+case $rule_number: {
+ AST::VariableDeclaration *node = makeAstNode<AST::VariableDeclaration> (driver->nodePool(), sym(1).sval, sym(2).Expression);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+VariableDeclarationNotIn: JsIdentifier InitialiserNotInOpt ;
+/.
+case $rule_number: {
+ AST::VariableDeclaration *node = makeAstNode<AST::VariableDeclaration> (driver->nodePool(), sym(1).sval, sym(2).Expression);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+Initialiser: T_EQ AssignmentExpression ;
+/.
+case $rule_number: {
+ // ### TODO: AST for initializer
+ sym(1) = sym(2);
+} break;
+./
+
+InitialiserOpt: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+InitialiserOpt: Initialiser ;
+
+InitialiserNotIn: T_EQ AssignmentExpressionNotIn ;
+/.
+case $rule_number: {
+ // ### TODO: AST for initializer
+ sym(1) = sym(2);
+} break;
+./
+
+InitialiserNotInOpt: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+InitialiserNotInOpt: InitialiserNotIn ;
+
+EmptyStatement: T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::EmptyStatement *node = makeAstNode<AST::EmptyStatement> (driver->nodePool());
+ node->semicolonToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+ExpressionStatement: Expression T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+ExpressionStatement: Expression T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::ExpressionStatement *node = makeAstNode<AST::ExpressionStatement> (driver->nodePool(), sym(1).Expression);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+IfStatement: T_IF T_LPAREN Expression T_RPAREN Statement T_ELSE Statement ;
+/.
+case $rule_number: {
+ AST::IfStatement *node = makeAstNode<AST::IfStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement, sym(7).Statement);
+ node->ifToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ node->elseToken = loc(5);
+ sym(1).Node = node;
+} break;
+./
+
+IfStatement: T_IF T_LPAREN Expression T_RPAREN Statement ;
+/.
+case $rule_number: {
+ AST::IfStatement *node = makeAstNode<AST::IfStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement);
+ node->ifToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+
+IterationStatement: T_DO Statement T_WHILE T_LPAREN Expression T_RPAREN T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+IterationStatement: T_DO Statement T_WHILE T_LPAREN Expression T_RPAREN T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::DoWhileStatement *node = makeAstNode<AST::DoWhileStatement> (driver->nodePool(), sym(2).Statement, sym(5).Expression);
+ node->doToken = loc(1);
+ node->whileToken = loc(3);
+ node->lparenToken = loc(4);
+ node->rparenToken = loc(6);
+ node->semicolonToken = loc(7);
+ sym(1).Node = node;
+} break;
+./
+
+IterationStatement: T_WHILE T_LPAREN Expression T_RPAREN Statement ;
+/.
+case $rule_number: {
+ AST::WhileStatement *node = makeAstNode<AST::WhileStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement);
+ node->whileToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+IterationStatement: T_FOR T_LPAREN ExpressionNotInOpt T_SEMICOLON ExpressionOpt T_SEMICOLON ExpressionOpt T_RPAREN Statement ;
+/.
+case $rule_number: {
+ AST::ForStatement *node = makeAstNode<AST::ForStatement> (driver->nodePool(), sym(3).Expression,
+ sym(5).Expression, sym(7).Expression, sym(9).Statement);
+ node->forToken = loc(1);
+ node->lparenToken = loc(2);
+ node->firstSemicolonToken = loc(4);
+ node->secondSemicolonToken = loc(6);
+ node->rparenToken = loc(8);
+ sym(1).Node = node;
+} break;
+./
+
+IterationStatement: T_FOR T_LPAREN T_VAR VariableDeclarationListNotIn T_SEMICOLON ExpressionOpt T_SEMICOLON ExpressionOpt T_RPAREN Statement ;
+/.
+case $rule_number: {
+ AST::LocalForStatement *node = makeAstNode<AST::LocalForStatement> (driver->nodePool(),
+ sym(4).VariableDeclarationList->finish (/*readOnly=*/false), sym(6).Expression,
+ sym(8).Expression, sym(10).Statement);
+ node->forToken = loc(1);
+ node->lparenToken = loc(2);
+ node->varToken = loc(3);
+ node->firstSemicolonToken = loc(5);
+ node->secondSemicolonToken = loc(7);
+ node->rparenToken = loc(9);
+ sym(1).Node = node;
+} break;
+./
+
+IterationStatement: T_FOR T_LPAREN LeftHandSideExpression T_IN Expression T_RPAREN Statement ;
+/.
+case $rule_number: {
+ AST:: ForEachStatement *node = makeAstNode<AST::ForEachStatement> (driver->nodePool(), sym(3).Expression,
+ sym(5).Expression, sym(7).Statement);
+ node->forToken = loc(1);
+ node->lparenToken = loc(2);
+ node->inToken = loc(4);
+ node->rparenToken = loc(6);
+ sym(1).Node = node;
+} break;
+./
+
+IterationStatement: T_FOR T_LPAREN T_VAR VariableDeclarationNotIn T_IN Expression T_RPAREN Statement ;
+/.
+case $rule_number: {
+ AST::LocalForEachStatement *node = makeAstNode<AST::LocalForEachStatement> (driver->nodePool(),
+ sym(4).VariableDeclaration, sym(6).Expression, sym(8).Statement);
+ node->forToken = loc(1);
+ node->lparenToken = loc(2);
+ node->varToken = loc(3);
+ node->inToken = loc(5);
+ node->rparenToken = loc(7);
+ sym(1).Node = node;
+} break;
+./
+
+ContinueStatement: T_CONTINUE T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+ContinueStatement: T_CONTINUE T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::ContinueStatement *node = makeAstNode<AST::ContinueStatement> (driver->nodePool());
+ node->continueToken = loc(1);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+ContinueStatement: T_CONTINUE JsIdentifier T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+ContinueStatement: T_CONTINUE JsIdentifier T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::ContinueStatement *node = makeAstNode<AST::ContinueStatement> (driver->nodePool(), sym(2).sval);
+ node->continueToken = loc(1);
+ node->identifierToken = loc(2);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+BreakStatement: T_BREAK T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+BreakStatement: T_BREAK T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::BreakStatement *node = makeAstNode<AST::BreakStatement> (driver->nodePool());
+ node->breakToken = loc(1);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+BreakStatement: T_BREAK JsIdentifier T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+BreakStatement: T_BREAK JsIdentifier T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::BreakStatement *node = makeAstNode<AST::BreakStatement> (driver->nodePool(), sym(2).sval);
+ node->breakToken = loc(1);
+ node->identifierToken = loc(2);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+ReturnStatement: T_RETURN ExpressionOpt T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+ReturnStatement: T_RETURN ExpressionOpt T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::ReturnStatement *node = makeAstNode<AST::ReturnStatement> (driver->nodePool(), sym(2).Expression);
+ node->returnToken = loc(1);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+WithStatement: T_WITH T_LPAREN Expression T_RPAREN Statement ;
+/.
+case $rule_number: {
+ AST::WithStatement *node = makeAstNode<AST::WithStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement);
+ node->withToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+SwitchStatement: T_SWITCH T_LPAREN Expression T_RPAREN CaseBlock ;
+/.
+case $rule_number: {
+ AST::SwitchStatement *node = makeAstNode<AST::SwitchStatement> (driver->nodePool(), sym(3).Expression, sym(5).CaseBlock);
+ node->switchToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+CaseBlock: T_LBRACE CaseClausesOpt T_RBRACE ;
+/.
+case $rule_number: {
+ AST::CaseBlock *node = makeAstNode<AST::CaseBlock> (driver->nodePool(), sym(2).CaseClauses);
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+CaseBlock: T_LBRACE CaseClausesOpt DefaultClause CaseClausesOpt T_RBRACE ;
+/.
+case $rule_number: {
+ AST::CaseBlock *node = makeAstNode<AST::CaseBlock> (driver->nodePool(), sym(2).CaseClauses, sym(3).DefaultClause, sym(4).CaseClauses);
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(5);
+ sym(1).Node = node;
+} break;
+./
+
+CaseClauses: CaseClause ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::CaseClauses> (driver->nodePool(), sym(1).CaseClause);
+} break;
+./
+
+CaseClauses: CaseClauses CaseClause ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::CaseClauses> (driver->nodePool(), sym(1).CaseClauses, sym(2).CaseClause);
+} break;
+./
+
+CaseClausesOpt: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+CaseClausesOpt: CaseClauses ;
+/.
+case $rule_number: {
+ sym(1).Node = sym(1).CaseClauses->finish ();
+} break;
+./
+
+CaseClause: T_CASE Expression T_COLON StatementListOpt ;
+/.
+case $rule_number: {
+ AST::CaseClause *node = makeAstNode<AST::CaseClause> (driver->nodePool(), sym(2).Expression, sym(4).StatementList);
+ node->caseToken = loc(1);
+ node->colonToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+DefaultClause: T_DEFAULT T_COLON StatementListOpt ;
+/.
+case $rule_number: {
+ AST::DefaultClause *node = makeAstNode<AST::DefaultClause> (driver->nodePool(), sym(3).StatementList);
+ node->defaultToken = loc(1);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+LabelledStatement: T_SIGNAL T_COLON Statement ;
+/.case $rule_number:./
+
+LabelledStatement: T_PROPERTY T_COLON Statement ;
+/.
+case $rule_number: {
+ AST::LabelledStatement *node = makeAstNode<AST::LabelledStatement> (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount()), sym(3).Statement);
+ node->identifierToken = loc(1);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+LabelledStatement: T_IDENTIFIER T_COLON Statement ;
+/.
+case $rule_number: {
+ AST::LabelledStatement *node = makeAstNode<AST::LabelledStatement> (driver->nodePool(), sym(1).sval, sym(3).Statement);
+ node->identifierToken = loc(1);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+ThrowStatement: T_THROW Expression T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+ThrowStatement: T_THROW Expression T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::ThrowStatement *node = makeAstNode<AST::ThrowStatement> (driver->nodePool(), sym(2).Expression);
+ node->throwToken = loc(1);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+TryStatement: T_TRY Block Catch ;
+/.
+case $rule_number: {
+ AST::TryStatement *node = makeAstNode<AST::TryStatement> (driver->nodePool(), sym(2).Statement, sym(3).Catch);
+ node->tryToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+TryStatement: T_TRY Block Finally ;
+/.
+case $rule_number: {
+ AST::TryStatement *node = makeAstNode<AST::TryStatement> (driver->nodePool(), sym(2).Statement, sym(3).Finally);
+ node->tryToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+TryStatement: T_TRY Block Catch Finally ;
+/.
+case $rule_number: {
+ AST::TryStatement *node = makeAstNode<AST::TryStatement> (driver->nodePool(), sym(2).Statement, sym(3).Catch, sym(4).Finally);
+ node->tryToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+Catch: T_CATCH T_LPAREN JsIdentifier T_RPAREN Block ;
+/.
+case $rule_number: {
+ AST::Catch *node = makeAstNode<AST::Catch> (driver->nodePool(), sym(3).sval, sym(5).Block);
+ node->catchToken = loc(1);
+ node->lparenToken = loc(2);
+ node->identifierToken = loc(3);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+./
+
+Finally: T_FINALLY Block ;
+/.
+case $rule_number: {
+ AST::Finally *node = makeAstNode<AST::Finally> (driver->nodePool(), sym(2).Block);
+ node->finallyToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+DebuggerStatement: T_DEBUGGER T_AUTOMATIC_SEMICOLON ; -- automatic semicolon
+DebuggerStatement: T_DEBUGGER T_SEMICOLON ;
+/.
+case $rule_number: {
+ AST::DebuggerStatement *node = makeAstNode<AST::DebuggerStatement> (driver->nodePool());
+ node->debuggerToken = loc(1);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+} break;
+./
+
+FunctionDeclaration: T_FUNCTION JsIdentifier T_LPAREN FormalParameterListOpt T_RPAREN T_LBRACE FunctionBodyOpt T_RBRACE ;
+/.
+case $rule_number: {
+ AST::FunctionDeclaration *node = makeAstNode<AST::FunctionDeclaration> (driver->nodePool(), sym(2).sval, sym(4).FormalParameterList, sym(7).FunctionBody);
+ node->functionToken = loc(1);
+ node->identifierToken = loc(2);
+ node->lparenToken = loc(3);
+ node->rparenToken = loc(5);
+ node->lbraceToken = loc(6);
+ node->rbraceToken = loc(8);
+ sym(1).Node = node;
+} break;
+./
+
+FunctionExpression: T_FUNCTION IdentifierOpt T_LPAREN FormalParameterListOpt T_RPAREN T_LBRACE FunctionBodyOpt T_RBRACE ;
+/.
+case $rule_number: {
+ AST::FunctionExpression *node = makeAstNode<AST::FunctionExpression> (driver->nodePool(), sym(2).sval, sym(4).FormalParameterList, sym(7).FunctionBody);
+ node->functionToken = loc(1);
+ if (sym(2).sval)
+ node->identifierToken = loc(2);
+ node->lparenToken = loc(3);
+ node->rparenToken = loc(5);
+ node->lbraceToken = loc(6);
+ node->rbraceToken = loc(8);
+ sym(1).Node = node;
+} break;
+./
+
+FormalParameterList: JsIdentifier ;
+/.
+case $rule_number: {
+ AST::FormalParameterList *node = makeAstNode<AST::FormalParameterList> (driver->nodePool(), sym(1).sval);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+./
+
+FormalParameterList: FormalParameterList T_COMMA JsIdentifier ;
+/.
+case $rule_number: {
+ AST::FormalParameterList *node = makeAstNode<AST::FormalParameterList> (driver->nodePool(), sym(1).FormalParameterList, sym(3).sval);
+ node->commaToken = loc(2);
+ node->identifierToken = loc(3);
+ sym(1).Node = node;
+} break;
+./
+
+FormalParameterListOpt: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+FormalParameterListOpt: FormalParameterList ;
+/.
+case $rule_number: {
+ sym(1).Node = sym(1).FormalParameterList->finish ();
+} break;
+./
+
+FunctionBodyOpt: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+FunctionBodyOpt: FunctionBody ;
+
+FunctionBody: SourceElements ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::FunctionBody> (driver->nodePool(), sym(1).SourceElements->finish ());
+} break;
+./
+
+--QmlJSProgram: SourceElements ;
+--/.
+--case $rule_number: {
+-- sym(1).Node = makeAstNode<AST::Program> (driver->nodePool(), sym(1).SourceElements->finish ());
+-- driver->changeAbstractSyntaxTree(sym(1).Node);
+--} break;
+--./
+
+SourceElements: SourceElement ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::SourceElements> (driver->nodePool(), sym(1).SourceElement);
+} break;
+./
+
+SourceElements: SourceElements SourceElement ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::SourceElements> (driver->nodePool(), sym(1).SourceElements, sym(2).SourceElement);
+} break;
+./
+
+SourceElement: Statement ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::StatementSourceElement> (driver->nodePool(), sym(1).Statement);
+} break;
+./
+
+SourceElement: FunctionDeclaration ;
+/.
+case $rule_number: {
+ sym(1).Node = makeAstNode<AST::FunctionSourceElement> (driver->nodePool(), sym(1).FunctionDeclaration);
+} break;
+./
+
+IdentifierOpt: ;
+/.
+case $rule_number: {
+ sym(1).sval = 0;
+} break;
+./
+
+IdentifierOpt: JsIdentifier ;
+
+PropertyNameAndValueListOpt: ;
+/.
+case $rule_number: {
+ sym(1).Node = 0;
+} break;
+./
+
+PropertyNameAndValueListOpt: PropertyNameAndValueList ;
+
+/.
+ } // switch
+ action = nt_action(state_stack[tos], lhs[r] - TERMINAL_COUNT);
+ } // if
+ } while (action != 0);
+
+ if (first_token == last_token) {
+ const int errorState = state_stack[tos];
+
+ // automatic insertion of `;'
+ if (t_action(errorState, T_AUTOMATIC_SEMICOLON) && automatic(driver, yytoken)) {
+ SavedToken &tk = token_buffer[0];
+ tk.token = yytoken;
+ tk.dval = yylval;
+ tk.loc = yylloc;
+
+ yylloc = yyprevlloc;
+ yylloc.offset += yylloc.length;
+ yylloc.startColumn += yylloc.length;
+ yylloc.length = 0;
+
+ //const QString msg = qApp->translate("QmlParser", "Missing `;'");
+ //diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, yylloc, msg));
+
+ first_token = &token_buffer[0];
+ last_token = &token_buffer[1];
+
+ yytoken = T_SEMICOLON;
+ yylval = 0;
+
+ action = errorState;
+
+ goto _Lcheck_token;
+ }
+
+ hadErrors = true;
+
+ token_buffer[0].token = yytoken;
+ token_buffer[0].dval = yylval;
+ token_buffer[0].loc = yylloc;
+
+ token_buffer[1].token = yytoken = lexer->lex();
+ token_buffer[1].dval = yylval = lexer->dval();
+ token_buffer[1].loc = yylloc = location(lexer);
+
+ if (t_action(errorState, yytoken)) {
+ const QString msg = qApp->translate("QmlParser", "Unexpected token `%1'").arg(QLatin1String(spell[token_buffer[0].token]));
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
+
+ action = errorState;
+ goto _Lcheck_token;
+ }
+
+ static int tokens[] = {
+ T_PLUS,
+ T_EQ,
+
+ T_COMMA,
+ T_COLON,
+ T_SEMICOLON,
+
+ T_RPAREN, T_RBRACKET, T_RBRACE,
+
+ T_NUMERIC_LITERAL,
+ T_IDENTIFIER,
+
+ T_LPAREN, T_LBRACKET, T_LBRACE,
+
+ EOF_SYMBOL
+ };
+
+ for (int *tk = tokens; *tk != EOF_SYMBOL; ++tk) {
+ int a = t_action(errorState, *tk);
+ if (a > 0 && t_action(a, yytoken)) {
+ const QString msg = qApp->translate("QmlParser", "Expected token `%1'").arg(QLatin1String(spell[*tk]));
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
+
+ yytoken = *tk;
+ yylval = 0;
+ yylloc = token_buffer[0].loc;
+ yylloc.length = 0;
+
+ first_token = &token_buffer[0];
+ last_token = &token_buffer[2];
+
+ action = errorState;
+ goto _Lcheck_token;
+ }
+ }
+
+ for (int tk = 1; tk < TERMINAL_COUNT; ++tk) {
+ if (tk == T_AUTOMATIC_SEMICOLON || tk == T_FEED_UI_PROGRAM ||
+ tk == T_FEED_JS_STATEMENT || tk == T_FEED_JS_EXPRESSION)
+ continue;
+
+ int a = t_action(errorState, tk);
+ if (a > 0 && t_action(a, yytoken)) {
+ const QString msg = qApp->translate("QmlParser", "Expected token `%1'").arg(QLatin1String(spell[tk]));
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
+
+ yytoken = tk;
+ yylval = 0;
+ yylloc = token_buffer[0].loc;
+ yylloc.length = 0;
+
+ action = errorState;
+ goto _Lcheck_token;
+ }
+ }
+
+ const QString msg = qApp->translate("QmlParser", "Syntax error");
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
+ }
+
+ return false;
+}
+
+QT_QML_END_NAMESPACE
+
+
+./
+/:
+QT_QML_END_NAMESPACE
+
+
+
+#endif // QMLJSPARSER_P_H
+:/
diff --git a/src/declarative/qml/parser/qmljsast.cpp b/src/declarative/qml/parser/qmljsast.cpp
new file mode 100644
index 0000000..4c45bc8
--- /dev/null
+++ b/src/declarative/qml/parser/qmljsast.cpp
@@ -0,0 +1,955 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 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 "qmljsast_p.h"
+#include "qmljsastvisitor_p.h"
+
+QT_QML_BEGIN_NAMESPACE
+
+namespace QmlJS { namespace AST {
+
+void Node::accept(Visitor *visitor)
+{
+ if (visitor->preVisit(this)) {
+ accept0(visitor);
+ }
+ visitor->postVisit(this);
+}
+
+void Node::accept(Node *node, Visitor *visitor)
+{
+ if (node)
+ node->accept(visitor);
+}
+
+ExpressionNode *Node::expressionCast()
+{
+ return 0;
+}
+
+BinaryExpression *Node::binaryExpressionCast()
+{
+ return 0;
+}
+
+Statement *Node::statementCast()
+{
+ return 0;
+}
+
+UiObjectMember *Node::uiObjectMemberCast()
+{
+ return 0;
+}
+
+ExpressionNode *ExpressionNode::expressionCast()
+{
+ return this;
+}
+
+BinaryExpression *BinaryExpression::binaryExpressionCast()
+{
+ return this;
+}
+
+Statement *Statement::statementCast()
+{
+ return this;
+}
+
+UiObjectMember *UiObjectMember::uiObjectMemberCast()
+{
+ return this;
+}
+
+void NestedExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+ visitor->endVisit(this);
+}
+
+void ThisExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void IdentifierExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void NullExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void TrueLiteral::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void FalseLiteral::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void StringLiteral::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void NumericLiteral::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void RegExpLiteral::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void ArrayLiteral::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(elements, visitor);
+ accept(elision, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void ObjectLiteral::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(properties, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void ElementList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (ElementList *it = this; it; it = it->next) {
+ accept(it->elision, visitor);
+ accept(it->expression, visitor);
+ }
+ }
+
+ visitor->endVisit(this);
+}
+
+void Elision::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ // ###
+ }
+
+ visitor->endVisit(this);
+}
+
+void PropertyNameAndValueList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (PropertyNameAndValueList *it = this; it; it = it->next) {
+ accept(it->name, visitor);
+ accept(it->value, visitor);
+ }
+ }
+
+ visitor->endVisit(this);
+}
+
+void IdentifierPropertyName::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void StringLiteralPropertyName::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void NumericLiteralPropertyName::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void ArrayMemberExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(base, visitor);
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void FieldMemberExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(base, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void NewMemberExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(base, visitor);
+ accept(arguments, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void NewExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void CallExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(base, visitor);
+ accept(arguments, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void ArgumentList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (ArgumentList *it = this; it; it = it->next) {
+ accept(it->expression, visitor);
+ }
+ }
+
+ visitor->endVisit(this);
+}
+
+void PostIncrementExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(base, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void PostDecrementExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(base, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void DeleteExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void VoidExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void TypeOfExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void PreIncrementExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void PreDecrementExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UnaryPlusExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UnaryMinusExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void TildeExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void NotExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void BinaryExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(left, visitor);
+ accept(right, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void ConditionalExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ accept(ok, visitor);
+ accept(ko, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void Expression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(left, visitor);
+ accept(right, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void Block::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(statements, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void StatementList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (StatementList *it = this; it; it = it->next) {
+ accept(it->statement, visitor);
+ }
+ }
+
+ visitor->endVisit(this);
+}
+
+void VariableStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(declarations, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void VariableDeclarationList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (VariableDeclarationList *it = this; it; it = it->next) {
+ accept(it->declaration, visitor);
+ }
+ }
+
+ visitor->endVisit(this);
+}
+
+void VariableDeclaration::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void EmptyStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void ExpressionStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void IfStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ accept(ok, visitor);
+ accept(ko, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void DoWhileStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(statement, visitor);
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void WhileStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ accept(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void ForStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(initialiser, visitor);
+ accept(condition, visitor);
+ accept(expression, visitor);
+ accept(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void LocalForStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(declarations, visitor);
+ accept(condition, visitor);
+ accept(expression, visitor);
+ accept(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void ForEachStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(initialiser, visitor);
+ accept(expression, visitor);
+ accept(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void LocalForEachStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(declaration, visitor);
+ accept(expression, visitor);
+ accept(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void ContinueStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void BreakStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void ReturnStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void WithStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ accept(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void SwitchStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ accept(block, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void CaseBlock::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(clauses, visitor);
+ accept(defaultClause, visitor);
+ accept(moreClauses, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void CaseClauses::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (CaseClauses *it = this; it; it = it->next) {
+ accept(it->clause, visitor);
+ }
+ }
+
+ visitor->endVisit(this);
+}
+
+void CaseClause::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ accept(statements, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void DefaultClause::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(statements, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void LabelledStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void ThrowStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void TryStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(statement, visitor);
+ accept(catchExpression, visitor);
+ accept(finallyExpression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void Catch::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void Finally::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void FunctionDeclaration::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(formals, visitor);
+ accept(body, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void FunctionExpression::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(formals, visitor);
+ accept(body, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void FormalParameterList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ // ###
+ }
+
+ visitor->endVisit(this);
+}
+
+void FunctionBody::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(elements, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void Program::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(elements, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void SourceElements::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (SourceElements *it = this; it; it = it->next) {
+ accept(it->element, visitor);
+ }
+ }
+
+ visitor->endVisit(this);
+}
+
+void FunctionSourceElement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(declaration, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void StatementSourceElement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void DebuggerStatement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+
+void UiProgram::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(imports, visitor);
+ accept(members, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiSignature::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(formals, visitor);
+ }
+ visitor->endVisit(this);
+}
+
+void UiFormalList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (UiFormalList *it = this; it; it = it->next) {
+ accept(it->formal, visitor);
+ }
+ }
+ visitor->endVisit(this);
+}
+
+void UiFormal::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+ visitor->endVisit(this);
+}
+
+void UiPublicMember::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(expression, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiObjectDefinition::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(qualifiedTypeNameId, visitor);
+ accept(initializer, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiObjectInitializer::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(members, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiObjectBinding::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(qualifiedId, visitor);
+ accept(qualifiedTypeNameId, visitor);
+ accept(initializer, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiScriptBinding::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(qualifiedId, visitor);
+ accept(statement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiArrayBinding::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(qualifiedId, visitor);
+ accept(members, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiObjectMemberList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (UiObjectMemberList *it = this; it; it = it->next)
+ accept(it->member, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiArrayMemberList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ for (UiArrayMemberList *it = this; it; it = it->next)
+ accept(it->member, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiQualifiedId::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiImport::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(importUri, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiImportList::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(import, visitor);
+ accept(next, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+void UiSourceElement::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ accept(sourceElement, visitor);
+ }
+
+ visitor->endVisit(this);
+}
+
+} } // namespace QmlJS::AST
+
+QT_QML_END_NAMESPACE
+
+
diff --git a/src/declarative/qml/parser/qmljsast_p.h b/src/declarative/qml/parser/qmljsast_p.h
new file mode 100644
index 0000000..ef8a66b
--- /dev/null
+++ b/src/declarative/qml/parser/qmljsast_p.h
@@ -0,0 +1,2677 @@
+/****************************************************************************
+**
+** 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 QMLJSAST_P_H
+#define QMLJSAST_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 "qmljsastvisitor_p.h"
+#include "qmljsglobal_p.h"
+#include <QtCore/QString>
+
+QT_QML_BEGIN_NAMESPACE
+
+#define QMLJS_DECLARE_AST_NODE(name) \
+ enum { K = Kind_##name };
+
+namespace QSOperator // ### rename
+{
+
+enum Op {
+ Add,
+ And,
+ InplaceAnd,
+ Assign,
+ BitAnd,
+ BitOr,
+ BitXor,
+ InplaceSub,
+ Div,
+ InplaceDiv,
+ Equal,
+ Ge,
+ Gt,
+ In,
+ InplaceAdd,
+ InstanceOf,
+ Le,
+ LShift,
+ InplaceLeftShift,
+ Lt,
+ Mod,
+ InplaceMod,
+ Mul,
+ InplaceMul,
+ NotEqual,
+ Or,
+ InplaceOr,
+ RShift,
+ InplaceRightShift,
+ StrictEqual,
+ StrictNotEqual,
+ Sub,
+ URShift,
+ InplaceURightShift,
+ InplaceXor
+};
+
+} // namespace QSOperator
+
+namespace QmlJS {
+class NameId;
+namespace AST {
+
+template <typename _T1, typename _T2>
+_T1 cast(_T2 *ast)
+{
+ if (ast && ast->kind == static_cast<_T1>(0)->K)
+ return static_cast<_T1>(ast);
+
+ return 0;
+}
+
+class Node
+{
+public:
+ enum Kind {
+ Kind_Undefined,
+
+ Kind_ArgumentList,
+ Kind_ArrayLiteral,
+ Kind_ArrayMemberExpression,
+ Kind_BinaryExpression,
+ Kind_Block,
+ Kind_BreakStatement,
+ Kind_CallExpression,
+ Kind_CaseBlock,
+ Kind_CaseClause,
+ Kind_CaseClauses,
+ Kind_Catch,
+ Kind_ConditionalExpression,
+ Kind_ContinueStatement,
+ Kind_DebuggerStatement,
+ Kind_DefaultClause,
+ Kind_DeleteExpression,
+ Kind_DoWhileStatement,
+ Kind_ElementList,
+ Kind_Elision,
+ Kind_EmptyStatement,
+ Kind_Expression,
+ Kind_ExpressionStatement,
+ Kind_FalseLiteral,
+ Kind_FieldMemberExpression,
+ Kind_Finally,
+ Kind_ForEachStatement,
+ Kind_ForStatement,
+ Kind_FormalParameterList,
+ Kind_FunctionBody,
+ Kind_FunctionDeclaration,
+ Kind_FunctionExpression,
+ Kind_FunctionSourceElement,
+ Kind_IdentifierExpression,
+ Kind_IdentifierPropertyName,
+ Kind_IfStatement,
+ Kind_LabelledStatement,
+ Kind_LocalForEachStatement,
+ Kind_LocalForStatement,
+ Kind_NewExpression,
+ Kind_NewMemberExpression,
+ Kind_NotExpression,
+ Kind_NullExpression,
+ Kind_NumericLiteral,
+ Kind_NumericLiteralPropertyName,
+ Kind_ObjectLiteral,
+ Kind_PostDecrementExpression,
+ Kind_PostIncrementExpression,
+ Kind_PreDecrementExpression,
+ Kind_PreIncrementExpression,
+ Kind_Program,
+ Kind_PropertyName,
+ Kind_PropertyNameAndValueList,
+ Kind_RegExpLiteral,
+ Kind_ReturnStatement,
+ Kind_SourceElement,
+ Kind_SourceElements,
+ Kind_StatementList,
+ Kind_StatementSourceElement,
+ Kind_StringLiteral,
+ Kind_StringLiteralPropertyName,
+ Kind_SwitchStatement,
+ Kind_ThisExpression,
+ Kind_ThrowStatement,
+ Kind_TildeExpression,
+ Kind_TrueLiteral,
+ Kind_TryStatement,
+ Kind_TypeOfExpression,
+ Kind_UnaryMinusExpression,
+ Kind_UnaryPlusExpression,
+ Kind_VariableDeclaration,
+ Kind_VariableDeclarationList,
+ Kind_VariableStatement,
+ Kind_VoidExpression,
+ Kind_WhileStatement,
+ Kind_WithStatement,
+ Kind_NestedExpression,
+
+ Kind_UiArrayBinding,
+ Kind_UiImport,
+ Kind_UiImportList,
+ Kind_UiObjectBinding,
+ Kind_UiObjectDefinition,
+ Kind_UiObjectInitializer,
+ Kind_UiObjectMemberList,
+ Kind_UiArrayMemberList,
+ Kind_UiProgram,
+ Kind_UiParameterList,
+ Kind_UiPublicMember,
+ Kind_UiQualifiedId,
+ Kind_UiScriptBinding,
+ Kind_UiSourceElement,
+ Kind_UiFormal,
+ Kind_UiFormalList,
+ Kind_UiSignature
+ };
+
+ inline Node()
+ : kind(Kind_Undefined) {}
+
+ virtual ~Node() {}
+
+ virtual ExpressionNode *expressionCast();
+ virtual BinaryExpression *binaryExpressionCast();
+ virtual Statement *statementCast();
+ virtual UiObjectMember *uiObjectMemberCast();
+
+ void accept(Visitor *visitor);
+ static void accept(Node *node, Visitor *visitor);
+
+ inline static void acceptChild(Node *node, Visitor *visitor)
+ { return accept(node, visitor); } // ### remove
+
+ virtual void accept0(Visitor *visitor) = 0;
+
+// attributes
+ int kind;
+};
+
+class ExpressionNode: public Node
+{
+public:
+ ExpressionNode() {}
+ virtual ~ExpressionNode() {}
+
+ virtual ExpressionNode *expressionCast();
+
+ virtual SourceLocation firstSourceLocation() const = 0;
+ virtual SourceLocation lastSourceLocation() const = 0;
+};
+
+class Statement: public Node
+{
+public:
+ Statement() {}
+ virtual ~Statement() {}
+
+ virtual Statement *statementCast();
+
+ virtual SourceLocation firstSourceLocation() const = 0;
+ virtual SourceLocation lastSourceLocation() const = 0;
+};
+
+class UiFormal: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UiFormal)
+
+ UiFormal(NameId *name, NameId *alias = 0)
+ : name(name), alias(alias)
+ { }
+
+ virtual SourceLocation firstSourceLocation() const
+ { return SourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return SourceLocation(); }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ NameId *name;
+ NameId *alias;
+ SourceLocation identifierToken;
+ SourceLocation asToken;
+ SourceLocation aliasToken;
+};
+
+class UiFormalList: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UiFormalList)
+
+ UiFormalList(UiFormal *formal)
+ : formal(formal), next(this) {}
+
+ UiFormalList(UiFormalList *previous, UiFormal *formal)
+ : formal(formal)
+ {
+ next = previous->next;
+ previous->next = this;
+ }
+
+ UiFormalList *finish()
+ {
+ UiFormalList *head = next;
+ next = 0;
+ return head;
+ }
+
+ virtual SourceLocation firstSourceLocation() const
+ { return SourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return SourceLocation(); }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ UiFormal *formal;
+ UiFormalList *next;
+};
+
+class UiSignature: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UiSignature)
+
+ UiSignature(UiFormalList *formals = 0)
+ : formals(formals)
+ { }
+
+ virtual SourceLocation firstSourceLocation() const
+ { return SourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return SourceLocation(); }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ SourceLocation lparenToken;
+ UiFormalList *formals;
+ SourceLocation rparenToken;
+};
+
+class NestedExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(NestedExpression)
+
+ NestedExpression(ExpressionNode *expression)
+ : expression(expression)
+ { kind = K; }
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return lparenToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return rparenToken; }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation lparenToken;
+ SourceLocation rparenToken;
+};
+
+class ThisExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(ThisExpression)
+
+ ThisExpression() { kind = K; }
+ virtual ~ThisExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return thisToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return thisToken; }
+
+// attributes
+ SourceLocation thisToken;
+};
+
+class IdentifierExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(IdentifierExpression)
+
+ IdentifierExpression(NameId *n):
+ name (n) { kind = K; }
+
+ virtual ~IdentifierExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return identifierToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return identifierToken; }
+
+// attributes
+ NameId *name;
+ SourceLocation identifierToken;
+};
+
+class NullExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(NullExpression)
+
+ NullExpression() { kind = K; }
+ virtual ~NullExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return nullToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return nullToken; }
+
+// attributes
+ SourceLocation nullToken;
+};
+
+class TrueLiteral: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(TrueLiteral)
+
+ TrueLiteral() { kind = K; }
+ virtual ~TrueLiteral() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return trueToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return trueToken; }
+
+// attributes
+ SourceLocation trueToken;
+};
+
+class FalseLiteral: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(FalseLiteral)
+
+ FalseLiteral() { kind = K; }
+ virtual ~FalseLiteral() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return falseToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return falseToken; }
+
+// attributes
+ SourceLocation falseToken;
+};
+
+class NumericLiteral: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(NumericLiteral)
+
+ NumericLiteral(double v):
+ value(v) { kind = K; }
+ virtual ~NumericLiteral() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return literalToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return literalToken; }
+
+// attributes:
+ double value;
+ SourceLocation literalToken;
+};
+
+class StringLiteral: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(StringLiteral)
+
+ StringLiteral(NameId *v):
+ value (v) { kind = K; }
+
+ virtual ~StringLiteral() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return literalToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return literalToken; }
+
+// attributes:
+ NameId *value;
+ SourceLocation literalToken;
+};
+
+class RegExpLiteral: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(RegExpLiteral)
+
+ RegExpLiteral(NameId *p, int f):
+ pattern (p), flags (f) { kind = K; }
+
+ virtual ~RegExpLiteral() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return literalToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return literalToken; }
+
+// attributes:
+ NameId *pattern;
+ int flags;
+ SourceLocation literalToken;
+};
+
+class ArrayLiteral: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(ArrayLiteral)
+
+ ArrayLiteral(Elision *e):
+ elements (0), elision (e)
+ { kind = K; }
+
+ ArrayLiteral(ElementList *elts):
+ elements (elts), elision (0)
+ { kind = K; }
+
+ ArrayLiteral(ElementList *elts, Elision *e):
+ elements (elts), elision (e)
+ { kind = K; }
+
+ virtual ~ArrayLiteral() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return lbracketToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return rbracketToken; }
+
+// attributes
+ ElementList *elements;
+ Elision *elision;
+ SourceLocation lbracketToken;
+ SourceLocation commaToken;
+ SourceLocation rbracketToken;
+};
+
+class ObjectLiteral: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(ObjectLiteral)
+
+ ObjectLiteral():
+ properties (0) { kind = K; }
+
+ ObjectLiteral(PropertyNameAndValueList *plist):
+ properties (plist) { kind = K; }
+
+ virtual ~ObjectLiteral() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return lbraceToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return rbraceToken; }
+
+// attributes
+ PropertyNameAndValueList *properties;
+ SourceLocation lbraceToken;
+ SourceLocation rbraceToken;
+};
+
+class ElementList: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(ElementList)
+
+ ElementList(Elision *e, ExpressionNode *expr):
+ elision (e), expression (expr), next (this)
+ { kind = K; }
+
+ ElementList(ElementList *previous, Elision *e, ExpressionNode *expr):
+ elision (e), expression (expr)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual ~ElementList() {}
+
+ inline ElementList *finish ()
+ {
+ ElementList *front = next;
+ next = 0;
+ return front;
+ }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ Elision *elision;
+ ExpressionNode *expression;
+ ElementList *next;
+ SourceLocation commaToken;
+};
+
+class Elision: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(Elision)
+
+ Elision():
+ next (this) { kind = K; }
+
+ Elision(Elision *previous)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual ~Elision() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ inline Elision *finish ()
+ {
+ Elision *front = next;
+ next = 0;
+ return front;
+ }
+
+// attributes
+ Elision *next;
+ SourceLocation commaToken;
+};
+
+class PropertyNameAndValueList: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(PropertyNameAndValueList)
+
+ PropertyNameAndValueList(PropertyName *n, ExpressionNode *v):
+ name (n), value (v), next (this)
+ { kind = K; }
+
+ PropertyNameAndValueList(PropertyNameAndValueList *previous, PropertyName *n, ExpressionNode *v):
+ name (n), value (v)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual ~PropertyNameAndValueList() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ inline PropertyNameAndValueList *finish ()
+ {
+ PropertyNameAndValueList *front = next;
+ next = 0;
+ return front;
+ }
+
+// attributes
+ PropertyName *name;
+ ExpressionNode *value;
+ PropertyNameAndValueList *next;
+ SourceLocation colonToken;
+ SourceLocation commaToken;
+};
+
+class PropertyName: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(PropertyName)
+
+ PropertyName() { kind = K; }
+ virtual ~PropertyName() {}
+
+// attributes
+ SourceLocation propertyNameToken;
+};
+
+class IdentifierPropertyName: public PropertyName
+{
+public:
+ QMLJS_DECLARE_AST_NODE(IdentifierPropertyName)
+
+ IdentifierPropertyName(NameId *n):
+ id (n) { kind = K; }
+
+ virtual ~IdentifierPropertyName() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ NameId *id;
+};
+
+class StringLiteralPropertyName: public PropertyName
+{
+public:
+ QMLJS_DECLARE_AST_NODE(StringLiteralPropertyName)
+
+ StringLiteralPropertyName(NameId *n):
+ id (n) { kind = K; }
+ virtual ~StringLiteralPropertyName() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ NameId *id;
+};
+
+class NumericLiteralPropertyName: public PropertyName
+{
+public:
+ QMLJS_DECLARE_AST_NODE(NumericLiteralPropertyName)
+
+ NumericLiteralPropertyName(double n):
+ id (n) { kind = K; }
+ virtual ~NumericLiteralPropertyName() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ double id;
+};
+
+class ArrayMemberExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(ArrayMemberExpression)
+
+ ArrayMemberExpression(ExpressionNode *b, ExpressionNode *e):
+ base (b), expression (e)
+ { kind = K; }
+
+ virtual ~ArrayMemberExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return base->firstSourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return rbracketToken; }
+
+// attributes
+ ExpressionNode *base;
+ ExpressionNode *expression;
+ SourceLocation lbracketToken;
+ SourceLocation rbracketToken;
+};
+
+class FieldMemberExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(FieldMemberExpression)
+
+ FieldMemberExpression(ExpressionNode *b, NameId *n):
+ base (b), name (n)
+ { kind = K; }
+
+ virtual ~FieldMemberExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return base->firstSourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return identifierToken; }
+
+ // attributes
+ ExpressionNode *base;
+ NameId *name;
+ SourceLocation dotToken;
+ SourceLocation identifierToken;
+};
+
+class NewMemberExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(NewMemberExpression)
+
+ NewMemberExpression(ExpressionNode *b, ArgumentList *a):
+ base (b), arguments (a)
+ { kind = K; }
+
+ virtual ~NewMemberExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return newToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return rparenToken; }
+
+ // attributes
+ ExpressionNode *base;
+ ArgumentList *arguments;
+ SourceLocation newToken;
+ SourceLocation lparenToken;
+ SourceLocation rparenToken;
+};
+
+class NewExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(NewExpression)
+
+ NewExpression(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~NewExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return newToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return expression->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation newToken;
+};
+
+class CallExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(CallExpression)
+
+ CallExpression(ExpressionNode *b, ArgumentList *a):
+ base (b), arguments (a)
+ { kind = K; }
+
+ virtual ~CallExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return base->firstSourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return rparenToken; }
+
+// attributes
+ ExpressionNode *base;
+ ArgumentList *arguments;
+ SourceLocation lparenToken;
+ SourceLocation rparenToken;
+};
+
+class ArgumentList: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(ArgumentList)
+
+ ArgumentList(ExpressionNode *e):
+ expression (e), next (this)
+ { kind = K; }
+
+ ArgumentList(ArgumentList *previous, ExpressionNode *e):
+ expression (e)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual ~ArgumentList() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ inline ArgumentList *finish ()
+ {
+ ArgumentList *front = next;
+ next = 0;
+ return front;
+ }
+
+// attributes
+ ExpressionNode *expression;
+ ArgumentList *next;
+ SourceLocation commaToken;
+};
+
+class PostIncrementExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(PostIncrementExpression)
+
+ PostIncrementExpression(ExpressionNode *b):
+ base (b) { kind = K; }
+
+ virtual ~PostIncrementExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return base->firstSourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return incrementToken; }
+
+// attributes
+ ExpressionNode *base;
+ SourceLocation incrementToken;
+};
+
+class PostDecrementExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(PostDecrementExpression)
+
+ PostDecrementExpression(ExpressionNode *b):
+ base (b) { kind = K; }
+
+ virtual ~PostDecrementExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return base->firstSourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return decrementToken; }
+
+// attributes
+ ExpressionNode *base;
+ SourceLocation decrementToken;
+};
+
+class DeleteExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(DeleteExpression)
+
+ DeleteExpression(ExpressionNode *e):
+ expression (e) { kind = K; }
+ virtual ~DeleteExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return deleteToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return expression->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation deleteToken;
+};
+
+class VoidExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(VoidExpression)
+
+ VoidExpression(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~VoidExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return voidToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return expression->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation voidToken;
+};
+
+class TypeOfExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(TypeOfExpression)
+
+ TypeOfExpression(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~TypeOfExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return typeofToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return expression->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation typeofToken;
+};
+
+class PreIncrementExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(PreIncrementExpression)
+
+ PreIncrementExpression(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~PreIncrementExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return incrementToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return expression->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation incrementToken;
+};
+
+class PreDecrementExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(PreDecrementExpression)
+
+ PreDecrementExpression(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~PreDecrementExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return decrementToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return expression->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation decrementToken;
+};
+
+class UnaryPlusExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UnaryPlusExpression)
+
+ UnaryPlusExpression(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~UnaryPlusExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return plusToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return expression->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation plusToken;
+};
+
+class UnaryMinusExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UnaryMinusExpression)
+
+ UnaryMinusExpression(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~UnaryMinusExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return minusToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return expression->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation minusToken;
+};
+
+class TildeExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(TildeExpression)
+
+ TildeExpression(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~TildeExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return tildeToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return expression->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation tildeToken;
+};
+
+class NotExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(NotExpression)
+
+ NotExpression(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~NotExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return notToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return expression->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation notToken;
+};
+
+class BinaryExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(BinaryExpression)
+
+ BinaryExpression(ExpressionNode *l, int o, ExpressionNode *r):
+ left (l), op (o), right (r)
+ { kind = K; }
+
+ virtual ~BinaryExpression() {}
+
+ virtual BinaryExpression *binaryExpressionCast();
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return left->firstSourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return right->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *left;
+ int op;
+ ExpressionNode *right;
+ SourceLocation operatorToken;
+};
+
+class ConditionalExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(ConditionalExpression)
+
+ ConditionalExpression(ExpressionNode *e, ExpressionNode *t, ExpressionNode *f):
+ expression (e), ok (t), ko (f)
+ { kind = K; }
+
+ virtual ~ConditionalExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return expression->firstSourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return ko->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ ExpressionNode *ok;
+ ExpressionNode *ko;
+ SourceLocation questionToken;
+ SourceLocation colonToken;
+};
+
+class Expression: public ExpressionNode // ### rename
+{
+public:
+ QMLJS_DECLARE_AST_NODE(Expression)
+
+ Expression(ExpressionNode *l, ExpressionNode *r):
+ left (l), right (r) { kind = K; }
+
+ virtual ~Expression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return left->firstSourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return right->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *left;
+ ExpressionNode *right;
+ SourceLocation commaToken;
+};
+
+class Block: public Statement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(Block)
+
+ Block(StatementList *slist):
+ statements (slist) { kind = K; }
+
+ virtual ~Block() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return lbraceToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return rbraceToken; }
+
+ // attributes
+ StatementList *statements;
+ SourceLocation lbraceToken;
+ SourceLocation rbraceToken;
+};
+
+class StatementList: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(StatementList)
+
+ StatementList(Statement *stmt):
+ statement (stmt), next (this)
+ { kind = K; }
+
+ StatementList(StatementList *previous, Statement *stmt):
+ statement (stmt)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual ~StatementList() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ inline StatementList *finish ()
+ {
+ StatementList *front = next;
+ next = 0;
+ return front;
+ }
+
+// attributes
+ Statement *statement;
+ StatementList *next;
+};
+
+class VariableStatement: public Statement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(VariableStatement)
+
+ VariableStatement(VariableDeclarationList *vlist):
+ declarations (vlist)
+ { kind = K; }
+
+ virtual ~VariableStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return declarationKindToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return semicolonToken; }
+
+// attributes
+ VariableDeclarationList *declarations;
+ SourceLocation declarationKindToken;
+ SourceLocation semicolonToken;
+};
+
+class VariableDeclaration: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(VariableDeclaration)
+
+ VariableDeclaration(NameId *n, ExpressionNode *e):
+ name (n), expression (e), readOnly(false)
+ { kind = K; }
+
+ virtual ~VariableDeclaration() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ NameId *name;
+ ExpressionNode *expression;
+ bool readOnly;
+ SourceLocation identifierToken;
+};
+
+class VariableDeclarationList: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(VariableDeclarationList)
+
+ VariableDeclarationList(VariableDeclaration *decl):
+ declaration (decl), next (this)
+ { kind = K; }
+
+ VariableDeclarationList(VariableDeclarationList *previous, VariableDeclaration *decl):
+ declaration (decl)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual ~VariableDeclarationList() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ inline VariableDeclarationList *finish (bool readOnly)
+ {
+ VariableDeclarationList *front = next;
+ next = 0;
+ if (readOnly) {
+ VariableDeclarationList *vdl;
+ for (vdl = front; vdl != 0; vdl = vdl->next)
+ vdl->declaration->readOnly = true;
+ }
+ return front;
+ }
+
+// attributes
+ VariableDeclaration *declaration;
+ VariableDeclarationList *next;
+ SourceLocation commaToken;
+};
+
+class EmptyStatement: public Statement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(EmptyStatement)
+
+ EmptyStatement() { kind = K; }
+ virtual ~EmptyStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return semicolonToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return semicolonToken; }
+
+// attributes
+ SourceLocation semicolonToken;
+};
+
+class ExpressionStatement: public Statement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(ExpressionStatement)
+
+ ExpressionStatement(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~ExpressionStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return expression->firstSourceLocation(); }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return semicolonToken; }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation semicolonToken;
+};
+
+class IfStatement: public Statement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(IfStatement)
+
+ IfStatement(ExpressionNode *e, Statement *t, Statement *f = 0):
+ expression (e), ok (t), ko (f)
+ { kind = K; }
+
+ virtual ~IfStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return ifToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ {
+ if (ko)
+ return ko->lastSourceLocation();
+
+ return ok->lastSourceLocation();
+ }
+
+// attributes
+ ExpressionNode *expression;
+ Statement *ok;
+ Statement *ko;
+ SourceLocation ifToken;
+ SourceLocation lparenToken;
+ SourceLocation rparenToken;
+ SourceLocation elseToken;
+};
+
+class DoWhileStatement: public Statement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(DoWhileStatement)
+
+ DoWhileStatement(Statement *stmt, ExpressionNode *e):
+ statement (stmt), expression (e)
+ { kind = K; }
+
+ virtual ~DoWhileStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return doToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return semicolonToken; }
+
+// attributes
+ Statement *statement;
+ ExpressionNode *expression;
+ SourceLocation doToken;
+ SourceLocation whileToken;
+ SourceLocation lparenToken;
+ SourceLocation rparenToken;
+ SourceLocation semicolonToken;
+};
+
+class WhileStatement: public Statement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(WhileStatement)
+
+ WhileStatement(ExpressionNode *e, Statement *stmt):
+ expression (e), statement (stmt)
+ { kind = K; }
+
+ virtual ~WhileStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return whileToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return statement->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ Statement *statement;
+ SourceLocation whileToken;
+ SourceLocation lparenToken;
+ SourceLocation rparenToken;
+};
+
+class ForStatement: public Statement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(ForStatement)
+
+ ForStatement(ExpressionNode *i, ExpressionNode *c, ExpressionNode *e, Statement *stmt):
+ initialiser (i), condition (c), expression (e), statement (stmt)
+ { kind = K; }
+
+ virtual ~ForStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return forToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return statement->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *initialiser;
+ ExpressionNode *condition;
+ ExpressionNode *expression;
+ Statement *statement;
+ SourceLocation forToken;
+ SourceLocation lparenToken;
+ SourceLocation firstSemicolonToken;
+ SourceLocation secondSemicolonToken;
+ SourceLocation rparenToken;
+};
+
+class LocalForStatement: public Statement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(LocalForStatement)
+
+ LocalForStatement(VariableDeclarationList *vlist, ExpressionNode *c, ExpressionNode *e, Statement *stmt):
+ declarations (vlist), condition (c), expression (e), statement (stmt)
+ { kind = K; }
+
+ virtual ~LocalForStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return forToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return statement->lastSourceLocation(); }
+
+// attributes
+ VariableDeclarationList *declarations;
+ ExpressionNode *condition;
+ ExpressionNode *expression;
+ Statement *statement;
+ SourceLocation forToken;
+ SourceLocation lparenToken;
+ SourceLocation varToken;
+ SourceLocation firstSemicolonToken;
+ SourceLocation secondSemicolonToken;
+ SourceLocation rparenToken;
+};
+
+class ForEachStatement: public Statement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(ForEachStatement)
+
+ ForEachStatement(ExpressionNode *i, ExpressionNode *e, Statement *stmt):
+ initialiser (i), expression (e), statement (stmt)
+ { kind = K; }
+
+ virtual ~ForEachStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return forToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return statement->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *initialiser;
+ ExpressionNode *expression;
+ Statement *statement;
+ SourceLocation forToken;
+ SourceLocation lparenToken;
+ SourceLocation inToken;
+ SourceLocation rparenToken;
+};
+
+class LocalForEachStatement: public Statement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(LocalForEachStatement)
+
+ LocalForEachStatement(VariableDeclaration *v, ExpressionNode *e, Statement *stmt):
+ declaration (v), expression (e), statement (stmt)
+ { kind = K; }
+
+ virtual ~LocalForEachStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return forToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return statement->lastSourceLocation(); }
+
+// attributes
+ VariableDeclaration *declaration;
+ ExpressionNode *expression;
+ Statement *statement;
+ SourceLocation forToken;
+ SourceLocation lparenToken;
+ SourceLocation varToken;
+ SourceLocation inToken;
+ SourceLocation rparenToken;
+};
+
+class ContinueStatement: public Statement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(ContinueStatement)
+
+ ContinueStatement(NameId *l = 0):
+ label (l) { kind = K; }
+
+ virtual ~ContinueStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return continueToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return semicolonToken; }
+
+// attributes
+ NameId *label;
+ SourceLocation continueToken;
+ SourceLocation identifierToken;
+ SourceLocation semicolonToken;
+};
+
+class BreakStatement: public Statement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(BreakStatement)
+
+ BreakStatement(NameId *l = 0):
+ label (l) { kind = K; }
+
+ virtual ~BreakStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return breakToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return semicolonToken; }
+
+ // attributes
+ NameId *label;
+ SourceLocation breakToken;
+ SourceLocation identifierToken;
+ SourceLocation semicolonToken;
+};
+
+class ReturnStatement: public Statement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(ReturnStatement)
+
+ ReturnStatement(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~ReturnStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return returnToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return semicolonToken; }
+
+// attributes
+ ExpressionNode *expression;
+ SourceLocation returnToken;
+ SourceLocation semicolonToken;
+};
+
+class WithStatement: public Statement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(WithStatement)
+
+ WithStatement(ExpressionNode *e, Statement *stmt):
+ expression (e), statement (stmt)
+ { kind = K; }
+
+ virtual ~WithStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return withToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return statement->lastSourceLocation(); }
+
+// attributes
+ ExpressionNode *expression;
+ Statement *statement;
+ SourceLocation withToken;
+ SourceLocation lparenToken;
+ SourceLocation rparenToken;
+};
+
+class CaseBlock: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(CaseBlock)
+
+ CaseBlock(CaseClauses *c, DefaultClause *d = 0, CaseClauses *r = 0):
+ clauses (c), defaultClause (d), moreClauses (r)
+ { kind = K; }
+
+ virtual ~CaseBlock() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ CaseClauses *clauses;
+ DefaultClause *defaultClause;
+ CaseClauses *moreClauses;
+ SourceLocation lbraceToken;
+ SourceLocation rbraceToken;
+};
+
+class SwitchStatement: public Statement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(SwitchStatement)
+
+ SwitchStatement(ExpressionNode *e, CaseBlock *b):
+ expression (e), block (b)
+ { kind = K; }
+
+ virtual ~SwitchStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return switchToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return block->rbraceToken; }
+
+// attributes
+ ExpressionNode *expression;
+ CaseBlock *block;
+ SourceLocation switchToken;
+ SourceLocation lparenToken;
+ SourceLocation rparenToken;
+};
+
+class CaseClauses: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(CaseClauses)
+
+ CaseClauses(CaseClause *c):
+ clause (c), next (this)
+ { kind = K; }
+
+ CaseClauses(CaseClauses *previous, CaseClause *c):
+ clause (c)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual ~CaseClauses() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ inline CaseClauses *finish ()
+ {
+ CaseClauses *front = next;
+ next = 0;
+ return front;
+ }
+
+//attributes
+ CaseClause *clause;
+ CaseClauses *next;
+};
+
+class CaseClause: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(CaseClause)
+
+ CaseClause(ExpressionNode *e, StatementList *slist):
+ expression (e), statements (slist)
+ { kind = K; }
+
+ virtual ~CaseClause() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ ExpressionNode *expression;
+ StatementList *statements;
+ SourceLocation caseToken;
+ SourceLocation colonToken;
+};
+
+class DefaultClause: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(DefaultClause)
+
+ DefaultClause(StatementList *slist):
+ statements (slist)
+ { kind = K; }
+
+ virtual ~DefaultClause() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ StatementList *statements;
+ SourceLocation defaultToken;
+ SourceLocation colonToken;
+};
+
+class LabelledStatement: public Statement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(LabelledStatement)
+
+ LabelledStatement(NameId *l, Statement *stmt):
+ label (l), statement (stmt)
+ { kind = K; }
+
+ virtual ~LabelledStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return identifierToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return statement->lastSourceLocation(); }
+
+// attributes
+ NameId *label;
+ Statement *statement;
+ SourceLocation identifierToken;
+ SourceLocation colonToken;
+};
+
+class ThrowStatement: public Statement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(ThrowStatement)
+
+ ThrowStatement(ExpressionNode *e):
+ expression (e) { kind = K; }
+
+ virtual ~ThrowStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return throwToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return semicolonToken; }
+
+ // attributes
+ ExpressionNode *expression;
+ SourceLocation throwToken;
+ SourceLocation semicolonToken;
+};
+
+class Catch: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(Catch)
+
+ Catch(NameId *n, Block *stmt):
+ name (n), statement (stmt)
+ { kind = K; }
+
+ virtual ~Catch() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ NameId *name;
+ Block *statement;
+ SourceLocation catchToken;
+ SourceLocation lparenToken;
+ SourceLocation identifierToken;
+ SourceLocation rparenToken;
+};
+
+class Finally: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(Finally)
+
+ Finally(Block *stmt):
+ statement (stmt)
+ { kind = K; }
+
+ virtual ~Finally() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ Block *statement;
+ SourceLocation finallyToken;
+};
+
+class TryStatement: public Statement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(TryStatement)
+
+ TryStatement(Statement *stmt, Catch *c, Finally *f):
+ statement (stmt), catchExpression (c), finallyExpression (f)
+ { kind = K; }
+
+ TryStatement(Statement *stmt, Finally *f):
+ statement (stmt), catchExpression (0), finallyExpression (f)
+ { kind = K; }
+
+ TryStatement(Statement *stmt, Catch *c):
+ statement (stmt), catchExpression (c), finallyExpression (0)
+ { kind = K; }
+
+ virtual ~TryStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return tryToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ {
+ if (finallyExpression)
+ return finallyExpression->statement->rbraceToken;
+ else if (catchExpression)
+ return catchExpression->statement->rbraceToken;
+
+ return statement->lastSourceLocation();
+ }
+
+// attributes
+ Statement *statement;
+ Catch *catchExpression;
+ Finally *finallyExpression;
+ SourceLocation tryToken;
+};
+
+class FunctionExpression: public ExpressionNode
+{
+public:
+ QMLJS_DECLARE_AST_NODE(FunctionExpression)
+
+ FunctionExpression(NameId *n, FormalParameterList *f, FunctionBody *b):
+ name (n), formals (f), body (b)
+ { kind = K; }
+
+ virtual ~FunctionExpression() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return functionToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return rbraceToken; }
+
+// attributes
+ NameId *name;
+ FormalParameterList *formals;
+ FunctionBody *body;
+ SourceLocation functionToken;
+ SourceLocation identifierToken;
+ SourceLocation lparenToken;
+ SourceLocation rparenToken;
+ SourceLocation lbraceToken;
+ SourceLocation rbraceToken;
+};
+
+class FunctionDeclaration: public FunctionExpression
+{
+public:
+ QMLJS_DECLARE_AST_NODE(FunctionDeclaration)
+
+ FunctionDeclaration(NameId *n, FormalParameterList *f, FunctionBody *b):
+ FunctionExpression(n, f, b)
+ { kind = K; }
+
+ virtual ~FunctionDeclaration() {}
+
+ virtual void accept0(Visitor *visitor);
+};
+
+class FormalParameterList: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(FormalParameterList)
+
+ FormalParameterList(NameId *n):
+ name (n), next (this)
+ { kind = K; }
+
+ FormalParameterList(FormalParameterList *previous, NameId *n):
+ name (n)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual ~FormalParameterList() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ inline FormalParameterList *finish ()
+ {
+ FormalParameterList *front = next;
+ next = 0;
+ return front;
+ }
+
+// attributes
+ NameId *name;
+ FormalParameterList *next;
+ SourceLocation commaToken;
+ SourceLocation identifierToken;
+};
+
+class FunctionBody: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(FunctionBody)
+
+ FunctionBody(SourceElements *elts):
+ elements (elts)
+ { kind = K; }
+
+ virtual ~FunctionBody() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ SourceElements *elements;
+};
+
+class Program: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(Program)
+
+ Program(SourceElements *elts):
+ elements (elts)
+ { kind = K; }
+
+ virtual ~Program() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ SourceElements *elements;
+};
+
+class SourceElements: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(SourceElements)
+
+ SourceElements(SourceElement *elt):
+ element (elt), next (this)
+ { kind = K; }
+
+ SourceElements(SourceElements *previous, SourceElement *elt):
+ element (elt)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual ~SourceElements() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ inline SourceElements *finish ()
+ {
+ SourceElements *front = next;
+ next = 0;
+ return front;
+ }
+
+// attributes
+ SourceElement *element;
+ SourceElements *next;
+};
+
+class SourceElement: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(SourceElement)
+
+ inline SourceElement()
+ { kind = K; }
+
+ virtual ~SourceElement() {}
+};
+
+class FunctionSourceElement: public SourceElement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(FunctionSourceElement)
+
+ FunctionSourceElement(FunctionDeclaration *f):
+ declaration (f)
+ { kind = K; }
+
+ virtual ~FunctionSourceElement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ FunctionDeclaration *declaration;
+};
+
+class StatementSourceElement: public SourceElement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(StatementSourceElement)
+
+ StatementSourceElement(Statement *stmt):
+ statement (stmt)
+ { kind = K; }
+
+ virtual ~StatementSourceElement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ Statement *statement;
+};
+
+class DebuggerStatement: public Statement
+{
+public:
+ QMLJS_DECLARE_AST_NODE(DebuggerStatement)
+
+ DebuggerStatement()
+ { kind = K; }
+
+ virtual ~DebuggerStatement() {}
+
+ virtual void accept0(Visitor *visitor);
+
+ virtual SourceLocation firstSourceLocation() const
+ { return debuggerToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return semicolonToken; }
+
+// attributes
+ SourceLocation debuggerToken;
+ SourceLocation semicolonToken;
+};
+
+class UiProgram: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UiProgram)
+
+ UiProgram(UiImportList *imports, UiObjectMemberList *members)
+ : imports(imports), members(members)
+ { kind = K; }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ UiImportList *imports;
+ UiObjectMemberList *members;
+};
+
+class UiQualifiedId: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UiQualifiedId)
+
+ UiQualifiedId(NameId *name)
+ : next(this), name(name)
+ { kind = K; }
+
+ UiQualifiedId(UiQualifiedId *previous, NameId *name)
+ : name(name)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual ~UiQualifiedId() {}
+
+ UiQualifiedId *finish()
+ {
+ UiQualifiedId *head = next;
+ next = 0;
+ return head;
+ }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ UiQualifiedId *next;
+ NameId *name;
+ SourceLocation identifierToken;
+};
+
+class UiImport: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UiImport)
+
+ UiImport(NameId *fileName)
+ : fileName(fileName), importUri(0), importId(0)
+ { kind = K; }
+
+ UiImport(UiQualifiedId *uri)
+ : fileName(0), importUri(uri), importId(0)
+ { kind = K; }
+
+ virtual SourceLocation firstSourceLocation() const
+ { return importToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return semicolonToken; }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ NameId *fileName;
+ UiQualifiedId *importUri;
+ NameId *importId;
+ SourceLocation importToken;
+ SourceLocation fileNameToken;
+ SourceLocation versionToken;
+ SourceLocation asToken;
+ SourceLocation importIdToken;
+ SourceLocation semicolonToken;
+};
+
+class UiImportList: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UiImportList)
+
+ UiImportList(UiImport *import)
+ : import(import),
+ next(this)
+ { kind = K; }
+
+ UiImportList(UiImportList *previous, UiImport *import)
+ : import(import)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual SourceLocation firstSourceLocation() const
+ {
+ if (import) return import->firstSourceLocation();
+ else return SourceLocation();
+ }
+
+ virtual SourceLocation lastSourceLocation() const
+ {
+ for (const UiImportList *it = this; it; it = it->next)
+ if (!it->next && it->import)
+ return it->import->lastSourceLocation();
+
+ return SourceLocation();
+ }
+
+ UiImportList *finish()
+ {
+ UiImportList *head = next;
+ next = 0;
+ return head;
+ }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ UiImport *import;
+ UiImportList *next;
+};
+
+class UiObjectMember: public Node
+{
+public:
+ virtual SourceLocation firstSourceLocation() const = 0;
+ virtual SourceLocation lastSourceLocation() const = 0;
+
+ virtual UiObjectMember *uiObjectMemberCast();
+};
+
+class UiObjectMemberList: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UiObjectMemberList)
+
+ UiObjectMemberList(UiObjectMember *member)
+ : next(this), member(member)
+ { kind = K; }
+
+ UiObjectMemberList(UiObjectMemberList *previous, UiObjectMember *member)
+ : member(member)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual void accept0(Visitor *visitor);
+
+ UiObjectMemberList *finish()
+ {
+ UiObjectMemberList *head = next;
+ next = 0;
+ return head;
+ }
+
+// attributes
+ UiObjectMemberList *next;
+ UiObjectMember *member;
+};
+
+class UiArrayMemberList: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UiArrayMemberList)
+
+ UiArrayMemberList(UiObjectMember *member)
+ : next(this), member(member)
+ { kind = K; }
+
+ UiArrayMemberList(UiArrayMemberList *previous, UiObjectMember *member)
+ : member(member)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual void accept0(Visitor *visitor);
+
+ UiArrayMemberList *finish()
+ {
+ UiArrayMemberList *head = next;
+ next = 0;
+ return head;
+ }
+
+// attributes
+ UiArrayMemberList *next;
+ UiObjectMember *member;
+ SourceLocation commaToken;
+};
+
+class UiObjectInitializer: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UiObjectInitializer)
+
+ UiObjectInitializer(UiObjectMemberList *members)
+ : members(members)
+ { kind = K; }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ SourceLocation lbraceToken;
+ UiObjectMemberList *members;
+ SourceLocation rbraceToken;
+};
+
+class UiParameterList: public Node
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UiParameterList)
+
+ UiParameterList(NameId *t, NameId *n):
+ type (t), name (n), next (this)
+ { kind = K; }
+
+ UiParameterList(UiParameterList *previous, NameId *t, NameId *n):
+ type (t), name (n)
+ {
+ kind = K;
+ next = previous->next;
+ previous->next = this;
+ }
+
+ virtual ~UiParameterList() {}
+
+ virtual void accept0(Visitor *) {}
+
+ inline UiParameterList *finish ()
+ {
+ UiParameterList *front = next;
+ next = 0;
+ return front;
+ }
+
+// attributes
+ NameId *type;
+ NameId *name;
+ UiParameterList *next;
+ SourceLocation commaToken;
+ SourceLocation identifierToken;
+};
+
+class UiPublicMember: public UiObjectMember
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UiPublicMember)
+
+ UiPublicMember(NameId *memberType,
+ NameId *name)
+ : type(Property), typeModifier(0), memberType(memberType), name(name), expression(0), isDefaultMember(false), isReadonlyMember(false), parameters(0)
+ { kind = K; }
+
+ UiPublicMember(NameId *memberType,
+ NameId *name,
+ ExpressionNode *expression)
+ : type(Property), typeModifier(0), memberType(memberType), name(name), expression(expression), isDefaultMember(false), isReadonlyMember(false), parameters(0)
+ { kind = K; }
+
+ virtual SourceLocation firstSourceLocation() const
+ {
+ if (defaultToken.isValid())
+ return defaultToken;
+ else if (readonlyToken.isValid())
+ return readonlyToken;
+
+ return propertyToken;
+ }
+
+ virtual SourceLocation lastSourceLocation() const
+ {
+ return semicolonToken;
+ }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ enum { Signal, Property } type;
+ NameId *typeModifier;
+ NameId *memberType;
+ NameId *name;
+ ExpressionNode *expression;
+ bool isDefaultMember;
+ bool isReadonlyMember;
+ UiParameterList *parameters;
+ SourceLocation defaultToken;
+ SourceLocation readonlyToken;
+ SourceLocation propertyToken;
+ SourceLocation typeModifierToken;
+ SourceLocation typeToken;
+ SourceLocation identifierToken;
+ SourceLocation colonToken;
+ SourceLocation semicolonToken;
+};
+
+class UiObjectDefinition: public UiObjectMember
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UiObjectDefinition)
+
+ UiObjectDefinition(UiQualifiedId *qualifiedTypeNameId,
+ UiObjectInitializer *initializer)
+ : qualifiedTypeNameId(qualifiedTypeNameId), initializer(initializer)
+ { kind = K; }
+
+ virtual SourceLocation firstSourceLocation() const
+ { return qualifiedTypeNameId->identifierToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return initializer->rbraceToken; }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ UiQualifiedId *qualifiedTypeNameId;
+ UiObjectInitializer *initializer;
+};
+
+class UiSourceElement: public UiObjectMember
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UiSourceElement)
+
+ UiSourceElement(Node *sourceElement)
+ : sourceElement(sourceElement)
+ { kind = K; }
+
+ virtual SourceLocation firstSourceLocation() const
+ {
+ if (FunctionDeclaration *funDecl = cast<FunctionDeclaration *>(sourceElement))
+ return funDecl->firstSourceLocation();
+ else if (VariableStatement *varStmt = cast<VariableStatement *>(sourceElement))
+ return varStmt->firstSourceLocation();
+
+ return SourceLocation();
+ }
+
+ virtual SourceLocation lastSourceLocation() const
+ {
+ if (FunctionDeclaration *funDecl = cast<FunctionDeclaration *>(sourceElement))
+ return funDecl->lastSourceLocation();
+ else if (VariableStatement *varStmt = cast<VariableStatement *>(sourceElement))
+ return varStmt->lastSourceLocation();
+
+ return SourceLocation();
+ }
+
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ Node *sourceElement;
+};
+
+class UiObjectBinding: public UiObjectMember
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UiObjectBinding)
+
+ UiObjectBinding(UiQualifiedId *qualifiedId,
+ UiQualifiedId *qualifiedTypeNameId,
+ UiObjectInitializer *initializer)
+ : qualifiedId(qualifiedId),
+ qualifiedTypeNameId(qualifiedTypeNameId),
+ initializer(initializer)
+ { kind = K; }
+
+ virtual SourceLocation firstSourceLocation() const
+ { return qualifiedId->identifierToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return initializer->rbraceToken; }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ UiQualifiedId *qualifiedId;
+ UiQualifiedId *qualifiedTypeNameId;
+ UiObjectInitializer *initializer;
+ SourceLocation colonToken;
+};
+
+class UiScriptBinding: public UiObjectMember
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UiScriptBinding)
+
+ UiScriptBinding(UiQualifiedId *qualifiedId,
+ Statement *statement)
+ : qualifiedId(qualifiedId),
+ statement(statement)
+ { kind = K; }
+
+ virtual SourceLocation firstSourceLocation() const
+ { return qualifiedId->identifierToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return statement->lastSourceLocation(); }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ UiQualifiedId *qualifiedId;
+ Statement *statement;
+ SourceLocation colonToken;
+};
+
+class UiArrayBinding: public UiObjectMember
+{
+public:
+ QMLJS_DECLARE_AST_NODE(UiArrayBinding)
+
+ UiArrayBinding(UiQualifiedId *qualifiedId,
+ UiArrayMemberList *members)
+ : qualifiedId(qualifiedId),
+ members(members)
+ { kind = K; }
+
+ virtual SourceLocation firstSourceLocation() const
+ { return lbracketToken; }
+
+ virtual SourceLocation lastSourceLocation() const
+ { return rbracketToken; }
+
+ virtual void accept0(Visitor *visitor);
+
+// attributes
+ UiQualifiedId *qualifiedId;
+ UiArrayMemberList *members;
+ SourceLocation colonToken;
+ SourceLocation lbracketToken;
+ SourceLocation rbracketToken;
+};
+
+} } // namespace AST
+
+
+
+QT_QML_END_NAMESPACE
+
+#endif
diff --git a/src/declarative/qml/parser/qmljsastfwd_p.h b/src/declarative/qml/parser/qmljsastfwd_p.h
new file mode 100644
index 0000000..fcb97ad
--- /dev/null
+++ b/src/declarative/qml/parser/qmljsastfwd_p.h
@@ -0,0 +1,188 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 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 QMLJSAST_FWD_P_H
+#define QMLJSAST_FWD_P_H
+
+#include <QtCore/qglobal.h>
+#include "qmljsglobal_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.
+//
+
+QT_QML_BEGIN_NAMESPACE
+
+namespace QmlJS { namespace AST {
+
+class SourceLocation
+{
+public:
+ SourceLocation(quint32 offset = 0, quint32 length = 0, quint32 line = 0, quint32 column = 0)
+ : offset(offset), length(length),
+ startLine(line), startColumn(column)
+ { }
+
+ bool isValid() const { return length != 0; }
+
+ quint32 begin() const { return offset; }
+ quint32 end() const { return offset + length; }
+
+// attributes
+ // ### encode
+ quint32 offset;
+ quint32 length;
+ quint32 startLine;
+ quint32 startColumn;
+};
+
+class Visitor;
+class Node;
+class ExpressionNode;
+class Statement;
+class ThisExpression;
+class IdentifierExpression;
+class NullExpression;
+class TrueLiteral;
+class FalseLiteral;
+class NumericLiteral;
+class StringLiteral;
+class RegExpLiteral;
+class ArrayLiteral;
+class ObjectLiteral;
+class ElementList;
+class Elision;
+class PropertyNameAndValueList;
+class PropertyName;
+class IdentifierPropertyName;
+class StringLiteralPropertyName;
+class NumericLiteralPropertyName;
+class ArrayMemberExpression;
+class FieldMemberExpression;
+class NewMemberExpression;
+class NewExpression;
+class CallExpression;
+class ArgumentList;
+class PostIncrementExpression;
+class PostDecrementExpression;
+class DeleteExpression;
+class VoidExpression;
+class TypeOfExpression;
+class PreIncrementExpression;
+class PreDecrementExpression;
+class UnaryPlusExpression;
+class UnaryMinusExpression;
+class TildeExpression;
+class NotExpression;
+class BinaryExpression;
+class ConditionalExpression;
+class Expression; // ### rename
+class Block;
+class StatementList;
+class VariableStatement;
+class VariableDeclarationList;
+class VariableDeclaration;
+class EmptyStatement;
+class ExpressionStatement;
+class IfStatement;
+class DoWhileStatement;
+class WhileStatement;
+class ForStatement;
+class LocalForStatement;
+class ForEachStatement;
+class LocalForEachStatement;
+class ContinueStatement;
+class BreakStatement;
+class ReturnStatement;
+class WithStatement;
+class SwitchStatement;
+class CaseBlock;
+class CaseClauses;
+class CaseClause;
+class DefaultClause;
+class LabelledStatement;
+class ThrowStatement;
+class TryStatement;
+class Catch;
+class Finally;
+class FunctionDeclaration;
+class FunctionExpression;
+class FormalParameterList;
+class FunctionBody;
+class Program;
+class SourceElements;
+class SourceElement;
+class FunctionSourceElement;
+class StatementSourceElement;
+class DebuggerStatement;
+class NestedExpression;
+
+// ui elements
+class UiProgram;
+class UiImportList;
+class UiImport;
+class UiPublicMember;
+class UiObjectDefinition;
+class UiObjectInitializer;
+class UiObjectBinding;
+class UiScriptBinding;
+class UiSourceElement;
+class UiArrayBinding;
+class UiObjectMember;
+class UiObjectMemberList;
+class UiArrayMemberList;
+class UiQualifiedId;
+class UiFormalList;
+class UiFormal;
+class UiSignature;
+
+} } // namespace AST
+
+QT_QML_END_NAMESPACE
+
+#endif
diff --git a/src/declarative/qml/parser/qmljsastvisitor.cpp b/src/declarative/qml/parser/qmljsastvisitor.cpp
new file mode 100644
index 0000000..642bcee
--- /dev/null
+++ b/src/declarative/qml/parser/qmljsastvisitor.cpp
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 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 "qmljsastvisitor_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QmlJS { namespace AST {
+
+Visitor::Visitor()
+{
+}
+
+Visitor::~Visitor()
+{
+}
+
+} } // namespace QmlJS::AST
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/parser/qmljsastvisitor_p.h b/src/declarative/qml/parser/qmljsastvisitor_p.h
new file mode 100644
index 0000000..eea492a
--- /dev/null
+++ b/src/declarative/qml/parser/qmljsastvisitor_p.h
@@ -0,0 +1,335 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 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 QMLJSASTVISITOR_P_H
+#define QMLJSASTVISITOR_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 "qmljsastfwd_p.h"
+#include "qmljsglobal_p.h"
+
+QT_QML_BEGIN_NAMESPACE
+
+namespace QmlJS { namespace AST {
+
+class Visitor
+{
+public:
+ Visitor();
+ virtual ~Visitor();
+
+ virtual bool preVisit(Node *) { return true; }
+ virtual void postVisit(Node *) {}
+
+ // Ui
+ virtual bool visit(UiProgram *) { return true; }
+ virtual bool visit(UiImportList *) { return true; }
+ virtual bool visit(UiImport *) { return true; }
+ virtual bool visit(UiPublicMember *) { return true; }
+ virtual bool visit(UiSourceElement *) { return true; }
+ virtual bool visit(UiObjectDefinition *) { return true; }
+ virtual bool visit(UiObjectInitializer *) { return true; }
+ virtual bool visit(UiObjectBinding *) { return true; }
+ virtual bool visit(UiScriptBinding *) { return true; }
+ virtual bool visit(UiArrayBinding *) { return true; }
+ virtual bool visit(UiObjectMemberList *) { return true; }
+ virtual bool visit(UiArrayMemberList *) { return true; }
+ virtual bool visit(UiQualifiedId *) { return true; }
+ virtual bool visit(UiSignature *) { return true; }
+ virtual bool visit(UiFormalList *) { return true; }
+ virtual bool visit(UiFormal *) { return true; }
+
+ virtual void endVisit(UiProgram *) {}
+ virtual void endVisit(UiImportList *) {}
+ virtual void endVisit(UiImport *) {}
+ virtual void endVisit(UiPublicMember *) {}
+ virtual void endVisit(UiSourceElement *) {}
+ virtual void endVisit(UiObjectDefinition *) {}
+ virtual void endVisit(UiObjectInitializer *) {}
+ virtual void endVisit(UiObjectBinding *) {}
+ virtual void endVisit(UiScriptBinding *) {}
+ virtual void endVisit(UiArrayBinding *) {}
+ virtual void endVisit(UiObjectMemberList *) {}
+ virtual void endVisit(UiArrayMemberList *) {}
+ virtual void endVisit(UiQualifiedId *) {}
+ virtual void endVisit(UiSignature *) {}
+ virtual void endVisit(UiFormalList *) {}
+ virtual void endVisit(UiFormal *) {}
+
+ // QmlJS
+ virtual bool visit(ThisExpression *) { return true; }
+ virtual void endVisit(ThisExpression *) {}
+
+ virtual bool visit(IdentifierExpression *) { return true; }
+ virtual void endVisit(IdentifierExpression *) {}
+
+ virtual bool visit(NullExpression *) { return true; }
+ virtual void endVisit(NullExpression *) {}
+
+ virtual bool visit(TrueLiteral *) { return true; }
+ virtual void endVisit(TrueLiteral *) {}
+
+ virtual bool visit(FalseLiteral *) { return true; }
+ virtual void endVisit(FalseLiteral *) {}
+
+ virtual bool visit(StringLiteral *) { return true; }
+ virtual void endVisit(StringLiteral *) {}
+
+ virtual bool visit(NumericLiteral *) { return true; }
+ virtual void endVisit(NumericLiteral *) {}
+
+ virtual bool visit(RegExpLiteral *) { return true; }
+ virtual void endVisit(RegExpLiteral *) {}
+
+ virtual bool visit(ArrayLiteral *) { return true; }
+ virtual void endVisit(ArrayLiteral *) {}
+
+ virtual bool visit(ObjectLiteral *) { return true; }
+ virtual void endVisit(ObjectLiteral *) {}
+
+ virtual bool visit(ElementList *) { return true; }
+ virtual void endVisit(ElementList *) {}
+
+ virtual bool visit(Elision *) { return true; }
+ virtual void endVisit(Elision *) {}
+
+ virtual bool visit(PropertyNameAndValueList *) { return true; }
+ virtual void endVisit(PropertyNameAndValueList *) {}
+
+ virtual bool visit(NestedExpression *) { return true; }
+ virtual void endVisit(NestedExpression *) {}
+
+ virtual bool visit(IdentifierPropertyName *) { return true; }
+ virtual void endVisit(IdentifierPropertyName *) {}
+
+ virtual bool visit(StringLiteralPropertyName *) { return true; }
+ virtual void endVisit(StringLiteralPropertyName *) {}
+
+ virtual bool visit(NumericLiteralPropertyName *) { return true; }
+ virtual void endVisit(NumericLiteralPropertyName *) {}
+
+ virtual bool visit(ArrayMemberExpression *) { return true; }
+ virtual void endVisit(ArrayMemberExpression *) {}
+
+ virtual bool visit(FieldMemberExpression *) { return true; }
+ virtual void endVisit(FieldMemberExpression *) {}
+
+ virtual bool visit(NewMemberExpression *) { return true; }
+ virtual void endVisit(NewMemberExpression *) {}
+
+ virtual bool visit(NewExpression *) { return true; }
+ virtual void endVisit(NewExpression *) {}
+
+ virtual bool visit(CallExpression *) { return true; }
+ virtual void endVisit(CallExpression *) {}
+
+ virtual bool visit(ArgumentList *) { return true; }
+ virtual void endVisit(ArgumentList *) {}
+
+ virtual bool visit(PostIncrementExpression *) { return true; }
+ virtual void endVisit(PostIncrementExpression *) {}
+
+ virtual bool visit(PostDecrementExpression *) { return true; }
+ virtual void endVisit(PostDecrementExpression *) {}
+
+ virtual bool visit(DeleteExpression *) { return true; }
+ virtual void endVisit(DeleteExpression *) {}
+
+ virtual bool visit(VoidExpression *) { return true; }
+ virtual void endVisit(VoidExpression *) {}
+
+ virtual bool visit(TypeOfExpression *) { return true; }
+ virtual void endVisit(TypeOfExpression *) {}
+
+ virtual bool visit(PreIncrementExpression *) { return true; }
+ virtual void endVisit(PreIncrementExpression *) {}
+
+ virtual bool visit(PreDecrementExpression *) { return true; }
+ virtual void endVisit(PreDecrementExpression *) {}
+
+ virtual bool visit(UnaryPlusExpression *) { return true; }
+ virtual void endVisit(UnaryPlusExpression *) {}
+
+ virtual bool visit(UnaryMinusExpression *) { return true; }
+ virtual void endVisit(UnaryMinusExpression *) {}
+
+ virtual bool visit(TildeExpression *) { return true; }
+ virtual void endVisit(TildeExpression *) {}
+
+ virtual bool visit(NotExpression *) { return true; }
+ virtual void endVisit(NotExpression *) {}
+
+ virtual bool visit(BinaryExpression *) { return true; }
+ virtual void endVisit(BinaryExpression *) {}
+
+ virtual bool visit(ConditionalExpression *) { return true; }
+ virtual void endVisit(ConditionalExpression *) {}
+
+ virtual bool visit(Expression *) { return true; }
+ virtual void endVisit(Expression *) {}
+
+ virtual bool visit(Block *) { return true; }
+ virtual void endVisit(Block *) {}
+
+ virtual bool visit(StatementList *) { return true; }
+ virtual void endVisit(StatementList *) {}
+
+ virtual bool visit(VariableStatement *) { return true; }
+ virtual void endVisit(VariableStatement *) {}
+
+ virtual bool visit(VariableDeclarationList *) { return true; }
+ virtual void endVisit(VariableDeclarationList *) {}
+
+ virtual bool visit(VariableDeclaration *) { return true; }
+ virtual void endVisit(VariableDeclaration *) {}
+
+ virtual bool visit(EmptyStatement *) { return true; }
+ virtual void endVisit(EmptyStatement *) {}
+
+ virtual bool visit(ExpressionStatement *) { return true; }
+ virtual void endVisit(ExpressionStatement *) {}
+
+ virtual bool visit(IfStatement *) { return true; }
+ virtual void endVisit(IfStatement *) {}
+
+ virtual bool visit(DoWhileStatement *) { return true; }
+ virtual void endVisit(DoWhileStatement *) {}
+
+ virtual bool visit(WhileStatement *) { return true; }
+ virtual void endVisit(WhileStatement *) {}
+
+ virtual bool visit(ForStatement *) { return true; }
+ virtual void endVisit(ForStatement *) {}
+
+ virtual bool visit(LocalForStatement *) { return true; }
+ virtual void endVisit(LocalForStatement *) {}
+
+ virtual bool visit(ForEachStatement *) { return true; }
+ virtual void endVisit(ForEachStatement *) {}
+
+ virtual bool visit(LocalForEachStatement *) { return true; }
+ virtual void endVisit(LocalForEachStatement *) {}
+
+ virtual bool visit(ContinueStatement *) { return true; }
+ virtual void endVisit(ContinueStatement *) {}
+
+ virtual bool visit(BreakStatement *) { return true; }
+ virtual void endVisit(BreakStatement *) {}
+
+ virtual bool visit(ReturnStatement *) { return true; }
+ virtual void endVisit(ReturnStatement *) {}
+
+ virtual bool visit(WithStatement *) { return true; }
+ virtual void endVisit(WithStatement *) {}
+
+ virtual bool visit(SwitchStatement *) { return true; }
+ virtual void endVisit(SwitchStatement *) {}
+
+ virtual bool visit(CaseBlock *) { return true; }
+ virtual void endVisit(CaseBlock *) {}
+
+ virtual bool visit(CaseClauses *) { return true; }
+ virtual void endVisit(CaseClauses *) {}
+
+ virtual bool visit(CaseClause *) { return true; }
+ virtual void endVisit(CaseClause *) {}
+
+ virtual bool visit(DefaultClause *) { return true; }
+ virtual void endVisit(DefaultClause *) {}
+
+ virtual bool visit(LabelledStatement *) { return true; }
+ virtual void endVisit(LabelledStatement *) {}
+
+ virtual bool visit(ThrowStatement *) { return true; }
+ virtual void endVisit(ThrowStatement *) {}
+
+ virtual bool visit(TryStatement *) { return true; }
+ virtual void endVisit(TryStatement *) {}
+
+ virtual bool visit(Catch *) { return true; }
+ virtual void endVisit(Catch *) {}
+
+ virtual bool visit(Finally *) { return true; }
+ virtual void endVisit(Finally *) {}
+
+ virtual bool visit(FunctionDeclaration *) { return true; }
+ virtual void endVisit(FunctionDeclaration *) {}
+
+ virtual bool visit(FunctionExpression *) { return true; }
+ virtual void endVisit(FunctionExpression *) {}
+
+ virtual bool visit(FormalParameterList *) { return true; }
+ virtual void endVisit(FormalParameterList *) {}
+
+ virtual bool visit(FunctionBody *) { return true; }
+ virtual void endVisit(FunctionBody *) {}
+
+ virtual bool visit(Program *) { return true; }
+ virtual void endVisit(Program *) {}
+
+ virtual bool visit(SourceElements *) { return true; }
+ virtual void endVisit(SourceElements *) {}
+
+ virtual bool visit(FunctionSourceElement *) { return true; }
+ virtual void endVisit(FunctionSourceElement *) {}
+
+ virtual bool visit(StatementSourceElement *) { return true; }
+ virtual void endVisit(StatementSourceElement *) {}
+
+ virtual bool visit(DebuggerStatement *) { return true; }
+ virtual void endVisit(DebuggerStatement *) {}
+};
+
+} } // namespace AST
+
+QT_QML_END_NAMESPACE
+
+#endif // QMLJSASTVISITOR_P_H
diff --git a/src/declarative/qml/parser/qmljsengine_p.cpp b/src/declarative/qml/parser/qmljsengine_p.cpp
new file mode 100644
index 0000000..32068c0
--- /dev/null
+++ b/src/declarative/qml/parser/qmljsengine_p.cpp
@@ -0,0 +1,210 @@
+/****************************************************************************
+**
+** 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 "qmljsglobal_p.h"
+#include "qmljsengine_p.h"
+#include "qmljsnodepool_p.h"
+#include <qnumeric.h>
+#include <QHash>
+
+QT_QML_BEGIN_NAMESPACE
+
+namespace QmlJS {
+
+uint qHash(const QmlJS::NameId &id)
+{ return qHash(id.asString()); }
+
+QString numberToString(double value)
+{ return QString::number(value); }
+
+int Ecma::RegExp::flagFromChar(const QChar &ch)
+{
+ static QHash<QChar, int> flagsHash;
+ if (flagsHash.isEmpty()) {
+ flagsHash[QLatin1Char('g')] = Global;
+ flagsHash[QLatin1Char('i')] = IgnoreCase;
+ flagsHash[QLatin1Char('m')] = Multiline;
+ }
+ QHash<QChar, int>::const_iterator it;
+ it = flagsHash.constFind(ch);
+ if (it == flagsHash.constEnd())
+ return 0;
+ return it.value();
+}
+
+QString Ecma::RegExp::flagsToString(int flags)
+{
+ QString result;
+ if (flags & Global)
+ result += QLatin1Char('g');
+ if (flags & IgnoreCase)
+ result += QLatin1Char('i');
+ if (flags & Multiline)
+ result += QLatin1Char('m');
+ return result;
+}
+
+NodePool::NodePool(const QString &fileName, Engine *engine)
+ : m_fileName(fileName), m_engine(engine)
+{
+ m_engine->setNodePool(this);
+}
+
+NodePool::~NodePool()
+{
+}
+
+Code *NodePool::createCompiledCode(AST::Node *, CompilationUnit &)
+{
+ Q_ASSERT(0);
+ return 0;
+}
+
+static int toDigit(char c)
+{
+ if ((c >= '0') && (c <= '9'))
+ return c - '0';
+ else if ((c >= 'a') && (c <= 'z'))
+ return 10 + c - 'a';
+ else if ((c >= 'A') && (c <= 'Z'))
+ return 10 + c - 'A';
+ return -1;
+}
+
+double integerFromString(const char *buf, int size, int radix)
+{
+ if (size == 0)
+ return qSNaN();
+
+ double sign = 1.0;
+ int i = 0;
+ if (buf[0] == '+') {
+ ++i;
+ } else if (buf[0] == '-') {
+ sign = -1.0;
+ ++i;
+ }
+
+ if (((size-i) >= 2) && (buf[i] == '0')) {
+ if (((buf[i+1] == 'x') || (buf[i+1] == 'X'))
+ && (radix < 34)) {
+ if ((radix != 0) && (radix != 16))
+ return 0;
+ radix = 16;
+ i += 2;
+ } else {
+ if (radix == 0) {
+ radix = 8;
+ ++i;
+ }
+ }
+ } else if (radix == 0) {
+ radix = 10;
+ }
+
+ int j = i;
+ for ( ; i < size; ++i) {
+ int d = toDigit(buf[i]);
+ if ((d == -1) || (d >= radix))
+ break;
+ }
+ double result;
+ if (j == i) {
+ if (!qstrcmp(buf, "Infinity"))
+ result = qInf();
+ else
+ result = qSNaN();
+ } else {
+ result = 0;
+ double multiplier = 1;
+ for (--i ; i >= j; --i, multiplier *= radix)
+ result += toDigit(buf[i]) * multiplier;
+ }
+ result *= sign;
+ return result;
+}
+
+double integerFromString(const QString &str, int radix)
+{
+ QByteArray ba = str.trimmed().toLatin1();
+ return integerFromString(ba.constData(), ba.size(), radix);
+}
+
+
+Engine::Engine()
+ : _lexer(0), _nodePool(0)
+{ }
+
+Engine::~Engine()
+{ }
+
+QSet<NameId> Engine::literals() const
+{ return _literals; }
+
+void Engine::addComment(int pos, int len, int line, int col)
+{ if (len > 0) _comments.append(QmlJS::AST::SourceLocation(pos, len, line, col)); }
+
+QList<QmlJS::AST::SourceLocation> Engine::comments() const
+{ return _comments; }
+
+NameId *Engine::intern(const QChar *u, int s)
+{ return const_cast<NameId *>(&*_literals.insert(NameId(u, s))); }
+
+QString Engine::toString(NameId *id)
+{ return id->asString(); }
+
+Lexer *Engine::lexer() const
+{ return _lexer; }
+
+void Engine::setLexer(Lexer *lexer)
+{ _lexer = lexer; }
+
+NodePool *Engine::nodePool() const
+{ return _nodePool; }
+
+void Engine::setNodePool(NodePool *nodePool)
+{ _nodePool = nodePool; }
+
+
+
+} // end of namespace QmlJS
+
+QT_QML_END_NAMESPACE
diff --git a/src/declarative/qml/parser/qmljsengine_p.h b/src/declarative/qml/parser/qmljsengine_p.h
new file mode 100644
index 0000000..8627a99
--- /dev/null
+++ b/src/declarative/qml/parser/qmljsengine_p.h
@@ -0,0 +1,173 @@
+/****************************************************************************
+**
+** 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 QMLJSENGINE_P_H
+#define QMLJSENGINE_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 <QString>
+#include <QSet>
+
+#include "qmljsglobal_p.h"
+#include "qmljsastfwd_p.h"
+
+QT_QML_BEGIN_NAMESPACE
+
+namespace QmlJS {
+class NameId
+{
+ QString _text;
+
+public:
+ NameId(const QChar *u, int s)
+ : _text(u, s)
+ { }
+
+ const QString asString() const
+ { return _text; }
+
+ bool operator == (const NameId &other) const
+ { return _text == other._text; }
+
+ bool operator != (const NameId &other) const
+ { return _text != other._text; }
+
+ bool operator < (const NameId &other) const
+ { return _text < other._text; }
+};
+
+uint qHash(const QmlJS::NameId &id);
+
+} // end of namespace QmlJS
+
+#if defined(Q_CC_MSVC) && _MSC_VER <= 1300
+//this ensures that code outside QmlJS can use the hash function
+//it also a workaround for some compilers
+inline uint qHash(const QmlJS::NameId &nameId) { return QmlJS::qHash(nameId); }
+#endif
+
+namespace QmlJS {
+
+class Lexer;
+class NodePool;
+
+namespace Ecma {
+
+class RegExp
+{
+public:
+ enum RegExpFlag {
+ Global = 0x01,
+ IgnoreCase = 0x02,
+ Multiline = 0x04
+ };
+
+public:
+ static int flagFromChar(const QChar &);
+ static QString flagsToString(int flags);
+};
+
+} // end of namespace Ecma
+
+class DiagnosticMessage
+{
+public:
+ enum Kind { Warning, Error };
+
+ DiagnosticMessage()
+ : kind(Error) {}
+
+ DiagnosticMessage(Kind kind, const AST::SourceLocation &loc, const QString &message)
+ : kind(kind), loc(loc), message(message) {}
+
+ bool isWarning() const
+ { return kind == Warning; }
+
+ bool isError() const
+ { return kind == Error; }
+
+ Kind kind;
+ AST::SourceLocation loc;
+ QString message;
+};
+
+class Engine
+{
+ Lexer *_lexer;
+ NodePool *_nodePool;
+ QSet<NameId> _literals;
+ QList<QmlJS::AST::SourceLocation> _comments;
+
+public:
+ Engine();
+ ~Engine();
+
+ QSet<NameId> literals() const;
+
+ void addComment(int pos, int len, int line, int col);
+ QList<QmlJS::AST::SourceLocation> comments() const;
+
+ NameId *intern(const QChar *u, int s);
+
+ static QString toString(NameId *id);
+
+ Lexer *lexer() const;
+ void setLexer(Lexer *lexer);
+
+ NodePool *nodePool() const;
+ void setNodePool(NodePool *nodePool);
+};
+
+} // end of namespace QmlJS
+
+QT_QML_END_NAMESPACE
+
+#endif // QMLJSENGINE_P_H
diff --git a/src/declarative/qml/parser/qmljsglobal_p.h b/src/declarative/qml/parser/qmljsglobal_p.h
new file mode 100644
index 0000000..99bb19f
--- /dev/null
+++ b/src/declarative/qml/parser/qmljsglobal_p.h
@@ -0,0 +1,14 @@
+#ifndef QMLJSGLOBAL_P_H
+#define QMLJSGLOBAL_P_H
+
+#include <QtCore/qglobal.h>
+
+#ifdef QT_CREATOR
+#define QT_QML_BEGIN_NAMESPACE
+#define QT_QML_END_NAMESPACE
+#else // !QT_CREATOR
+#define QT_QML_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
+#define QT_QML_END_NAMESPACE QT_END_NAMESPACE
+#endif // QT_CREATOR
+
+#endif // QMLJSGLOBAL_P_H
diff --git a/src/declarative/qml/parser/qmljsgrammar.cpp b/src/declarative/qml/parser/qmljsgrammar.cpp
new file mode 100644
index 0000000..da3ce2a
--- /dev/null
+++ b/src/declarative/qml/parser/qmljsgrammar.cpp
@@ -0,0 +1,960 @@
+// This file was generated by qlalr - DO NOT EDIT!
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore 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 "qmljsgrammar_p.h"
+
+const char *const QmlJSGrammar::spell [] = {
+ "end of file", "&", "&&", "&=", "break", "case", "catch", ":", ";", "continue",
+ "default", "delete", "/", "/=", "do", ".", "else", "=", "==", "===",
+ "finally", "for", "function", ">=", ">", ">>", ">>=", ">>>", ">>>=", "identifier",
+ "if", "in", "instanceof", "{", "[", "<=", "(", "<", "<<", "<<=",
+ "-", "-=", "--", "new", "!", "!=", "!==", "numeric literal", "|", "|=",
+ "||", "+", "+=", "++", "?", "}", "]", "%", "%=", "return",
+ ")", ";", 0, "*", "*=", "string literal", "property", "signal", "readonly", "switch",
+ "this", "throw", "~", "try", "typeof", "var", "void", "while", "with", "^",
+ "^=", "null", "true", "false", "const", "debugger", "reserved word", "multiline string literal", "comment", "public",
+ "import", "as", 0, 0, 0, 0, 0, 0};
+
+const int QmlJSGrammar::lhs [] = {
+ 98, 98, 98, 98, 99, 103, 103, 106, 106, 108,
+ 107, 107, 107, 107, 107, 107, 107, 107, 110, 105,
+ 104, 113, 113, 114, 114, 115, 115, 112, 102, 102,
+ 102, 102, 102, 102, 102, 121, 121, 121, 122, 122,
+ 123, 123, 102, 102, 102, 102, 102, 102, 102, 102,
+ 102, 102, 102, 102, 102, 102, 102, 102, 102, 102,
+ 111, 111, 111, 111, 126, 126, 126, 126, 126, 126,
+ 126, 126, 126, 126, 126, 126, 126, 126, 126, 126,
+ 126, 126, 116, 128, 128, 128, 128, 127, 127, 130,
+ 130, 132, 132, 132, 132, 132, 132, 133, 133, 133,
+ 133, 133, 133, 133, 133, 133, 133, 133, 133, 133,
+ 133, 133, 133, 133, 133, 133, 133, 133, 133, 133,
+ 133, 133, 133, 133, 133, 133, 133, 133, 134, 134,
+ 109, 109, 109, 109, 109, 137, 137, 138, 138, 138,
+ 138, 136, 136, 139, 139, 140, 140, 141, 141, 141,
+ 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
+ 143, 143, 143, 143, 144, 144, 144, 145, 145, 145,
+ 145, 146, 146, 146, 146, 146, 146, 146, 147, 147,
+ 147, 147, 147, 147, 148, 148, 148, 148, 148, 149,
+ 149, 149, 149, 149, 150, 150, 151, 151, 152, 152,
+ 153, 153, 154, 154, 155, 155, 156, 156, 157, 157,
+ 158, 158, 159, 159, 160, 160, 161, 161, 131, 131,
+ 162, 162, 163, 163, 163, 163, 163, 163, 163, 163,
+ 163, 163, 163, 163, 101, 101, 164, 164, 165, 165,
+ 166, 166, 100, 100, 100, 100, 100, 100, 100, 100,
+ 100, 100, 100, 100, 100, 100, 100, 117, 178, 178,
+ 177, 177, 125, 125, 179, 179, 180, 180, 182, 182,
+ 181, 183, 186, 184, 184, 187, 185, 185, 118, 119,
+ 119, 120, 120, 167, 167, 167, 167, 167, 167, 167,
+ 168, 168, 168, 168, 169, 169, 169, 169, 170, 170,
+ 171, 173, 188, 188, 191, 191, 189, 189, 192, 190,
+ 172, 172, 172, 174, 174, 175, 175, 175, 193, 194,
+ 176, 176, 124, 135, 198, 198, 195, 195, 196, 196,
+ 199, 200, 200, 201, 201, 197, 197, 129, 129, 202};
+
+const int QmlJSGrammar:: rhs[] = {
+ 2, 2, 2, 2, 2, 1, 1, 1, 2, 1,
+ 2, 2, 3, 3, 5, 5, 4, 4, 2, 0,
+ 1, 1, 2, 1, 3, 2, 3, 2, 1, 5,
+ 4, 3, 3, 3, 3, 1, 1, 1, 0, 1,
+ 2, 4, 6, 6, 3, 3, 7, 7, 4, 4,
+ 5, 5, 6, 6, 7, 7, 7, 7, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 2, 3, 3, 4, 5, 3,
+ 4, 3, 1, 1, 2, 3, 4, 1, 2, 3,
+ 5, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 4, 3, 5, 1, 2, 4, 4, 4,
+ 3, 0, 1, 1, 3, 1, 1, 1, 2, 2,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 1, 3, 3, 3, 1, 3, 3, 1, 3, 3,
+ 3, 1, 3, 3, 3, 3, 3, 3, 1, 3,
+ 3, 3, 3, 3, 1, 3, 3, 3, 3, 1,
+ 3, 3, 3, 3, 1, 3, 1, 3, 1, 3,
+ 1, 3, 1, 3, 1, 3, 1, 3, 1, 3,
+ 1, 3, 1, 3, 1, 5, 1, 5, 1, 3,
+ 1, 3, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 3, 0, 1, 1, 3,
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 3, 1, 2,
+ 0, 1, 3, 3, 1, 1, 1, 3, 1, 3,
+ 2, 2, 2, 0, 1, 2, 0, 1, 1, 2,
+ 2, 7, 5, 7, 7, 5, 9, 10, 7, 8,
+ 2, 2, 3, 3, 2, 2, 3, 3, 3, 3,
+ 5, 5, 3, 5, 1, 2, 0, 1, 4, 3,
+ 3, 3, 3, 3, 3, 3, 3, 4, 5, 2,
+ 2, 2, 8, 8, 1, 3, 0, 1, 0, 1,
+ 1, 1, 2, 1, 1, 0, 1, 0, 1, 2};
+
+const int QmlJSGrammar::action_default [] = {
+ 0, 0, 0, 0, 20, 0, 168, 235, 199, 207,
+ 203, 147, 219, 195, 3, 132, 66, 148, 211, 215,
+ 136, 165, 146, 151, 131, 185, 172, 0, 73, 74,
+ 69, 336, 61, 338, 0, 0, 0, 0, 71, 0,
+ 0, 67, 70, 0, 0, 62, 64, 63, 72, 65,
+ 0, 68, 0, 0, 161, 0, 0, 148, 167, 150,
+ 149, 0, 0, 0, 163, 164, 162, 166, 0, 196,
+ 0, 0, 0, 0, 186, 0, 0, 0, 0, 0,
+ 0, 176, 0, 0, 0, 170, 171, 169, 174, 178,
+ 177, 175, 173, 188, 187, 189, 0, 204, 0, 200,
+ 0, 0, 142, 129, 141, 130, 98, 99, 100, 125,
+ 101, 126, 102, 103, 104, 105, 106, 107, 108, 109,
+ 110, 111, 112, 113, 114, 127, 115, 116, 117, 118,
+ 119, 120, 121, 122, 123, 124, 128, 0, 0, 140,
+ 236, 143, 0, 144, 0, 145, 139, 0, 232, 225,
+ 223, 230, 231, 229, 228, 234, 227, 226, 224, 233,
+ 220, 0, 208, 0, 0, 212, 0, 0, 216, 0,
+ 0, 142, 134, 0, 133, 0, 138, 152, 0, 337,
+ 327, 328, 0, 325, 0, 326, 0, 329, 243, 250,
+ 249, 257, 245, 0, 246, 330, 0, 335, 247, 248,
+ 253, 251, 332, 331, 334, 254, 0, 265, 0, 0,
+ 0, 0, 336, 61, 0, 338, 62, 237, 279, 63,
+ 0, 0, 0, 266, 0, 0, 255, 256, 0, 244,
+ 252, 280, 281, 324, 333, 0, 295, 296, 297, 298,
+ 0, 291, 292, 293, 294, 321, 322, 0, 0, 0,
+ 0, 0, 284, 285, 241, 239, 201, 209, 205, 221,
+ 197, 242, 0, 148, 213, 217, 190, 179, 0, 0,
+ 198, 0, 0, 0, 0, 191, 0, 0, 0, 0,
+ 0, 183, 181, 184, 182, 180, 193, 192, 194, 0,
+ 206, 0, 202, 0, 240, 148, 0, 222, 237, 238,
+ 0, 237, 0, 0, 287, 0, 0, 0, 289, 0,
+ 210, 0, 0, 214, 0, 0, 218, 277, 0, 269,
+ 278, 272, 0, 276, 0, 237, 270, 0, 237, 0,
+ 0, 288, 0, 0, 0, 290, 337, 327, 0, 0,
+ 329, 0, 323, 0, 313, 0, 0, 0, 283, 0,
+ 282, 0, 339, 0, 97, 259, 262, 0, 98, 265,
+ 101, 126, 103, 104, 69, 108, 109, 61, 110, 113,
+ 67, 70, 62, 237, 63, 72, 116, 65, 118, 68,
+ 120, 121, 266, 123, 124, 128, 0, 90, 0, 0,
+ 92, 96, 94, 81, 93, 95, 0, 91, 80, 260,
+ 258, 136, 137, 142, 0, 135, 0, 312, 0, 299,
+ 300, 0, 311, 0, 0, 0, 302, 307, 305, 308,
+ 0, 0, 306, 307, 0, 303, 0, 304, 261, 310,
+ 0, 261, 309, 0, 314, 315, 0, 261, 316, 317,
+ 0, 0, 318, 0, 0, 0, 319, 320, 154, 153,
+ 0, 0, 0, 286, 0, 0, 0, 301, 274, 267,
+ 0, 275, 271, 0, 273, 263, 0, 264, 268, 84,
+ 0, 0, 88, 75, 0, 77, 86, 0, 78, 87,
+ 89, 79, 85, 76, 0, 82, 158, 156, 160, 157,
+ 155, 159, 2, 59, 83, 0, 0, 62, 64, 63,
+ 29, 4, 0, 60, 0, 38, 37, 36, 0, 0,
+ 51, 0, 52, 0, 57, 58, 0, 38, 0, 0,
+ 0, 0, 0, 47, 48, 0, 49, 0, 50, 0,
+ 53, 54, 0, 0, 0, 0, 0, 55, 56, 0,
+ 45, 39, 46, 40, 0, 0, 0, 0, 42, 0,
+ 43, 44, 41, 0, 0, 28, 32, 33, 34, 35,
+ 136, 261, 0, 0, 98, 265, 101, 126, 103, 104,
+ 69, 108, 109, 61, 110, 113, 67, 70, 62, 237,
+ 63, 72, 116, 65, 118, 68, 120, 121, 266, 123,
+ 124, 128, 136, 0, 24, 0, 0, 30, 25, 31,
+ 26, 22, 0, 27, 23, 6, 0, 8, 0, 7,
+ 0, 1, 19, 10, 0, 11, 0, 12, 0, 17,
+ 18, 0, 13, 14, 0, 15, 16, 9, 21, 5,
+ 340};
+
+const int QmlJSGrammar::goto_default [] = {
+ 5, 611, 355, 193, 501, 610, 629, 605, 609, 607,
+ 612, 20, 608, 16, 500, 602, 593, 555, 502, 188,
+ 192, 194, 198, 518, 544, 543, 197, 229, 24, 471,
+ 470, 353, 352, 7, 351, 354, 104, 15, 142, 22,
+ 11, 141, 17, 23, 54, 21, 6, 26, 25, 266,
+ 13, 260, 8, 256, 10, 258, 9, 257, 18, 264,
+ 19, 265, 12, 259, 255, 296, 408, 261, 262, 199,
+ 190, 189, 201, 230, 200, 205, 226, 227, 191, 357,
+ 356, 228, 460, 459, 318, 319, 462, 321, 461, 320,
+ 416, 420, 423, 419, 418, 438, 439, 182, 196, 178,
+ 181, 195, 203, 202, 0};
+
+const int QmlJSGrammar::action_index [] = {
+ 251, 1237, 2238, 974, -45, 51, 122, -98, 52, -11,
+ -39, 182, -98, 389, 36, -98, -98, 628, 58, 75,
+ 246, 228, -98, -98, -98, 438, 309, 1237, -98, -98,
+ -98, 348, -98, 2050, 1772, 1237, 1237, 1237, -98, 800,
+ 1237, -98, -98, 1237, 1237, -98, -98, -98, -98, -98,
+ 1237, -98, 1237, 1237, -98, 1237, 1237, 97, 226, -98,
+ -98, 1237, 1237, 1237, -98, -98, -98, 200, 1237, 389,
+ 1237, 1237, 1237, 1237, 418, 1237, 1237, 1237, 1237, 1237,
+ 1237, 212, 1237, 1237, 1237, 144, 121, 71, 309, 309,
+ 164, 156, 179, 448, 428, 408, 1237, -51, 1237, 101,
+ 1956, 1237, 1237, -98, -98, -98, -98, -98, -98, -98,
+ -98, -98, -98, -98, -98, -98, -98, -98, -98, -98,
+ -98, -98, -98, -98, -98, -98, -98, -98, -98, -98,
+ -98, -98, -98, -98, -98, -98, -98, 236, 1237, -98,
+ -98, 31, 16, -98, 1237, -98, -98, 1237, -98, -98,
+ -98, -98, -98, -98, -98, -98, -98, -98, -98, -98,
+ -98, 1237, 2, 1237, 1237, 41, 35, 1237, -98, 1956,
+ 1237, 1237, -98, 102, -98, 6, -98, -98, 20, -98,
+ 299, 53, 14, -98, 321, -98, -22, 2332, -98, -98,
+ -98, -98, -98, 216, -98, -98, -28, -98, -98, -98,
+ -98, -98, -98, 2332, -98, -98, 469, -98, 533, 115,
+ 2238, -2, 335, -3, -36, 2520, 50, 1237, -98, 64,
+ 33, 1237, 21, -98, 5, -14, -98, -98, 306, -98,
+ -98, -98, -98, -98, -98, 74, -98, -98, -98, -98,
+ 117, -98, -98, -98, -98, -98, -98, -57, -18, 1237,
+ 140, 109, -98, -98, 1324, -98, 104, 67, 27, -98,
+ 330, 84, 29, 585, 80, 92, 464, 171, 295, 1237,
+ 314, 1237, 1237, 1237, 1237, 346, 1237, 1237, 1237, 1237,
+ 1237, 309, 309, 309, 309, 309, 386, 464, 464, 1237,
+ 27, 1237, 87, 1237, -98, 529, 1237, -98, 1237, 83,
+ 38, 1237, 48, 2238, -98, 1237, 143, 2238, -98, 1237,
+ 30, 1237, 1237, 81, 77, 1237, -98, 56, 126, 90,
+ -98, -98, 1237, -98, 290, 1237, -98, 42, 1237, 44,
+ 2238, -98, 1237, 133, 2238, -98, 22, 285, -37, -9,
+ 2332, -30, -98, 2238, -98, 1237, 141, 2238, 10, 2238,
+ -98, 26, 24, -24, -98, -98, 2238, 25, 453, 23,
+ 533, 106, 1237, 2238, 9, -29, 361, -4, -31, 800,
+ -6, 55, -98, 1415, -98, -1, -23, 8, 1237, 7,
+ -21, 1237, 1, 1237, -27, -19, 1237, -98, 2144, 28,
+ -98, -98, -98, -98, -98, -98, 1237, -98, -98, -98,
+ -98, 211, -98, 1237, 17, -98, 2238, -98, 98, -98,
+ -98, 2238, -98, 1237, 105, 37, -98, 63, -98, 62,
+ 99, 1237, -98, 60, 57, -98, 4, -98, 2238, -98,
+ 116, 2238, -98, 180, -98, -98, 112, 2238, 18, -98,
+ 11, 13, -98, 325, 3, 19, -98, -98, -98, -98,
+ 1237, 132, 2238, -98, 1237, 139, 2238, -98, 32, -98,
+ 174, -98, -98, 1237, -98, -98, 229, -98, -98, -98,
+ 108, 1682, -98, -98, 1862, -98, -98, 1505, -98, -98,
+ -98, -98, -98, -98, 125, -98, -98, -98, -98, -98,
+ -98, -98, -98, -98, 111, 46, 792, 184, 34, 85,
+ -98, -98, 136, -98, 185, -98, -98, -98, 65, 204,
+ -98, 1237, -98, 207, -98, -98, 193, 61, 43, 225,
+ 73, 88, 66, -98, -98, 214, -98, 1237, -98, 158,
+ -98, -98, 181, 91, 72, 1237, 172, -98, -98, 187,
+ -98, 157, -98, 47, -50, 274, 178, 250, -98, 113,
+ -98, -98, -98, 1592, 1062, -98, -98, -98, -98, -98,
+ 271, 2426, 1772, 15, 461, 146, 445, 76, 1237, 2238,
+ -5, 0, 370, 12, -15, 706, 89, 78, -98, 1415,
+ -98, 100, 59, 82, 1237, 86, 54, 1237, 79, 1237,
+ 45, 39, 279, 149, -98, 68, 617, -98, -98, -98,
+ -98, -98, 1150, -98, -98, -98, 886, -98, 240, -61,
+ 714, -98, -98, 129, 259, -98, 190, -98, 69, -98,
+ -98, 255, -98, -98, 94, -98, -98, -98, -98, -98,
+ -98,
+
+ -105, 23, 25, 216, -105, -105, -105, -105, -105, -105,
+ -105, -105, -105, -105, -105, -105, -105, -44, -105, -105,
+ -105, -105, -105, -105, -105, -105, -105, 70, -105, -105,
+ -105, 28, -105, -105, 20, 39, 97, 163, -105, 178,
+ 159, -105, -105, 156, 164, -105, -105, -105, -105, -105,
+ 132, -105, 153, 135, -105, 139, 140, -105, -105, -105,
+ -105, 103, 92, 144, -105, -105, -105, -105, 125, -105,
+ 154, 162, 83, 84, -105, 88, 82, 81, 75, 66,
+ 122, -105, 116, 98, 104, -105, -105, -105, -105, -105,
+ -105, -105, -105, -105, -105, -105, 106, -105, 113, -105,
+ 86, 80, 52, -105, -105, -105, -105, -105, -105, -105,
+ -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+ -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+ -105, -105, -105, -105, -105, -105, -105, -105, 34, -105,
+ -105, -105, -105, -105, 38, -105, -105, 43, -105, -105,
+ -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+ -105, 136, -105, 91, -29, -105, -105, 3, -105, 225,
+ 37, 71, -105, -105, -105, -105, -105, -105, -105, -105,
+ -3, -105, -105, -105, 18, -105, -105, 27, -105, -105,
+ -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+ -105, -105, -105, 87, -105, -105, 62, -105, 56, -105,
+ 50, -105, 31, -105, -105, -105, -105, 59, -105, -105,
+ -105, 47, 69, -105, -105, -105, -105, -105, 67, -105,
+ -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+ -105, -105, -105, -105, -105, -105, -105, -105, -105, 30,
+ -105, -105, -105, -105, 96, -105, -105, -105, -105, -105,
+ -105, -105, -105, -105, -105, -105, -105, -105, 10, 184,
+ -105, 222, 226, 232, 202, -105, 124, 114, 112, 110,
+ 95, -105, -105, -105, -105, -105, -105, -105, -105, 212,
+ -105, 192, -105, 177, -105, -105, 208, -105, 107, -105,
+ -105, 255, -105, 11, -105, 13, -105, 44, -105, 206,
+ -105, 169, 176, -105, -105, 183, -105, -105, -105, -105,
+ -105, -105, 173, -105, 167, 117, -105, -105, 191, -105,
+ 54, -105, 55, -105, 58, -105, -105, 102, -105, -105,
+ 89, -105, -105, 57, -105, 46, -105, 45, -105, 49,
+ -105, -105, -105, -105, -105, -105, 77, -105, 64, -105,
+ 51, -105, 109, 61, -105, -105, 48, -105, -105, 152,
+ -105, -105, -105, 79, -105, -105, -105, -105, 4, -105,
+ -16, 153, -105, 74, -105, -105, -11, -105, 0, -105,
+ -105, -105, -105, -105, -105, -105, -5, -105, -105, -105,
+ -105, -105, -105, 68, -105, -105, 41, -105, -105, -105,
+ -105, 90, -105, -1, -105, -105, -105, -105, -105, -93,
+ -105, 32, -105, -4, -105, -105, -105, -105, -22, -105,
+ -105, -14, -105, -105, -105, -105, -105, -105, -26, -105,
+ -105, -2, -105, 60, -105, 53, -105, -105, -105, -105,
+ 65, -105, 76, -105, 78, -105, 72, -105, -105, -105,
+ -105, -105, -105, 21, -105, -105, 85, -105, -105, -105,
+ -105, 22, -105, -105, 180, -105, -105, 33, -105, -105,
+ -105, -105, -105, -105, -105, -105, -105, -105, -105, -105,
+ -105, -105, -105, -105, -105, -105, 73, -105, -105, -105,
+ -105, -105, -105, -105, 63, -105, -105, -105, -105, -105,
+ -105, 12, -105, -105, -105, -105, -105, -105, -105, -12,
+ -105, -105, -105, -105, -105, -105, -105, 6, -105, -105,
+ -105, -105, -15, -105, -105, 9, -105, -105, -105, -105,
+ -105, -9, -105, -105, -105, -7, -18, -13, -105, -105,
+ -105, -105, -105, 277, 266, -105, -105, -105, -105, -105,
+ -105, -105, 269, 2, 26, -105, 24, -105, 170, 16,
+ -105, -105, 19, -105, -105, 182, -105, -105, -105, 35,
+ -105, -105, -105, -105, 42, -105, 29, 153, -105, 128,
+ -105, -105, -105, -105, -105, -105, 349, -105, -105, -105,
+ -105, -105, 274, -105, -105, -105, 14, -105, -105, 15,
+ 218, -105, -105, -105, 7, -105, -105, -105, -105, -105,
+ -105, 17, -105, -105, -105, -105, -105, -105, -105, -105,
+ -105};
+
+const int QmlJSGrammar::action_info [] = {
+ 345, -114, -106, -92, 343, 345, -95, 254, -122, 450,
+ 549, 187, 437, 413, -119, -117, -106, 454, 249, -92,
+ 248, 345, 454, 339, 340, 342, 349, 233, 98, 606,
+ -125, 398, 388, 386, 254, 396, 254, 96, 441, 144,
+ 98, 450, 167, 161, 138, 606, 437, 443, 554, 463,
+ 96, 630, 437, 68, 437, 546, 180, 406, 337, 427,
+ 161, 184, -96, 445, 428, 421, 176, 421, 421, 413,
+ 417, 411, 525, 322, 186, 454, 146, 405, 289, 535,
+ 400, 450, 309, 309, 315, -96, -122, 437, 269, -117,
+ 298, 138, 293, -119, 509, 413, -114, 521, 519, 301,
+ 532, 554, 68, 328, 330, 269, 291, -95, 303, 424,
+ 138, 55, 504, 138, 539, 289, 474, 522, 440, 0,
+ 534, 332, 56, 431, 138, 163, 169, 524, 523, 164,
+ 620, 619, 441, 138, 324, 239, 238, 246, 245, 59,
+ 138, 138, 311, 553, 169, 170, 312, 138, 138, 138,
+ 60, 138, 0, -125, 425, 626, 625, 596, 174, 410,
+ 409, 55, 55, 170, 475, 415, 138, 246, 245, 554,
+ 253, 252, 56, 56, 551, 550, 246, 245, 244, 243,
+ 138, 82, 466, 83, 55, 485, 505, 325, 138, 82,
+ 0, 83, 452, 334, 84, 56, 82, 100, 83, 456,
+ 251, 347, 84, 307, 82, 597, 83, 505, 169, 84,
+ 505, 511, 61, 517, 505, 138, 101, 84, 102, 531,
+ 530, 527, 0, 541, 138, 0, 169, 170, 0, 403,
+ 0, 0, 507, 538, 537, 467, 465, 82, 61, 83,
+ 61, 435, 434, 506, 138, 170, 0, 403, 542, 540,
+ 84, 623, 622, 507, 505, 0, 507, 62, 32, 507,
+ 507, 169, 0, 63, 506, 512, 510, 506, 515, 514,
+ 506, 506, 0, 0, 0, 528, 526, 232, 231, 32,
+ 170, 621, 171, 62, 32, 62, 169, 616, 32, 63,
+ 0, 63, 139, 0, 169, 45, 47, 46, 0, 0,
+ 507, 617, 615, 32, -83, 170, 0, 171, 0, 0,
+ 0, 506, -83, 170, 32, 171, 45, 47, 46, 32,
+ 0, 45, 47, 46, 32, 45, 47, 46, 32, 0,
+ 0, 614, 271, 272, 82, 32, 83, 0, 0, 0,
+ 45, 47, 46, 4, 3, 2, 1, 84, 271, 272,
+ 32, 45, 47, 46, 32, 0, 45, 47, 46, 273,
+ 274, 45, 47, 46, 32, 45, 47, 46, 0, 276,
+ 277, 0, 45, 47, 46, 273, 274, 32, 278, 0,
+ 0, 279, 0, 280, 0, 0, 0, 45, 47, 46,
+ 32, 45, 47, 46, 0, 0, 0, -336, 0, 32,
+ 0, 45, 47, 46, 0, 0, -336, 70, 71, 276,
+ 277, 0, 0, 0, 45, 47, 46, 0, 278, 0,
+ 0, 279, 0, 280, 0, 0, 0, 45, 47, 46,
+ 0, 75, 76, 0, 72, 73, 45, 47, 46, 77,
+ 78, 75, 76, 79, 0, 80, 0, 0, 0, 77,
+ 78, 75, 76, 79, 0, 80, 0, 0, 0, 77,
+ 78, 75, 76, 79, 0, 80, 0, 0, 0, 77,
+ 78, 75, 76, 79, 32, 80, 0, 0, 0, 77,
+ 78, 0, 32, 79, 0, 80, 0, 276, 277, 0,
+ 32, 0, 0, 0, 0, 0, 278, 0, 32, 279,
+ 0, 280, 0, 0, 0, 0, 242, 241, 0, 0,
+ 0, 45, 47, 46, 237, 236, 0, 0, 0, 45,
+ 47, 46, 237, 236, 0, 0, 0, 45, 47, 46,
+ 237, 236, 148, 0, 0, 45, 47, 46, 0, 0,
+ 0, 0, 149, 0, 0, 0, 150, 0, 0, 0,
+ 0, 0, 0, 0, 0, 151, 0, 152, 0, 0,
+ 0, 0, 32, 0, 0, 0, 0, 0, 153, 0,
+ 154, 59, 0, 0, 0, 0, 0, 0, 155, 0,
+ 0, 156, 60, 0, 0, 0, 0, 157, 148, 0,
+ 0, 0, 0, 158, 242, 241, 0, 0, 149, 45,
+ 47, 46, 150, 0, 0, 0, 0, 0, 0, 159,
+ 0, 151, 0, 152, 0, 0, 305, 0, 0, 0,
+ 0, 0, 0, 0, 153, 0, 154, 59, 0, 28,
+ 29, 148, 0, 0, 155, 0, 0, 156, 60, 31,
+ 0, 149, 0, 157, 0, 150, 32, 0, 0, 158,
+ 33, 34, 0, 35, 151, 0, 152, 0, 0, 0,
+ 496, 0, 0, 0, 42, 159, 0, 153, 0, 154,
+ 59, 0, 0, 0, 0, 0, 0, 155, 0, 0,
+ 156, 60, 48, 45, 47, 46, 157, 49, 0, 0,
+ 0, 0, 158, 0, 0, 0, 0, 0, 41, 51,
+ 30, 0, 0, 0, 38, 0, 0, 0, 159, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 28, 29,
+ 0, 0, 0, 0, 0, 0, 28, 29, 31, 0,
+ 0, 0, 0, 0, 0, 32, 31, 0, 0, 33,
+ 34, 0, 35, 32, 0, 0, 0, 33, 34, 39,
+ 35, 0, 0, 42, 0, 0, 0, 496, 0, 0,
+ 0, 42, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 48, 45, 47, 46, 0, 49, 0, 0, 48,
+ 45, 47, 46, 0, 49, 0, 0, 41, 51, 30,
+ 0, 0, 0, 38, 0, 41, 51, 30, 0, 0,
+ 0, 38, 0, 0, 28, 29, 0, 0, 0, 0,
+ 0, 0, 28, 29, 31, 0, 0, 0, 0, 0,
+ 0, 32, 31, 0, 0, 33, 34, 0, 35, 32,
+ 0, 0, 0, 33, 34, 496, 35, 0, 0, 42,
+ 0, 0, 0, 39, 0, 0, 0, 42, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 48, 45, 47,
+ 46, 0, 49, 0, 0, 48, 45, 47, 46, 0,
+ 49, 0, 0, 41, 51, 30, 0, 0, 0, 38,
+ 0, 41, 51, 30, 0, 0, 0, 38, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 28, 29,
+ 0, 0, 0, 0, 0, 0, 0, 0, 31, 0,
+ 0, 0, 0, 0, 0, 32, 0, 0, 0, 33,
+ 34, 0, 35, 0, 0, 0, 0, 0, 0, 496,
+ 0, 0, 0, 42, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 48, 45, 47, 46, 0, 49, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 41, 51, 30,
+ 0, 0, 0, 38, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 495, 0, 28, 29, 0, 0,
+ 0, 0, 0, 0, 0, 0, 212, 0, 0, 0,
+ 0, 0, 0, 32, 0, 0, 0, 33, 34, 0,
+ 35, 0, 0, 0, 0, 0, 0, 496, 0, 0,
+ 0, 42, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 48,
+ 497, 499, 498, 0, 49, 0, 0, 0, 0, 223,
+ 0, 0, 0, 0, 0, 41, 51, 30, 207, 0,
+ 0, 38, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 495, 0, 28, 29, 0, 0, 0, 0,
+ 0, 0, 0, 0, 212, 0, 0, 0, 0, 0,
+ 0, 32, 0, 0, 0, 33, 34, 0, 35, 0,
+ 0, 0, 0, 0, 0, 496, 0, 0, 0, 42,
+ 0, 0, 0, 0, 0, 0, 0, 600, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 48, 497, 499,
+ 498, 0, 49, 0, 0, 0, 0, 223, 0, 0,
+ 0, 0, 0, 41, 51, 30, 207, 0, 0, 38,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 495, 0, 28, 29, 0, 0, 0, 0, 0, 0,
+ 0, 0, 212, 0, 0, 0, 0, 0, 0, 32,
+ 0, 0, 0, 33, 34, 0, 35, 0, 0, 0,
+ 0, 0, 0, 496, 0, 0, 0, 42, 0, 0,
+ 0, 0, 0, 0, 0, 603, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 48, 497, 499, 498, 0,
+ 49, 0, 0, 0, 0, 223, 0, 0, 0, 0,
+ 0, 41, 51, 30, 207, 0, 0, 38, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 27, 28,
+ 29, 0, 0, 0, 0, 0, 0, 0, 0, 31,
+ 0, 0, 0, 0, 0, 0, 32, 0, 0, 0,
+ 33, 34, 0, 35, 0, 0, 0, 36, 0, 37,
+ 39, 40, 0, 0, 42, 0, 0, 0, 43, 0,
+ 44, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 48, 45, 47, 46, 0, 49, 0, 50,
+ 0, 52, 0, 53, 0, 0, 0, 0, 41, 51,
+ 30, 0, 0, 0, 38, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 27, 28, 29, 0, 0,
+ 0, 0, 0, 0, 0, 0, 31, 0, 0, 0,
+ 0, 0, 0, 32, 0, 0, 0, 33, 34, 0,
+ 35, 0, 0, 0, 36, 0, 37, 39, 40, 0,
+ 0, 42, 0, 0, 0, 43, 0, 44, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 48,
+ 45, 47, 46, 0, 49, 0, 50, 0, 52, 268,
+ 53, 0, 0, 0, 0, 41, 51, 30, 0, 0,
+ 0, 38, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, -115, 0, 0, 0, 27, 28, 29, 0,
+ 0, 0, 0, 0, 0, 0, 0, 31, 0, 0,
+ 0, 0, 0, 0, 32, 0, 0, 0, 33, 34,
+ 0, 35, 0, 0, 0, 36, 0, 37, 39, 40,
+ 0, 0, 42, 0, 0, 0, 43, 0, 44, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 48, 45, 47, 46, 0, 49, 0, 50, 0, 52,
+ 0, 53, 0, 0, 0, 0, 41, 51, 30, 0,
+ 0, 0, 38, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 480, 0, 0, 27, 28, 29, 0,
+ 0, 0, 0, 0, 0, 0, 0, 31, 0, 0,
+ 0, 0, 0, 0, 32, 0, 0, 0, 33, 34,
+ 0, 35, 0, 0, 0, 36, 0, 37, 39, 40,
+ 0, 0, 42, 0, 0, 0, 43, 0, 44, 0,
+ 0, 481, 0, 0, 0, 0, 0, 0, 0, 0,
+ 48, 45, 47, 46, 0, 49, 0, 50, 0, 52,
+ 0, 53, 0, 0, 0, 0, 41, 51, 30, 0,
+ 0, 0, 38, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 27, 28, 29, 0, 0, 0, 0,
+ 0, 0, 0, 0, 31, 0, 0, 0, 0, 0,
+ 0, 32, 214, 0, 0, 561, 562, 0, 35, 0,
+ 0, 0, 36, 0, 37, 39, 40, 0, 0, 42,
+ 0, 0, 0, 43, 0, 44, 0, 0, 0, 0,
+ 0, 0, 0, 218, 0, 0, 0, 48, 45, 47,
+ 46, 0, 49, 0, 50, 0, 52, 0, 53, 0,
+ 0, 0, 0, 41, 51, 30, 0, 0, 0, 38,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 480, 0, 0, 27, 28, 29, 0, 0, 0, 0,
+ 0, 0, 0, 0, 31, 0, 0, 0, 0, 0,
+ 0, 32, 0, 0, 0, 33, 34, 0, 35, 0,
+ 0, 0, 36, 0, 37, 39, 40, 0, 0, 42,
+ 0, 0, 0, 43, 0, 44, 0, 0, 483, 0,
+ 0, 0, 0, 0, 0, 0, 0, 48, 45, 47,
+ 46, 0, 49, 0, 50, 0, 52, 0, 53, 0,
+ 0, 0, 0, 41, 51, 30, 0, 0, 0, 38,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 472, 0, 0, 27, 28, 29, 0, 0, 0, 0,
+ 0, 0, 0, 0, 31, 0, 0, 0, 0, 0,
+ 0, 32, 0, 0, 0, 33, 34, 0, 35, 0,
+ 0, 0, 36, 0, 37, 39, 40, 0, 0, 42,
+ 0, 0, 0, 43, 0, 44, 0, 0, 473, 0,
+ 0, 0, 0, 0, 0, 0, 0, 48, 45, 47,
+ 46, 0, 49, 0, 50, 0, 52, 0, 53, 0,
+ 0, 0, 0, 41, 51, 30, 0, 0, 0, 38,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 472, 0, 0, 27, 28, 29, 0, 0, 0, 0,
+ 0, 0, 0, 0, 31, 0, 0, 0, 0, 0,
+ 0, 32, 0, 0, 0, 33, 34, 0, 35, 0,
+ 0, 0, 36, 0, 37, 39, 40, 0, 0, 42,
+ 0, 0, 0, 43, 0, 44, 0, 0, 478, 0,
+ 0, 0, 0, 0, 0, 0, 0, 48, 45, 47,
+ 46, 0, 49, 0, 50, 0, 52, 0, 53, 0,
+ 0, 0, 0, 41, 51, 30, 0, 0, 0, 38,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 106, 107, 108, 0, 0, 110, 112, 113, 0, 0,
+ 114, 0, 115, 0, 0, 0, 117, 118, 119, 0,
+ 0, 0, 0, 0, 0, 32, 120, 121, 122, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 123,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 126, 0, 0, 0, 0,
+ 0, 0, 45, 47, 46, 127, 128, 129, 0, 131,
+ 132, 133, 134, 135, 136, 0, 0, 124, 130, 116,
+ 109, 111, 125, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 106, 107, 108, 0, 0, 110,
+ 112, 113, 0, 0, 114, 0, 115, 0, 0, 0,
+ 117, 118, 119, 0, 0, 0, 0, 0, 0, 390,
+ 120, 121, 122, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 123, 0, 0, 0, 391, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 126,
+ 0, 0, 0, 0, 0, 395, 392, 394, 0, 127,
+ 128, 129, 0, 131, 132, 133, 134, 135, 136, 0,
+ 0, 124, 130, 116, 109, 111, 125, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 106, 107,
+ 108, 0, 0, 110, 112, 113, 0, 0, 114, 0,
+ 115, 0, 0, 0, 117, 118, 119, 0, 0, 0,
+ 0, 0, 0, 390, 120, 121, 122, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 123, 0, 0,
+ 0, 391, 0, 0, 0, 0, 0, 0, 0, 393,
+ 0, 0, 0, 126, 0, 0, 0, 0, 0, 395,
+ 392, 394, 0, 127, 128, 129, 0, 131, 132, 133,
+ 134, 135, 136, 0, 0, 124, 130, 116, 109, 111,
+ 125, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 206, 0, 0, 0, 0, 208, 0, 27,
+ 28, 29, 210, 0, 0, 0, 0, 0, 0, 211,
+ 31, 0, 0, 0, 0, 0, 0, 213, 214, 0,
+ 0, 215, 34, 0, 35, 0, 0, 0, 36, 0,
+ 37, 39, 40, 0, 0, 42, 0, 0, 0, 43,
+ 0, 44, 0, 0, 0, 0, 0, 217, 0, 218,
+ 0, 0, 0, 48, 216, 219, 46, 220, 49, 221,
+ 50, 222, 52, 223, 53, 224, 225, 0, 0, 41,
+ 51, 30, 207, 209, 0, 38, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 206, 0, 0, 0,
+ 0, 208, 0, 27, 28, 29, 210, 0, 0, 0,
+ 0, 0, 0, 211, 212, 0, 0, 0, 0, 0,
+ 0, 213, 214, 0, 0, 215, 34, 0, 35, 0,
+ 0, 0, 36, 0, 37, 39, 40, 0, 0, 42,
+ 0, 0, 0, 43, 0, 44, 0, 0, 0, 0,
+ 0, 217, 0, 218, 0, 0, 0, 48, 216, 219,
+ 46, 220, 49, 221, 50, 222, 52, 223, 53, 224,
+ 225, 0, 0, 41, 51, 30, 207, 209, 0, 38,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 564, 107, 108, 0, 0, 566, 112, 568, 28, 29,
+ 569, 0, 115, 0, 0, 0, 117, 571, 572, 0,
+ 0, 0, 0, 0, 0, 573, 574, 121, 122, 215,
+ 34, 0, 35, 0, 0, 0, 36, 0, 37, 575,
+ 40, 0, 0, 577, 0, 0, 0, 43, 0, 44,
+ 0, 0, 0, 0, 0, 579, 0, 218, 0, 0,
+ 0, 581, 578, 580, 46, 582, 583, 584, 50, 586,
+ 587, 588, 589, 590, 591, 0, 0, 576, 585, 570,
+ 565, 567, 125, 38, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 358, 107, 108, 0, 0, 360,
+ 112, 362, 28, 29, 363, 0, 115, 0, 0, 0,
+ 117, 365, 366, 0, 0, 0, 0, 0, 0, 367,
+ 368, 121, 122, 215, 34, 0, 35, 0, 0, 0,
+ 36, 0, 37, 369, 40, 0, 0, 371, 0, 0,
+ 0, 43, 0, 44, 0, -261, 0, 0, 0, 373,
+ 0, 218, 0, 0, 0, 375, 372, 374, 46, 376,
+ 377, 378, 50, 380, 381, 382, 383, 384, 385, 0,
+ 0, 370, 379, 364, 359, 361, 125, 38, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ 548, 422, 414, 436, 166, 547, 552, 433, 533, 529,
+ 183, 520, 536, 304, 545, 513, 306, 447, 247, 599,
+ 618, 147, 387, 317, 627, 613, 14, 492, 397, 204,
+ 624, 185, 179, 250, 389, 430, 168, 240, 299, 235,
+ 173, 179, 484, 407, 336, 433, 308, 348, 436, 346,
+ 433, 350, 247, 469, 464, 482, 331, 429, 333, 344,
+ 335, 179, 299, 247, 240, 432, 479, 140, 451, 240,
+ 442, 145, 446, 444, 457, 235, 160, 235, 453, 399,
+ 458, 455, 299, 137, 516, 143, 508, 426, 436, 204,
+ 0, 204, 412, 0, 0, 0, 0, 0, 458, 103,
+ 0, 143, 0, 0, 143, 0, 404, 0, 57, 175,
+ 299, 0, 57, 91, 177, 183, 57, 57, 449, 0,
+ 299, 105, 90, 57, 57, 57, 57, 0, 89, 88,
+ 57, 94, 95, 57, 57, 81, 65, 57, 263, 57,
+ 57, 486, 285, 267, 86, 57, 57, 64, 57, 165,
+ 87, 57, 57, 177, 57, 57, 57, 284, 57, 283,
+ 97, 282, 85, 401, 57, 99, 57, 57, 468, 92,
+ 57, 281, 449, 300, 57, 69, 491, 57, 57, 449,
+ 317, 57, 57, 327, 58, 67, 57, 341, 66, 401,
+ 234, 402, 162, 401, 299, 57, 57, 448, 57, 338,
+ 489, 57, 74, 488, 57, 57, 57, 487, 490, 477,
+ 93, 57, 57, 476, 177, 295, 267, 402, 295, 295,
+ 267, 402, 0, 267, 267, 295, 57, 494, 313, 494,
+ 267, 267, 628, 0, 57, 270, 595, 323, 103, 267,
+ 314, 294, 493, 503, 57, 292, 0, 316, 57, 267,
+ 295, 288, 326, 267, 57, 267, 0, 329, 299, 267,
+ 105, 172, 0, 310, 57, 0, 0, 290, 57, 267,
+ 601, 275, 297, 267, 57, 286, 0, 494, 604, 267,
+ 592, 287, 0, 594, 0, 494, 0, 595, 560, 0,
+ 0, 0, 493, 503, 0, 563, 556, 557, 558, 559,
+ 493, 503, 469, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 302, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 494, 0, 0, 598, 0, 0, 0, 595, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0};
+
+const int QmlJSGrammar::action_check [] = {
+ 36, 7, 7, 7, 7, 36, 7, 36, 7, 36,
+ 60, 33, 33, 36, 7, 7, 7, 36, 36, 7,
+ 77, 36, 36, 60, 33, 55, 16, 55, 79, 90,
+ 7, 55, 8, 7, 36, 7, 36, 48, 20, 8,
+ 79, 36, 7, 2, 8, 90, 33, 36, 33, 17,
+ 48, 0, 33, 1, 33, 8, 36, 7, 36, 55,
+ 2, 8, 7, 60, 7, 5, 60, 5, 5, 36,
+ 33, 7, 29, 17, 60, 36, 60, 60, 48, 7,
+ 55, 36, 2, 2, 7, 7, 7, 33, 1, 7,
+ 61, 8, 8, 7, 29, 36, 7, 24, 37, 61,
+ 66, 33, 1, 61, 60, 1, 79, 7, 60, 10,
+ 8, 40, 66, 8, 29, 48, 8, 29, 6, -1,
+ 29, 31, 51, 7, 8, 50, 15, 61, 62, 54,
+ 61, 62, 20, 8, 8, 61, 62, 61, 62, 42,
+ 8, 8, 50, 7, 15, 34, 54, 8, 8, 8,
+ 53, 8, -1, 7, 55, 61, 62, 8, 56, 61,
+ 62, 40, 40, 34, 56, 60, 8, 61, 62, 33,
+ 61, 62, 51, 51, 61, 62, 61, 62, 61, 62,
+ 8, 25, 8, 27, 40, 60, 29, 61, 8, 25,
+ -1, 27, 60, 60, 38, 51, 25, 15, 27, 60,
+ 60, 60, 38, 60, 25, 56, 27, 29, 15, 38,
+ 29, 7, 12, 29, 29, 8, 34, 38, 36, 61,
+ 62, 7, -1, 36, 8, -1, 15, 34, -1, 36,
+ -1, -1, 75, 61, 62, 61, 62, 25, 12, 27,
+ 12, 61, 62, 86, 8, 34, -1, 36, 61, 62,
+ 38, 61, 62, 75, 29, -1, 75, 57, 29, 75,
+ 75, 15, -1, 63, 86, 61, 62, 86, 61, 62,
+ 86, 86, -1, -1, -1, 61, 62, 61, 62, 29,
+ 34, 91, 36, 57, 29, 57, 15, 47, 29, 63,
+ -1, 63, 56, -1, 15, 66, 67, 68, -1, -1,
+ 75, 61, 62, 29, 33, 34, -1, 36, -1, -1,
+ -1, 86, 33, 34, 29, 36, 66, 67, 68, 29,
+ -1, 66, 67, 68, 29, 66, 67, 68, 29, -1,
+ -1, 91, 18, 19, 25, 29, 27, -1, -1, -1,
+ 66, 67, 68, 92, 93, 94, 95, 38, 18, 19,
+ 29, 66, 67, 68, 29, -1, 66, 67, 68, 45,
+ 46, 66, 67, 68, 29, 66, 67, 68, -1, 23,
+ 24, -1, 66, 67, 68, 45, 46, 29, 32, -1,
+ -1, 35, -1, 37, -1, -1, -1, 66, 67, 68,
+ 29, 66, 67, 68, -1, -1, -1, 36, -1, 29,
+ -1, 66, 67, 68, -1, -1, 36, 18, 19, 23,
+ 24, -1, -1, -1, 66, 67, 68, -1, 32, -1,
+ -1, 35, -1, 37, -1, -1, -1, 66, 67, 68,
+ -1, 23, 24, -1, 45, 46, 66, 67, 68, 31,
+ 32, 23, 24, 35, -1, 37, -1, -1, -1, 31,
+ 32, 23, 24, 35, -1, 37, -1, -1, -1, 31,
+ 32, 23, 24, 35, -1, 37, -1, -1, -1, 31,
+ 32, 23, 24, 35, 29, 37, -1, -1, -1, 31,
+ 32, -1, 29, 35, -1, 37, -1, 23, 24, -1,
+ 29, -1, -1, -1, -1, -1, 32, -1, 29, 35,
+ -1, 37, -1, -1, -1, -1, 61, 62, -1, -1,
+ -1, 66, 67, 68, 61, 62, -1, -1, -1, 66,
+ 67, 68, 61, 62, -1, -1, -1, 66, 67, 68,
+ 61, 62, 3, -1, -1, 66, 67, 68, -1, -1,
+ -1, -1, 13, -1, -1, -1, 17, -1, -1, -1,
+ -1, -1, -1, -1, -1, 26, -1, 28, -1, -1,
+ -1, -1, 29, -1, -1, -1, -1, -1, 39, -1,
+ 41, 42, -1, -1, -1, -1, -1, -1, 49, -1,
+ -1, 52, 53, -1, -1, -1, -1, 58, 3, -1,
+ -1, -1, -1, 64, 61, 62, -1, -1, 13, 66,
+ 67, 68, 17, -1, -1, -1, -1, -1, -1, 80,
+ -1, 26, -1, 28, -1, -1, 31, -1, -1, -1,
+ -1, -1, -1, -1, 39, -1, 41, 42, -1, 12,
+ 13, 3, -1, -1, 49, -1, -1, 52, 53, 22,
+ -1, 13, -1, 58, -1, 17, 29, -1, -1, 64,
+ 33, 34, -1, 36, 26, -1, 28, -1, -1, -1,
+ 43, -1, -1, -1, 47, 80, -1, 39, -1, 41,
+ 42, -1, -1, -1, -1, -1, -1, 49, -1, -1,
+ 52, 53, 65, 66, 67, 68, 58, 70, -1, -1,
+ -1, -1, 64, -1, -1, -1, -1, -1, 81, 82,
+ 83, -1, -1, -1, 87, -1, -1, -1, 80, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 12, 13,
+ -1, -1, -1, -1, -1, -1, 12, 13, 22, -1,
+ -1, -1, -1, -1, -1, 29, 22, -1, -1, 33,
+ 34, -1, 36, 29, -1, -1, -1, 33, 34, 43,
+ 36, -1, -1, 47, -1, -1, -1, 43, -1, -1,
+ -1, 47, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 65, 66, 67, 68, -1, 70, -1, -1, 65,
+ 66, 67, 68, -1, 70, -1, -1, 81, 82, 83,
+ -1, -1, -1, 87, -1, 81, 82, 83, -1, -1,
+ -1, 87, -1, -1, 12, 13, -1, -1, -1, -1,
+ -1, -1, 12, 13, 22, -1, -1, -1, -1, -1,
+ -1, 29, 22, -1, -1, 33, 34, -1, 36, 29,
+ -1, -1, -1, 33, 34, 43, 36, -1, -1, 47,
+ -1, -1, -1, 43, -1, -1, -1, 47, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 65, 66, 67,
+ 68, -1, 70, -1, -1, 65, 66, 67, 68, -1,
+ 70, -1, -1, 81, 82, 83, -1, -1, -1, 87,
+ -1, 81, 82, 83, -1, -1, -1, 87, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 12, 13,
+ -1, -1, -1, -1, -1, -1, -1, -1, 22, -1,
+ -1, -1, -1, -1, -1, 29, -1, -1, -1, 33,
+ 34, -1, 36, -1, -1, -1, -1, -1, -1, 43,
+ -1, -1, -1, 47, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 65, 66, 67, 68, -1, 70, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 81, 82, 83,
+ -1, -1, -1, 87, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 10, -1, 12, 13, -1, -1,
+ -1, -1, -1, -1, -1, -1, 22, -1, -1, -1,
+ -1, -1, -1, 29, -1, -1, -1, 33, 34, -1,
+ 36, -1, -1, -1, -1, -1, -1, 43, -1, -1,
+ -1, 47, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 65,
+ 66, 67, 68, -1, 70, -1, -1, -1, -1, 75,
+ -1, -1, -1, -1, -1, 81, 82, 83, 84, -1,
+ -1, 87, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 10, -1, 12, 13, -1, -1, -1, -1,
+ -1, -1, -1, -1, 22, -1, -1, -1, -1, -1,
+ -1, 29, -1, -1, -1, 33, 34, -1, 36, -1,
+ -1, -1, -1, -1, -1, 43, -1, -1, -1, 47,
+ -1, -1, -1, -1, -1, -1, -1, 55, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 65, 66, 67,
+ 68, -1, 70, -1, -1, -1, -1, 75, -1, -1,
+ -1, -1, -1, 81, 82, 83, 84, -1, -1, 87,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 10, -1, 12, 13, -1, -1, -1, -1, -1, -1,
+ -1, -1, 22, -1, -1, -1, -1, -1, -1, 29,
+ -1, -1, -1, 33, 34, -1, 36, -1, -1, -1,
+ -1, -1, -1, 43, -1, -1, -1, 47, -1, -1,
+ -1, -1, -1, -1, -1, 55, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 65, 66, 67, 68, -1,
+ 70, -1, -1, -1, -1, 75, -1, -1, -1, -1,
+ -1, 81, 82, 83, 84, -1, -1, 87, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 11, 12,
+ 13, -1, -1, -1, -1, -1, -1, -1, -1, 22,
+ -1, -1, -1, -1, -1, -1, 29, -1, -1, -1,
+ 33, 34, -1, 36, -1, -1, -1, 40, -1, 42,
+ 43, 44, -1, -1, 47, -1, -1, -1, 51, -1,
+ 53, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 65, 66, 67, 68, -1, 70, -1, 72,
+ -1, 74, -1, 76, -1, -1, -1, -1, 81, 82,
+ 83, -1, -1, -1, 87, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 11, 12, 13, -1, -1,
+ -1, -1, -1, -1, -1, -1, 22, -1, -1, -1,
+ -1, -1, -1, 29, -1, -1, -1, 33, 34, -1,
+ 36, -1, -1, -1, 40, -1, 42, 43, 44, -1,
+ -1, 47, -1, -1, -1, 51, -1, 53, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 65,
+ 66, 67, 68, -1, 70, -1, 72, -1, 74, 75,
+ 76, -1, -1, -1, -1, 81, 82, 83, -1, -1,
+ -1, 87, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 7, -1, -1, -1, 11, 12, 13, -1,
+ -1, -1, -1, -1, -1, -1, -1, 22, -1, -1,
+ -1, -1, -1, -1, 29, -1, -1, -1, 33, 34,
+ -1, 36, -1, -1, -1, 40, -1, 42, 43, 44,
+ -1, -1, 47, -1, -1, -1, 51, -1, 53, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 65, 66, 67, 68, -1, 70, -1, 72, -1, 74,
+ -1, 76, -1, -1, -1, -1, 81, 82, 83, -1,
+ -1, -1, 87, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 8, -1, -1, 11, 12, 13, -1,
+ -1, -1, -1, -1, -1, -1, -1, 22, -1, -1,
+ -1, -1, -1, -1, 29, -1, -1, -1, 33, 34,
+ -1, 36, -1, -1, -1, 40, -1, 42, 43, 44,
+ -1, -1, 47, -1, -1, -1, 51, -1, 53, -1,
+ -1, 56, -1, -1, -1, -1, -1, -1, -1, -1,
+ 65, 66, 67, 68, -1, 70, -1, 72, -1, 74,
+ -1, 76, -1, -1, -1, -1, 81, 82, 83, -1,
+ -1, -1, 87, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 11, 12, 13, -1, -1, -1, -1,
+ -1, -1, -1, -1, 22, -1, -1, -1, -1, -1,
+ -1, 29, 30, -1, -1, 33, 34, -1, 36, -1,
+ -1, -1, 40, -1, 42, 43, 44, -1, -1, 47,
+ -1, -1, -1, 51, -1, 53, -1, -1, -1, -1,
+ -1, -1, -1, 61, -1, -1, -1, 65, 66, 67,
+ 68, -1, 70, -1, 72, -1, 74, -1, 76, -1,
+ -1, -1, -1, 81, 82, 83, -1, -1, -1, 87,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 8, -1, -1, 11, 12, 13, -1, -1, -1, -1,
+ -1, -1, -1, -1, 22, -1, -1, -1, -1, -1,
+ -1, 29, -1, -1, -1, 33, 34, -1, 36, -1,
+ -1, -1, 40, -1, 42, 43, 44, -1, -1, 47,
+ -1, -1, -1, 51, -1, 53, -1, -1, 56, -1,
+ -1, -1, -1, -1, -1, -1, -1, 65, 66, 67,
+ 68, -1, 70, -1, 72, -1, 74, -1, 76, -1,
+ -1, -1, -1, 81, 82, 83, -1, -1, -1, 87,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 8, -1, -1, 11, 12, 13, -1, -1, -1, -1,
+ -1, -1, -1, -1, 22, -1, -1, -1, -1, -1,
+ -1, 29, -1, -1, -1, 33, 34, -1, 36, -1,
+ -1, -1, 40, -1, 42, 43, 44, -1, -1, 47,
+ -1, -1, -1, 51, -1, 53, -1, -1, 56, -1,
+ -1, -1, -1, -1, -1, -1, -1, 65, 66, 67,
+ 68, -1, 70, -1, 72, -1, 74, -1, 76, -1,
+ -1, -1, -1, 81, 82, 83, -1, -1, -1, 87,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 8, -1, -1, 11, 12, 13, -1, -1, -1, -1,
+ -1, -1, -1, -1, 22, -1, -1, -1, -1, -1,
+ -1, 29, -1, -1, -1, 33, 34, -1, 36, -1,
+ -1, -1, 40, -1, 42, 43, 44, -1, -1, 47,
+ -1, -1, -1, 51, -1, 53, -1, -1, 56, -1,
+ -1, -1, -1, -1, -1, -1, -1, 65, 66, 67,
+ 68, -1, 70, -1, 72, -1, 74, -1, 76, -1,
+ -1, -1, -1, 81, 82, 83, -1, -1, -1, 87,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 4, 5, 6, -1, -1, 9, 10, 11, -1, -1,
+ 14, -1, 16, -1, -1, -1, 20, 21, 22, -1,
+ -1, -1, -1, -1, -1, 29, 30, 31, 32, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 43,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 59, -1, -1, -1, -1,
+ -1, -1, 66, 67, 68, 69, 70, 71, -1, 73,
+ 74, 75, 76, 77, 78, -1, -1, 81, 82, 83,
+ 84, 85, 86, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4, 5, 6, -1, -1, 9,
+ 10, 11, -1, -1, 14, -1, 16, -1, -1, -1,
+ 20, 21, 22, -1, -1, -1, -1, -1, -1, 29,
+ 30, 31, 32, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 43, -1, -1, -1, 47, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 59,
+ -1, -1, -1, -1, -1, 65, 66, 67, -1, 69,
+ 70, 71, -1, 73, 74, 75, 76, 77, 78, -1,
+ -1, 81, 82, 83, 84, 85, 86, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 4, 5,
+ 6, -1, -1, 9, 10, 11, -1, -1, 14, -1,
+ 16, -1, -1, -1, 20, 21, 22, -1, -1, -1,
+ -1, -1, -1, 29, 30, 31, 32, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 43, -1, -1,
+ -1, 47, -1, -1, -1, -1, -1, -1, -1, 55,
+ -1, -1, -1, 59, -1, -1, -1, -1, -1, 65,
+ 66, 67, -1, 69, 70, 71, -1, 73, 74, 75,
+ 76, 77, 78, -1, -1, 81, 82, 83, 84, 85,
+ 86, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4, -1, -1, -1, -1, 9, -1, 11,
+ 12, 13, 14, -1, -1, -1, -1, -1, -1, 21,
+ 22, -1, -1, -1, -1, -1, -1, 29, 30, -1,
+ -1, 33, 34, -1, 36, -1, -1, -1, 40, -1,
+ 42, 43, 44, -1, -1, 47, -1, -1, -1, 51,
+ -1, 53, -1, -1, -1, -1, -1, 59, -1, 61,
+ -1, -1, -1, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 76, 77, 78, -1, -1, 81,
+ 82, 83, 84, 85, -1, 87, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4, -1, -1, -1,
+ -1, 9, -1, 11, 12, 13, 14, -1, -1, -1,
+ -1, -1, -1, 21, 22, -1, -1, -1, -1, -1,
+ -1, 29, 30, -1, -1, 33, 34, -1, 36, -1,
+ -1, -1, 40, -1, 42, 43, 44, -1, -1, 47,
+ -1, -1, -1, 51, -1, 53, -1, -1, -1, -1,
+ -1, 59, -1, 61, -1, -1, -1, 65, 66, 67,
+ 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
+ 78, -1, -1, 81, 82, 83, 84, 85, -1, 87,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 4, 5, 6, -1, -1, 9, 10, 11, 12, 13,
+ 14, -1, 16, -1, -1, -1, 20, 21, 22, -1,
+ -1, -1, -1, -1, -1, 29, 30, 31, 32, 33,
+ 34, -1, 36, -1, -1, -1, 40, -1, 42, 43,
+ 44, -1, -1, 47, -1, -1, -1, 51, -1, 53,
+ -1, -1, -1, -1, -1, 59, -1, 61, -1, -1,
+ -1, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ 74, 75, 76, 77, 78, -1, -1, 81, 82, 83,
+ 84, 85, 86, 87, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4, 5, 6, -1, -1, 9,
+ 10, 11, 12, 13, 14, -1, 16, -1, -1, -1,
+ 20, 21, 22, -1, -1, -1, -1, -1, -1, 29,
+ 30, 31, 32, 33, 34, -1, 36, -1, -1, -1,
+ 40, -1, 42, 43, 44, -1, -1, 47, -1, -1,
+ -1, 51, -1, 53, -1, 55, -1, -1, -1, 59,
+ -1, 61, -1, -1, -1, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, -1,
+ -1, 81, 82, 83, 84, 85, 86, 87, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+
+ 13, 94, 3, 19, 33, 23, 13, 3, 23, 3,
+ 13, 23, 3, 2, 23, 3, 3, 19, 2, 17,
+ 13, 65, 33, 13, 9, 11, 3, 2, 33, 2,
+ 13, 13, 13, 3, 34, 3, 33, 13, 3, 13,
+ 3, 13, 3, 2, 13, 3, 2, 2, 19, 3,
+ 3, 2, 2, 33, 33, 33, 2, 79, 3, 2,
+ 2, 13, 3, 2, 13, 79, 33, 33, 3, 13,
+ 96, 33, 19, 13, 2, 13, 33, 13, 2, 2,
+ 13, 3, 3, 3, 11, 33, 23, 91, 19, 2,
+ -1, 2, 2, -1, -1, -1, -1, -1, 13, 13,
+ -1, 33, -1, -1, 33, -1, 38, -1, 42, 38,
+ 3, -1, 42, 47, 44, 13, 42, 42, 44, -1,
+ 3, 35, 47, 42, 42, 42, 42, -1, 47, 47,
+ 42, 48, 48, 42, 42, 47, 44, 42, 42, 42,
+ 42, 44, 47, 47, 46, 42, 42, 44, 42, 58,
+ 46, 42, 42, 44, 42, 42, 42, 47, 42, 47,
+ 54, 47, 46, 11, 42, 52, 42, 42, 83, 47,
+ 42, 47, 44, 66, 42, 50, 44, 42, 42, 44,
+ 13, 42, 42, 66, 45, 45, 42, 98, 44, 11,
+ 103, 39, 56, 11, 3, 42, 42, 44, 42, 97,
+ 44, 42, 48, 44, 42, 42, 42, 44, 44, 29,
+ 48, 42, 42, 33, 44, 42, 47, 39, 42, 42,
+ 47, 39, -1, 47, 47, 42, 42, 11, 59, 11,
+ 47, 47, 14, -1, 42, 51, 18, 64, 13, 47,
+ 64, 64, 26, 27, 42, 53, -1, 64, 42, 47,
+ 42, 49, 85, 47, 42, 47, -1, 66, 3, 47,
+ 35, 36, -1, 57, 42, -1, -1, 55, 42, 47,
+ 4, 49, 64, 47, 42, 49, -1, 11, 4, 47,
+ 11, 49, -1, 14, -1, 11, -1, 18, 11, -1,
+ -1, -1, 26, 27, -1, 18, 19, 20, 21, 22,
+ 26, 27, 33, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 66, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 11, -1, -1, 14, -1, -1, -1, 18, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1};
+
diff --git a/src/declarative/qml/parser/qmljsgrammar_p.h b/src/declarative/qml/parser/qmljsgrammar_p.h
new file mode 100644
index 0000000..b297f81
--- /dev/null
+++ b/src/declarative/qml/parser/qmljsgrammar_p.h
@@ -0,0 +1,207 @@
+// This file was generated by qlalr - DO NOT EDIT!
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore 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$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QMLJSGRAMMAR_P_H
+#define QMLJSGRAMMAR_P_H
+
+class QmlJSGrammar
+{
+public:
+ enum {
+ EOF_SYMBOL = 0,
+ REDUCE_HERE = 97,
+ SHIFT_THERE = 96,
+ T_AND = 1,
+ T_AND_AND = 2,
+ T_AND_EQ = 3,
+ T_AS = 91,
+ T_AUTOMATIC_SEMICOLON = 62,
+ T_BREAK = 4,
+ T_CASE = 5,
+ T_CATCH = 6,
+ T_COLON = 7,
+ T_COMMA = 8,
+ T_COMMENT = 88,
+ T_CONST = 84,
+ T_CONTINUE = 9,
+ T_DEBUGGER = 85,
+ T_DEFAULT = 10,
+ T_DELETE = 11,
+ T_DIVIDE_ = 12,
+ T_DIVIDE_EQ = 13,
+ T_DO = 14,
+ T_DOT = 15,
+ T_ELSE = 16,
+ T_EQ = 17,
+ T_EQ_EQ = 18,
+ T_EQ_EQ_EQ = 19,
+ T_FALSE = 83,
+ T_FEED_JS_EXPRESSION = 95,
+ T_FEED_JS_STATEMENT = 94,
+ T_FEED_UI_OBJECT_MEMBER = 93,
+ T_FEED_UI_PROGRAM = 92,
+ T_FINALLY = 20,
+ T_FOR = 21,
+ T_FUNCTION = 22,
+ T_GE = 23,
+ T_GT = 24,
+ T_GT_GT = 25,
+ T_GT_GT_EQ = 26,
+ T_GT_GT_GT = 27,
+ T_GT_GT_GT_EQ = 28,
+ T_IDENTIFIER = 29,
+ T_IF = 30,
+ T_IMPORT = 90,
+ T_IN = 31,
+ T_INSTANCEOF = 32,
+ T_LBRACE = 33,
+ T_LBRACKET = 34,
+ T_LE = 35,
+ T_LPAREN = 36,
+ T_LT = 37,
+ T_LT_LT = 38,
+ T_LT_LT_EQ = 39,
+ T_MINUS = 40,
+ T_MINUS_EQ = 41,
+ T_MINUS_MINUS = 42,
+ T_MULTILINE_STRING_LITERAL = 87,
+ T_NEW = 43,
+ T_NOT = 44,
+ T_NOT_EQ = 45,
+ T_NOT_EQ_EQ = 46,
+ T_NULL = 81,
+ T_NUMERIC_LITERAL = 47,
+ T_OR = 48,
+ T_OR_EQ = 49,
+ T_OR_OR = 50,
+ T_PLUS = 51,
+ T_PLUS_EQ = 52,
+ T_PLUS_PLUS = 53,
+ T_PROPERTY = 66,
+ T_PUBLIC = 89,
+ T_QUESTION = 54,
+ T_RBRACE = 55,
+ T_RBRACKET = 56,
+ T_READONLY = 68,
+ T_REMAINDER = 57,
+ T_REMAINDER_EQ = 58,
+ T_RESERVED_WORD = 86,
+ T_RETURN = 59,
+ T_RPAREN = 60,
+ T_SEMICOLON = 61,
+ T_SIGNAL = 67,
+ T_STAR = 63,
+ T_STAR_EQ = 64,
+ T_STRING_LITERAL = 65,
+ T_SWITCH = 69,
+ T_THIS = 70,
+ T_THROW = 71,
+ T_TILDE = 72,
+ T_TRUE = 82,
+ T_TRY = 73,
+ T_TYPEOF = 74,
+ T_VAR = 75,
+ T_VOID = 76,
+ T_WHILE = 77,
+ T_WITH = 78,
+ T_XOR = 79,
+ T_XOR_EQ = 80,
+
+ ACCEPT_STATE = 630,
+ RULE_COUNT = 340,
+ STATE_COUNT = 631,
+ TERMINAL_COUNT = 98,
+ NON_TERMINAL_COUNT = 105,
+
+ GOTO_INDEX_OFFSET = 631,
+ GOTO_INFO_OFFSET = 2618,
+ GOTO_CHECK_OFFSET = 2618
+ };
+
+ static const char *const spell [];
+ static const int lhs [];
+ static const int rhs [];
+ static const int goto_default [];
+ static const int action_default [];
+ static const int action_index [];
+ static const int action_info [];
+ static const int action_check [];
+
+ static inline int nt_action (int state, int nt)
+ {
+ const int *const goto_index = &action_index [GOTO_INDEX_OFFSET];
+ const int *const goto_check = &action_check [GOTO_CHECK_OFFSET];
+
+ const int yyn = goto_index [state] + nt;
+
+ if (yyn < 0 || goto_check [yyn] != nt)
+ return goto_default [nt];
+
+ const int *const goto_info = &action_info [GOTO_INFO_OFFSET];
+ return goto_info [yyn];
+ }
+
+ static inline int t_action (int state, int token)
+ {
+ const int yyn = action_index [state] + token;
+
+ if (yyn < 0 || action_check [yyn] != token)
+ return - action_default [state];
+
+ return action_info [yyn];
+ }
+};
+
+
+#endif // QMLJSGRAMMAR_P_H
+
diff --git a/src/declarative/qml/parser/qmljslexer.cpp b/src/declarative/qml/parser/qmljslexer.cpp
new file mode 100644
index 0000000..2c03c21
--- /dev/null
+++ b/src/declarative/qml/parser/qmljslexer.cpp
@@ -0,0 +1,1160 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "qmljsglobal_p.h"
+#include "qmljsengine_p.h"
+#include "qmljslexer_p.h"
+#include "qmljsgrammar_p.h"
+
+#include <QtGui/qapplication.h>
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+QT_QML_BEGIN_NAMESPACE
+
+extern double qstrtod(const char *s00, char const **se, bool *ok);
+
+#define shiftWindowsLineBreak() \
+ do { \
+ if (((current == '\r') && (next1 == '\n')) \
+ || ((current == '\n') && (next1 == '\r'))) { \
+ shift(1); \
+ } \
+ } \
+ while (0)
+
+namespace QmlJS {
+extern double integerFromString(const char *buf, int size, int radix);
+}
+
+using namespace QmlJS;
+
+Lexer::Lexer(Engine *eng, bool tokenizeComments)
+ : driver(eng),
+ yylineno(0),
+ done(false),
+ size8(128), size16(128),
+ pos8(0), pos16(0),
+ terminator(false),
+ restrKeyword(false),
+ delimited(false),
+ stackToken(-1),
+ state(Start),
+ pos(0),
+ code(0), length(0),
+ yycolumn(0),
+ startpos(0),
+ startlineno(0), startcolumn(0),
+ bol(true),
+ current(0), next1(0), next2(0), next3(0),
+ err(NoError),
+ wantRx(false),
+ check_reserved(true),
+ parenthesesState(IgnoreParentheses),
+ parenthesesCount(0),
+ prohibitAutomaticSemicolon(false),
+ tokenizeComments(tokenizeComments)
+{
+ driver->setLexer(this);
+ // allocate space for read buffers
+ buffer8 = new char[size8];
+ buffer16 = new QChar[size16];
+ pattern = 0;
+ flags = 0;
+
+}
+
+Lexer::~Lexer()
+{
+ delete [] buffer8;
+ delete [] buffer16;
+}
+
+void Lexer::setCode(const QString &c, int lineno)
+{
+ errmsg = QString();
+ yylineno = lineno;
+ yycolumn = 1;
+ restrKeyword = false;
+ delimited = false;
+ stackToken = -1;
+ pos = 0;
+ code = c.unicode();
+ length = c.length();
+ bol = true;
+
+ // read first characters
+ current = (length > 0) ? code[0].unicode() : 0;
+ next1 = (length > 1) ? code[1].unicode() : 0;
+ next2 = (length > 2) ? code[2].unicode() : 0;
+ next3 = (length > 3) ? code[3].unicode() : 0;
+}
+
+void Lexer::shift(uint p)
+{
+ while (p--) {
+ ++pos;
+ ++yycolumn;
+ current = next1;
+ next1 = next2;
+ next2 = next3;
+ next3 = (pos + 3 < length) ? code[pos+3].unicode() : 0;
+ }
+}
+
+void Lexer::setDone(State s)
+{
+ state = s;
+ done = true;
+}
+
+int Lexer::findReservedWord(const QChar *c, int size) const
+{
+ switch (size) {
+ case 2: {
+ if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('o'))
+ return QmlJSGrammar::T_DO;
+ else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('f'))
+ return QmlJSGrammar::T_IF;
+ else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n'))
+ return QmlJSGrammar::T_IN;
+ else if (c[0] == QLatin1Char('a') && c[1] == QLatin1Char('s'))
+ return QmlJSGrammar::T_AS;
+ } break;
+
+ case 3: {
+ if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('o') && c[2] == QLatin1Char('r'))
+ return QmlJSGrammar::T_FOR;
+ else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('e') && c[2] == QLatin1Char('w'))
+ return QmlJSGrammar::T_NEW;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r') && c[2] == QLatin1Char('y'))
+ return QmlJSGrammar::T_TRY;
+ else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('a') && c[2] == QLatin1Char('r'))
+ return QmlJSGrammar::T_VAR;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n') && c[2] == QLatin1Char('t'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 4: {
+ if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('a')
+ && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('e'))
+ return QmlJSGrammar::T_CASE;
+ else if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('l')
+ && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('e'))
+ return QmlJSGrammar::T_ELSE;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('h')
+ && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('s'))
+ return QmlJSGrammar::T_THIS;
+ else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('d'))
+ return QmlJSGrammar::T_VOID;
+ else if (c[0] == QLatin1Char('w') && c[1] == QLatin1Char('i')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('h'))
+ return QmlJSGrammar::T_WITH;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r')
+ && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('e'))
+ return QmlJSGrammar::T_TRUE;
+ else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('u')
+ && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('l'))
+ return QmlJSGrammar::T_NULL;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('n')
+ && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('m'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('b') && c[1] == QLatin1Char('y')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('e'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('l') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('g'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('h')
+ && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('r'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('g') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('o'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 5: {
+ if (c[0] == QLatin1Char('b') && c[1] == QLatin1Char('r')
+ && c[2] == QLatin1Char('e') && c[3] == QLatin1Char('a')
+ && c[4] == QLatin1Char('k'))
+ return QmlJSGrammar::T_BREAK;
+ else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('a')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('c')
+ && c[4] == QLatin1Char('h'))
+ return QmlJSGrammar::T_CATCH;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('h')
+ && c[2] == QLatin1Char('r') && c[3] == QLatin1Char('o')
+ && c[4] == QLatin1Char('w'))
+ return QmlJSGrammar::T_THROW;
+ else if (c[0] == QLatin1Char('w') && c[1] == QLatin1Char('h')
+ && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('l')
+ && c[4] == QLatin1Char('e'))
+ return QmlJSGrammar::T_WHILE;
+ else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('s')
+ && c[4] == QLatin1Char('t'))
+ return QmlJSGrammar::T_CONST;
+ else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('a')
+ && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('s')
+ && c[4] == QLatin1Char('e'))
+ return QmlJSGrammar::T_FALSE;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('h')
+ && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('r')
+ && c[4] == QLatin1Char('t'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('u')
+ && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('e')
+ && c[4] == QLatin1Char('r'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('i')
+ && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('a')
+ && c[4] == QLatin1Char('l'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('l')
+ && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('s')
+ && c[4] == QLatin1Char('s'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('l')
+ && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('a')
+ && c[4] == QLatin1Char('t'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 6: {
+ if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('e')
+ && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('e')
+ && c[4] == QLatin1Char('t') && c[5] == QLatin1Char('e'))
+ return QmlJSGrammar::T_DELETE;
+ else if (c[0] == QLatin1Char('r') && c[1] == QLatin1Char('e')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('u')
+ && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('n'))
+ return QmlJSGrammar::T_RETURN;
+ else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('w')
+ && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('t')
+ && c[4] == QLatin1Char('c') && c[5] == QLatin1Char('h'))
+ return QmlJSGrammar::T_SWITCH;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('y')
+ && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('e')
+ && c[4] == QLatin1Char('o') && c[5] == QLatin1Char('f'))
+ return QmlJSGrammar::T_TYPEOF;
+ else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('m')
+ && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('o')
+ && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('t'))
+ return QmlJSGrammar::T_IMPORT;
+ else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('i')
+ && c[2] == QLatin1Char('g') && c[3] == QLatin1Char('n')
+ && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('l'))
+ return QmlJSGrammar::T_SIGNAL;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('x')
+ && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('o')
+ && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('t'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('t')
+ && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('t')
+ && c[4] == QLatin1Char('i') && c[5] == QLatin1Char('c'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('b')
+ && c[4] == QLatin1Char('l') && c[5] == QLatin1Char('e'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('m')
+ && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('o')
+ && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('t'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('u')
+ && c[2] == QLatin1Char('b') && c[3] == QLatin1Char('l')
+ && c[4] == QLatin1Char('i') && c[5] == QLatin1Char('c'))
+ return QmlJSGrammar::T_PUBLIC;
+ else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('a')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('i')
+ && c[4] == QLatin1Char('v') && c[5] == QLatin1Char('e'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('h')
+ && c[2] == QLatin1Char('r') && c[3] == QLatin1Char('o')
+ && c[4] == QLatin1Char('w') && c[5] == QLatin1Char('s'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 7: {
+ if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('e')
+ && c[2] == QLatin1Char('f') && c[3] == QLatin1Char('a')
+ && c[4] == QLatin1Char('u') && c[5] == QLatin1Char('l')
+ && c[6] == QLatin1Char('t'))
+ return QmlJSGrammar::T_DEFAULT;
+ else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('i')
+ && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('a')
+ && c[4] == QLatin1Char('l') && c[5] == QLatin1Char('l')
+ && c[6] == QLatin1Char('y'))
+ return QmlJSGrammar::T_FINALLY;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('b') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('l')
+ && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('a')
+ && c[6] == QLatin1Char('n'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('x')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('e')
+ && c[4] == QLatin1Char('n') && c[5] == QLatin1Char('d')
+ && c[6] == QLatin1Char('s'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('a')
+ && c[2] == QLatin1Char('c') && c[3] == QLatin1Char('k')
+ && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('g')
+ && c[6] == QLatin1Char('e'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('r')
+ && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('v')
+ && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('t')
+ && c[6] == QLatin1Char('e'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 8: {
+ if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('t')
+ && c[4] == QLatin1Char('i') && c[5] == QLatin1Char('n')
+ && c[6] == QLatin1Char('u') && c[7] == QLatin1Char('e'))
+ return QmlJSGrammar::T_CONTINUE;
+ else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('u')
+ && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('c')
+ && c[4] == QLatin1Char('t') && c[5] == QLatin1Char('i')
+ && c[6] == QLatin1Char('o') && c[7] == QLatin1Char('n'))
+ return QmlJSGrammar::T_FUNCTION;
+ else if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('e')
+ && c[2] == QLatin1Char('b') && c[3] == QLatin1Char('u')
+ && c[4] == QLatin1Char('g') && c[5] == QLatin1Char('g')
+ && c[6] == QLatin1Char('e') && c[7] == QLatin1Char('r'))
+ return QmlJSGrammar::T_DEBUGGER;
+ else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('r')
+ && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('p')
+ && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('r')
+ && c[6] == QLatin1Char('t') && c[7] == QLatin1Char('y'))
+ return QmlJSGrammar::T_PROPERTY;
+ else if (c[0] == QLatin1Char('r') && c[1] == QLatin1Char('e')
+ && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('d')
+ && c[4] == QLatin1Char('o') && c[5] == QLatin1Char('n')
+ && c[6] == QLatin1Char('l') && c[7] == QLatin1Char('y'))
+ return QmlJSGrammar::T_READONLY;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('a') && c[1] == QLatin1Char('b')
+ && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('t')
+ && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('a')
+ && c[6] == QLatin1Char('c') && c[7] == QLatin1Char('t'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('o')
+ && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('a')
+ && c[4] == QLatin1Char('t') && c[5] == QLatin1Char('i')
+ && c[6] == QLatin1Char('l') && c[7] == QLatin1Char('e'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 9: {
+ if (check_reserved) {
+ if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n')
+ && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('e')
+ && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('f')
+ && c[6] == QLatin1Char('a') && c[7] == QLatin1Char('c')
+ && c[8] == QLatin1Char('e'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r')
+ && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('n')
+ && c[4] == QLatin1Char('s') && c[5] == QLatin1Char('i')
+ && c[6] == QLatin1Char('e') && c[7] == QLatin1Char('n')
+ && c[8] == QLatin1Char('t'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('r')
+ && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('t')
+ && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('c')
+ && c[6] == QLatin1Char('t') && c[7] == QLatin1Char('e')
+ && c[8] == QLatin1Char('d'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 10: {
+ if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n')
+ && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('t')
+ && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('n')
+ && c[6] == QLatin1Char('c') && c[7] == QLatin1Char('e')
+ && c[8] == QLatin1Char('o') && c[9] == QLatin1Char('f'))
+ return QmlJSGrammar::T_INSTANCEOF;
+ else if (check_reserved) {
+ if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('m')
+ && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('l')
+ && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('m')
+ && c[6] == QLatin1Char('e') && c[7] == QLatin1Char('n')
+ && c[8] == QLatin1Char('t') && c[9] == QLatin1Char('s'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ case 12: {
+ if (check_reserved) {
+ if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('y')
+ && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('c')
+ && c[4] == QLatin1Char('h') && c[5] == QLatin1Char('r')
+ && c[6] == QLatin1Char('o') && c[7] == QLatin1Char('n')
+ && c[8] == QLatin1Char('i') && c[9] == QLatin1Char('z')
+ && c[10] == QLatin1Char('e') && c[11] == QLatin1Char('d'))
+ return QmlJSGrammar::T_RESERVED_WORD;
+ }
+ } break;
+
+ } // switch
+
+ return -1;
+}
+
+int Lexer::lex()
+{
+ int token = 0;
+ state = Start;
+ ushort stringType = 0; // either single or double quotes
+ bool multiLineString = false;
+ pos8 = pos16 = 0;
+ done = false;
+ terminator = false;
+
+ // did we push a token on the stack previously ?
+ // (after an automatic semicolon insertion)
+ if (stackToken >= 0) {
+ setDone(Other);
+ token = stackToken;
+ stackToken = -1;
+ }
+
+ while (!done) {
+ switch (state) {
+ case Start:
+ if (isWhiteSpace()) {
+ // do nothing
+ } else if (current == '/' && next1 == '/') {
+ recordStartPos();
+ shift(1);
+ state = InSingleLineComment;
+ } else if (current == '/' && next1 == '*') {
+ recordStartPos();
+ shift(1);
+ state = InMultiLineComment;
+ } else if (current == 0) {
+ syncProhibitAutomaticSemicolon();
+ if (!terminator && !delimited && !prohibitAutomaticSemicolon) {
+ // automatic semicolon insertion if program incomplete
+ token = QmlJSGrammar::T_SEMICOLON;
+ stackToken = 0;
+ setDone(Other);
+ } else {
+ setDone(Eof);
+ }
+ } else if (isLineTerminator()) {
+ shiftWindowsLineBreak();
+ yylineno++;
+ yycolumn = 0;
+ bol = true;
+ terminator = true;
+ syncProhibitAutomaticSemicolon();
+ if (restrKeyword) {
+ token = QmlJSGrammar::T_SEMICOLON;
+ setDone(Other);
+ }
+ } else if (current == '"' || current == '\'') {
+ recordStartPos();
+ state = InString;
+ multiLineString = false;
+ stringType = current;
+ } else if (isIdentLetter(current)) {
+ recordStartPos();
+ record16(current);
+ state = InIdentifier;
+ } else if (current == '0') {
+ recordStartPos();
+ record8(current);
+ state = InNum0;
+ } else if (isDecimalDigit(current)) {
+ recordStartPos();
+ record8(current);
+ state = InNum;
+ } else if (current == '.' && isDecimalDigit(next1)) {
+ recordStartPos();
+ record8(current);
+ state = InDecimal;
+ } else {
+ recordStartPos();
+ token = matchPunctuator(current, next1, next2, next3);
+ if (token != -1) {
+ if (terminator && !delimited && !prohibitAutomaticSemicolon
+ && (token == QmlJSGrammar::T_PLUS_PLUS
+ || token == QmlJSGrammar::T_MINUS_MINUS)) {
+ // automatic semicolon insertion
+ stackToken = token;
+ token = QmlJSGrammar::T_SEMICOLON;
+ }
+ setDone(Other);
+ }
+ else {
+ setDone(Bad);
+ err = IllegalCharacter;
+ errmsg = qApp->translate("QmlParser", "Illegal character");
+ }
+ }
+ break;
+ case InString:
+ if (current == stringType) {
+ shift(1);
+ setDone(String);
+ } else if (isLineTerminator()) {
+ multiLineString = true;
+ record16(current);
+ } else if (current == 0 || isLineTerminator()) {
+ setDone(Bad);
+ err = UnclosedStringLiteral;
+ errmsg = qApp->translate("QmlParser", "Unclosed string at end of line");
+ } else if (current == '\\') {
+ state = InEscapeSequence;
+ } else {
+ record16(current);
+ }
+ break;
+ // Escape Sequences inside of strings
+ case InEscapeSequence:
+ if (isOctalDigit(current)) {
+ if (current >= '0' && current <= '3' &&
+ isOctalDigit(next1) && isOctalDigit(next2)) {
+ record16(convertOctal(current, next1, next2));
+ shift(2);
+ state = InString;
+ } else if (isOctalDigit(current) &&
+ isOctalDigit(next1)) {
+ record16(convertOctal('0', current, next1));
+ shift(1);
+ state = InString;
+ } else if (isOctalDigit(current)) {
+ record16(convertOctal('0', '0', current));
+ state = InString;
+ } else {
+ setDone(Bad);
+ err = IllegalEscapeSequence;
+ errmsg = qApp->translate("QmlParser", "Illegal escape squence");
+ }
+ } else if (current == 'x')
+ state = InHexEscape;
+ else if (current == 'u')
+ state = InUnicodeEscape;
+ else {
+ if (isLineTerminator()) {
+ shiftWindowsLineBreak();
+ yylineno++;
+ yycolumn = 0;
+ bol = true;
+ } else {
+ record16(singleEscape(current));
+ }
+ state = InString;
+ }
+ break;
+ case InHexEscape:
+ if (isHexDigit(current) && isHexDigit(next1)) {
+ state = InString;
+ record16(QLatin1Char(convertHex(current, next1)));
+ shift(1);
+ } else if (current == stringType) {
+ record16(QLatin1Char('x'));
+ shift(1);
+ setDone(String);
+ } else {
+ record16(QLatin1Char('x'));
+ record16(current);
+ state = InString;
+ }
+ break;
+ case InUnicodeEscape:
+ if (isHexDigit(current) && isHexDigit(next1) &&
+ isHexDigit(next2) && isHexDigit(next3)) {
+ record16(convertUnicode(current, next1, next2, next3));
+ shift(3);
+ state = InString;
+ } else if (current == stringType) {
+ record16(QLatin1Char('u'));
+ shift(1);
+ setDone(String);
+ } else {
+ setDone(Bad);
+ err = IllegalUnicodeEscapeSequence;
+ errmsg = qApp->translate("QmlParser", "Illegal unicode escape sequence");
+ }
+ break;
+ case InSingleLineComment:
+ if (isLineTerminator()) {
+ shiftWindowsLineBreak();
+ yylineno++;
+ yycolumn = 0;
+ terminator = true;
+ bol = true;
+ if (restrKeyword) {
+ token = QmlJSGrammar::T_SEMICOLON;
+ setDone(Other);
+ } else
+ state = Start;
+ driver->addComment(startpos, tokenLength(), startlineno, startcolumn);
+ } else if (current == 0) {
+ driver->addComment(startpos, tokenLength(), startlineno, startcolumn);
+ setDone(Eof);
+ }
+
+ break;
+ case InMultiLineComment:
+ if (current == 0) {
+ setDone(Bad);
+ err = UnclosedComment;
+ errmsg = qApp->translate("QmlParser", "Unclosed comment at end of file");
+ driver->addComment(startpos, tokenLength(), startlineno, startcolumn);
+ } else if (isLineTerminator()) {
+ shiftWindowsLineBreak();
+ yylineno++;
+ } else if (current == '*' && next1 == '/') {
+ state = Start;
+ shift(1);
+ driver->addComment(startpos, tokenLength(), startlineno, startcolumn);
+ }
+
+ break;
+ case InIdentifier:
+ if (isIdentLetter(current) || isDecimalDigit(current)) {
+ record16(current);
+ break;
+ }
+ setDone(Identifier);
+ break;
+ case InNum0:
+ if (current == 'x' || current == 'X') {
+ record8(current);
+ state = InHex;
+ } else if (current == '.') {
+ record8(current);
+ state = InDecimal;
+ } else if (current == 'e' || current == 'E') {
+ record8(current);
+ state = InExponentIndicator;
+ } else if (isOctalDigit(current)) {
+ record8(current);
+ state = InOctal;
+ } else if (isDecimalDigit(current)) {
+ record8(current);
+ state = InDecimal;
+ } else {
+ setDone(Number);
+ }
+ break;
+ case InHex:
+ if (isHexDigit(current))
+ record8(current);
+ else
+ setDone(Hex);
+ break;
+ case InOctal:
+ if (isOctalDigit(current)) {
+ record8(current);
+ } else if (isDecimalDigit(current)) {
+ record8(current);
+ state = InDecimal;
+ } else {
+ setDone(Octal);
+ }
+ break;
+ case InNum:
+ if (isDecimalDigit(current)) {
+ record8(current);
+ } else if (current == '.') {
+ record8(current);
+ state = InDecimal;
+ } else if (current == 'e' || current == 'E') {
+ record8(current);
+ state = InExponentIndicator;
+ } else {
+ setDone(Number);
+ }
+ break;
+ case InDecimal:
+ if (isDecimalDigit(current)) {
+ record8(current);
+ } else if (current == 'e' || current == 'E') {
+ record8(current);
+ state = InExponentIndicator;
+ } else {
+ setDone(Number);
+ }
+ break;
+ case InExponentIndicator:
+ if (current == '+' || current == '-') {
+ record8(current);
+ } else if (isDecimalDigit(current)) {
+ record8(current);
+ state = InExponent;
+ } else {
+ setDone(Bad);
+ err = IllegalExponentIndicator;
+ errmsg = qApp->translate("QmlParser", "Illegal syntax for exponential number");
+ }
+ break;
+ case InExponent:
+ if (isDecimalDigit(current)) {
+ record8(current);
+ } else {
+ setDone(Number);
+ }
+ break;
+ default:
+ Q_ASSERT_X(0, "Lexer::lex", "Unhandled state in switch statement");
+ }
+
+ // move on to the next character
+ if (!done)
+ shift(1);
+ if (state != Start && state != InSingleLineComment)
+ bol = false;
+ }
+
+ // no identifiers allowed directly after numeric literal, e.g. "3in" is bad
+ if ((state == Number || state == Octal || state == Hex)
+ && isIdentLetter(current)) {
+ state = Bad;
+ err = IllegalIdentifier;
+ errmsg = qApp->translate("QmlParser", "Identifier cannot start with numeric literal");
+ }
+
+ // terminate string
+ buffer8[pos8] = '\0';
+
+ double dval = 0;
+ if (state == Number) {
+ dval = qstrtod(buffer8, 0, 0);
+ } else if (state == Hex) { // scan hex numbers
+ dval = integerFromString(buffer8, pos8, 16);
+ state = Number;
+ } else if (state == Octal) { // scan octal number
+ dval = integerFromString(buffer8, pos8, 8);
+ state = Number;
+ }
+
+ restrKeyword = false;
+ delimited = false;
+
+ switch (parenthesesState) {
+ case IgnoreParentheses:
+ break;
+ case CountParentheses:
+ if (token == QmlJSGrammar::T_RPAREN) {
+ --parenthesesCount;
+ if (parenthesesCount == 0)
+ parenthesesState = BalancedParentheses;
+ } else if (token == QmlJSGrammar::T_LPAREN) {
+ ++parenthesesCount;
+ }
+ break;
+ case BalancedParentheses:
+ parenthesesState = IgnoreParentheses;
+ break;
+ }
+
+ switch (state) {
+ case Eof:
+ return 0;
+ case Other:
+ if (token == QmlJSGrammar::T_RBRACE || token == QmlJSGrammar::T_SEMICOLON)
+ delimited = true;
+ return token;
+ case Identifier:
+ if ((token = findReservedWord(buffer16, pos16)) < 0) {
+ /* TODO: close leak on parse error. same holds true for String */
+ if (driver)
+ qsyylval.ustr = driver->intern(buffer16, pos16);
+ else
+ qsyylval.ustr = 0;
+ return QmlJSGrammar::T_IDENTIFIER;
+ }
+ if (token == QmlJSGrammar::T_CONTINUE || token == QmlJSGrammar::T_BREAK
+ || token == QmlJSGrammar::T_RETURN || token == QmlJSGrammar::T_THROW) {
+ restrKeyword = true;
+ } else if (token == QmlJSGrammar::T_IF || token == QmlJSGrammar::T_FOR
+ || token == QmlJSGrammar::T_WHILE || token == QmlJSGrammar::T_WITH) {
+ parenthesesState = CountParentheses;
+ parenthesesCount = 0;
+ } else if (token == QmlJSGrammar::T_DO) {
+ parenthesesState = BalancedParentheses;
+ }
+ return token;
+ case String:
+ if (driver)
+ qsyylval.ustr = driver->intern(buffer16, pos16);
+ else
+ qsyylval.ustr = 0;
+ return multiLineString?QmlJSGrammar::T_MULTILINE_STRING_LITERAL:QmlJSGrammar::T_STRING_LITERAL;
+ case Number:
+ qsyylval.dval = dval;
+ return QmlJSGrammar::T_NUMERIC_LITERAL;
+ case Bad:
+ return -1;
+ default:
+ Q_ASSERT(!"unhandled numeration value in switch");
+ return -1;
+ }
+}
+
+bool Lexer::isWhiteSpace() const
+{
+ return (current == ' ' || current == '\t' ||
+ current == 0x0b || current == 0x0c);
+}
+
+bool Lexer::isLineTerminator() const
+{
+ return (current == '\n' || current == '\r');
+}
+
+bool Lexer::isIdentLetter(ushort c)
+{
+ // ASCII-biased, since all reserved words are ASCII, aand hence the
+ // bulk of content to be parsed.
+ if ((c >= 'a' && c <= 'z')
+ || (c >= 'A' && c <= 'Z')
+ || c == '$'
+ || c == '_')
+ return true;
+ if (c < 128)
+ return false;
+ return QChar(c).isLetterOrNumber();
+}
+
+bool Lexer::isDecimalDigit(ushort c)
+{
+ return (c >= '0' && c <= '9');
+}
+
+bool Lexer::isHexDigit(ushort c) const
+{
+ return ((c >= '0' && c <= '9')
+ || (c >= 'a' && c <= 'f')
+ || (c >= 'A' && c <= 'F'));
+}
+
+bool Lexer::isOctalDigit(ushort c) const
+{
+ return (c >= '0' && c <= '7');
+}
+
+int Lexer::matchPunctuator(ushort c1, ushort c2,
+ ushort c3, ushort c4)
+{
+ if (c1 == '>' && c2 == '>' && c3 == '>' && c4 == '=') {
+ shift(4);
+ return QmlJSGrammar::T_GT_GT_GT_EQ;
+ } else if (c1 == '=' && c2 == '=' && c3 == '=') {
+ shift(3);
+ return QmlJSGrammar::T_EQ_EQ_EQ;
+ } else if (c1 == '!' && c2 == '=' && c3 == '=') {
+ shift(3);
+ return QmlJSGrammar::T_NOT_EQ_EQ;
+ } else if (c1 == '>' && c2 == '>' && c3 == '>') {
+ shift(3);
+ return QmlJSGrammar::T_GT_GT_GT;
+ } else if (c1 == '<' && c2 == '<' && c3 == '=') {
+ shift(3);
+ return QmlJSGrammar::T_LT_LT_EQ;
+ } else if (c1 == '>' && c2 == '>' && c3 == '=') {
+ shift(3);
+ return QmlJSGrammar::T_GT_GT_EQ;
+ } else if (c1 == '<' && c2 == '=') {
+ shift(2);
+ return QmlJSGrammar::T_LE;
+ } else if (c1 == '>' && c2 == '=') {
+ shift(2);
+ return QmlJSGrammar::T_GE;
+ } else if (c1 == '!' && c2 == '=') {
+ shift(2);
+ return QmlJSGrammar::T_NOT_EQ;
+ } else if (c1 == '+' && c2 == '+') {
+ shift(2);
+ return QmlJSGrammar::T_PLUS_PLUS;
+ } else if (c1 == '-' && c2 == '-') {
+ shift(2);
+ return QmlJSGrammar::T_MINUS_MINUS;
+ } else if (c1 == '=' && c2 == '=') {
+ shift(2);
+ return QmlJSGrammar::T_EQ_EQ;
+ } else if (c1 == '+' && c2 == '=') {
+ shift(2);
+ return QmlJSGrammar::T_PLUS_EQ;
+ } else if (c1 == '-' && c2 == '=') {
+ shift(2);
+ return QmlJSGrammar::T_MINUS_EQ;
+ } else if (c1 == '*' && c2 == '=') {
+ shift(2);
+ return QmlJSGrammar::T_STAR_EQ;
+ } else if (c1 == '/' && c2 == '=') {
+ shift(2);
+ return QmlJSGrammar::T_DIVIDE_EQ;
+ } else if (c1 == '&' && c2 == '=') {
+ shift(2);
+ return QmlJSGrammar::T_AND_EQ;
+ } else if (c1 == '^' && c2 == '=') {
+ shift(2);
+ return QmlJSGrammar::T_XOR_EQ;
+ } else if (c1 == '%' && c2 == '=') {
+ shift(2);
+ return QmlJSGrammar::T_REMAINDER_EQ;
+ } else if (c1 == '|' && c2 == '=') {
+ shift(2);
+ return QmlJSGrammar::T_OR_EQ;
+ } else if (c1 == '<' && c2 == '<') {
+ shift(2);
+ return QmlJSGrammar::T_LT_LT;
+ } else if (c1 == '>' && c2 == '>') {
+ shift(2);
+ return QmlJSGrammar::T_GT_GT;
+ } else if (c1 == '&' && c2 == '&') {
+ shift(2);
+ return QmlJSGrammar::T_AND_AND;
+ } else if (c1 == '|' && c2 == '|') {
+ shift(2);
+ return QmlJSGrammar::T_OR_OR;
+ }
+
+ switch(c1) {
+ case '=': shift(1); return QmlJSGrammar::T_EQ;
+ case '>': shift(1); return QmlJSGrammar::T_GT;
+ case '<': shift(1); return QmlJSGrammar::T_LT;
+ case ',': shift(1); return QmlJSGrammar::T_COMMA;
+ case '!': shift(1); return QmlJSGrammar::T_NOT;
+ case '~': shift(1); return QmlJSGrammar::T_TILDE;
+ case '?': shift(1); return QmlJSGrammar::T_QUESTION;
+ case ':': shift(1); return QmlJSGrammar::T_COLON;
+ case '.': shift(1); return QmlJSGrammar::T_DOT;
+ case '+': shift(1); return QmlJSGrammar::T_PLUS;
+ case '-': shift(1); return QmlJSGrammar::T_MINUS;
+ case '*': shift(1); return QmlJSGrammar::T_STAR;
+ case '/': shift(1); return QmlJSGrammar::T_DIVIDE_;
+ case '&': shift(1); return QmlJSGrammar::T_AND;
+ case '|': shift(1); return QmlJSGrammar::T_OR;
+ case '^': shift(1); return QmlJSGrammar::T_XOR;
+ case '%': shift(1); return QmlJSGrammar::T_REMAINDER;
+ case '(': shift(1); return QmlJSGrammar::T_LPAREN;
+ case ')': shift(1); return QmlJSGrammar::T_RPAREN;
+ case '{': shift(1); return QmlJSGrammar::T_LBRACE;
+ case '}': shift(1); return QmlJSGrammar::T_RBRACE;
+ case '[': shift(1); return QmlJSGrammar::T_LBRACKET;
+ case ']': shift(1); return QmlJSGrammar::T_RBRACKET;
+ case ';': shift(1); return QmlJSGrammar::T_SEMICOLON;
+
+ default: return -1;
+ }
+}
+
+ushort Lexer::singleEscape(ushort c) const
+{
+ switch(c) {
+ case 'b':
+ return 0x08;
+ case 't':
+ return 0x09;
+ case 'n':
+ return 0x0A;
+ case 'v':
+ return 0x0B;
+ case 'f':
+ return 0x0C;
+ case 'r':
+ return 0x0D;
+ case '"':
+ return 0x22;
+ case '\'':
+ return 0x27;
+ case '\\':
+ return 0x5C;
+ default:
+ return c;
+ }
+}
+
+ushort Lexer::convertOctal(ushort c1, ushort c2,
+ ushort c3) const
+{
+ return ((c1 - '0') * 64 + (c2 - '0') * 8 + c3 - '0');
+}
+
+unsigned char Lexer::convertHex(ushort c)
+{
+ if (c >= '0' && c <= '9')
+ return (c - '0');
+ else if (c >= 'a' && c <= 'f')
+ return (c - 'a' + 10);
+ else
+ return (c - 'A' + 10);
+}
+
+unsigned char Lexer::convertHex(ushort c1, ushort c2)
+{
+ return ((convertHex(c1) << 4) + convertHex(c2));
+}
+
+QChar Lexer::convertUnicode(ushort c1, ushort c2,
+ ushort c3, ushort c4)
+{
+ return QChar((convertHex(c3) << 4) + convertHex(c4),
+ (convertHex(c1) << 4) + convertHex(c2));
+}
+
+void Lexer::record8(ushort c)
+{
+ Q_ASSERT(c <= 0xff);
+
+ // enlarge buffer if full
+ if (pos8 >= size8 - 1) {
+ char *tmp = new char[2 * size8];
+ memcpy(tmp, buffer8, size8 * sizeof(char));
+ delete [] buffer8;
+ buffer8 = tmp;
+ size8 *= 2;
+ }
+
+ buffer8[pos8++] = (char) c;
+}
+
+void Lexer::record16(QChar c)
+{
+ // enlarge buffer if full
+ if (pos16 >= size16 - 1) {
+ QChar *tmp = new QChar[2 * size16];
+ memcpy(tmp, buffer16, size16 * sizeof(QChar));
+ delete [] buffer16;
+ buffer16 = tmp;
+ size16 *= 2;
+ }
+
+ buffer16[pos16++] = c;
+}
+
+void Lexer::recordStartPos()
+{
+ startpos = pos;
+ startlineno = yylineno;
+ startcolumn = yycolumn;
+}
+
+bool Lexer::scanRegExp(RegExpBodyPrefix prefix)
+{
+ pos16 = 0;
+ bool lastWasEscape = false;
+
+ if (prefix == EqualPrefix)
+ record16(QLatin1Char('='));
+
+ while (1) {
+ if (isLineTerminator() || current == 0) {
+ errmsg = qApp->translate("QmlParser", "Unterminated regular expression literal");
+ return false;
+ }
+ else if (current != '/' || lastWasEscape == true)
+ {
+ record16(current);
+ lastWasEscape = !lastWasEscape && (current == '\\');
+ }
+ else {
+ if (driver)
+ pattern = driver->intern(buffer16, pos16);
+ else
+ pattern = 0;
+ pos16 = 0;
+ shift(1);
+ break;
+ }
+ shift(1);
+ }
+
+ flags = 0;
+ while (isIdentLetter(current)) {
+ int flag = Ecma::RegExp::flagFromChar(current);
+ if (flag == 0) {
+ errmsg = qApp->translate("QmlParser", "Invalid regular expression flag '%0'")
+ .arg(QChar(current));
+ return false;
+ }
+ flags |= flag;
+ record16(current);
+ shift(1);
+ }
+
+ return true;
+}
+
+void Lexer::syncProhibitAutomaticSemicolon()
+{
+ if (parenthesesState == BalancedParentheses) {
+ // we have seen something like "if (foo)", which means we should
+ // never insert an automatic semicolon at this point, since it would
+ // then be expanded into an empty statement (ECMA-262 7.9.1)
+ prohibitAutomaticSemicolon = true;
+ parenthesesState = IgnoreParentheses;
+ } else {
+ prohibitAutomaticSemicolon = false;
+ }
+}
+
+QT_QML_END_NAMESPACE
+
+
diff --git a/src/declarative/qml/parser/qmljslexer_p.h b/src/declarative/qml/parser/qmljslexer_p.h
new file mode 100644
index 0000000..50f7c4b
--- /dev/null
+++ b/src/declarative/qml/parser/qmljslexer_p.h
@@ -0,0 +1,249 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 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 QMLJSLEXER_P_H
+#define QMLJSLEXER_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/QString>
+
+#include "qmljsglobal_p.h"
+
+QT_QML_BEGIN_NAMESPACE
+
+namespace QmlJS {
+
+class Engine;
+class NameId;
+
+class Lexer
+{
+public:
+ Lexer(Engine *eng, bool tokenizeComments = false);
+ ~Lexer();
+
+ void setCode(const QString &c, int lineno);
+ int lex();
+
+ int currentLineNo() const { return yylineno; }
+ int currentColumnNo() const { return yycolumn; }
+
+ int tokenOffset() const { return startpos; }
+ int tokenLength() const { return pos - startpos; }
+
+ int startLineNo() const { return startlineno; }
+ int startColumnNo() const { return startcolumn; }
+
+ int endLineNo() const { return currentLineNo(); }
+ int endColumnNo() const
+ { int col = currentColumnNo(); return (col > 0) ? col - 1 : col; }
+
+ bool prevTerminator() const { return terminator; }
+
+ enum State { Start,
+ Identifier,
+ InIdentifier,
+ InSingleLineComment,
+ InMultiLineComment,
+ InNum,
+ InNum0,
+ InHex,
+ InOctal,
+ InDecimal,
+ InExponentIndicator,
+ InExponent,
+ Hex,
+ Octal,
+ Number,
+ String,
+ Eof,
+ InString,
+ InEscapeSequence,
+ InHexEscape,
+ InUnicodeEscape,
+ Other,
+ Bad };
+
+ enum Error {
+ NoError,
+ IllegalCharacter,
+ UnclosedStringLiteral,
+ IllegalEscapeSequence,
+ IllegalUnicodeEscapeSequence,
+ UnclosedComment,
+ IllegalExponentIndicator,
+ IllegalIdentifier
+ };
+
+ enum ParenthesesState {
+ IgnoreParentheses,
+ CountParentheses,
+ BalancedParentheses
+ };
+
+ enum RegExpBodyPrefix {
+ NoPrefix,
+ EqualPrefix
+ };
+
+ bool scanRegExp(RegExpBodyPrefix prefix = NoPrefix);
+
+ NameId *pattern;
+ int flags;
+
+ State lexerState() const
+ { return state; }
+
+ QString errorMessage() const
+ { return errmsg; }
+ void setErrorMessage(const QString &err)
+ { errmsg = err; }
+ void setErrorMessage(const char *err)
+ { setErrorMessage(QString::fromLatin1(err)); }
+
+ Error error() const
+ { return err; }
+ void clearError()
+ { err = NoError; }
+
+private:
+ Engine *driver;
+ int yylineno;
+ bool done;
+ char *buffer8;
+ QChar *buffer16;
+ uint size8, size16;
+ uint pos8, pos16;
+ bool terminator;
+ bool restrKeyword;
+ // encountered delimiter like "'" and "}" on last run
+ bool delimited;
+ int stackToken;
+
+ State state;
+ void setDone(State s);
+ uint pos;
+ void shift(uint p);
+ int lookupKeyword(const char *);
+
+ bool isWhiteSpace() const;
+ bool isLineTerminator() const;
+ bool isHexDigit(ushort c) const;
+ bool isOctalDigit(ushort c) const;
+
+ int matchPunctuator(ushort c1, ushort c2,
+ ushort c3, ushort c4);
+ ushort singleEscape(ushort c) const;
+ ushort convertOctal(ushort c1, ushort c2,
+ ushort c3) const;
+public:
+ static unsigned char convertHex(ushort c1);
+ static unsigned char convertHex(ushort c1, ushort c2);
+ static QChar convertUnicode(ushort c1, ushort c2,
+ ushort c3, ushort c4);
+ static bool isIdentLetter(ushort c);
+ static bool isDecimalDigit(ushort c);
+
+ inline int ival() const { return qsyylval.ival; }
+ inline double dval() const { return qsyylval.dval; }
+ inline NameId *ustr() const { return qsyylval.ustr; }
+
+ const QChar *characterBuffer() const { return buffer16; }
+ int characterCount() const { return pos16; }
+
+private:
+ void record8(ushort c);
+ void record16(QChar c);
+ void recordStartPos();
+
+ int findReservedWord(const QChar *buffer, int size) const;
+
+ void syncProhibitAutomaticSemicolon();
+
+ const QChar *code;
+ uint length;
+ int yycolumn;
+ int startpos;
+ int startlineno;
+ int startcolumn;
+ int bol; // begin of line
+
+ union {
+ int ival;
+ double dval;
+ NameId *ustr;
+ } qsyylval;
+
+ // current and following unicode characters
+ ushort current, next1, next2, next3;
+
+ struct keyword {
+ const char *name;
+ int token;
+ };
+
+ QString errmsg;
+ Error err;
+
+ bool wantRx;
+ bool check_reserved;
+
+ ParenthesesState parenthesesState;
+ int parenthesesCount;
+ bool prohibitAutomaticSemicolon;
+ bool tokenizeComments;
+};
+
+} // namespace QmlJS
+
+QT_QML_END_NAMESPACE
+
+#endif
diff --git a/src/declarative/qml/parser/qmljsmemorypool_p.h b/src/declarative/qml/parser/qmljsmemorypool_p.h
new file mode 100644
index 0000000..70e7737
--- /dev/null
+++ b/src/declarative/qml/parser/qmljsmemorypool_p.h
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** 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 QMLJSMEMORYPOOL_P_H
+#define QMLJSMEMORYPOOL_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/qglobal.h>
+#include <QtCore/qshareddata.h>
+#include <string.h>
+
+#include "qmljsglobal_p.h"
+
+QT_QML_BEGIN_NAMESPACE
+
+namespace QmlJS {
+
+class MemoryPool : public QSharedData
+{
+public:
+ enum { maxBlockCount = -1 };
+ enum { defaultBlockSize = 1 << 12 };
+
+ MemoryPool() {
+ m_blockIndex = maxBlockCount;
+ m_currentIndex = 0;
+ m_storage = 0;
+ m_currentBlock = 0;
+ m_currentBlockSize = 0;
+ }
+
+ virtual ~MemoryPool() {
+ for (int index = 0; index < m_blockIndex + 1; ++index)
+ qFree(m_storage[index]);
+
+ qFree(m_storage);
+ }
+
+ char *allocate(int bytes) {
+ bytes += (8 - bytes) & 7; // ensure multiple of 8 bytes (maintain alignment)
+ if (m_currentBlock == 0 || m_currentBlockSize < m_currentIndex + bytes) {
+ ++m_blockIndex;
+ m_currentBlockSize = defaultBlockSize << m_blockIndex;
+
+ m_storage = reinterpret_cast<char**>(qRealloc(m_storage, sizeof(char*) * (1 + m_blockIndex)));
+ m_currentBlock = m_storage[m_blockIndex] = reinterpret_cast<char*>(qMalloc(m_currentBlockSize));
+ ::memset(m_currentBlock, 0, m_currentBlockSize);
+
+ m_currentIndex = (8 - quintptr(m_currentBlock)) & 7; // ensure first chunk is 64-bit aligned
+ Q_ASSERT(m_currentIndex + bytes <= m_currentBlockSize);
+ }
+
+ char *p = reinterpret_cast<char *>
+ (m_currentBlock + m_currentIndex);
+
+ m_currentIndex += bytes;
+
+ return p;
+ }
+
+ int bytesAllocated() const {
+ int bytes = 0;
+ for (int index = 0; index < m_blockIndex; ++index)
+ bytes += (defaultBlockSize << index);
+ bytes += m_currentIndex;
+ return bytes;
+ }
+
+private:
+ int m_blockIndex;
+ int m_currentIndex;
+ char *m_currentBlock;
+ int m_currentBlockSize;
+ char **m_storage;
+
+private:
+ Q_DISABLE_COPY(MemoryPool)
+};
+
+} // namespace QmlJS
+
+QT_QML_END_NAMESPACE
+
+#endif
diff --git a/src/declarative/qml/parser/qmljsnodepool_p.h b/src/declarative/qml/parser/qmljsnodepool_p.h
new file mode 100644
index 0000000..dfe3bac
--- /dev/null
+++ b/src/declarative/qml/parser/qmljsnodepool_p.h
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** 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 QMLJSNODEPOOL_P_H
+#define QMLJSNODEPOOL_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/QHash>
+#include <QtCore/QString>
+
+#include "qmljsglobal_p.h"
+#include "qmljsmemorypool_p.h"
+
+QT_QML_BEGIN_NAMESPACE
+
+namespace QmlJS {
+
+namespace AST {
+class Node;
+} // namespace AST
+
+class Code;
+class CompilationUnit;
+class Engine;
+
+template <typename NodeType>
+inline NodeType *makeAstNode(MemoryPool *storage)
+{
+ NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType();
+ return node;
+}
+
+template <typename NodeType, typename Arg1>
+inline NodeType *makeAstNode(MemoryPool *storage, Arg1 arg1)
+{
+ NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType(arg1);
+ return node;
+}
+
+template <typename NodeType, typename Arg1, typename Arg2>
+inline NodeType *makeAstNode(MemoryPool *storage, Arg1 arg1, Arg2 arg2)
+{
+ NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType(arg1, arg2);
+ return node;
+}
+
+template <typename NodeType, typename Arg1, typename Arg2, typename Arg3>
+inline NodeType *makeAstNode(MemoryPool *storage, Arg1 arg1, Arg2 arg2, Arg3 arg3)
+{
+ NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType(arg1, arg2, arg3);
+ return node;
+}
+
+template <typename NodeType, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+inline NodeType *makeAstNode(MemoryPool *storage, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
+{
+ NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType(arg1, arg2, arg3, arg4);
+ return node;
+}
+
+class NodePool : public MemoryPool
+{
+public:
+ NodePool(const QString &fileName, Engine *engine);
+ virtual ~NodePool();
+
+ Code *createCompiledCode(AST::Node *node, CompilationUnit &compilation);
+
+ inline QString fileName() const { return m_fileName; }
+ inline Engine *engine() const { return m_engine; }
+#ifndef J_SCRIPT_NO_EVENT_NOTIFY
+ inline qint64 id() const { return m_id; }
+#endif
+
+private:
+ QHash<AST::Node*, Code*> m_codeCache;
+ QString m_fileName;
+ Engine *m_engine;
+#ifndef J_SCRIPT_NO_EVENT_NOTIFY
+ qint64 m_id;
+#endif
+
+private:
+ Q_DISABLE_COPY(NodePool)
+};
+
+} // namespace QmlJS
+
+QT_QML_END_NAMESPACE
+
+#endif
diff --git a/src/declarative/qml/parser/qmljsparser.cpp b/src/declarative/qml/parser/qmljsparser.cpp
new file mode 100644
index 0000000..402aaeb
--- /dev/null
+++ b/src/declarative/qml/parser/qmljsparser.cpp
@@ -0,0 +1,1825 @@
+// This file was generated by qlalr - DO NOT EDIT!
+
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 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 <QtCore/QtDebug>
+#include <QtGui/QApplication>
+
+#include <string.h>
+
+#include "qmljsengine_p.h"
+#include "qmljslexer_p.h"
+#include "qmljsast_p.h"
+#include "qmljsnodepool_p.h"
+
+
+
+#include "qmljsparser_p.h"
+#include <QVarLengthArray>
+
+//
+// This file is automatically generated from qmljs.g.
+// Changes will be lost.
+//
+
+using namespace QmlJS;
+
+QT_QML_BEGIN_NAMESPACE
+
+void Parser::reallocateStack()
+{
+ if (! stack_size)
+ stack_size = 128;
+ else
+ stack_size <<= 1;
+
+ sym_stack = reinterpret_cast<Value*> (qRealloc(sym_stack, stack_size * sizeof(Value)));
+ state_stack = reinterpret_cast<int*> (qRealloc(state_stack, stack_size * sizeof(int)));
+ location_stack = reinterpret_cast<AST::SourceLocation*> (qRealloc(location_stack, stack_size * sizeof(AST::SourceLocation)));
+}
+
+inline static bool automatic(Engine *driver, int token)
+{
+ return token == QmlJSGrammar::T_RBRACE
+ || token == 0
+ || driver->lexer()->prevTerminator();
+}
+
+
+Parser::Parser(Engine *engine):
+ driver(engine),
+ tos(0),
+ stack_size(0),
+ sym_stack(0),
+ state_stack(0),
+ location_stack(0),
+ first_token(0),
+ last_token(0)
+{
+}
+
+Parser::~Parser()
+{
+ if (stack_size) {
+ qFree(sym_stack);
+ qFree(state_stack);
+ qFree(location_stack);
+ }
+}
+
+static inline AST::SourceLocation location(Lexer *lexer)
+{
+ AST::SourceLocation loc;
+ loc.offset = lexer->tokenOffset();
+ loc.length = lexer->tokenLength();
+ loc.startLine = lexer->startLineNo();
+ loc.startColumn = lexer->startColumnNo();
+ return loc;
+}
+
+AST::UiQualifiedId *Parser::reparseAsQualifiedId(AST::ExpressionNode *expr)
+{
+ QVarLengthArray<NameId *, 4> nameIds;
+ QVarLengthArray<AST::SourceLocation, 4> locations;
+
+ AST::ExpressionNode *it = expr;
+ while (AST::FieldMemberExpression *m = AST::cast<AST::FieldMemberExpression *>(it)) {
+ nameIds.append(m->name);
+ locations.append(m->identifierToken);
+ it = m->base;
+ }
+
+ if (AST::IdentifierExpression *idExpr = AST::cast<AST::IdentifierExpression *>(it)) {
+ AST::UiQualifiedId *q = makeAstNode<AST::UiQualifiedId>(driver->nodePool(), idExpr->name);
+ q->identifierToken = idExpr->identifierToken;
+
+ AST::UiQualifiedId *currentId = q;
+ for (int i = nameIds.size() - 1; i != -1; --i) {
+ currentId = makeAstNode<AST::UiQualifiedId>(driver->nodePool(), currentId, nameIds[i]);
+ currentId->identifierToken = locations[i];
+ }
+
+ return currentId->finish();
+ }
+
+ return 0;
+}
+
+bool Parser::parse(int startToken)
+{
+ Lexer *lexer = driver->lexer();
+ bool hadErrors = false;
+ int yytoken = -1;
+ int action = 0;
+
+ token_buffer[0].token = startToken;
+ first_token = &token_buffer[0];
+ last_token = &token_buffer[1];
+
+ tos = -1;
+ program = 0;
+
+ do {
+ if (++tos == stack_size)
+ reallocateStack();
+
+ state_stack[tos] = action;
+
+ _Lcheck_token:
+ if (yytoken == -1 && -TERMINAL_COUNT != action_index[action]) {
+ yyprevlloc = yylloc;
+
+ if (first_token == last_token) {
+ yytoken = lexer->lex();
+ yylval = lexer->dval();
+ yylloc = location(lexer);
+ } else {
+ yytoken = first_token->token;
+ yylval = first_token->dval;
+ yylloc = first_token->loc;
+ ++first_token;
+ }
+ }
+
+ action = t_action(action, yytoken);
+ if (action > 0) {
+ if (action != ACCEPT_STATE) {
+ yytoken = -1;
+ sym(1).dval = yylval;
+ loc(1) = yylloc;
+ } else {
+ --tos;
+ return ! hadErrors;
+ }
+ } else if (action < 0) {
+ const int r = -action - 1;
+ tos -= rhs[r];
+
+ switch (r) {
+
+case 0: {
+ sym(1).Node = sym(2).Node;
+ program = sym(1).Node;
+} break;
+
+case 1: {
+ sym(1).Node = sym(2).Node;
+ program = sym(1).Node;
+} break;
+
+case 2: {
+ sym(1).Node = sym(2).Node;
+ program = sym(1).Node;
+} break;
+
+case 3: {
+ sym(1).Node = sym(2).Node;
+ program = sym(1).Node;
+} break;
+
+case 4: {
+ sym(1).UiProgram = makeAstNode<AST::UiProgram> (driver->nodePool(), sym(1).UiImportList,
+ sym(2).UiObjectMemberList->finish());
+} break;
+
+case 6: {
+ sym(1).Node = sym(1).UiImportList->finish();
+} break;
+
+case 7: {
+ sym(1).Node = makeAstNode<AST::UiImportList> (driver->nodePool(), sym(1).UiImport);
+} break;
+
+case 8: {
+ sym(1).Node = makeAstNode<AST::UiImportList> (driver->nodePool(),
+ sym(1).UiImportList, sym(2).UiImport);
+} break;
+
+case 11: {
+ sym(1).UiImport->semicolonToken = loc(2);
+} break;
+
+case 13: {
+ sym(1).UiImport->versionToken = loc(2);
+ sym(1).UiImport->semicolonToken = loc(3);
+} break;
+
+case 15: {
+ sym(1).UiImport->versionToken = loc(2);
+ sym(1).UiImport->asToken = loc(3);
+ sym(1).UiImport->importIdToken = loc(4);
+ sym(1).UiImport->importId = sym(4).sval;
+ sym(1).UiImport->semicolonToken = loc(5);
+} break;
+
+case 17: {
+ sym(1).UiImport->asToken = loc(2);
+ sym(1).UiImport->importIdToken = loc(3);
+ sym(1).UiImport->importId = sym(3).sval;
+ sym(1).UiImport->semicolonToken = loc(4);
+} break;
+
+case 18: {
+ AST::UiImport *node = 0;
+
+ if (AST::StringLiteral *importIdLiteral = AST::cast<AST::StringLiteral *>(sym(2).Expression)) {
+ node = makeAstNode<AST::UiImport>(driver->nodePool(), importIdLiteral->value);
+ node->fileNameToken = loc(2);
+ } else if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(2).Expression)) {
+ QString text;
+ for (AST::UiQualifiedId *q = qualifiedId; q; q = q->next) {
+ text += q->name->asString();
+ if (q->next) text += QLatin1String(".");
+ }
+ node = makeAstNode<AST::UiImport>(driver->nodePool(), qualifiedId);
+ node->fileNameToken = loc(2);
+ }
+
+ sym(1).Node = node;
+
+ if (! node) {
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1),
+ QLatin1String("Expected a qualified name id or a string literal")));
+
+ return false; // ### remove me
+ }
+} break;
+
+case 19: {
+ sym(1).Node = 0;
+} break;
+
+case 20: {
+ sym(1).Node = makeAstNode<AST::UiObjectMemberList> (driver->nodePool(), sym(1).UiObjectMember);
+} break;
+
+case 21: {
+ sym(1).Node = makeAstNode<AST::UiObjectMemberList> (driver->nodePool(), sym(1).UiObjectMember);
+} break;
+
+case 22: {
+ AST::UiObjectMemberList *node = makeAstNode<AST:: UiObjectMemberList> (driver->nodePool(),
+ sym(1).UiObjectMemberList, sym(2).UiObjectMember);
+ sym(1).Node = node;
+} break;
+
+case 23: {
+ sym(1).Node = makeAstNode<AST::UiArrayMemberList> (driver->nodePool(), sym(1).UiObjectMember);
+} break;
+
+case 24: {
+ AST::UiArrayMemberList *node = makeAstNode<AST::UiArrayMemberList> (driver->nodePool(),
+ sym(1).UiArrayMemberList, sym(3).UiObjectMember);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 25: {
+ AST::UiObjectInitializer *node = makeAstNode<AST::UiObjectInitializer> (driver->nodePool(), (AST::UiObjectMemberList*)0);
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 26: {
+ AST::UiObjectInitializer *node = makeAstNode<AST::UiObjectInitializer> (driver->nodePool(), sym(2).UiObjectMemberList->finish());
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 27: {
+ AST::UiObjectDefinition *node = makeAstNode<AST::UiObjectDefinition> (driver->nodePool(), sym(1).UiQualifiedId,
+ sym(2).UiObjectInitializer);
+ sym(1).Node = node;
+} break;
+
+case 29: {
+ AST::UiArrayBinding *node = makeAstNode<AST::UiArrayBinding> (driver->nodePool(),
+ sym(1).UiQualifiedId, sym(4).UiArrayMemberList->finish());
+ node->colonToken = loc(2);
+ node->lbracketToken = loc(3);
+ node->rbracketToken = loc(5);
+ sym(1).Node = node;
+} break;
+
+case 30: {
+ AST::UiObjectBinding *node = makeAstNode<AST::UiObjectBinding> (driver->nodePool(),
+ sym(1).UiQualifiedId, sym(3).UiQualifiedId, sym(4).UiObjectInitializer);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+case 31:case 32:case 33:case 34:
+{
+ AST::UiScriptBinding *node = makeAstNode<AST::UiScriptBinding> (driver->nodePool(),
+ sym(1).UiQualifiedId, sym(3).Statement);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 35:
+
+case 36: {
+ sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount());
+ break;
+}
+
+case 38: {
+ sym(1).Node = 0;
+} break;
+
+case 39: {
+ sym(1).Node = sym(1).UiParameterList->finish ();
+} break;
+
+case 40: {
+ AST::UiParameterList *node = makeAstNode<AST::UiParameterList> (driver->nodePool(), sym(1).sval, sym(2).sval);
+ node->identifierToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 41: {
+ AST::UiParameterList *node = makeAstNode<AST::UiParameterList> (driver->nodePool(), sym(1).UiParameterList, sym(3).sval, sym(4).sval);
+ node->commaToken = loc(2);
+ node->identifierToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 43: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), (NameId *)0, sym(2).sval);
+ node->type = AST::UiPublicMember::Signal;
+ node->propertyToken = loc(1);
+ node->typeToken = loc(2);
+ node->identifierToken = loc(2);
+ node->parameters = sym(4).UiParameterList;
+ node->semicolonToken = loc(6);
+ sym(1).Node = node;
+} break;
+
+case 45: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), (NameId *)0, sym(2).sval);
+ node->type = AST::UiPublicMember::Signal;
+ node->propertyToken = loc(1);
+ node->typeToken = loc(2);
+ node->identifierToken = loc(2);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 47: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(4).sval, sym(6).sval);
+ node->typeModifier = sym(2).sval;
+ node->propertyToken = loc(1);
+ node->typeModifierToken = loc(2);
+ node->typeToken = loc(4);
+ node->identifierToken = loc(6);
+ node->semicolonToken = loc(7);
+ sym(1).Node = node;
+} break;
+
+case 49: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(2).sval, sym(3).sval);
+ node->propertyToken = loc(1);
+ node->typeToken = loc(2);
+ node->identifierToken = loc(3);
+ node->semicolonToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 51: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(3).sval, sym(4).sval);
+ node->isDefaultMember = true;
+ node->defaultToken = loc(1);
+ node->propertyToken = loc(2);
+ node->typeToken = loc(3);
+ node->identifierToken = loc(4);
+ node->semicolonToken = loc(5);
+ sym(1).Node = node;
+} break;
+
+case 53: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(2).sval, sym(3).sval,
+ sym(5).Expression);
+ node->propertyToken = loc(1);
+ node->typeToken = loc(2);
+ node->identifierToken = loc(3);
+ node->colonToken = loc(4);
+ node->semicolonToken = loc(6);
+ sym(1).Node = node;
+} break;
+
+case 55: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(3).sval, sym(4).sval,
+ sym(6).Expression);
+ node->isReadonlyMember = true;
+ node->readonlyToken = loc(1);
+ node->propertyToken = loc(2);
+ node->typeToken = loc(3);
+ node->identifierToken = loc(4);
+ node->colonToken = loc(5);
+ node->semicolonToken = loc(7);
+ sym(1).Node = node;
+} break;
+
+case 57: {
+ AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(3).sval, sym(4).sval,
+ sym(6).Expression);
+ node->isDefaultMember = true;
+ node->defaultToken = loc(1);
+ node->propertyToken = loc(2);
+ node->typeToken = loc(3);
+ node->identifierToken = loc(4);
+ node->colonToken = loc(5);
+ node->semicolonToken = loc(7);
+ sym(1).Node = node;
+} break;
+
+case 58: {
+ sym(1).Node = makeAstNode<AST::UiSourceElement>(driver->nodePool(), sym(1).Node);
+} break;
+
+case 59: {
+ sym(1).Node = makeAstNode<AST::UiSourceElement>(driver->nodePool(), sym(1).Node);
+} break;
+
+case 61: {
+ QString s = QLatin1String(QmlJSGrammar::spell[T_PROPERTY]);
+ sym(1).sval = driver->intern(s.constData(), s.length());
+ break;
+}
+
+case 62: {
+ QString s = QLatin1String(QmlJSGrammar::spell[T_SIGNAL]);
+ sym(1).sval = driver->intern(s.constData(), s.length());
+ break;
+}
+
+case 63: {
+ QString s = QLatin1String(QmlJSGrammar::spell[T_READONLY]);
+ sym(1).sval = driver->intern(s.constData(), s.length());
+ break;
+}
+
+case 64: {
+ AST::ThisExpression *node = makeAstNode<AST::ThisExpression> (driver->nodePool());
+ node->thisToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 65: {
+ AST::IdentifierExpression *node = makeAstNode<AST::IdentifierExpression> (driver->nodePool(), sym(1).sval);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 66: {
+ AST::NullExpression *node = makeAstNode<AST::NullExpression> (driver->nodePool());
+ node->nullToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 67: {
+ AST::TrueLiteral *node = makeAstNode<AST::TrueLiteral> (driver->nodePool());
+ node->trueToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 68: {
+ AST::FalseLiteral *node = makeAstNode<AST::FalseLiteral> (driver->nodePool());
+ node->falseToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 69: {
+ AST::NumericLiteral *node = makeAstNode<AST::NumericLiteral> (driver->nodePool(), sym(1).dval);
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+} break;
+case 70:
+case 71: {
+ AST::StringLiteral *node = makeAstNode<AST::StringLiteral> (driver->nodePool(), sym(1).sval);
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 72: {
+ bool rx = lexer->scanRegExp(Lexer::NoPrefix);
+ if (!rx) {
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage()));
+ return false; // ### remove me
+ }
+ AST::RegExpLiteral *node = makeAstNode<AST::RegExpLiteral> (driver->nodePool(), lexer->pattern, lexer->flags);
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 73: {
+ bool rx = lexer->scanRegExp(Lexer::EqualPrefix);
+ if (!rx) {
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage()));
+ return false;
+ }
+ AST::RegExpLiteral *node = makeAstNode<AST::RegExpLiteral> (driver->nodePool(), lexer->pattern, lexer->flags);
+ node->literalToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 74: {
+ AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), (AST::Elision *) 0);
+ node->lbracketToken = loc(1);
+ node->rbracketToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 75: {
+ AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).Elision->finish());
+ node->lbracketToken = loc(1);
+ node->rbracketToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 76: {
+ AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).ElementList->finish ());
+ node->lbracketToken = loc(1);
+ node->rbracketToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 77: {
+ AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).ElementList->finish (),
+ (AST::Elision *) 0);
+ node->lbracketToken = loc(1);
+ node->commaToken = loc(3);
+ node->rbracketToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 78: {
+ AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).ElementList->finish (),
+ sym(4).Elision->finish());
+ node->lbracketToken = loc(1);
+ node->commaToken = loc(3);
+ node->rbracketToken = loc(5);
+ sym(1).Node = node;
+} break;
+
+case 79: {
+ AST::ObjectLiteral *node = 0;
+ if (sym(2).Node)
+ node = makeAstNode<AST::ObjectLiteral> (driver->nodePool(),
+ sym(2).PropertyNameAndValueList->finish ());
+ else
+ node = makeAstNode<AST::ObjectLiteral> (driver->nodePool());
+ node->lbraceToken = loc(1);
+ node->lbraceToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 80: {
+ AST::ObjectLiteral *node = makeAstNode<AST::ObjectLiteral> (driver->nodePool(),
+ sym(2).PropertyNameAndValueList->finish ());
+ node->lbraceToken = loc(1);
+ node->lbraceToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 81: {
+ AST::NestedExpression *node = makeAstNode<AST::NestedExpression>(driver->nodePool(), sym(2).Expression);
+ node->lparenToken = loc(1);
+ node->rparenToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 82: {
+ if (AST::ArrayMemberExpression *mem = AST::cast<AST::ArrayMemberExpression *>(sym(1).Expression)) {
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, mem->lbracketToken,
+ QLatin1String("Ignored annotation")));
+
+ sym(1).Expression = mem->base;
+ }
+
+ if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(1).Expression)) {
+ sym(1).UiQualifiedId = qualifiedId;
+ } else {
+ sym(1).UiQualifiedId = 0;
+
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1),
+ QLatin1String("Expected a qualified name id")));
+
+ return false; // ### recover
+ }
+} break;
+
+case 83: {
+ sym(1).Node = makeAstNode<AST::ElementList> (driver->nodePool(), (AST::Elision *) 0, sym(1).Expression);
+} break;
+
+case 84: {
+ sym(1).Node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).Elision->finish(), sym(2).Expression);
+} break;
+
+case 85: {
+ AST::ElementList *node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).ElementList,
+ (AST::Elision *) 0, sym(3).Expression);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 86: {
+ AST::ElementList *node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).ElementList, sym(3).Elision->finish(),
+ sym(4).Expression);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 87: {
+ AST::Elision *node = makeAstNode<AST::Elision> (driver->nodePool());
+ node->commaToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 88: {
+ AST::Elision *node = makeAstNode<AST::Elision> (driver->nodePool(), sym(1).Elision);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 89: {
+ AST::PropertyNameAndValueList *node = makeAstNode<AST::PropertyNameAndValueList> (driver->nodePool(),
+ sym(1).PropertyName, sym(3).Expression);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 90: {
+ AST::PropertyNameAndValueList *node = makeAstNode<AST::PropertyNameAndValueList> (driver->nodePool(),
+ sym(1).PropertyNameAndValueList, sym(3).PropertyName, sym(5).Expression);
+ node->commaToken = loc(2);
+ node->colonToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 91: {
+ AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), sym(1).sval);
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+case 92:
+case 93: {
+ AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount()));
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 94: {
+ AST::StringLiteralPropertyName *node = makeAstNode<AST::StringLiteralPropertyName> (driver->nodePool(), sym(1).sval);
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 95: {
+ AST::NumericLiteralPropertyName *node = makeAstNode<AST::NumericLiteralPropertyName> (driver->nodePool(), sym(1).dval);
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 96: {
+ AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), sym(1).sval);
+ node->propertyNameToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 97:
+
+case 98:
+
+case 99:
+
+case 100:
+
+case 101:
+
+case 102:
+
+case 103:
+
+case 104:
+
+case 105:
+
+case 106:
+
+case 107:
+
+case 108:
+
+case 109:
+
+case 110:
+
+case 111:
+
+case 112:
+
+case 113:
+
+case 114:
+
+case 115:
+
+case 116:
+
+case 117:
+
+case 118:
+
+case 119:
+
+case 120:
+
+case 121:
+
+case 122:
+
+case 123:
+
+case 124:
+
+case 125:
+
+case 126:
+
+case 127:
+{
+ sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount());
+} break;
+
+case 132: {
+ AST::ArrayMemberExpression *node = makeAstNode<AST::ArrayMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).Expression);
+ node->lbracketToken = loc(2);
+ node->rbracketToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 133: {
+ AST::FieldMemberExpression *node = makeAstNode<AST::FieldMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).sval);
+ node->dotToken = loc(2);
+ node->identifierToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 134: {
+ AST::NewMemberExpression *node = makeAstNode<AST::NewMemberExpression> (driver->nodePool(), sym(2).Expression, sym(4).ArgumentList);
+ node->newToken = loc(1);
+ node->lparenToken = loc(3);
+ node->rparenToken = loc(5);
+ sym(1).Node = node;
+} break;
+
+case 136: {
+ AST::NewExpression *node = makeAstNode<AST::NewExpression> (driver->nodePool(), sym(2).Expression);
+ node->newToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 137: {
+ AST::CallExpression *node = makeAstNode<AST::CallExpression> (driver->nodePool(), sym(1).Expression, sym(3).ArgumentList);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 138: {
+ AST::CallExpression *node = makeAstNode<AST::CallExpression> (driver->nodePool(), sym(1).Expression, sym(3).ArgumentList);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 139: {
+ AST::ArrayMemberExpression *node = makeAstNode<AST::ArrayMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).Expression);
+ node->lbracketToken = loc(2);
+ node->rbracketToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 140: {
+ AST::FieldMemberExpression *node = makeAstNode<AST::FieldMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).sval);
+ node->dotToken = loc(2);
+ node->identifierToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 141: {
+ sym(1).Node = 0;
+} break;
+
+case 142: {
+ sym(1).Node = sym(1).ArgumentList->finish();
+} break;
+
+case 143: {
+ sym(1).Node = makeAstNode<AST::ArgumentList> (driver->nodePool(), sym(1).Expression);
+} break;
+
+case 144: {
+ AST::ArgumentList *node = makeAstNode<AST::ArgumentList> (driver->nodePool(), sym(1).ArgumentList, sym(3).Expression);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 148: {
+ AST::PostIncrementExpression *node = makeAstNode<AST::PostIncrementExpression> (driver->nodePool(), sym(1).Expression);
+ node->incrementToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 149: {
+ AST::PostDecrementExpression *node = makeAstNode<AST::PostDecrementExpression> (driver->nodePool(), sym(1).Expression);
+ node->decrementToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 151: {
+ AST::DeleteExpression *node = makeAstNode<AST::DeleteExpression> (driver->nodePool(), sym(2).Expression);
+ node->deleteToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 152: {
+ AST::VoidExpression *node = makeAstNode<AST::VoidExpression> (driver->nodePool(), sym(2).Expression);
+ node->voidToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 153: {
+ AST::TypeOfExpression *node = makeAstNode<AST::TypeOfExpression> (driver->nodePool(), sym(2).Expression);
+ node->typeofToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 154: {
+ AST::PreIncrementExpression *node = makeAstNode<AST::PreIncrementExpression> (driver->nodePool(), sym(2).Expression);
+ node->incrementToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 155: {
+ AST::PreDecrementExpression *node = makeAstNode<AST::PreDecrementExpression> (driver->nodePool(), sym(2).Expression);
+ node->decrementToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 156: {
+ AST::UnaryPlusExpression *node = makeAstNode<AST::UnaryPlusExpression> (driver->nodePool(), sym(2).Expression);
+ node->plusToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 157: {
+ AST::UnaryMinusExpression *node = makeAstNode<AST::UnaryMinusExpression> (driver->nodePool(), sym(2).Expression);
+ node->minusToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 158: {
+ AST::TildeExpression *node = makeAstNode<AST::TildeExpression> (driver->nodePool(), sym(2).Expression);
+ node->tildeToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 159: {
+ AST::NotExpression *node = makeAstNode<AST::NotExpression> (driver->nodePool(), sym(2).Expression);
+ node->notToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 161: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Mul, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 162: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Div, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 163: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Mod, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 165: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Add, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 166: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Sub, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 168: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::LShift, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 169: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::RShift, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 170: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::URShift, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 172: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Lt, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 173: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Gt, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 174: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Le, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 175: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Ge, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 176: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::InstanceOf, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 177: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::In, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 179: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Lt, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 180: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Gt, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 181: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Le, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 182: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Ge, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 183: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::InstanceOf, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 185: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Equal, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 186: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::NotEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 187: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::StrictEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 188: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::StrictNotEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 190: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Equal, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 191: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::NotEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 192: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::StrictEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 193: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::StrictNotEqual, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 195: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitAnd, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 197: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitAnd, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 199: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitXor, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 201: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitXor, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 203: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitOr, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 205: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::BitOr, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 207: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::And, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 209: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::And, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 211: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Or, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 213: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ QSOperator::Or, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 215: {
+ AST::ConditionalExpression *node = makeAstNode<AST::ConditionalExpression> (driver->nodePool(), sym(1).Expression,
+ sym(3).Expression, sym(5).Expression);
+ node->questionToken = loc(2);
+ node->colonToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 217: {
+ AST::ConditionalExpression *node = makeAstNode<AST::ConditionalExpression> (driver->nodePool(), sym(1).Expression,
+ sym(3).Expression, sym(5).Expression);
+ node->questionToken = loc(2);
+ node->colonToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 219: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ sym(2).ival, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 221: {
+ AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression,
+ sym(2).ival, sym(3).Expression);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 222: {
+ sym(1).ival = QSOperator::Assign;
+} break;
+
+case 223: {
+ sym(1).ival = QSOperator::InplaceMul;
+} break;
+
+case 224: {
+ sym(1).ival = QSOperator::InplaceDiv;
+} break;
+
+case 225: {
+ sym(1).ival = QSOperator::InplaceMod;
+} break;
+
+case 226: {
+ sym(1).ival = QSOperator::InplaceAdd;
+} break;
+
+case 227: {
+ sym(1).ival = QSOperator::InplaceSub;
+} break;
+
+case 228: {
+ sym(1).ival = QSOperator::InplaceLeftShift;
+} break;
+
+case 229: {
+ sym(1).ival = QSOperator::InplaceRightShift;
+} break;
+
+case 230: {
+ sym(1).ival = QSOperator::InplaceURightShift;
+} break;
+
+case 231: {
+ sym(1).ival = QSOperator::InplaceAnd;
+} break;
+
+case 232: {
+ sym(1).ival = QSOperator::InplaceXor;
+} break;
+
+case 233: {
+ sym(1).ival = QSOperator::InplaceOr;
+} break;
+
+case 235: {
+ AST::Expression *node = makeAstNode<AST::Expression> (driver->nodePool(), sym(1).Expression, sym(3).Expression);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 236: {
+ sym(1).Node = 0;
+} break;
+
+case 239: {
+ AST::Expression *node = makeAstNode<AST::Expression> (driver->nodePool(), sym(1).Expression, sym(3).Expression);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 240: {
+ sym(1).Node = 0;
+} break;
+
+case 257: {
+ AST::Block *node = makeAstNode<AST::Block> (driver->nodePool(), sym(2).StatementList);
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 258: {
+ sym(1).Node = makeAstNode<AST::StatementList> (driver->nodePool(), sym(1).Statement);
+} break;
+
+case 259: {
+ sym(1).Node = makeAstNode<AST::StatementList> (driver->nodePool(), sym(1).StatementList, sym(2).Statement);
+} break;
+
+case 260: {
+ sym(1).Node = 0;
+} break;
+
+case 261: {
+ sym(1).Node = sym(1).StatementList->finish ();
+} break;
+
+case 263: {
+ AST::VariableStatement *node = makeAstNode<AST::VariableStatement> (driver->nodePool(),
+ sym(2).VariableDeclarationList->finish (/*readOnly=*/sym(1).ival == T_CONST));
+ node->declarationKindToken = loc(1);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 264: {
+ sym(1).ival = T_CONST;
+} break;
+
+case 265: {
+ sym(1).ival = T_VAR;
+} break;
+
+case 266: {
+ sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclaration);
+} break;
+
+case 267: {
+ AST::VariableDeclarationList *node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(),
+ sym(1).VariableDeclarationList, sym(3).VariableDeclaration);
+ node->commaToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 268: {
+ sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclaration);
+} break;
+
+case 269: {
+ sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclarationList, sym(3).VariableDeclaration);
+} break;
+
+case 270: {
+ AST::VariableDeclaration *node = makeAstNode<AST::VariableDeclaration> (driver->nodePool(), sym(1).sval, sym(2).Expression);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 271: {
+ AST::VariableDeclaration *node = makeAstNode<AST::VariableDeclaration> (driver->nodePool(), sym(1).sval, sym(2).Expression);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 272: {
+ // ### TODO: AST for initializer
+ sym(1) = sym(2);
+} break;
+
+case 273: {
+ sym(1).Node = 0;
+} break;
+
+case 275: {
+ // ### TODO: AST for initializer
+ sym(1) = sym(2);
+} break;
+
+case 276: {
+ sym(1).Node = 0;
+} break;
+
+case 278: {
+ AST::EmptyStatement *node = makeAstNode<AST::EmptyStatement> (driver->nodePool());
+ node->semicolonToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 280: {
+ AST::ExpressionStatement *node = makeAstNode<AST::ExpressionStatement> (driver->nodePool(), sym(1).Expression);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 281: {
+ AST::IfStatement *node = makeAstNode<AST::IfStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement, sym(7).Statement);
+ node->ifToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ node->elseToken = loc(5);
+ sym(1).Node = node;
+} break;
+
+case 282: {
+ AST::IfStatement *node = makeAstNode<AST::IfStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement);
+ node->ifToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 284: {
+ AST::DoWhileStatement *node = makeAstNode<AST::DoWhileStatement> (driver->nodePool(), sym(2).Statement, sym(5).Expression);
+ node->doToken = loc(1);
+ node->whileToken = loc(3);
+ node->lparenToken = loc(4);
+ node->rparenToken = loc(6);
+ node->semicolonToken = loc(7);
+ sym(1).Node = node;
+} break;
+
+case 285: {
+ AST::WhileStatement *node = makeAstNode<AST::WhileStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement);
+ node->whileToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 286: {
+ AST::ForStatement *node = makeAstNode<AST::ForStatement> (driver->nodePool(), sym(3).Expression,
+ sym(5).Expression, sym(7).Expression, sym(9).Statement);
+ node->forToken = loc(1);
+ node->lparenToken = loc(2);
+ node->firstSemicolonToken = loc(4);
+ node->secondSemicolonToken = loc(6);
+ node->rparenToken = loc(8);
+ sym(1).Node = node;
+} break;
+
+case 287: {
+ AST::LocalForStatement *node = makeAstNode<AST::LocalForStatement> (driver->nodePool(),
+ sym(4).VariableDeclarationList->finish (/*readOnly=*/false), sym(6).Expression,
+ sym(8).Expression, sym(10).Statement);
+ node->forToken = loc(1);
+ node->lparenToken = loc(2);
+ node->varToken = loc(3);
+ node->firstSemicolonToken = loc(5);
+ node->secondSemicolonToken = loc(7);
+ node->rparenToken = loc(9);
+ sym(1).Node = node;
+} break;
+
+case 288: {
+ AST:: ForEachStatement *node = makeAstNode<AST::ForEachStatement> (driver->nodePool(), sym(3).Expression,
+ sym(5).Expression, sym(7).Statement);
+ node->forToken = loc(1);
+ node->lparenToken = loc(2);
+ node->inToken = loc(4);
+ node->rparenToken = loc(6);
+ sym(1).Node = node;
+} break;
+
+case 289: {
+ AST::LocalForEachStatement *node = makeAstNode<AST::LocalForEachStatement> (driver->nodePool(),
+ sym(4).VariableDeclaration, sym(6).Expression, sym(8).Statement);
+ node->forToken = loc(1);
+ node->lparenToken = loc(2);
+ node->varToken = loc(3);
+ node->inToken = loc(5);
+ node->rparenToken = loc(7);
+ sym(1).Node = node;
+} break;
+
+case 291: {
+ AST::ContinueStatement *node = makeAstNode<AST::ContinueStatement> (driver->nodePool());
+ node->continueToken = loc(1);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 293: {
+ AST::ContinueStatement *node = makeAstNode<AST::ContinueStatement> (driver->nodePool(), sym(2).sval);
+ node->continueToken = loc(1);
+ node->identifierToken = loc(2);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 295: {
+ AST::BreakStatement *node = makeAstNode<AST::BreakStatement> (driver->nodePool());
+ node->breakToken = loc(1);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 297: {
+ AST::BreakStatement *node = makeAstNode<AST::BreakStatement> (driver->nodePool(), sym(2).sval);
+ node->breakToken = loc(1);
+ node->identifierToken = loc(2);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 299: {
+ AST::ReturnStatement *node = makeAstNode<AST::ReturnStatement> (driver->nodePool(), sym(2).Expression);
+ node->returnToken = loc(1);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 300: {
+ AST::WithStatement *node = makeAstNode<AST::WithStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement);
+ node->withToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 301: {
+ AST::SwitchStatement *node = makeAstNode<AST::SwitchStatement> (driver->nodePool(), sym(3).Expression, sym(5).CaseBlock);
+ node->switchToken = loc(1);
+ node->lparenToken = loc(2);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 302: {
+ AST::CaseBlock *node = makeAstNode<AST::CaseBlock> (driver->nodePool(), sym(2).CaseClauses);
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 303: {
+ AST::CaseBlock *node = makeAstNode<AST::CaseBlock> (driver->nodePool(), sym(2).CaseClauses, sym(3).DefaultClause, sym(4).CaseClauses);
+ node->lbraceToken = loc(1);
+ node->rbraceToken = loc(5);
+ sym(1).Node = node;
+} break;
+
+case 304: {
+ sym(1).Node = makeAstNode<AST::CaseClauses> (driver->nodePool(), sym(1).CaseClause);
+} break;
+
+case 305: {
+ sym(1).Node = makeAstNode<AST::CaseClauses> (driver->nodePool(), sym(1).CaseClauses, sym(2).CaseClause);
+} break;
+
+case 306: {
+ sym(1).Node = 0;
+} break;
+
+case 307: {
+ sym(1).Node = sym(1).CaseClauses->finish ();
+} break;
+
+case 308: {
+ AST::CaseClause *node = makeAstNode<AST::CaseClause> (driver->nodePool(), sym(2).Expression, sym(4).StatementList);
+ node->caseToken = loc(1);
+ node->colonToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 309: {
+ AST::DefaultClause *node = makeAstNode<AST::DefaultClause> (driver->nodePool(), sym(3).StatementList);
+ node->defaultToken = loc(1);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+case 310:
+case 311: {
+ AST::LabelledStatement *node = makeAstNode<AST::LabelledStatement> (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount()), sym(3).Statement);
+ node->identifierToken = loc(1);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 312: {
+ AST::LabelledStatement *node = makeAstNode<AST::LabelledStatement> (driver->nodePool(), sym(1).sval, sym(3).Statement);
+ node->identifierToken = loc(1);
+ node->colonToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 314: {
+ AST::ThrowStatement *node = makeAstNode<AST::ThrowStatement> (driver->nodePool(), sym(2).Expression);
+ node->throwToken = loc(1);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 315: {
+ AST::TryStatement *node = makeAstNode<AST::TryStatement> (driver->nodePool(), sym(2).Statement, sym(3).Catch);
+ node->tryToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 316: {
+ AST::TryStatement *node = makeAstNode<AST::TryStatement> (driver->nodePool(), sym(2).Statement, sym(3).Finally);
+ node->tryToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 317: {
+ AST::TryStatement *node = makeAstNode<AST::TryStatement> (driver->nodePool(), sym(2).Statement, sym(3).Catch, sym(4).Finally);
+ node->tryToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 318: {
+ AST::Catch *node = makeAstNode<AST::Catch> (driver->nodePool(), sym(3).sval, sym(5).Block);
+ node->catchToken = loc(1);
+ node->lparenToken = loc(2);
+ node->identifierToken = loc(3);
+ node->rparenToken = loc(4);
+ sym(1).Node = node;
+} break;
+
+case 319: {
+ AST::Finally *node = makeAstNode<AST::Finally> (driver->nodePool(), sym(2).Block);
+ node->finallyToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 321: {
+ AST::DebuggerStatement *node = makeAstNode<AST::DebuggerStatement> (driver->nodePool());
+ node->debuggerToken = loc(1);
+ node->semicolonToken = loc(2);
+ sym(1).Node = node;
+} break;
+
+case 322: {
+ AST::FunctionDeclaration *node = makeAstNode<AST::FunctionDeclaration> (driver->nodePool(), sym(2).sval, sym(4).FormalParameterList, sym(7).FunctionBody);
+ node->functionToken = loc(1);
+ node->identifierToken = loc(2);
+ node->lparenToken = loc(3);
+ node->rparenToken = loc(5);
+ node->lbraceToken = loc(6);
+ node->rbraceToken = loc(8);
+ sym(1).Node = node;
+} break;
+
+case 323: {
+ AST::FunctionExpression *node = makeAstNode<AST::FunctionExpression> (driver->nodePool(), sym(2).sval, sym(4).FormalParameterList, sym(7).FunctionBody);
+ node->functionToken = loc(1);
+ if (sym(2).sval)
+ node->identifierToken = loc(2);
+ node->lparenToken = loc(3);
+ node->rparenToken = loc(5);
+ node->lbraceToken = loc(6);
+ node->rbraceToken = loc(8);
+ sym(1).Node = node;
+} break;
+
+case 324: {
+ AST::FormalParameterList *node = makeAstNode<AST::FormalParameterList> (driver->nodePool(), sym(1).sval);
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+} break;
+
+case 325: {
+ AST::FormalParameterList *node = makeAstNode<AST::FormalParameterList> (driver->nodePool(), sym(1).FormalParameterList, sym(3).sval);
+ node->commaToken = loc(2);
+ node->identifierToken = loc(3);
+ sym(1).Node = node;
+} break;
+
+case 326: {
+ sym(1).Node = 0;
+} break;
+
+case 327: {
+ sym(1).Node = sym(1).FormalParameterList->finish ();
+} break;
+
+case 328: {
+ sym(1).Node = 0;
+} break;
+
+case 330: {
+ sym(1).Node = makeAstNode<AST::FunctionBody> (driver->nodePool(), sym(1).SourceElements->finish ());
+} break;
+
+case 331: {
+ sym(1).Node = makeAstNode<AST::SourceElements> (driver->nodePool(), sym(1).SourceElement);
+} break;
+
+case 332: {
+ sym(1).Node = makeAstNode<AST::SourceElements> (driver->nodePool(), sym(1).SourceElements, sym(2).SourceElement);
+} break;
+
+case 333: {
+ sym(1).Node = makeAstNode<AST::StatementSourceElement> (driver->nodePool(), sym(1).Statement);
+} break;
+
+case 334: {
+ sym(1).Node = makeAstNode<AST::FunctionSourceElement> (driver->nodePool(), sym(1).FunctionDeclaration);
+} break;
+
+case 335: {
+ sym(1).sval = 0;
+} break;
+
+case 337: {
+ sym(1).Node = 0;
+} break;
+
+ } // switch
+ action = nt_action(state_stack[tos], lhs[r] - TERMINAL_COUNT);
+ } // if
+ } while (action != 0);
+
+ if (first_token == last_token) {
+ const int errorState = state_stack[tos];
+
+ // automatic insertion of `;'
+ if (t_action(errorState, T_AUTOMATIC_SEMICOLON) && automatic(driver, yytoken)) {
+ SavedToken &tk = token_buffer[0];
+ tk.token = yytoken;
+ tk.dval = yylval;
+ tk.loc = yylloc;
+
+ yylloc = yyprevlloc;
+ yylloc.offset += yylloc.length;
+ yylloc.startColumn += yylloc.length;
+ yylloc.length = 0;
+
+ //const QString msg = qApp->translate("QmlParser", "Missing `;'");
+ //diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, yylloc, msg));
+
+ first_token = &token_buffer[0];
+ last_token = &token_buffer[1];
+
+ yytoken = T_SEMICOLON;
+ yylval = 0;
+
+ action = errorState;
+
+ goto _Lcheck_token;
+ }
+
+ hadErrors = true;
+
+ token_buffer[0].token = yytoken;
+ token_buffer[0].dval = yylval;
+ token_buffer[0].loc = yylloc;
+
+ token_buffer[1].token = yytoken = lexer->lex();
+ token_buffer[1].dval = yylval = lexer->dval();
+ token_buffer[1].loc = yylloc = location(lexer);
+
+ if (t_action(errorState, yytoken)) {
+ const QString msg = qApp->translate("QmlParser", "Unexpected token `%1'").arg(QLatin1String(spell[token_buffer[0].token]));
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
+
+ action = errorState;
+ goto _Lcheck_token;
+ }
+
+ static int tokens[] = {
+ T_PLUS,
+ T_EQ,
+
+ T_COMMA,
+ T_COLON,
+ T_SEMICOLON,
+
+ T_RPAREN, T_RBRACKET, T_RBRACE,
+
+ T_NUMERIC_LITERAL,
+ T_IDENTIFIER,
+
+ T_LPAREN, T_LBRACKET, T_LBRACE,
+
+ EOF_SYMBOL
+ };
+
+ for (int *tk = tokens; *tk != EOF_SYMBOL; ++tk) {
+ int a = t_action(errorState, *tk);
+ if (a > 0 && t_action(a, yytoken)) {
+ const QString msg = qApp->translate("QmlParser", "Expected token `%1'").arg(QLatin1String(spell[*tk]));
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
+
+ yytoken = *tk;
+ yylval = 0;
+ yylloc = token_buffer[0].loc;
+ yylloc.length = 0;
+
+ first_token = &token_buffer[0];
+ last_token = &token_buffer[2];
+
+ action = errorState;
+ goto _Lcheck_token;
+ }
+ }
+
+ for (int tk = 1; tk < TERMINAL_COUNT; ++tk) {
+ if (tk == T_AUTOMATIC_SEMICOLON || tk == T_FEED_UI_PROGRAM ||
+ tk == T_FEED_JS_STATEMENT || tk == T_FEED_JS_EXPRESSION)
+ continue;
+
+ int a = t_action(errorState, tk);
+ if (a > 0 && t_action(a, yytoken)) {
+ const QString msg = qApp->translate("QmlParser", "Expected token `%1'").arg(QLatin1String(spell[tk]));
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
+
+ yytoken = tk;
+ yylval = 0;
+ yylloc = token_buffer[0].loc;
+ yylloc.length = 0;
+
+ action = errorState;
+ goto _Lcheck_token;
+ }
+ }
+
+ const QString msg = qApp->translate("QmlParser", "Syntax error");
+ diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
+ }
+
+ return false;
+}
+
+QT_QML_END_NAMESPACE
+
+
diff --git a/src/declarative/qml/parser/qmljsparser_p.h b/src/declarative/qml/parser/qmljsparser_p.h
new file mode 100644
index 0000000..b35bec3
--- /dev/null
+++ b/src/declarative/qml/parser/qmljsparser_p.h
@@ -0,0 +1,242 @@
+// This file was generated by qlalr - DO NOT EDIT!
+
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 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$
+**
+****************************************************************************/
+
+//
+// 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.
+//
+
+//
+// This file is automatically generated from qmljs.g.
+// Changes will be lost.
+//
+
+#ifndef QMLJSPARSER_P_H
+#define QMLJSPARSER_P_H
+
+#include "qmljsglobal_p.h"
+#include "qmljsgrammar_p.h"
+#include "qmljsast_p.h"
+#include "qmljsengine_p.h"
+
+#include <QtCore/QList>
+#include <QtCore/QString>
+
+QT_QML_BEGIN_NAMESPACE
+
+namespace QmlJS {
+
+class Engine;
+class NameId;
+
+class Parser: protected QmlJSGrammar
+{
+public:
+ union Value {
+ int ival;
+ double dval;
+ NameId *sval;
+ AST::ArgumentList *ArgumentList;
+ AST::CaseBlock *CaseBlock;
+ AST::CaseClause *CaseClause;
+ AST::CaseClauses *CaseClauses;
+ AST::Catch *Catch;
+ AST::DefaultClause *DefaultClause;
+ AST::ElementList *ElementList;
+ AST::Elision *Elision;
+ AST::ExpressionNode *Expression;
+ AST::Finally *Finally;
+ AST::FormalParameterList *FormalParameterList;
+ AST::FunctionBody *FunctionBody;
+ AST::FunctionDeclaration *FunctionDeclaration;
+ AST::Node *Node;
+ AST::PropertyName *PropertyName;
+ AST::PropertyNameAndValueList *PropertyNameAndValueList;
+ AST::SourceElement *SourceElement;
+ AST::SourceElements *SourceElements;
+ AST::Statement *Statement;
+ AST::StatementList *StatementList;
+ AST::Block *Block;
+ AST::VariableDeclaration *VariableDeclaration;
+ AST::VariableDeclarationList *VariableDeclarationList;
+
+ AST::UiProgram *UiProgram;
+ AST::UiImportList *UiImportList;
+ AST::UiImport *UiImport;
+ AST::UiParameterList *UiParameterList;
+ AST::UiPublicMember *UiPublicMember;
+ AST::UiObjectDefinition *UiObjectDefinition;
+ AST::UiObjectInitializer *UiObjectInitializer;
+ AST::UiObjectBinding *UiObjectBinding;
+ AST::UiScriptBinding *UiScriptBinding;
+ AST::UiArrayBinding *UiArrayBinding;
+ AST::UiObjectMember *UiObjectMember;
+ AST::UiObjectMemberList *UiObjectMemberList;
+ AST::UiArrayMemberList *UiArrayMemberList;
+ AST::UiQualifiedId *UiQualifiedId;
+ AST::UiSignature *UiSignature;
+ AST::UiFormalList *UiFormalList;
+ AST::UiFormal *UiFormal;
+ };
+
+public:
+ Parser(Engine *engine);
+ ~Parser();
+
+ // parse a UI program
+ bool parse() { return parse(T_FEED_UI_PROGRAM); }
+ bool parseStatement() { return parse(T_FEED_JS_STATEMENT); }
+ bool parseExpression() { return parse(T_FEED_JS_EXPRESSION); }
+ bool parseUiObjectMember() { return parse(T_FEED_UI_OBJECT_MEMBER); }
+
+ AST::UiProgram *ast() const
+ { return AST::cast<AST::UiProgram *>(program); }
+
+ AST::Statement *statement() const
+ {
+ if (! program)
+ return 0;
+
+ return program->statementCast();
+ }
+
+ AST::ExpressionNode *expression() const
+ {
+ if (! program)
+ return 0;
+
+ return program->expressionCast();
+ }
+
+ AST::UiObjectMember *uiObjectMember() const
+ {
+ if (! program)
+ return 0;
+
+ return program->uiObjectMemberCast();
+ }
+
+ QList<DiagnosticMessage> diagnosticMessages() const
+ { return diagnostic_messages; }
+
+ inline DiagnosticMessage diagnosticMessage() const
+ {
+ foreach (const DiagnosticMessage &d, diagnostic_messages) {
+ if (! d.kind == DiagnosticMessage::Warning)
+ return d;
+ }
+
+ return DiagnosticMessage();
+ }
+
+ inline QString errorMessage() const
+ { return diagnosticMessage().message; }
+
+ inline int errorLineNumber() const
+ { return diagnosticMessage().loc.startLine; }
+
+ inline int errorColumnNumber() const
+ { return diagnosticMessage().loc.startColumn; }
+
+protected:
+ bool parse(int startToken);
+
+ void reallocateStack();
+
+ inline Value &sym(int index)
+ { return sym_stack [tos + index - 1]; }
+
+ inline AST::SourceLocation &loc(int index)
+ { return location_stack [tos + index - 1]; }
+
+ AST::UiQualifiedId *reparseAsQualifiedId(AST::ExpressionNode *expr);
+
+protected:
+ Engine *driver;
+ int tos;
+ int stack_size;
+ Value *sym_stack;
+ int *state_stack;
+ AST::SourceLocation *location_stack;
+
+ AST::Node *program;
+
+ // error recovery
+ enum { TOKEN_BUFFER_SIZE = 3 };
+
+ struct SavedToken {
+ int token;
+ double dval;
+ AST::SourceLocation loc;
+ };
+
+ double yylval;
+ AST::SourceLocation yylloc;
+ AST::SourceLocation yyprevlloc;
+
+ SavedToken token_buffer[TOKEN_BUFFER_SIZE];
+ SavedToken *first_token;
+ SavedToken *last_token;
+
+ QList<DiagnosticMessage> diagnostic_messages;
+};
+
+} // end of namespace QmlJS
+
+
+
+#define J_SCRIPT_REGEXPLITERAL_RULE1 72
+
+#define J_SCRIPT_REGEXPLITERAL_RULE2 73
+
+QT_QML_END_NAMESPACE
+
+
+
+#endif // QMLJSPARSER_P_H
diff --git a/src/declarative/qml/qbitfield_p.h b/src/declarative/qml/qbitfield_p.h
new file mode 100644
index 0000000..70d5041
--- /dev/null
+++ b/src/declarative/qml/qbitfield_p.h
@@ -0,0 +1,165 @@
+/****************************************************************************
+**
+** 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 QBITFIELD_P_H
+#define QBITFIELD_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/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class QBitField
+{
+public:
+ inline QBitField();
+ inline QBitField(const quint32 *, int bits);
+ inline QBitField(const QBitField &);
+ inline ~QBitField();
+
+ inline QBitField &operator=(const QBitField &);
+
+ inline quint32 size() const;
+ inline QBitField united(const QBitField &);
+ inline bool testBit(int) const;
+
+private:
+ quint32 bits:31;
+ quint32 *ownData;
+ const quint32 *data;
+};
+
+QBitField::QBitField()
+: bits(0), ownData(0), data(0)
+{
+}
+
+QBitField::QBitField(const quint32 *bitData, int bitCount)
+: bits((quint32)bitCount), ownData(0), data(bitData)
+{
+}
+
+QBitField::QBitField(const QBitField &other)
+: bits(other.bits), ownData(other.ownData), data(other.data)
+{
+ if (ownData)
+ ++(*ownData);
+}
+
+QBitField::~QBitField()
+{
+ if (ownData)
+ if(0 == --(*ownData)) delete [] ownData;
+}
+
+QBitField &QBitField::operator=(const QBitField &other)
+{
+ if (other.data == data)
+ return *this;
+
+ if (ownData)
+ if(0 == --(*ownData)) delete [] ownData;
+
+ bits = other.bits;
+ ownData = other.ownData;
+ data = other.data;
+
+ if (ownData)
+ ++(*ownData);
+
+ return *this;
+}
+
+inline quint32 QBitField::size() const
+{
+ return bits;
+}
+
+QBitField QBitField::united(const QBitField &o)
+{
+ if (o.bits == 0) {
+ return *this;
+ } else if (bits == 0) {
+ return o;
+ } else {
+ int max = (bits > o.bits)?bits:o.bits;
+ int length = (max + 31) / 32;
+ QBitField rv;
+ rv.bits = max;
+ rv.ownData = new quint32[length + 1];
+ *(rv.ownData) = 1;
+ rv.data = rv.ownData + 1;
+ if (bits > o.bits) {
+ ::memcpy((quint32 *)rv.data, data, length * sizeof(quint32));
+ for (quint32 ii = 0; ii < (o.bits + 31) / 32; ++ii)
+ ((quint32 *)rv.data)[ii] |= o.data[ii];
+ } else {
+ ::memcpy((quint32 *)rv.data, o.data, length * sizeof(quint32));
+ for (quint32 ii = 0; ii < (bits + 31) / 32; ++ii)
+ ((quint32 *)rv.data)[ii] |= data[ii];
+ }
+ return rv;
+ }
+}
+
+bool QBitField::testBit(int b) const
+{
+ Q_ASSERT(b >= 0);
+ if ((quint32)b < bits) {
+ return data[b / 32] & (1 << (b % 32));
+ } else {
+ return false;
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif // QBITFIELD_P_H
diff --git a/src/declarative/qml/qmetaobjectbuilder.cpp b/src/declarative/qml/qmetaobjectbuilder.cpp
new file mode 100644
index 0000000..e7a7591
--- /dev/null
+++ b/src/declarative/qml/qmetaobjectbuilder.cpp
@@ -0,0 +1,2573 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore 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 http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmetaobjectbuilder_p.h"
+#ifndef Q_OS_WIN
+#include <stdint.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QMetaObjectBuilder
+ \internal
+ \brief The QMetaObjectBuilder class supports building QMetaObject objects at runtime.
+
+*/
+
+/*!
+ \enum QMetaObjectBuilder::AddMember
+ This enum defines which members of QMetaObject should be copied by QMetaObjectBuilder::addMetaObject()
+
+ \value ClassName Add the class name.
+ \value SuperClass Add the super class.
+ \value Methods Add methods that aren't signals or slots.
+ \value Signals Add signals.
+ \value Slots Add slots.
+ \value Constructors Add constructors.
+ \value Properties Add properties.
+ \value Enumerators Add enumerators.
+ \value ClassInfos Add items of class information.
+ \value RelatedMetaObjects Add related meta objects.
+ \value StaticMetacall Add the static metacall function.
+ \value PublicMethods Add public methods (ignored for signals).
+ \value ProtectedMethods Add protected methods (ignored for signals).
+ \value PrivateMethods All private methods (ignored for signals).
+ \value AllMembers Add all members.
+ \value AllPrimaryMembers Add everything except the class name, super class, and static metacall function.
+*/
+
+// copied from moc's generator.cpp
+uint qvariant_nameToType(const char* name)
+{
+ if (!name)
+ return 0;
+
+ if (strcmp(name, "QVariant") == 0)
+ return 0xffffffff;
+ if (strcmp(name, "QCString") == 0)
+ return QMetaType::QByteArray;
+ if (strcmp(name, "Q_LLONG") == 0)
+ return QMetaType::LongLong;
+ if (strcmp(name, "Q_ULLONG") == 0)
+ return QMetaType::ULongLong;
+ if (strcmp(name, "QIconSet") == 0)
+ return QMetaType::QIcon;
+
+ uint tp = QMetaType::type(name);
+ return tp < QMetaType::User ? tp : 0;
+}
+
+/*
+ Returns true if the type is a QVariant types.
+*/
+bool isVariantType(const char* type)
+{
+ return qvariant_nameToType(type) != 0;
+}
+
+// copied from qmetaobject.cpp
+// do not touch without touching the moc as well
+enum PropertyFlags {
+ Invalid = 0x00000000,
+ Readable = 0x00000001,
+ Writable = 0x00000002,
+ Resettable = 0x00000004,
+ EnumOrFlag = 0x00000008,
+ StdCppSet = 0x00000100,
+// Override = 0x00000200,
+ Designable = 0x00001000,
+ ResolveDesignable = 0x00002000,
+ Scriptable = 0x00004000,
+ ResolveScriptable = 0x00008000,
+ Stored = 0x00010000,
+ ResolveStored = 0x00020000,
+ Editable = 0x00040000,
+ ResolveEditable = 0x00080000,
+ User = 0x00100000,
+ ResolveUser = 0x00200000,
+ Notify = 0x00400000,
+ Dynamic = 0x00800000
+};
+
+enum MethodFlags {
+ AccessPrivate = 0x00,
+ AccessProtected = 0x01,
+ AccessPublic = 0x02,
+ AccessMask = 0x03, //mask
+
+ MethodMethod = 0x00,
+ MethodSignal = 0x04,
+ MethodSlot = 0x08,
+ MethodConstructor = 0x0c,
+ MethodTypeMask = 0x0c,
+
+ MethodCompatibility = 0x10,
+ MethodCloned = 0x20,
+ MethodScriptable = 0x40
+};
+
+struct QMetaObjectPrivate
+{
+ int revision;
+ int className;
+ int classInfoCount, classInfoData;
+ int methodCount, methodData;
+ int propertyCount, propertyData;
+ int enumeratorCount, enumeratorData;
+ int constructorCount, constructorData;
+ int flags;
+};
+
+static inline const QMetaObjectPrivate *priv(const uint* data)
+{ return reinterpret_cast<const QMetaObjectPrivate*>(data); }
+// end of copied lines from qmetaobject.cpp
+
+class QMetaMethodBuilderPrivate
+{
+public:
+ QMetaMethodBuilderPrivate
+ (QMetaMethod::MethodType _methodType,
+ const QByteArray& _signature,
+ const QByteArray& _returnType = QByteArray(),
+ QMetaMethod::Access _access = QMetaMethod::Public)
+ : signature(QMetaObject::normalizedSignature(_signature.constData())),
+ returnType(QMetaObject::normalizedType(_returnType)),
+ attributes(((int)_access) | (((int)_methodType) << 2))
+ {
+ }
+
+ QByteArray signature;
+ QByteArray returnType;
+ QList<QByteArray> parameterNames;
+ QByteArray tag;
+ int attributes;
+
+ QMetaMethod::MethodType methodType() const
+ {
+ return (QMetaMethod::MethodType)((attributes & MethodTypeMask) >> 2);
+ }
+
+ QMetaMethod::Access access() const
+ {
+ return (QMetaMethod::Access)(attributes & AccessMask);
+ }
+
+ void setAccess(QMetaMethod::Access value)
+ {
+ attributes = ((attributes & ~AccessMask) | (int)value);
+ }
+};
+
+class QMetaPropertyBuilderPrivate
+{
+public:
+ QMetaPropertyBuilderPrivate
+ (const QByteArray& _name, const QByteArray& _type, int notifierIdx=-1)
+ : name(_name),
+ type(QMetaObject::normalizedType(_type.constData())),
+ flags(Readable | Writable), notifySignal(-1)
+ {
+ if (notifierIdx >= 0) {
+ flags |= Notify;
+ notifySignal = notifierIdx;
+ }
+ }
+
+ QByteArray name;
+ QByteArray type;
+ int flags;
+ int notifySignal;
+
+ bool flag(int f) const
+ {
+ return ((flags & f) != 0);
+ }
+
+ void setFlag(int f, bool value)
+ {
+ if (value)
+ flags |= f;
+ else
+ flags &= ~f;
+ }
+};
+
+class QMetaEnumBuilderPrivate
+{
+public:
+ QMetaEnumBuilderPrivate(const QByteArray& _name)
+ : name(_name), isFlag(false)
+ {
+ }
+
+ QByteArray name;
+ bool isFlag;
+ QList<QByteArray> keys;
+ QList<int> values;
+};
+
+class QMetaObjectBuilderPrivate
+{
+public:
+ QMetaObjectBuilderPrivate()
+ : flags(0)
+ {
+ superClass = &QObject::staticMetaObject;
+ staticMetacallFunction = 0;
+ }
+
+ QByteArray className;
+ const QMetaObject *superClass;
+ QMetaObjectBuilder::StaticMetacallFunction staticMetacallFunction;
+ QList<QMetaMethodBuilderPrivate> methods;
+ QList<QMetaMethodBuilderPrivate> constructors;
+ QList<QMetaPropertyBuilderPrivate> properties;
+ QList<QByteArray> classInfoNames;
+ QList<QByteArray> classInfoValues;
+ QList<QMetaEnumBuilderPrivate> enumerators;
+#ifdef Q_NO_DATA_RELOCATION
+ QList<QMetaObjectAccessor> relatedMetaObjects;
+#else
+ QList<const QMetaObject *> relatedMetaObjects;
+#endif
+ int flags;
+};
+
+/*!
+ Constructs a new QMetaObjectBuilder.
+*/
+QMetaObjectBuilder::QMetaObjectBuilder()
+{
+ d = new QMetaObjectBuilderPrivate();
+}
+
+/*!
+ Constructs a new QMetaObjectBuilder which is a copy of the
+ meta object information in \a prototype. Note: the super class
+ contents for \a prototype are not copied, only the immediate
+ class that is defined by \a prototype.
+
+ The \a members parameter indicates which members of \a prototype
+ should be added. The default is AllMembers.
+
+ \sa addMetaObject()
+*/
+QMetaObjectBuilder::QMetaObjectBuilder
+ (const QMetaObject *prototype, QMetaObjectBuilder::AddMembers members)
+{
+ d = new QMetaObjectBuilderPrivate();
+ addMetaObject(prototype, members);
+}
+
+/*!
+ Destroys this meta object builder.
+*/
+QMetaObjectBuilder::~QMetaObjectBuilder()
+{
+ delete d;
+}
+
+/*!
+ Returns the name of the class being constructed by this
+ meta object builder. The default value is an empty QByteArray.
+
+ \sa setClassName(), superClass()
+*/
+QByteArray QMetaObjectBuilder::className() const
+{
+ return d->className;
+}
+
+/*!
+ Sets the \a name of the class being constructed by this
+ meta object builder.
+
+ \sa className(), setSuperClass()
+*/
+void QMetaObjectBuilder::setClassName(const QByteArray& name)
+{
+ d->className = name;
+}
+
+/*!
+ Returns the superclass meta object of the class being constructed
+ by this meta object builder. The default value is the meta object
+ for QObject.
+
+ \sa setSuperClass(), className()
+*/
+const QMetaObject *QMetaObjectBuilder::superClass() const
+{
+ return d->superClass;
+}
+
+/*!
+ Sets the superclass meta object of the class being constructed
+ by this meta object builder to \a meta. The \a meta parameter
+ must not be null.
+
+ \sa superClass(), setClassName()
+*/
+void QMetaObjectBuilder::setSuperClass(const QMetaObject *meta)
+{
+ Q_ASSERT(meta);
+ d->superClass = meta;
+}
+
+/*!
+ Returns the flags of the class being constructed by this meta object
+ builder.
+
+ \sa setFlags()
+*/
+QMetaObjectBuilder::MetaObjectFlags QMetaObjectBuilder::flags() const
+{
+ return (QMetaObjectBuilder::MetaObjectFlags)d->flags;
+}
+
+/*!
+ Sets the \a flags of the class being constructed by this meta object
+ builder.
+
+ \sa flags()
+*/
+void QMetaObjectBuilder::setFlags(MetaObjectFlags flags)
+{
+ d->flags = flags;
+}
+
+/*!
+ Returns the number of methods in this class, excluding the number
+ of methods in the base class. These include signals and slots
+ as well as normal member functions.
+
+ \sa addMethod(), method(), removeMethod(), indexOfMethod()
+*/
+int QMetaObjectBuilder::methodCount() const
+{
+ return d->methods.size();
+}
+
+/*!
+ Returns the number of constructors in this class.
+
+ \sa addConstructor(), constructor(), removeConstructor(), indexOfConstructor()
+*/
+int QMetaObjectBuilder::constructorCount() const
+{
+ return d->constructors.size();
+}
+
+/*!
+ Returns the number of properties in this class, excluding the number
+ of properties in the base class.
+
+ \sa addProperty(), property(), removeProperty(), indexOfProperty()
+*/
+int QMetaObjectBuilder::propertyCount() const
+{
+ return d->properties.size();
+}
+
+/*!
+ Returns the number of enumerators in this class, excluding the
+ number of enumerators in the base class.
+
+ \sa addEnumerator(), enumerator(), removeEnumerator()
+ \sa indexOfEnumerator()
+*/
+int QMetaObjectBuilder::enumeratorCount() const
+{
+ return d->enumerators.size();
+}
+
+/*!
+ Returns the number of items of class information in this class,
+ exclusing the number of items of class information in the base class.
+
+ \sa addClassInfo(), classInfoName(), classInfoValue(), removeClassInfo()
+ \sa indexOfClassInfo()
+*/
+int QMetaObjectBuilder::classInfoCount() const
+{
+ return d->classInfoNames.size();
+}
+
+/*!
+ Returns the number of related meta objects that are associated
+ with this class.
+
+ Related meta objects are used when resolving the enumerated type
+ associated with a property, where the enumerated type is in a
+ different class from the property.
+
+ \sa addRelatedMetaObject(), relatedMetaObject()
+ \sa removeRelatedMetaObject()
+*/
+int QMetaObjectBuilder::relatedMetaObjectCount() const
+{
+ return d->relatedMetaObjects.size();
+}
+
+/*!
+ Adds a new public method to this class with the specified \a signature.
+ Returns an object that can be used to adjust the other attributes
+ of the method. The \a signature will be normalized before it is
+ added to the class.
+
+ \sa method(), methodCount(), removeMethod(), indexOfMethod()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::addMethod(const QByteArray& signature)
+{
+ int index = d->methods.size();
+ d->methods.append(QMetaMethodBuilderPrivate(QMetaMethod::Method, signature));
+ return QMetaMethodBuilder(this, index);
+}
+
+/*!
+ Adds a new public method to this class with the specified
+ \a signature and \a returnType. Returns an object that can be
+ used to adjust the other attributes of the method. The \a signature
+ and \a returnType will be normalized before they are added to
+ the class. If \a returnType is empty, then it indicates that
+ the method has \c{void} as its return type.
+
+ \sa method(), methodCount(), removeMethod(), indexOfMethod()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::addMethod
+ (const QByteArray& signature, const QByteArray& returnType)
+{
+ int index = d->methods.size();
+ d->methods.append(QMetaMethodBuilderPrivate
+ (QMetaMethod::Method, signature, returnType));
+ return QMetaMethodBuilder(this, index);
+}
+
+/*!
+ Adds a new public method to this class that has the same information as
+ \a prototype. This is used to clone the methods of an existing
+ QMetaObject. Returns an object that can be used to adjust the
+ attributes of the method.
+
+ This function will detect if \a prototype is an ordinary method,
+ signal, slot, or constructor and act accordingly.
+
+ \sa method(), methodCount(), removeMethod(), indexOfMethod()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::addMethod(const QMetaMethod& prototype)
+{
+ QMetaMethodBuilder method;
+ if (prototype.methodType() == QMetaMethod::Method)
+ method = addMethod(prototype.signature());
+ else if (prototype.methodType() == QMetaMethod::Signal)
+ method = addSignal(prototype.signature());
+ else if (prototype.methodType() == QMetaMethod::Slot)
+ method = addSlot(prototype.signature());
+ else if (prototype.methodType() == QMetaMethod::Constructor)
+ method = addConstructor(prototype.signature());
+ method.setReturnType(prototype.typeName());
+ method.setParameterNames(prototype.parameterNames());
+ method.setTag(prototype.tag());
+ method.setAccess(prototype.access());
+ method.setAttributes(prototype.attributes());
+ return method;
+}
+
+/*!
+ Adds a new public slot to this class with the specified \a signature.
+ Returns an object that can be used to adjust the other attributes
+ of the slot. The \a signature will be normalized before it is
+ added to the class.
+
+ \sa addMethod(), addSignal(), indexOfSlot()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::addSlot(const QByteArray& signature)
+{
+ int index = d->methods.size();
+ d->methods.append(QMetaMethodBuilderPrivate(QMetaMethod::Slot, signature));
+ return QMetaMethodBuilder(this, index);
+}
+
+/*!
+ Adds a new signal to this class with the specified \a signature.
+ Returns an object that can be used to adjust the other attributes
+ of the signal. The \a signature will be normalized before it is
+ added to the class.
+
+ \sa addMethod(), addSlot(), indexOfSignal()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::addSignal(const QByteArray& signature)
+{
+ int index = d->methods.size();
+ d->methods.append(QMetaMethodBuilderPrivate
+ (QMetaMethod::Signal, signature, QByteArray(), QMetaMethod::Protected));
+ return QMetaMethodBuilder(this, index);
+}
+
+/*!
+ Adds a new constructor to this class with the specified \a signature.
+ Returns an object that can be used to adjust the other attributes
+ of the constructor. The \a signature will be normalized before it is
+ added to the class.
+
+ \sa constructor(), constructorCount(), removeConstructor()
+ \sa indexOfConstructor()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::addConstructor(const QByteArray& signature)
+{
+ int index = d->constructors.size();
+ d->constructors.append(QMetaMethodBuilderPrivate(QMetaMethod::Constructor, signature));
+ return QMetaMethodBuilder(this, -(index + 1));
+}
+
+/*!
+ Adds a new constructor to this class that has the same information as
+ \a prototype. This is used to clone the constructors of an existing
+ QMetaObject. Returns an object that can be used to adjust the
+ attributes of the constructor.
+
+ This function requires that \a prototype be a constructor.
+
+ \sa constructor(), constructorCount(), removeConstructor()
+ \sa indexOfConstructor()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::addConstructor(const QMetaMethod& prototype)
+{
+ Q_ASSERT(prototype.methodType() == QMetaMethod::Constructor);
+ QMetaMethodBuilder ctor = addConstructor(prototype.signature());
+ ctor.setReturnType(prototype.typeName());
+ ctor.setParameterNames(prototype.parameterNames());
+ ctor.setTag(prototype.tag());
+ ctor.setAccess(prototype.access());
+ ctor.setAttributes(prototype.attributes());
+ return ctor;
+}
+
+/*!
+ Adds a new readable/writable property to this class with the
+ specified \a name and \a type. Returns an object that can be used
+ to adjust the other attributes of the property. The \a type will
+ be normalized before it is added to the class. \a notifierId will
+ be registered as the property's \e notify signal.
+
+ \sa property(), propertyCount(), removeProperty(), indexOfProperty()
+*/
+QMetaPropertyBuilder QMetaObjectBuilder::addProperty
+ (const QByteArray& name, const QByteArray& type, int notifierId)
+{
+ int index = d->properties.size();
+ d->properties.append(QMetaPropertyBuilderPrivate(name, type, notifierId));
+ return QMetaPropertyBuilder(this, index);
+}
+
+/*!
+ Adds a new property to this class that has the same information as
+ \a prototype. This is used to clone the properties of an existing
+ QMetaObject. Returns an object that can be used to adjust the
+ attributes of the property.
+
+ \sa property(), propertyCount(), removeProperty(), indexOfProperty()
+*/
+QMetaPropertyBuilder QMetaObjectBuilder::addProperty(const QMetaProperty& prototype)
+{
+ QMetaPropertyBuilder property = addProperty(prototype.name(), prototype.typeName());
+ property.setReadable(prototype.isReadable());
+ property.setWritable(prototype.isWritable());
+ property.setResettable(prototype.isResettable());
+ property.setDesignable(prototype.isDesignable());
+ property.setScriptable(prototype.isScriptable());
+ property.setStored(prototype.isStored());
+ property.setEditable(prototype.isEditable());
+ property.setUser(prototype.isUser());
+ property.setStdCppSet(prototype.hasStdCppSet());
+ property.setEnumOrFlag(prototype.isEnumType());
+ if (prototype.hasNotifySignal()) {
+ // Find an existing method for the notify signal, or add a new one.
+ QMetaMethod method = prototype.notifySignal();
+ int index = indexOfMethod(method.signature());
+ if (index == -1)
+ index = addMethod(method).index();
+ d->properties[property._index].notifySignal = index;
+ d->properties[property._index].setFlag(Notify, true);
+ }
+ return property;
+}
+
+/*!
+ Adds a new enumerator to this class with the specified
+ \a name. Returns an object that can be used to adjust
+ the other attributes of the enumerator.
+
+ \sa enumerator(), enumeratorCount(), removeEnumerator(),
+ \sa indexOfEnumerator()
+*/
+QMetaEnumBuilder QMetaObjectBuilder::addEnumerator(const QByteArray& name)
+{
+ int index = d->enumerators.size();
+ d->enumerators.append(QMetaEnumBuilderPrivate(name));
+ return QMetaEnumBuilder(this, index);
+}
+
+/*!
+ Adds a new enumerator to this class that has the same information as
+ \a prototype. This is used to clone the enumerators of an existing
+ QMetaObject. Returns an object that can be used to adjust the
+ attributes of the enumerator.
+
+ \sa enumerator(), enumeratorCount(), removeEnumerator(),
+ \sa indexOfEnumerator()
+*/
+QMetaEnumBuilder QMetaObjectBuilder::addEnumerator(const QMetaEnum& prototype)
+{
+ QMetaEnumBuilder en = addEnumerator(prototype.name());
+ en.setIsFlag(prototype.isFlag());
+ int count = prototype.keyCount();
+ for (int index = 0; index < count; ++index)
+ en.addKey(prototype.key(index), prototype.value(index));
+ return en;
+}
+
+/*!
+ Adds \a name and \a value as an item of class information to this class.
+ Returns the index of the new item of class information.
+
+ \sa classInfoCount(), classInfoName(), classInfoValue(), removeClassInfo()
+ \sa indexOfClassInfo()
+*/
+int QMetaObjectBuilder::addClassInfo(const QByteArray& name, const QByteArray& value)
+{
+ int index = d->classInfoNames.size();
+ d->classInfoNames += name;
+ d->classInfoValues += value;
+ return index;
+}
+
+/*!
+ Adds \a meta to this class as a related meta object. Returns
+ the index of the new related meta object entry.
+
+ Related meta objects are used when resolving the enumerated type
+ associated with a property, where the enumerated type is in a
+ different class from the property.
+
+ \sa relatedMetaObjectCount(), relatedMetaObject()
+ \sa removeRelatedMetaObject()
+*/
+#ifdef Q_NO_DATA_RELOCATION
+int QMetaObjectBuilder::addRelatedMetaObject(const QMetaObjectAccessor &meta)
+#else
+int QMetaObjectBuilder::addRelatedMetaObject(const QMetaObject *meta)
+#endif
+{
+ Q_ASSERT(meta);
+ int index = d->relatedMetaObjects.size();
+ d->relatedMetaObjects.append(meta);
+ return index;
+}
+
+/*!
+ Adds the contents of \a prototype to this meta object builder.
+ This function is useful for cloning the contents of an existing QMetaObject.
+
+ The \a members parameter indicates which members of \a prototype
+ should be added. The default is AllMembers.
+*/
+void QMetaObjectBuilder::addMetaObject
+ (const QMetaObject *prototype, QMetaObjectBuilder::AddMembers members)
+{
+ Q_ASSERT(prototype);
+ int index;
+
+ if ((members & ClassName) != 0)
+ d->className = prototype->className();
+
+ if ((members & SuperClass) != 0)
+ d->superClass = prototype->superClass();
+
+ if ((members & (Methods | Signals | Slots)) != 0) {
+ for (index = prototype->methodOffset(); index < prototype->methodCount(); ++index) {
+ QMetaMethod method = prototype->method(index);
+ if (method.methodType() != QMetaMethod::Signal) {
+ if (method.access() == QMetaMethod::Public && (members & PublicMethods) == 0)
+ continue;
+ if (method.access() == QMetaMethod::Private && (members & PrivateMethods) == 0)
+ continue;
+ if (method.access() == QMetaMethod::Protected && (members & ProtectedMethods) == 0)
+ continue;
+ }
+ if (method.methodType() == QMetaMethod::Method && (members & Methods) != 0) {
+ addMethod(method);
+ } else if (method.methodType() == QMetaMethod::Signal &&
+ (members & Signals) != 0) {
+ addMethod(method);
+ } else if (method.methodType() == QMetaMethod::Slot &&
+ (members & Slots) != 0) {
+ addMethod(method);
+ }
+ }
+ }
+
+ if ((members & Constructors) != 0) {
+ for (index = 0; index < prototype->constructorCount(); ++index)
+ addConstructor(prototype->constructor(index));
+ }
+
+ if ((members & Properties) != 0) {
+ for (index = prototype->propertyOffset(); index < prototype->propertyCount(); ++index)
+ addProperty(prototype->property(index));
+ }
+
+ if ((members & Enumerators) != 0) {
+ for (index = prototype->enumeratorOffset(); index < prototype->enumeratorCount(); ++index)
+ addEnumerator(prototype->enumerator(index));
+ }
+
+ if ((members & ClassInfos) != 0) {
+ for (index = prototype->classInfoOffset(); index < prototype->classInfoCount(); ++index) {
+ QMetaClassInfo ci = prototype->classInfo(index);
+ addClassInfo(ci.name(), ci.value());
+ }
+ }
+
+ if ((members & RelatedMetaObjects) != 0) {
+#ifdef Q_NO_DATA_RELOCATION
+ const QMetaObjectAccessor *objects = 0;
+#else
+ const QMetaObject **objects;
+ if (priv(prototype->d.data)->revision < 2) {
+ objects = (const QMetaObject **)(prototype->d.extradata);
+ } else
+#endif
+ {
+ const QMetaObjectExtraData *extra = (const QMetaObjectExtraData *)(prototype->d.extradata);
+ if (extra)
+ objects = extra->objects;
+ else
+ objects = 0;
+ }
+ if (objects) {
+ while (*objects != 0) {
+ addRelatedMetaObject(*objects);
+ ++objects;
+ }
+ }
+ }
+
+ if ((members & StaticMetacall) != 0) {
+ if (priv(prototype->d.data)->revision >= 2) {
+ const QMetaObjectExtraData *extra =
+ (const QMetaObjectExtraData *)(prototype->d.extradata);
+ if (extra && extra->static_metacall)
+ setStaticMetacallFunction(extra->static_metacall);
+ }
+ }
+}
+
+/*!
+ Returns the method at \a index in this class.
+
+ \sa methodCount(), addMethod(), removeMethod(), indexOfMethod()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::method(int index) const
+{
+ if (index >= 0 && index < d->methods.size())
+ return QMetaMethodBuilder(this, index);
+ else
+ return QMetaMethodBuilder();
+}
+
+/*!
+ Returns the constructor at \a index in this class.
+
+ \sa methodCount(), addMethod(), removeMethod(), indexOfConstructor()
+*/
+QMetaMethodBuilder QMetaObjectBuilder::constructor(int index) const
+{
+ if (index >= 0 && index < d->constructors.size())
+ return QMetaMethodBuilder(this, -(index + 1));
+ else
+ return QMetaMethodBuilder();
+}
+
+/*!
+ Returns the property at \a index in this class.
+
+ \sa methodCount(), addMethod(), removeMethod(), indexOfProperty()
+*/
+QMetaPropertyBuilder QMetaObjectBuilder::property(int index) const
+{
+ if (index >= 0 && index < d->properties.size())
+ return QMetaPropertyBuilder(this, index);
+ else
+ return QMetaPropertyBuilder();
+}
+
+/*!
+ Returns the enumerator at \a index in this class.
+
+ \sa enumeratorCount(), addEnumerator(), removeEnumerator()
+ \sa indexOfEnumerator()
+*/
+QMetaEnumBuilder QMetaObjectBuilder::enumerator(int index) const
+{
+ if (index >= 0 && index < d->enumerators.size())
+ return QMetaEnumBuilder(this, index);
+ else
+ return QMetaEnumBuilder();
+}
+
+/*!
+ Returns the related meta object at \a index in this class.
+
+ Related meta objects are used when resolving the enumerated type
+ associated with a property, where the enumerated type is in a
+ different class from the property.
+
+ \sa relatedMetaObjectCount(), addRelatedMetaObject()
+ \sa removeRelatedMetaObject()
+*/
+const QMetaObject *QMetaObjectBuilder::relatedMetaObject(int index) const
+{
+ if (index >= 0 && index < d->relatedMetaObjects.size())
+#ifdef Q_NO_DATA_RELOCATION
+ return &((*(d->relatedMetaObjects[index]))());
+#else
+ return d->relatedMetaObjects[index];
+#endif
+ else
+ return 0;
+}
+
+/*!
+ Returns the name of the item of class information at \a index
+ in this class.
+
+ \sa classInfoCount(), addClassInfo(), classInfoValue(), removeClassInfo()
+ \sa indexOfClassInfo()
+*/
+QByteArray QMetaObjectBuilder::classInfoName(int index) const
+{
+ if (index >= 0 && index < d->classInfoNames.size())
+ return d->classInfoNames[index];
+ else
+ return QByteArray();
+}
+
+/*!
+ Returns the value of the item of class information at \a index
+ in this class.
+
+ \sa classInfoCount(), addClassInfo(), classInfoName(), removeClassInfo()
+ \sa indexOfClassInfo()
+*/
+QByteArray QMetaObjectBuilder::classInfoValue(int index) const
+{
+ if (index >= 0 && index < d->classInfoValues.size())
+ return d->classInfoValues[index];
+ else
+ return QByteArray();
+}
+
+/*!
+ Removes the method at \a index from this class. The indices of
+ all following methods will be adjusted downwards by 1. If the
+ method is registered as a notify signal on a property, then the
+ notify signal will be removed from the property.
+
+ \sa methodCount(), addMethod(), method(), indexOfMethod()
+*/
+void QMetaObjectBuilder::removeMethod(int index)
+{
+ if (index >= 0 && index < d->methods.size()) {
+ d->methods.removeAt(index);
+ for (int prop = 0; prop < d->properties.size(); ++prop) {
+ // Adjust the indices of property notify signal references.
+ if (d->properties[prop].notifySignal == index)
+ d->properties[prop].notifySignal = -1;
+ else if (d->properties[prop].notifySignal > index)
+ (d->properties[prop].notifySignal)--;
+ }
+ }
+}
+
+/*!
+ Removes the constructor at \a index from this class. The indices of
+ all following constructors will be adjusted downwards by 1.
+
+ \sa constructorCount(), addConstructor(), constructor()
+ \sa indexOfConstructor()
+*/
+void QMetaObjectBuilder::removeConstructor(int index)
+{
+ if (index >= 0 && index < d->constructors.size())
+ d->constructors.removeAt(index);
+}
+
+/*!
+ Removes the property at \a index from this class. The indices of
+ all following properties will be adjusted downwards by 1.
+
+ \sa propertyCount(), addProperty(), property(), indexOfProperty()
+*/
+void QMetaObjectBuilder::removeProperty(int index)
+{
+ if (index >= 0 && index < d->properties.size())
+ d->properties.removeAt(index);
+}
+
+/*!
+ Removes the enumerator at \a index from this class. The indices of
+ all following enumerators will be adjusted downwards by 1.
+
+ \sa enumertorCount(), addEnumerator(), enumerator()
+ \sa indexOfEnumerator()
+*/
+void QMetaObjectBuilder::removeEnumerator(int index)
+{
+ if (index >= 0 && index < d->enumerators.size())
+ d->enumerators.removeAt(index);
+}
+
+/*!
+ Removes the item of class information at \a index from this class.
+ The indices of all following items will be adjusted downwards by 1.
+
+ \sa classInfoCount(), addClassInfo(), classInfoName(), classInfoValue()
+ \sa indexOfClassInfo()
+*/
+void QMetaObjectBuilder::removeClassInfo(int index)
+{
+ if (index >= 0 && index < d->classInfoNames.size()) {
+ d->classInfoNames.removeAt(index);
+ d->classInfoValues.removeAt(index);
+ }
+}
+
+/*!
+ Removes the related meta object at \a index from this class.
+ The indices of all following related meta objects will be adjusted
+ downwards by 1.
+
+ Related meta objects are used when resolving the enumerated type
+ associated with a property, where the enumerated type is in a
+ different class from the property.
+
+ \sa relatedMetaObjectCount(), addRelatedMetaObject()
+ \sa relatedMetaObject()
+*/
+void QMetaObjectBuilder::removeRelatedMetaObject(int index)
+{
+ if (index >= 0 && index < d->relatedMetaObjects.size())
+ d->relatedMetaObjects.removeAt(index);
+}
+
+/*!
+ Finds a method with the specified \a signature and returns its index;
+ otherwise returns -1. The \a signature will be normalized by this method.
+
+ \sa method(), methodCount(), addMethod(), removeMethod()
+*/
+int QMetaObjectBuilder::indexOfMethod(const QByteArray& signature)
+{
+ QByteArray sig = QMetaObject::normalizedSignature(signature);
+ for (int index = 0; index < d->methods.size(); ++index) {
+ if (sig == d->methods[index].signature)
+ return index;
+ }
+ return -1;
+}
+
+/*!
+ Finds a signal with the specified \a signature and returns its index;
+ otherwise returns -1. The \a signature will be normalized by this method.
+
+ \sa indexOfMethod(), indexOfSlot()
+*/
+int QMetaObjectBuilder::indexOfSignal(const QByteArray& signature)
+{
+ QByteArray sig = QMetaObject::normalizedSignature(signature);
+ for (int index = 0; index < d->methods.size(); ++index) {
+ if (sig == d->methods[index].signature &&
+ d->methods[index].methodType() == QMetaMethod::Signal)
+ return index;
+ }
+ return -1;
+}
+
+/*!
+ Finds a slot with the specified \a signature and returns its index;
+ otherwise returns -1. The \a signature will be normalized by this method.
+
+ \sa indexOfMethod(), indexOfSignal()
+*/
+int QMetaObjectBuilder::indexOfSlot(const QByteArray& signature)
+{
+ QByteArray sig = QMetaObject::normalizedSignature(signature);
+ for (int index = 0; index < d->methods.size(); ++index) {
+ if (sig == d->methods[index].signature &&
+ d->methods[index].methodType() == QMetaMethod::Slot)
+ return index;
+ }
+ return -1;
+}
+
+/*!
+ Finds a constructor with the specified \a signature and returns its index;
+ otherwise returns -1. The \a signature will be normalized by this method.
+
+ \sa constructor(), constructorCount(), addConstructor(), removeConstructor()
+*/
+int QMetaObjectBuilder::indexOfConstructor(const QByteArray& signature)
+{
+ QByteArray sig = QMetaObject::normalizedSignature(signature);
+ for (int index = 0; index < d->constructors.size(); ++index) {
+ if (sig == d->constructors[index].signature)
+ return index;
+ }
+ return -1;
+}
+
+/*!
+ Finds a property with the specified \a name and returns its index;
+ otherwise returns -1.
+
+ \sa property(), propertyCount(), addProperty(), removeProperty()
+*/
+int QMetaObjectBuilder::indexOfProperty(const QByteArray& name)
+{
+ for (int index = 0; index < d->properties.size(); ++index) {
+ if (name == d->properties[index].name)
+ return index;
+ }
+ return -1;
+}
+
+/*!
+ Finds an enumerator with the specified \a name and returns its index;
+ otherwise returns -1.
+
+ \sa enumertor(), enumeratorCount(), addEnumerator(), removeEnumerator()
+*/
+int QMetaObjectBuilder::indexOfEnumerator(const QByteArray& name)
+{
+ for (int index = 0; index < d->enumerators.size(); ++index) {
+ if (name == d->enumerators[index].name)
+ return index;
+ }
+ return -1;
+}
+
+/*!
+ Finds an item of class information with the specified \a name and
+ returns its index; otherwise returns -1.
+
+ \sa classInfoName(), classInfoValue(), classInfoCount(), addClassInfo()
+ \sa removeClassInfo()
+*/
+int QMetaObjectBuilder::indexOfClassInfo(const QByteArray& name)
+{
+ for (int index = 0; index < d->classInfoNames.size(); ++index) {
+ if (name == d->classInfoNames[index])
+ return index;
+ }
+ return -1;
+}
+
+// Align on a specific type boundary.
+#define ALIGN(size,type) \
+ (size) = ((size) + sizeof(type) - 1) & ~(sizeof(type) - 1)
+
+// Build a string into a QMetaObject representation. Returns the
+// position in the string table where the string was placed.
+static int buildString
+ (char *buf, char *str, int *offset, const QByteArray& value, int empty)
+{
+ if (value.size() == 0 && empty >= 0)
+ return empty;
+ if (buf) {
+ memcpy(str + *offset, value.constData(), value.size());
+ str[*offset + value.size()] = '\0';
+ }
+ int posn = *offset;
+ *offset += value.size() + 1;
+ return posn;
+}
+
+// Build the parameter array string for a method.
+static QByteArray buildParameterNames
+ (const QByteArray& signature, const QList<QByteArray>& parameterNames)
+{
+ // If the parameter name list is specified, then concatenate them.
+ if (!parameterNames.isEmpty()) {
+ QByteArray names;
+ bool first = true;
+ foreach (QByteArray name, parameterNames) {
+ if (first)
+ first = false;
+ else
+ names += (char)',';
+ names += name;
+ }
+ return names;
+ }
+
+ // Count commas in the signature, excluding those inside template arguments.
+ int index = signature.indexOf('(');
+ if (index < 0)
+ return QByteArray();
+ ++index;
+ if (index >= signature.size())
+ return QByteArray();
+ if (signature[index] == ')')
+ return QByteArray();
+ int count = 1;
+ int brackets = 0;
+ while (index < signature.size() && signature[index] != ',') {
+ char ch = signature[index++];
+ if (ch == '<')
+ ++brackets;
+ else if (ch == '>')
+ --brackets;
+ else if (ch == ',' && brackets <= 0)
+ ++count;
+ }
+ return QByteArray(count - 1, ',');
+}
+
+// Build a QMetaObject in "buf" based on the information in "d".
+// If "buf" is null, then return the number of bytes needed to
+// build the QMetaObject. Returns -1 if the metaobject if
+// relocatable is set, but the metaobject contains extradata.
+static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
+ bool relocatable)
+{
+ int size = 0;
+ int dataIndex;
+ int enumIndex;
+ int index;
+ bool hasNotifySignals = false;
+
+ if (relocatable &&
+ (d->relatedMetaObjects.size() > 0 || d->staticMetacallFunction))
+ return -1;
+
+ // Create the main QMetaObject structure at the start of the buffer.
+ QMetaObject *meta = reinterpret_cast<QMetaObject *>(buf);
+ size += sizeof(QMetaObject);
+ ALIGN(size, int);
+ if (buf) {
+ if (!relocatable) meta->d.superdata = d->superClass;
+ meta->d.extradata = 0;
+ }
+
+ // Populate the QMetaObjectPrivate structure.
+ QMetaObjectPrivate *pmeta
+ = reinterpret_cast<QMetaObjectPrivate *>(buf + size);
+ int pmetaSize = size;
+ dataIndex = 13; // Number of fields in the QMetaObjectPrivate.
+ for (index = 0; index < d->properties.size(); ++index) {
+ if (d->properties[index].notifySignal != -1) {
+ hasNotifySignals = true;
+ break;
+ }
+ }
+ if (buf) {
+ pmeta->revision = 3;
+ pmeta->flags = d->flags;
+ pmeta->className = 0; // Class name is always the first string.
+
+ pmeta->classInfoCount = d->classInfoNames.size();
+ pmeta->classInfoData = dataIndex;
+ dataIndex += 2 * d->classInfoNames.size();
+
+ pmeta->methodCount = d->methods.size();
+ pmeta->methodData = dataIndex;
+ dataIndex += 5 * d->methods.size();
+
+ pmeta->propertyCount = d->properties.size();
+ pmeta->propertyData = dataIndex;
+ dataIndex += 3 * d->properties.size();
+ if (hasNotifySignals)
+ dataIndex += d->properties.size();
+
+ pmeta->enumeratorCount = d->enumerators.size();
+ pmeta->enumeratorData = dataIndex;
+ dataIndex += 4 * d->enumerators.size();
+
+ pmeta->constructorCount = d->constructors.size();
+ pmeta->constructorData = dataIndex;
+ dataIndex += 5 * d->constructors.size();
+ } else {
+ dataIndex += 2 * d->classInfoNames.size();
+ dataIndex += 5 * d->methods.size();
+ dataIndex += 3 * d->properties.size();
+ if (hasNotifySignals)
+ dataIndex += d->properties.size();
+ dataIndex += 4 * d->enumerators.size();
+ dataIndex += 5 * d->constructors.size();
+ }
+
+ // Allocate space for the enumerator key names and values.
+ enumIndex = dataIndex;
+ for (index = 0; index < d->enumerators.size(); ++index) {
+ QMetaEnumBuilderPrivate *enumerator = &(d->enumerators[index]);
+ dataIndex += 2 * enumerator->keys.size();
+ }
+
+ // Zero terminator at the end of the data offset table.
+ ++dataIndex;
+
+ // Find the start of the data and string tables.
+ int *data = reinterpret_cast<int *>(pmeta);
+ size += dataIndex * sizeof(int);
+ char *str = reinterpret_cast<char *>(buf + size);
+ if (buf) {
+ if (relocatable) {
+ meta->d.stringdata = reinterpret_cast<const char *>((intptr_t)size);
+ meta->d.data = reinterpret_cast<uint *>((intptr_t)pmetaSize);
+ } else {
+ meta->d.stringdata = str;
+ meta->d.data = reinterpret_cast<uint *>(data);
+ }
+ }
+
+ // Reset the current data position to just past the QMetaObjectPrivate.
+ dataIndex = 13;
+
+ // Add the class name to the string table.
+ int offset = 0;
+ buildString(buf, str, &offset, d->className, -1);
+
+ // Add a common empty string, which is used to indicate "void"
+ // method returns, empty tag strings, etc.
+ int empty = buildString(buf, str, &offset, QByteArray(), -1);
+
+ // Output the class infos,
+ for (index = 0; index < d->classInfoNames.size(); ++index) {
+ int name = buildString(buf, str, &offset, d->classInfoNames[index], empty);
+ int value = buildString(buf, str, &offset, d->classInfoValues[index], empty);
+ if (buf) {
+ data[dataIndex] = name;
+ data[dataIndex + 1] = value;
+ }
+ dataIndex += 2;
+ }
+
+ // Output the methods in the class.
+ for (index = 0; index < d->methods.size(); ++index) {
+ QMetaMethodBuilderPrivate *method = &(d->methods[index]);
+ int sig = buildString(buf, str, &offset, method->signature, empty);
+ int params;
+ QByteArray names = buildParameterNames
+ (method->signature, method->parameterNames);
+ params = buildString(buf, str, &offset, names, empty);
+ int ret = buildString(buf, str, &offset, method->returnType, empty);
+ int tag = buildString(buf, str, &offset, method->tag, empty);
+ int attrs = method->attributes;
+ if (buf) {
+ data[dataIndex] = sig;
+ data[dataIndex + 1] = params;
+ data[dataIndex + 2] = ret;
+ data[dataIndex + 3] = tag;
+ data[dataIndex + 4] = attrs;
+ }
+ dataIndex += 5;
+ }
+
+ // Output the properties in the class.
+ for (index = 0; index < d->properties.size(); ++index) {
+ QMetaPropertyBuilderPrivate *prop = &(d->properties[index]);
+ int name = buildString(buf, str, &offset, prop->name, empty);
+ int type = buildString(buf, str, &offset, prop->type, empty);
+ int flags = prop->flags;
+
+ if (!isVariantType(prop->type)) {
+ flags |= EnumOrFlag;
+ } else {
+ flags |= qvariant_nameToType(prop->type) << 24;
+ }
+
+ if (buf) {
+ data[dataIndex] = name;
+ data[dataIndex + 1] = type;
+ data[dataIndex + 2] = flags;
+ }
+ dataIndex += 3;
+ }
+ if (hasNotifySignals) {
+ for (index = 0; index < d->properties.size(); ++index) {
+ QMetaPropertyBuilderPrivate *prop = &(d->properties[index]);
+ if (buf) {
+ if (prop->notifySignal != -1)
+ data[dataIndex] = prop->notifySignal;
+ else
+ data[dataIndex] = 0;
+ }
+ ++dataIndex;
+ }
+ }
+
+ // Output the enumerators in the class.
+ for (index = 0; index < d->enumerators.size(); ++index) {
+ QMetaEnumBuilderPrivate *enumerator = &(d->enumerators[index]);
+ int name = buildString(buf, str, &offset, enumerator->name, empty);
+ int isFlag = (int)(enumerator->isFlag);
+ int count = enumerator->keys.size();
+ int enumOffset = enumIndex;
+ if (buf) {
+ data[dataIndex] = name;
+ data[dataIndex + 1] = isFlag;
+ data[dataIndex + 2] = count;
+ data[dataIndex + 3] = enumOffset;
+ }
+ for (int key = 0; key < count; ++key) {
+ int keyIndex = buildString(buf, str, &offset, enumerator->keys[key], empty);
+ if (buf) {
+ data[enumOffset++] = keyIndex;
+ data[enumOffset++] = enumerator->values[key];
+ }
+ }
+ dataIndex += 4;
+ enumIndex += 2 * count;
+ }
+
+ // Output the constructors in the class.
+ for (index = 0; index < d->constructors.size(); ++index) {
+ QMetaMethodBuilderPrivate *method = &(d->constructors[index]);
+ int sig = buildString(buf, str, &offset, method->signature, empty);
+ int params;
+ QByteArray names = buildParameterNames
+ (method->signature, method->parameterNames);
+ params = buildString(buf, str, &offset, names, empty);
+ int ret = buildString(buf, str, &offset, method->returnType, empty);
+ int tag = buildString(buf, str, &offset, method->tag, empty);
+ int attrs = method->attributes;
+ if (buf) {
+ data[dataIndex] = sig;
+ data[dataIndex + 1] = params;
+ data[dataIndex + 2] = ret;
+ data[dataIndex + 3] = tag;
+ data[dataIndex + 4] = attrs;
+ }
+ dataIndex += 5;
+ }
+
+ // One more empty string to act as a terminator.
+ buildString(buf, str, &offset, QByteArray(), -1);
+ size += offset;
+
+ // Output the zero terminator in the data array.
+ if (buf)
+ data[enumIndex] = 0;
+
+ // Create the extradata block if we need one.
+ if (d->relatedMetaObjects.size() > 0 || d->staticMetacallFunction) {
+ ALIGN(size, QMetaObject **);
+ ALIGN(size, QMetaObjectBuilder::StaticMetacallFunction);
+ QMetaObjectExtraData *extra =
+ reinterpret_cast<QMetaObjectExtraData *>(buf + size);
+ size += sizeof(QMetaObjectExtraData);
+ ALIGN(size, QMetaObject *);
+#ifdef Q_NO_DATA_RELOCATION
+ QMetaObjectAccessor *objects =
+ reinterpret_cast<QMetaObjectAccessor *>(buf + size);
+#else
+ const QMetaObject **objects =
+ reinterpret_cast<const QMetaObject **>(buf + size);
+#endif
+ if (buf) {
+ if (d->relatedMetaObjects.size() > 0) {
+ extra->objects = objects;
+ for (index = 0; index < d->relatedMetaObjects.size(); ++index)
+ objects[index] = d->relatedMetaObjects[index];
+ objects[index] = 0;
+ } else {
+ extra->objects = 0;
+ }
+ extra->static_metacall = d->staticMetacallFunction;
+ meta->d.extradata = reinterpret_cast<void *>(extra);
+ }
+ if (d->relatedMetaObjects.size() > 0)
+ size += sizeof(QMetaObject *) * (d->relatedMetaObjects.size() + 1);
+ }
+
+ // Align the final size and return it.
+ ALIGN(size, void *);
+ return size;
+}
+
+/*!
+ Converts this meta object builder into a concrete QMetaObject.
+ The return value should be deallocated using qFree() once it
+ is no longer needed.
+
+ The returned meta object is a snapshot of the state of the
+ QMetaObjectBuilder. Any further modifications to the QMetaObjectBuilder
+ will not be reflected in previous meta objects returned by
+ this method.
+*/
+QMetaObject *QMetaObjectBuilder::toMetaObject() const
+{
+ int size = buildMetaObject(d, 0, false);
+ char *buf = reinterpret_cast<char *>(qMalloc(size));
+ buildMetaObject(d, buf, false);
+ return reinterpret_cast<QMetaObject *>(buf);
+}
+
+/*
+ \internal
+
+ Converts this meta object builder into relocatable data. This data can
+ be stored, copied and later passed to fromRelocatableData() to create a
+ concrete QMetaObject.
+
+ The data is specific to the architecture on which it was created, but is not
+ specific to the process that created it. Not all meta object builder's can
+ be converted to data in this way. If \a ok is provided, it will be set to
+ true if the conversion succeeds, and false otherwise. If a
+ staticMetacallFunction() or any relatedMetaObject()'s are specified the
+ conversion to relocatable data will fail.
+*/
+QByteArray QMetaObjectBuilder::toRelocatableData(bool *ok) const
+{
+ int size = buildMetaObject(d, 0, true);
+ if (size == -1) {
+ if (ok) *ok = false;
+ return QByteArray();
+ }
+
+ QByteArray data;
+ data.resize(size);
+ char *buf = data.data();
+ buildMetaObject(d, buf, true);
+ if (ok) *ok = true;
+ return data;
+}
+
+/*
+ \internal
+
+ Sets the \a data returned from toRelocatableData() onto a concrete
+ QMetaObject instance, \a output. As the meta object's super class is not
+ saved in the relocatable data, it must be passed as \a superClass.
+*/
+void QMetaObjectBuilder::fromRelocatableData(QMetaObject *output,
+ const QMetaObject *superclass,
+ const QByteArray &data)
+{
+ if (!output)
+ return;
+
+ const char *buf = data.constData();
+ const QMetaObject *dataMo = reinterpret_cast<const QMetaObject *>(buf);
+
+ intptr_t stringdataOffset = (intptr_t)dataMo->d.stringdata;
+ intptr_t dataOffset = (intptr_t)dataMo->d.data;
+
+ output->d.superdata = superclass;
+ output->d.stringdata = buf + stringdataOffset;
+ output->d.data = reinterpret_cast<const uint *>(buf + dataOffset);
+}
+
+/*!
+ \typedef QMetaObjectBuilder::StaticMetacallFunction
+
+ Typedef for static metacall functions. The three parameters are
+ the call type value, the constructor index, and the
+ array of parameters.
+*/
+
+/*!
+ Returns the static metacall function to use to construct objects
+ of this class. The default value is null.
+
+ \sa setStaticMetacallFunction()
+*/
+QMetaObjectBuilder::StaticMetacallFunction QMetaObjectBuilder::staticMetacallFunction() const
+{
+ return d->staticMetacallFunction;
+}
+
+/*!
+ Sets the static metacall function to use to construct objects
+ of this class to \a value. The default value is null.
+
+ \sa staticMetacallFunction()
+*/
+void QMetaObjectBuilder::setStaticMetacallFunction
+ (QMetaObjectBuilder::StaticMetacallFunction value)
+{
+ d->staticMetacallFunction = value;
+}
+
+#ifndef QT_NO_DATASTREAM
+
+/*!
+ Serializes the contents of the meta object builder onto \a stream.
+
+ \sa deserialize()
+*/
+void QMetaObjectBuilder::serialize(QDataStream& stream) const
+{
+ int index;
+
+ // Write the class and super class names.
+ stream << d->className;
+ if (d->superClass)
+ stream << QByteArray(d->superClass->className());
+ else
+ stream << QByteArray();
+
+ // Write the counts for each type of class member.
+ stream << d->classInfoNames.size();
+ stream << d->methods.size();
+ stream << d->properties.size();
+ stream << d->enumerators.size();
+ stream << d->constructors.size();
+ stream << d->relatedMetaObjects.size();
+
+ // Write the items of class information.
+ for (index = 0; index < d->classInfoNames.size(); ++index) {
+ stream << d->classInfoNames[index];
+ stream << d->classInfoValues[index];
+ }
+
+ // Write the methods.
+ for (index = 0; index < d->methods.size(); ++index) {
+ const QMetaMethodBuilderPrivate *method = &(d->methods[index]);
+ stream << method->signature;
+ stream << method->returnType;
+ stream << method->parameterNames;
+ stream << method->tag;
+ stream << method->attributes;
+ }
+
+ // Write the properties.
+ for (index = 0; index < d->properties.size(); ++index) {
+ const QMetaPropertyBuilderPrivate *property = &(d->properties[index]);
+ stream << property->name;
+ stream << property->type;
+ stream << property->flags;
+ stream << property->notifySignal;
+ }
+
+ // Write the enumerators.
+ for (index = 0; index < d->enumerators.size(); ++index) {
+ const QMetaEnumBuilderPrivate *enumerator = &(d->enumerators[index]);
+ stream << enumerator->name;
+ stream << enumerator->isFlag;
+ stream << enumerator->keys;
+ stream << enumerator->values;
+ }
+
+ // Write the constructors.
+ for (index = 0; index < d->constructors.size(); ++index) {
+ const QMetaMethodBuilderPrivate *method = &(d->constructors[index]);
+ stream << method->signature;
+ stream << method->returnType;
+ stream << method->parameterNames;
+ stream << method->tag;
+ stream << method->attributes;
+ }
+
+ // Write the related meta objects.
+#ifdef Q_NO_DATA_RELOCATION
+ //### What do we do here?
+#else
+ for (index = 0; index < d->relatedMetaObjects.size(); ++index) {
+ const QMetaObject *meta = d->relatedMetaObjects[index];
+ stream << QByteArray(meta->className());
+ }
+#endif
+
+ // Add an extra empty QByteArray for additional data in future versions.
+ // This should help maintain backwards compatibility, allowing older
+ // versions to read newer data.
+ stream << QByteArray();
+}
+
+// Resolve a class name using the name reference map.
+static const QMetaObject *resolveClassName
+ (const QMap<QByteArray, const QMetaObject *>& references,
+ const QByteArray& name)
+{
+ if (name == QByteArray("QObject"))
+ return &QObject::staticMetaObject;
+ else
+ return references.value(name, 0);
+}
+
+/*!
+ Deserializes a meta object builder from \a stream into
+ this meta object builder.
+
+ The \a references parameter specifies a mapping from class names
+ to QMetaObject instances for resolving the super class name and
+ related meta objects in the object that is deserialized.
+ The meta object for QObject is implicitly added to \a references
+ and does not need to be supplied.
+
+ The QDataStream::status() value on \a stream will be set to
+ QDataStream::ReadCorruptData if the input data is corrupt.
+ The status will be set to QDataStream::ReadPastEnd if the
+ input was exhausted before the full meta object was read.
+
+ \sa serialize()
+*/
+void QMetaObjectBuilder::deserialize
+ (QDataStream& stream,
+ const QMap<QByteArray, const QMetaObject *>& references)
+{
+ QByteArray name;
+ const QMetaObject *cl;
+ int index;
+
+ // Clear all members in the builder to their default states.
+ d->className.clear();
+ d->superClass = &QObject::staticMetaObject;
+ d->classInfoNames.clear();
+ d->classInfoValues.clear();
+ d->methods.clear();
+ d->properties.clear();
+ d->enumerators.clear();
+ d->constructors.clear();
+ d->relatedMetaObjects.clear();
+ d->staticMetacallFunction = 0;
+
+ // Read the class and super class names.
+ stream >> d->className;
+ stream >> name;
+ if (name.isEmpty()) {
+ d->superClass = 0;
+ } else if ((cl = resolveClassName(references, name)) != 0) {
+ d->superClass = cl;
+ } else {
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+
+ // Read the counts for each type of class member.
+ int classInfoCount, methodCount, propertyCount;
+ int enumeratorCount, constructorCount, relatedMetaObjectCount;
+ stream >> classInfoCount;
+ stream >> methodCount;
+ stream >> propertyCount;
+ stream >> enumeratorCount;
+ stream >> constructorCount;
+ stream >> relatedMetaObjectCount;
+ if (classInfoCount < 0 || methodCount < 0 ||
+ propertyCount < 0 || enumeratorCount < 0 ||
+ constructorCount < 0 || relatedMetaObjectCount < 0) {
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+
+ // Read the items of class information.
+ for (index = 0; index < classInfoCount; ++index) {
+ if (stream.status() != QDataStream::Ok)
+ return;
+ QByteArray value;
+ stream >> name;
+ stream >> value;
+ addClassInfo(name, value);
+ }
+
+ // Read the member methods.
+ for (index = 0; index < methodCount; ++index) {
+ if (stream.status() != QDataStream::Ok)
+ return;
+ stream >> name;
+ addMethod(name);
+ QMetaMethodBuilderPrivate *method = &(d->methods[index]);
+ stream >> method->returnType;
+ stream >> method->parameterNames;
+ stream >> method->tag;
+ stream >> method->attributes;
+ if (method->methodType() == QMetaMethod::Constructor) {
+ // Cannot add a constructor in this set of methods.
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+ }
+
+ // Read the properties.
+ for (index = 0; index < propertyCount; ++index) {
+ if (stream.status() != QDataStream::Ok)
+ return;
+ QByteArray type;
+ stream >> name;
+ stream >> type;
+ addProperty(name, type);
+ QMetaPropertyBuilderPrivate *property = &(d->properties[index]);
+ stream >> property->flags;
+ stream >> property->notifySignal;
+ if (property->notifySignal < -1 ||
+ property->notifySignal >= d->methods.size()) {
+ // Notify signal method index is out of range.
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+ if (property->notifySignal >= 0 &&
+ d->methods[property->notifySignal].methodType() != QMetaMethod::Signal) {
+ // Notify signal method index does not refer to a signal.
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+ }
+
+ // Read the enumerators.
+ for (index = 0; index < enumeratorCount; ++index) {
+ if (stream.status() != QDataStream::Ok)
+ return;
+ stream >> name;
+ addEnumerator(name);
+ QMetaEnumBuilderPrivate *enumerator = &(d->enumerators[index]);
+ stream >> enumerator->isFlag;
+ stream >> enumerator->keys;
+ stream >> enumerator->values;
+ if (enumerator->keys.size() != enumerator->values.size()) {
+ // Mismatch between number of keys and number of values.
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+ }
+
+ // Read the constructor methods.
+ for (index = 0; index < constructorCount; ++index) {
+ if (stream.status() != QDataStream::Ok)
+ return;
+ stream >> name;
+ addConstructor(name);
+ QMetaMethodBuilderPrivate *method = &(d->constructors[index]);
+ stream >> method->returnType;
+ stream >> method->parameterNames;
+ stream >> method->tag;
+ stream >> method->attributes;
+ if (method->methodType() != QMetaMethod::Constructor) {
+ // The type must be Constructor.
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+ }
+
+ // Read the related meta objects.
+#ifdef Q_NO_DATA_RELOCATION
+ //### What do we do here
+#else
+ for (index = 0; index < relatedMetaObjectCount; ++index) {
+ if (stream.status() != QDataStream::Ok)
+ return;
+ stream >> name;
+ cl = resolveClassName(references, name);
+ if (!cl) {
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+ addRelatedMetaObject(cl);
+ }
+#endif
+
+ // Read the extra data block, which is reserved for future use.
+ stream >> name;
+}
+
+#endif // !QT_NO_DATASTREAM
+
+/*!
+ \class QMetaMethodBuilder
+ \internal
+ \brief The QMetaMethodBuilder class enables modifications to a method definition on a meta object builder.
+*/
+
+QMetaMethodBuilderPrivate *QMetaMethodBuilder::d_func() const
+{
+ // Positive indices indicate methods, negative indices indicate constructors.
+ if (_mobj && _index >= 0 && _index < _mobj->d->methods.size())
+ return &(_mobj->d->methods[_index]);
+ else if (_mobj && -_index >= 1 && -_index <= _mobj->d->constructors.size())
+ return &(_mobj->d->constructors[(-_index) - 1]);
+ else
+ return 0;
+}
+
+/*!
+ \fn QMetaMethodBuilder::QMetaMethodBuilder()
+ \internal
+*/
+
+/*!
+ Returns the index of this method within its QMetaObjectBuilder.
+*/
+int QMetaMethodBuilder::index() const
+{
+ if (_index >= 0)
+ return _index; // Method, signal, or slot
+ else
+ return (-_index) - 1; // Constructor
+}
+
+/*!
+ Returns the type of this method (signal, slot, method, or constructor).
+*/
+QMetaMethod::MethodType QMetaMethodBuilder::methodType() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ return d->methodType();
+ else
+ return QMetaMethod::Method;
+}
+
+/*!
+ Returns the signature of this method.
+
+ \sa parameterNames(), returnType()
+*/
+QByteArray QMetaMethodBuilder::signature() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ return d->signature;
+ else
+ return QByteArray();
+}
+
+/*!
+ Returns the return type for this method; empty if the method's
+ return type is \c{void}.
+
+ \sa setReturnType(), signature()
+*/
+QByteArray QMetaMethodBuilder::returnType() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ return d->returnType;
+ else
+ return QByteArray();
+}
+
+/*!
+ Sets the return type for this method to \a value. If \a value
+ is empty, then the method's return type is \c{void}. The \a value
+ will be normalized before it is added to the method.
+
+ \sa returnType(), signature()
+*/
+void QMetaMethodBuilder::setReturnType(const QByteArray& value)
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ d->returnType = QMetaObject::normalizedType(value);
+}
+
+/*!
+ Returns the list of parameter names for this method.
+
+ \sa setParameterNames()
+*/
+QList<QByteArray> QMetaMethodBuilder::parameterNames() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ return d->parameterNames;
+ else
+ return QList<QByteArray>();
+}
+
+/*!
+ Sets the list of parameter names for this method to \a value.
+
+ \sa parameterNames()
+*/
+void QMetaMethodBuilder::setParameterNames(const QList<QByteArray>& value)
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ d->parameterNames = value;
+}
+
+/*!
+ Returns the tag associated with this method.
+
+ \sa setTag()
+*/
+QByteArray QMetaMethodBuilder::tag() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ return d->tag;
+ else
+ return QByteArray();
+}
+
+/*!
+ Sets the tag associated with this method to \a value.
+
+ \sa setTag()
+*/
+void QMetaMethodBuilder::setTag(const QByteArray& value)
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ d->tag = value;
+}
+
+/*!
+ Returns the access specification of this method (private, protected,
+ or public). The default value is QMetaMethod::Public for methods,
+ slots, and constructors. The default value is QMetaMethod::Protected
+ for signals.
+
+ \sa setAccess()
+*/
+QMetaMethod::Access QMetaMethodBuilder::access() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ return d->access();
+ else
+ return QMetaMethod::Public;
+}
+
+/*!
+ Sets the access specification of this method (private, protected,
+ or public) to \a value. If the method is a signal, this function
+ will be ignored.
+
+ \sa access()
+*/
+void QMetaMethodBuilder::setAccess(QMetaMethod::Access value)
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d && d->methodType() != QMetaMethod::Signal)
+ d->setAccess(value);
+}
+
+/*!
+ Returns the additional attributes for this method.
+
+ \sa setAttributes()
+*/
+int QMetaMethodBuilder::attributes() const
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ return (d->attributes >> 4);
+ else
+ return 0;
+}
+
+/*!
+ Sets the additional attributes for this method to \a value.
+
+ \sa attributes()
+*/
+void QMetaMethodBuilder::setAttributes(int value)
+{
+ QMetaMethodBuilderPrivate *d = d_func();
+ if (d)
+ d->attributes = ((d->attributes & 0x0f) | (value << 4));
+}
+
+/*!
+ \class QMetaPropertyBuilder
+ \internal
+ \brief The QMetaPropertyBuilder class enables modifications to a property definition on a meta object builder.
+*/
+
+QMetaPropertyBuilderPrivate *QMetaPropertyBuilder::d_func() const
+{
+ if (_mobj && _index >= 0 && _index < _mobj->d->properties.size())
+ return &(_mobj->d->properties[_index]);
+ else
+ return 0;
+}
+
+/*!
+ \fn QMetaPropertyBuilder::QMetaPropertyBuilder()
+ \internal
+*/
+
+/*!
+ \fn int QMetaPropertyBuilder::index() const
+
+ Returns the index of this property within its QMetaObjectBuilder.
+*/
+
+/*!
+ Returns the name associated with this property.
+
+ \sa type()
+*/
+QByteArray QMetaPropertyBuilder::name() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->name;
+ else
+ return QByteArray();
+}
+
+/*!
+ Returns the type associated with this property.
+
+ \sa name()
+*/
+QByteArray QMetaPropertyBuilder::type() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->type;
+ else
+ return QByteArray();
+}
+
+/*!
+ Returns true if this property has a notify signal; false otherwise.
+
+ \sa notifySignal(), setNotifySignal(), removeNotifySignal()
+*/
+bool QMetaPropertyBuilder::hasNotifySignal() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Notify);
+ else
+ return false;
+}
+
+/*!
+ Returns the notify signal associated with this property.
+
+ \sa hasNotifySignal(), setNotifySignal(), removeNotifySignal()
+*/
+QMetaMethodBuilder QMetaPropertyBuilder::notifySignal() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d && d->notifySignal >= 0)
+ return QMetaMethodBuilder(_mobj, d->notifySignal);
+ else
+ return QMetaMethodBuilder();
+}
+
+/*!
+ Sets the notify signal associated with this property to \a value.
+
+ \sa hasNotifySignal(), notifySignal(), removeNotifySignal()
+*/
+void QMetaPropertyBuilder::setNotifySignal(const QMetaMethodBuilder& value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d) {
+ if (value._mobj) {
+ d->notifySignal = value._index;
+ d->setFlag(Notify, true);
+ } else {
+ d->notifySignal = -1;
+ d->setFlag(Notify, false);
+ }
+ }
+}
+
+/*!
+ Removes the notify signal from this property.
+
+ \sa hasNotifySignal(), notifySignal(), setNotifySignal()
+*/
+void QMetaPropertyBuilder::removeNotifySignal()
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d) {
+ d->notifySignal = -1;
+ d->setFlag(Notify, false);
+ }
+}
+
+/*!
+ Returns true if this property is readable; otherwise returns false.
+ The default value is true.
+
+ \sa setReadable(), isWritable()
+*/
+bool QMetaPropertyBuilder::isReadable() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Readable);
+ else
+ return false;
+}
+
+/*!
+ Returns true if this property is writable; otherwise returns false.
+ The default value is true.
+
+ \sa setWritable(), isReadable()
+*/
+bool QMetaPropertyBuilder::isWritable() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Writable);
+ else
+ return false;
+}
+
+/*!
+ Returns true if this property can be reset to a default value; otherwise
+ returns false. The default value is false.
+
+ \sa setResettable()
+*/
+bool QMetaPropertyBuilder::isResettable() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Resettable);
+ else
+ return false;
+}
+
+/*!
+ Returns true if this property is designable; otherwise returns false.
+ This default value is false.
+
+ \sa setDesignable(), isScriptable(), isStored()
+*/
+bool QMetaPropertyBuilder::isDesignable() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Designable);
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property is scriptable; otherwise returns false.
+ This default value is false.
+
+ \sa setScriptable(), isDesignable(), isStored()
+*/
+bool QMetaPropertyBuilder::isScriptable() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Scriptable);
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property is stored; otherwise returns false.
+ This default value is false.
+
+ \sa setStored(), isDesignable(), isScriptable()
+*/
+bool QMetaPropertyBuilder::isStored() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Stored);
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property is editable; otherwise returns false.
+ This default value is false.
+
+ \sa setEditable(), isDesignable(), isScriptable(), isStored()
+*/
+bool QMetaPropertyBuilder::isEditable() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Editable);
+ else
+ return false;
+}
+
+/*!
+ Returns true if this property is designated as the \c USER
+ property, i.e., the one that the user can edit or that is
+ significant in some other way. Otherwise it returns
+ false. This default value is false.
+
+ \sa setUser(), isDesignable(), isScriptable()
+*/
+bool QMetaPropertyBuilder::isUser() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(User);
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property has a C++ setter function that
+ follows Qt's standard "name" / "setName" pattern. Designer and uic
+ query hasStdCppSet() in order to avoid expensive
+ QObject::setProperty() calls. All properties in Qt [should] follow
+ this pattern. The default value is false.
+
+ \sa setStdCppSet()
+*/
+bool QMetaPropertyBuilder::hasStdCppSet() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(StdCppSet);
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property is an enumerator or flag type;
+ otherwise returns false. This default value is false.
+
+ \sa setEnumOrFlag()
+*/
+bool QMetaPropertyBuilder::isEnumOrFlag() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(EnumOrFlag);
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property has the dynamic flag set;
+ otherwise returns false. The default value is false.
+
+ \sa setDynamic()
+*/
+bool QMetaPropertyBuilder::isDynamic() const
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ return d->flag(Dynamic);
+ else
+ return false;
+}
+
+/*!
+ Sets this property to readable if \a value is true.
+
+ \sa isReadable(), setWritable()
+*/
+void QMetaPropertyBuilder::setReadable(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Readable, value);
+}
+
+/*!
+ Sets this property to writable if \a value is true.
+
+ \sa isWritable(), setReadable()
+*/
+void QMetaPropertyBuilder::setWritable(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Writable, value);
+}
+
+/*!
+ Sets this property to resettable if \a value is true.
+
+ \sa isResettable()
+*/
+void QMetaPropertyBuilder::setResettable(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Resettable, value);
+}
+
+/*!
+ Sets this property to designable if \a value is true.
+
+ \sa isDesignable(), setScriptable(), setStored()
+*/
+void QMetaPropertyBuilder::setDesignable(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Designable, value);
+}
+
+/*!
+ Sets this property to scriptable if \a value is true.
+
+ \sa isScriptable(), setDesignable(), setStored()
+*/
+void QMetaPropertyBuilder::setScriptable(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Scriptable, value);
+}
+
+/*!
+ Sets this property to storable if \a value is true.
+
+ \sa isStored(), setDesignable(), setScriptable()
+*/
+void QMetaPropertyBuilder::setStored(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Stored, value);
+}
+
+/*!
+ Sets this property to editable if \a value is true.
+
+ \sa isEditable(), setDesignable(), setScriptable(), setStored()
+*/
+void QMetaPropertyBuilder::setEditable(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Editable, value);
+}
+
+/*!
+ Sets the \c USER flag on this property to \a value.
+
+ \sa isUser(), setDesignable(), setScriptable()
+*/
+void QMetaPropertyBuilder::setUser(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(User, value);
+}
+
+/*!
+ Sets the C++ setter flag on this property to \a value, which is
+ true if the property has a C++ setter function that follows Qt's
+ standard "name" / "setName" pattern.
+
+ \sa hasStdCppSet()
+*/
+void QMetaPropertyBuilder::setStdCppSet(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(StdCppSet, value);
+}
+
+/*!
+ Sets this property to be of an enumerator or flag type if
+ \a value is true.
+
+ \sa isEnumOrFlag()
+*/
+void QMetaPropertyBuilder::setEnumOrFlag(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(EnumOrFlag, value);
+}
+
+/*!
+ Sets this property to have the dynamic flag if \a value is
+ true.
+
+ \sa isDynamic()
+*/
+void QMetaPropertyBuilder::setDynamic(bool value)
+{
+ QMetaPropertyBuilderPrivate *d = d_func();
+ if (d)
+ d->setFlag(Dynamic, value);
+}
+
+/*!
+ \class QMetaEnumBuilder
+ \internal
+ \brief The QMetaEnumBuilder class enables modifications to an enumerator definition on a meta object builder.
+*/
+
+QMetaEnumBuilderPrivate *QMetaEnumBuilder::d_func() const
+{
+ if (_mobj && _index >= 0 && _index < _mobj->d->enumerators.size())
+ return &(_mobj->d->enumerators[_index]);
+ else
+ return 0;
+}
+
+/*!
+ \fn QMetaEnumBuilder::QMetaEnumBuilder()
+ \internal
+*/
+
+/*!
+ \fn int QMetaEnumBuilder::index() const
+
+ Returns the index of this enumerator within its QMetaObjectBuilder.
+*/
+
+/*!
+ Returns the name of the enumerator (without the scope).
+*/
+QByteArray QMetaEnumBuilder::name() const
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d)
+ return d->name;
+ else
+ return QByteArray();
+}
+
+/*!
+ Returns true if this enumerator is used as a flag; otherwise returns
+ false.
+
+ \sa setIsFlag()
+*/
+bool QMetaEnumBuilder::isFlag() const
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d)
+ return d->isFlag;
+ else
+ return false;
+}
+
+/*!
+ Sets this enumerator to be used as a flag if \a value is true.
+
+ \sa isFlag()
+*/
+void QMetaEnumBuilder::setIsFlag(bool value)
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d)
+ d->isFlag = value;
+}
+
+/*!
+ Returns the number of keys.
+
+ \sa key(), addKey()
+*/
+int QMetaEnumBuilder::keyCount() const
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d)
+ return d->keys.size();
+ else
+ return 0;
+}
+
+/*!
+ Returns the key with the given \a index, or an empty QByteArray
+ if no such key exists.
+
+ \sa keyCount(), addKey(), value()
+*/
+QByteArray QMetaEnumBuilder::key(int index) const
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d && index >= 0 && index < d->keys.size())
+ return d->keys[index];
+ else
+ return QByteArray();
+}
+
+/*!
+ Returns the value with the given \a index; or returns -1 if there
+ is no such value.
+
+ \sa keyCount(), addKey(), key()
+*/
+int QMetaEnumBuilder::value(int index) const
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d && index >= 0 && index < d->keys.size())
+ return d->values[index];
+ else
+ return -1;
+}
+
+/*!
+ Adds a new key called \a name to this enumerator, associated
+ with \a value. Returns the index of the new key.
+
+ \sa keyCount(), key(), value(), removeKey()
+*/
+int QMetaEnumBuilder::addKey(const QByteArray& name, int value)
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d) {
+ int index = d->keys.size();
+ d->keys += name;
+ d->values += value;
+ return index;
+ } else {
+ return -1;
+ }
+}
+
+/*!
+ Removes the key at \a index from this enumerator.
+
+ \sa addKey()
+*/
+void QMetaEnumBuilder::removeKey(int index)
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d && index >= 0 && index < d->keys.size()) {
+ d->keys.removeAt(index);
+ d->values.removeAt(index);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmetaobjectbuilder_p.h b/src/declarative/qml/qmetaobjectbuilder_p.h
new file mode 100644
index 0000000..fc26c11
--- /dev/null
+++ b/src/declarative/qml/qmetaobjectbuilder_p.h
@@ -0,0 +1,321 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore 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 http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMETAOBJECTBUILDER_H
+#define QMETAOBJECTBUILDER_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of moc. This header file may change from version to version without notice,
+// or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qobject.h>
+#include <QtCore/qmetaobject.h>
+#include <QtCore/qdatastream.h>
+#include <QtCore/qmap.h>
+
+QT_BEGIN_NAMESPACE
+
+class QMetaObjectBuilderPrivate;
+class QMetaMethodBuilder;
+class QMetaMethodBuilderPrivate;
+class QMetaPropertyBuilder;
+class QMetaPropertyBuilderPrivate;
+class QMetaEnumBuilder;
+class QMetaEnumBuilderPrivate;
+
+class Q_DECLARATIVE_EXPORT QMetaObjectBuilder
+{
+public:
+ enum AddMember
+ {
+ ClassName = 0x00000001,
+ SuperClass = 0x00000002,
+ Methods = 0x00000004,
+ Signals = 0x00000008,
+ Slots = 0x00000010,
+ Constructors = 0x00000020,
+ Properties = 0x00000040,
+ Enumerators = 0x00000080,
+ ClassInfos = 0x00000100,
+ RelatedMetaObjects = 0x00000200,
+ StaticMetacall = 0x00000400,
+ PublicMethods = 0x00000800,
+ ProtectedMethods = 0x00001000,
+ PrivateMethods = 0x00002000,
+ AllMembers = 0x7FFFFFFF,
+ AllPrimaryMembers = 0x7FFFFBFC
+ };
+ Q_DECLARE_FLAGS(AddMembers, AddMember)
+
+ enum MetaObjectFlag {
+ DynamicMetaObject = 0x01
+ };
+ Q_DECLARE_FLAGS(MetaObjectFlags, MetaObjectFlag)
+
+ QMetaObjectBuilder();
+ explicit QMetaObjectBuilder(const QMetaObject *prototype, QMetaObjectBuilder::AddMembers members = AllMembers);
+ virtual ~QMetaObjectBuilder();
+
+ QByteArray className() const;
+ void setClassName(const QByteArray& name);
+
+ const QMetaObject *superClass() const;
+ void setSuperClass(const QMetaObject *meta);
+
+ MetaObjectFlags flags() const;
+ void setFlags(MetaObjectFlags);
+
+ int methodCount() const;
+ int constructorCount() const;
+ int propertyCount() const;
+ int enumeratorCount() const;
+ int classInfoCount() const;
+ int relatedMetaObjectCount() const;
+
+ QMetaMethodBuilder addMethod(const QByteArray& signature);
+ QMetaMethodBuilder addMethod(const QByteArray& signature, const QByteArray& returnType);
+ QMetaMethodBuilder addMethod(const QMetaMethod& prototype);
+
+ QMetaMethodBuilder addSlot(const QByteArray& signature);
+ QMetaMethodBuilder addSignal(const QByteArray& signature);
+
+ QMetaMethodBuilder addConstructor(const QByteArray& signature);
+ QMetaMethodBuilder addConstructor(const QMetaMethod& prototype);
+
+ QMetaPropertyBuilder addProperty(const QByteArray& name, const QByteArray& type, int notifierId=-1);
+ QMetaPropertyBuilder addProperty(const QMetaProperty& prototype);
+
+ QMetaEnumBuilder addEnumerator(const QByteArray& name);
+ QMetaEnumBuilder addEnumerator(const QMetaEnum& prototype);
+
+ int addClassInfo(const QByteArray& name, const QByteArray& value);
+
+#ifdef Q_NO_DATA_RELOCATION
+ int addRelatedMetaObject(const QMetaObjectAccessor &meta);
+#else
+ int addRelatedMetaObject(const QMetaObject *meta);
+#endif
+
+ void addMetaObject(const QMetaObject *prototype, QMetaObjectBuilder::AddMembers members = AllMembers);
+
+ QMetaMethodBuilder method(int index) const;
+ QMetaMethodBuilder constructor(int index) const;
+ QMetaPropertyBuilder property(int index) const;
+ QMetaEnumBuilder enumerator(int index) const;
+ const QMetaObject *relatedMetaObject(int index) const;
+
+ QByteArray classInfoName(int index) const;
+ QByteArray classInfoValue(int index) const;
+
+ void removeMethod(int index);
+ void removeConstructor(int index);
+ void removeProperty(int index);
+ void removeEnumerator(int index);
+ void removeClassInfo(int index);
+ void removeRelatedMetaObject(int index);
+
+ int indexOfMethod(const QByteArray& signature);
+ int indexOfSignal(const QByteArray& signature);
+ int indexOfSlot(const QByteArray& signature);
+ int indexOfConstructor(const QByteArray& signature);
+ int indexOfProperty(const QByteArray& name);
+ int indexOfEnumerator(const QByteArray& name);
+ int indexOfClassInfo(const QByteArray& name);
+
+ typedef int (*StaticMetacallFunction)(QMetaObject::Call, int, void **);
+
+ QMetaObjectBuilder::StaticMetacallFunction staticMetacallFunction() const;
+ void setStaticMetacallFunction(QMetaObjectBuilder::StaticMetacallFunction value);
+
+ QMetaObject *toMetaObject() const;
+ QByteArray toRelocatableData(bool * = 0) const;
+ static void fromRelocatableData(QMetaObject *, const QMetaObject *, const QByteArray &);
+
+#ifndef QT_NO_DATASTREAM
+ void serialize(QDataStream& stream) const;
+ void deserialize
+ (QDataStream& stream,
+ const QMap<QByteArray, const QMetaObject *>& references);
+#endif
+
+private:
+ Q_DISABLE_COPY(QMetaObjectBuilder)
+
+ QMetaObjectBuilderPrivate *d;
+
+ friend class QMetaMethodBuilder;
+ friend class QMetaPropertyBuilder;
+ friend class QMetaEnumBuilder;
+};
+
+class Q_DECLARATIVE_EXPORT QMetaMethodBuilder
+{
+public:
+ QMetaMethodBuilder() : _mobj(0), _index(0) {}
+
+ int index() const;
+
+ QMetaMethod::MethodType methodType() const;
+ QByteArray signature() const;
+
+ QByteArray returnType() const;
+ void setReturnType(const QByteArray& value);
+
+ QList<QByteArray> parameterNames() const;
+ void setParameterNames(const QList<QByteArray>& value);
+
+ QByteArray tag() const;
+ void setTag(const QByteArray& value);
+
+ QMetaMethod::Access access() const;
+ void setAccess(QMetaMethod::Access value);
+
+ int attributes() const;
+ void setAttributes(int value);
+
+private:
+ const QMetaObjectBuilder *_mobj;
+ int _index;
+
+ friend class QMetaObjectBuilder;
+ friend class QMetaPropertyBuilder;
+
+ QMetaMethodBuilder(const QMetaObjectBuilder *mobj, int index)
+ : _mobj(mobj), _index(index) {}
+
+ QMetaMethodBuilderPrivate *d_func() const;
+};
+
+class Q_DECLARATIVE_EXPORT QMetaPropertyBuilder
+{
+public:
+ QMetaPropertyBuilder() : _mobj(0), _index(0) {}
+
+ int index() const { return _index; }
+
+ QByteArray name() const;
+ QByteArray type() const;
+
+ bool hasNotifySignal() const;
+ QMetaMethodBuilder notifySignal() const;
+ void setNotifySignal(const QMetaMethodBuilder& value);
+ void removeNotifySignal();
+
+ bool isReadable() const;
+ bool isWritable() const;
+ bool isResettable() const;
+ bool isDesignable() const;
+ bool isScriptable() const;
+ bool isStored() const;
+ bool isEditable() const;
+ bool isUser() const;
+ bool hasStdCppSet() const;
+ bool isEnumOrFlag() const;
+ bool isDynamic() const;
+
+ void setReadable(bool value);
+ void setWritable(bool value);
+ void setResettable(bool value);
+ void setDesignable(bool value);
+ void setScriptable(bool value);
+ void setStored(bool value);
+ void setEditable(bool value);
+ void setUser(bool value);
+ void setStdCppSet(bool value);
+ void setEnumOrFlag(bool value);
+ void setDynamic(bool value);
+
+private:
+ const QMetaObjectBuilder *_mobj;
+ int _index;
+
+ friend class QMetaObjectBuilder;
+
+ QMetaPropertyBuilder(const QMetaObjectBuilder *mobj, int index)
+ : _mobj(mobj), _index(index) {}
+
+ QMetaPropertyBuilderPrivate *d_func() const;
+};
+
+class Q_DECLARATIVE_EXPORT QMetaEnumBuilder
+{
+public:
+ QMetaEnumBuilder() : _mobj(0), _index(0) {}
+
+ int index() const { return _index; }
+
+ QByteArray name() const;
+
+ bool isFlag() const;
+ void setIsFlag(bool value);
+
+ int keyCount() const;
+ QByteArray key(int index) const;
+ int value(int index) const;
+
+ int addKey(const QByteArray& name, int value);
+ void removeKey(int index);
+
+private:
+ const QMetaObjectBuilder *_mobj;
+ int _index;
+
+ friend class QMetaObjectBuilder;
+
+ QMetaEnumBuilder(const QMetaObjectBuilder *mobj, int index)
+ : _mobj(mobj), _index(index) {}
+
+ QMetaEnumBuilderPrivate *d_func() const;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QMetaObjectBuilder::AddMembers)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QMetaObjectBuilder::MetaObjectFlags)
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/declarative/qml/qml.h b/src/declarative/qml/qml.h
new file mode 100644
index 0000000..818b4e7
--- /dev/null
+++ b/src/declarative/qml/qml.h
@@ -0,0 +1,155 @@
+/****************************************************************************
+**
+** 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 QML_H
+#define QML_H
+
+#include <QtCore/qbytearray.h>
+#include <QtCore/qstringlist.h>
+#include <QtCore/qurl.h>
+#include <QtCore/qmetaobject.h>
+#include <QtDeclarative/qfxglobal.h>
+#include <QtDeclarative/qmlmetatype.h>
+#include <QtDeclarative/qmlmetaproperty.h>
+#include <QtDeclarative/qmlparserstatus.h>
+#include <QtDeclarative/qmlpropertyvaluesource.h>
+#include <QtDeclarative/qmllist.h>
+
+QT_BEGIN_HEADER
+
+QT_MODULE(Declarative)
+
+#define QML_DECLARE_TYPE(TYPE) \
+ Q_DECLARE_METATYPE(TYPE *) \
+ Q_DECLARE_METATYPE(QList<TYPE *> *) \
+ Q_DECLARE_METATYPE(QmlList<TYPE *> *)
+
+#define QML_DECLARE_TYPE_HASMETATYPE(TYPE) \
+ Q_DECLARE_METATYPE(QList<TYPE *> *) \
+ Q_DECLARE_METATYPE(QmlList<TYPE *> *)
+
+#define QML_DECLARE_INTERFACE(INTERFACE) \
+ QML_DECLARE_TYPE(INTERFACE)
+
+#define QML_DECLARE_INTERFACE_HASMETATYPE(INTERFACE) \
+ QML_DECLARE_TYPE_HASMETATYPE(INTERFACE)
+
+enum { /* TYPEINFO flags */
+ QML_HAS_ATTACHED_PROPERTIES = 0x01,
+};
+
+#define QML_DECLARE_TYPEINFO(TYPE, FLAGS) \
+template <> \
+class QmlTypeInfo<TYPE > \
+{ \
+public: \
+ enum { \
+ hasAttachedProperties = (((FLAGS) & QML_HAS_ATTACHED_PROPERTIES) == QML_HAS_ATTACHED_PROPERTIES) \
+ }; \
+};
+
+QT_BEGIN_NAMESPACE
+
+#if defined(Q_OS_SYMBIAN)
+#define QML_DEFINE_INTERFACE(INTERFACE) \
+ static int defineInterface##INTERFACE = qmlRegisterInterface<INTERFACE>(#INTERFACE);
+
+#define QML_DEFINE_EXTENDED_TYPE(URI, VERSION_MAJ, VERSION_MIN_FROM, VERSION_MIN_TO, NAME, TYPE, EXTENSION) \
+ static int registerExtended##TYPE = qmlRegisterExtendedType<TYPE,EXTENSION>(#URI, VERSION_MAJ, VERSION_MIN_FROM, VERSION_MIN_TO, #NAME, #TYPE);
+
+#define QML_DEFINE_TYPE(URI, VERSION_MAJ, VERSION_MIN_FROM, VERSION_MIN_TO, NAME, TYPE) \
+ static int defineType##TYPE = qmlRegisterType<TYPE>(#URI, VERSION_MAJ, VERSION_MIN_FROM, VERSION_MIN_TO, #NAME, #TYPE);
+
+#define QML_DEFINE_EXTENDED_NOCREATE_TYPE(TYPE, EXTENSION) \
+ static int registerExtendedNoCreate##TYPE = qmlRegisterExtendedType<TYPE,EXTENSION>(#TYPE);
+
+#define QML_DEFINE_NOCREATE_TYPE(TYPE) \
+ static int registerNoCreate##TYPE = qmlRegisterType<TYPE>(#TYPE);
+
+#else
+
+#define QML_DEFINE_INTERFACE(INTERFACE) \
+ template<> QmlPrivate::InstanceType QmlPrivate::Define<INTERFACE *,0,0,0>::instance(qmlRegisterInterface<INTERFACE>(#INTERFACE));
+
+#define QML_DEFINE_EXTENDED_TYPE(URI, VERSION_MAJ, VERSION_MIN_FROM, VERSION_MIN_TO, NAME, TYPE, EXTENSION) \
+ template<> QmlPrivate::InstanceType QmlPrivate::Define<TYPE *,(VERSION_MAJ), (VERSION_MIN_FROM), (VERSION_MIN_TO)>::instance(qmlRegisterExtendedType<TYPE,EXTENSION>(#URI, VERSION_MAJ, VERSION_MIN_FROM, VERSION_MIN_TO, #NAME, #TYPE));
+
+#define QML_DEFINE_TYPE(URI, VERSION_MAJ, VERSION_MIN_FROM, VERSION_MIN_TO, NAME, TYPE) \
+ template<> QmlPrivate::InstanceType QmlPrivate::Define<TYPE *,(VERSION_MAJ), (VERSION_MIN_FROM), (VERSION_MIN_TO)>::instance(qmlRegisterType<TYPE>(#URI, VERSION_MAJ, VERSION_MIN_FROM, VERSION_MIN_TO, #NAME, #TYPE));
+
+#define QML_DEFINE_EXTENDED_NOCREATE_TYPE(TYPE, EXTENSION) \
+ template<> QmlPrivate::InstanceType QmlPrivate::Define<TYPE *,0,0,0>::instance(qmlRegisterExtendedType<TYPE,EXTENSION>(#TYPE));
+
+#define QML_DEFINE_NOCREATE_TYPE(TYPE) \
+ template<> QmlPrivate::InstanceType QmlPrivate::Define<TYPE *,0,0,0>::instance(qmlRegisterType<TYPE>(#TYPE));
+
+#endif
+
+class QmlContext;
+class QmlEngine;
+Q_DECLARATIVE_EXPORT void qmlExecuteDeferred(QObject *);
+Q_DECLARATIVE_EXPORT QmlContext *qmlContext(const QObject *);
+Q_DECLARATIVE_EXPORT QmlEngine *qmlEngine(const QObject *);
+Q_DECLARATIVE_EXPORT QObject *qmlAttachedPropertiesObjectById(int, const QObject *, bool create = true);
+
+template<typename T>
+QObject *qmlAttachedPropertiesObject(const QObject *obj, bool create = true)
+{
+ // ### is this threadsafe?
+ static int idx = -1;
+
+ if (idx == -1)
+ idx = QmlMetaType::attachedPropertiesFuncId(&T::staticMetaObject);
+
+ if (idx == -1 || !obj)
+ return 0;
+
+ return qmlAttachedPropertiesObjectById(idx, obj, create);
+}
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QObject)
+Q_DECLARE_METATYPE(QVariant)
+
+QT_END_HEADER
+
+#endif // QML_H
diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri
new file mode 100644
index 0000000..cbc2f85
--- /dev/null
+++ b/src/declarative/qml/qml.pri
@@ -0,0 +1,121 @@
+SOURCES += qml/qmlparser.cpp \
+ qml/qmlinstruction.cpp \
+ qml/qmlvmemetaobject.cpp \
+ qml/qmlengine.cpp \
+ qml/qmlexpression.cpp \
+ qml/qmlbinding.cpp \
+ qml/qmlmetaproperty.cpp \
+ qml/qmlcomponentjs.cpp \
+ qml/qmlcomponent.cpp \
+ qml/qmlcontext.cpp \
+ qml/qmlcustomparser.cpp \
+ qml/qmlpropertyvaluesource.cpp \
+ qml/qmlpropertyvalueinterceptor.cpp \
+ qml/qmlproxymetaobject.cpp \
+ qml/qmlvme.cpp \
+ qml/qmlcompiler.cpp \
+ qml/qmlcompileddata.cpp \
+ qml/qmlboundsignal.cpp \
+ qml/qmldom.cpp \
+ qml/qmlrefcount.cpp \
+ qml/qmlprivate.cpp \
+ qml/qmlmetatype.cpp \
+ qml/qmlstringconverters.cpp \
+ qml/qmlclassfactory.cpp \
+ qml/qmlparserstatus.cpp \
+ qml/qmlcompositetypemanager.cpp \
+ qml/qmlinfo.cpp \
+ qml/qmlerror.cpp \
+ qml/qmlscriptparser.cpp \
+ qml/qmlenginedebug.cpp \
+ qml/qmlrewrite.cpp \
+ qml/qmlbasicscript.cpp \
+ qml/qmlvaluetype.cpp \
+ qml/qmlbindingoptimizations.cpp \
+ qml/qmlxmlhttprequest.cpp \
+ qml/qmlsqldatabase.cpp \
+ qml/qmetaobjectbuilder.cpp \
+ qml/qmlwatcher.cpp \
+ qml/qmlscript.cpp \
+ qml/qmlcleanup.cpp \
+ qml/qmlpropertycache.cpp \
+ qml/qmlintegercache.cpp \
+ qml/qmltypenamecache.cpp \
+ qml/qmlscriptstring.cpp \
+ qml/qmlobjectscriptclass.cpp \
+ qml/qmlcontextscriptclass.cpp \
+ qml/qmlglobalscriptclass.cpp \
+ qml/qmlvaluetypescriptclass.cpp \
+ qml/qmltypenamescriptclass.cpp \
+ qml/qmllistscriptclass.cpp
+
+HEADERS += qml/qmlparser_p.h \
+ qml/qmlinstruction_p.h \
+ qml/qmlvmemetaobject_p.h \
+ qml/qml.h \
+ qml/qmlbinding.h \
+ qml/qmlbinding_p.h \
+ qml/qmlmetaproperty.h \
+ qml/qmlcomponentjs_p.h \
+ qml/qmlcomponentjs_p_p.h \
+ qml/qmlcomponent.h \
+ qml/qmlcomponent_p.h \
+ qml/qmlcustomparser_p.h \
+ qml/qmlcustomparser_p_p.h \
+ qml/qmlpropertyvaluesource.h \
+ qml/qmlpropertyvalueinterceptor.h \
+ qml/qmlboundsignal_p.h \
+ qml/qmlparserstatus.h \
+ qml/qmlproxymetaobject_p.h \
+ qml/qmlvme_p.h \
+ qml/qmlcompiler_p.h \
+ qml/qmlengine_p.h \
+ qml/qmlexpression_p.h \
+ qml/qmlprivate.h \
+ qml/qmldom.h \
+ qml/qmldom_p.h \
+ qml/qmlrefcount_p.h \
+ qml/qmlmetatype.h \
+ qml/qmlengine.h \
+ qml/qmlcontext.h \
+ qml/qmlexpression.h \
+ qml/qmlstringconverters_p.h \
+ qml/qmlclassfactory_p.h \
+ qml/qmlinfo.h \
+ qml/qmlmetaproperty_p.h \
+ qml/qmlcontext_p.h \
+ qml/qmlcompositetypedata_p.h \
+ qml/qmlcompositetypemanager_p.h \
+ qml/qmllist.h \
+ qml/qmldeclarativedata_p.h \
+ qml/qmlerror.h \
+ qml/qmlscriptparser_p.h \
+ qml/qmlbasicscript_p.h \
+ qml/qmlenginedebug_p.h \
+ qml/qmlrewrite_p.h \
+ qml/qpodvector_p.h \
+ qml/qbitfield_p.h \
+ qml/qmlvaluetype_p.h \
+ qml/qmlbindingoptimizations_p.h \
+ qml/qmlxmlhttprequest_p.h \
+ qml/qmlsqldatabase_p.h \
+ qml/qmetaobjectbuilder_p.h \
+ qml/qmlwatcher_p.h \
+ qml/qmlcleanup_p.h \
+ qml/qmlpropertycache_p.h \
+ qml/qmlintegercache_p.h \
+ qml/qmltypenamecache_p.h \
+ qml/qmlscriptstring.h \
+ qml/qmlobjectscriptclass_p.h \
+ qml/qmlcontextscriptclass_p.h \
+ qml/qmlglobalscriptclass_p.h \
+ qml/qmlvaluetypescriptclass_p.h \
+ qml/qmltypenamescriptclass_p.h \
+ qml/qmllistscriptclass_p.h
+
+# for qtscript debugger
+contains(QT_CONFIG, scripttools):QT += scripttools
+
+include(parser/parser.pri)
+include(rewriter/rewriter.pri)
+
diff --git a/src/declarative/qml/qmlbasicscript.cpp b/src/declarative/qml/qmlbasicscript.cpp
new file mode 100644
index 0000000..b7aac54
--- /dev/null
+++ b/src/declarative/qml/qmlbasicscript.cpp
@@ -0,0 +1,763 @@
+/****************************************************************************
+**
+** 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 "qmlbasicscript_p.h"
+#include <QColor>
+#include <QDebug>
+#include <private/qmlengine_p.h>
+#include <private/qmlcontext_p.h>
+#include <QStack>
+#include <private/qfxperf_p.h>
+#include <private/qmlrefcount_p.h>
+#include <private/qmljsast_p.h>
+#include <private/qmljsengine_p.h>
+
+QT_BEGIN_NAMESPACE
+
+DEFINE_BOOL_CONFIG_OPTION(qmlBasicScriptDump, QML_BASICSCRIPT_DUMP);
+
+using namespace QmlJS;
+
+struct ScriptInstruction {
+ enum {
+ LoadIdObject, // fetch
+ FetchConstant, // constant
+ FetchContextConstant, // constant
+ FetchRootConstant, // constant
+
+ Equals, // NA
+
+ Int, // integer
+ Bool, // boolean
+ } type;
+
+ union {
+ struct {
+ int idx;
+ } fetch;
+ struct {
+ int value;
+ } integer;
+ struct {
+ bool value;
+ } boolean;
+ struct {
+ short idx;
+ short notify;
+ int type;
+ } constant;
+ };
+};
+
+class QmlBasicScriptPrivate
+{
+public:
+ enum Flags { OwnData = 0x00000001 };
+
+ int size;
+ int stateSize;
+ int instructionCount;
+ int exprLen;
+
+ ScriptInstruction *instructions() const { return (ScriptInstruction *)((char *)this + sizeof(QmlBasicScriptPrivate)); }
+
+ const char *expr() const
+ {
+ return (const char *)(instructions() + instructionCount);
+ }
+
+ const char *data() const
+ {
+ return (const char *)(instructions() + instructionCount) + exprLen + 1;
+ }
+
+ static unsigned int alignRound(int s)
+ {
+ if (s % 4)
+ s += 4 - (s % 4);
+ return s;
+ }
+};
+
+static QVariant fetch_value(QObject *o, int idx, int type)
+{
+ if (!o)
+ return QVariant();
+
+ switch(type) {
+ case QVariant::String:
+ {
+ QString val;
+ void *args[] = { &val, 0 };
+ QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args);
+ return QVariant(val);
+ }
+ break;
+ case QVariant::UInt:
+ {
+ uint val;
+ void *args[] = { &val, 0 };
+ QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args);
+ return QVariant(val);
+ }
+ break;
+ case QVariant::Int:
+ {
+ int val;
+ void *args[] = { &val, 0 };
+ QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args);
+ return QVariant(val);
+ }
+ break;
+ case QMetaType::Float:
+ {
+ float val;
+ void *args[] = { &val, 0 };
+ QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args);
+ return QVariant(val);
+ }
+ break;
+ case QVariant::Double:
+ {
+ double val;
+ void *args[] = { &val, 0 };
+ QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args);
+ return QVariant(val);
+ }
+ break;
+ case QVariant::Color:
+ {
+ QColor val;
+ void *args[] = { &val, 0 };
+ QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args);
+ return QVariant(val);
+ }
+ break;
+ case QVariant::Bool:
+ {
+ bool val;
+ void *args[] = { &val, 0 };
+ QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args);
+ return QVariant(val);
+ }
+ break;
+ default:
+ {
+ // If the object is null, we extract the predicted type. While this isn't
+ // 100% reliable, in many cases it gives us better error messages if we
+ // assign this null-object to an incompatible property
+ if (QmlMetaType::isObject(type)) {
+ // NOTE: This assumes a cast to QObject does not alter the
+ // object pointer
+ QObject *val = 0;
+ void *args[] = { &val, 0 };
+ QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args);
+ if (!val) return QVariant(type, &val);
+ else return QVariant::fromValue(val);
+ } else {
+ QVariant var = o->metaObject()->property(idx).read(o);
+ if (QmlMetaType::isObject(var.userType())) {
+ QObject *obj = 0;
+ obj = *(QObject **)var.data();
+ if (!obj) var = QVariant(var.userType(), &obj);
+ else var = QVariant::fromValue(obj);
+ }
+ return var;
+ }
+ }
+ break;
+ };
+}
+
+struct QmlBasicScriptCompiler
+{
+ QmlBasicScriptCompiler()
+ : script(0), stateSize(0) {}
+
+ QmlBasicScript *script;
+ int stateSize;
+
+ QmlParser::Object *context;
+ QmlParser::Object *component;
+ QHash<QString, QmlParser::Object *> ids;
+
+ bool compile(QmlJS::AST::Node *);
+
+ bool compileExpression(QmlJS::AST::Node *);
+
+ bool tryConstant(QmlJS::AST::Node *);
+ bool parseConstant(QmlJS::AST::Node *);
+ bool tryName(QmlJS::AST::Node *);
+ bool parseName(QmlJS::AST::Node *);
+
+ bool buildName(QStringList &, QmlJS::AST::Node *);
+ const QMetaObject *fetch(int type, const QMetaObject *, int idx);
+
+ bool tryBinaryExpression(QmlJS::AST::Node *);
+ bool compileBinaryExpression(QmlJS::AST::Node *);
+
+ QByteArray data;
+ QList<ScriptInstruction> bytecode;
+};
+
+/*!
+ \internal
+ \class QmlBasicScript
+ \brief The QmlBasicScript class provides a fast implementation of a limited subset of QmlJS bindings.
+
+ QmlBasicScript instances are used to accelerate binding. Instead of using
+ the slower, fully fledged QmlJS engine, many simple bindings can be
+ evaluated using the QmlBasicScript engine.
+
+ To see if the QmlBasicScript engine can handle a binding, call compile()
+ and check the return value, or isValid() afterwards.
+
+ To accelerate binding, QmlBasicScript can return a precompiled
+ version of itself that can be saved for future use. Call compileData() to
+ get an opaque pointer to the compiled state, and compileDataSize() for the
+ size of this data in bytes. This data can be saved and passed to future
+ instances of the QmlBasicScript constructor. The initial copy of compile
+ data is owned by the QmlBindScript instance on which compile() was called.
+*/
+
+/*!
+ Create a new QmlBasicScript instance.
+*/
+QmlBasicScript::QmlBasicScript()
+: flags(0), d(0), rc(0)
+{
+}
+
+/*!
+ Load the QmlBasicScript instance with saved \a data.
+
+ \a data \b must be data previously acquired from calling compileData() on a
+ previously created QmlBasicScript instance. Any other data will almost
+ certainly cause the QmlBasicScript engine to crash.
+
+ \a data must continue to be valid throughout the QmlBasicScript instance
+ life. It does not assume ownership of the memory.
+
+ If \a owner is set, it is referenced on creation and dereferenced on
+ destruction of this instance.
+*/
+
+void QmlBasicScript::load(const char *data, QmlRefCount *owner)
+{
+ clear();
+ d = (QmlBasicScriptPrivate *)data;
+ rc = owner;
+ if (rc) rc->addref();
+}
+
+/*!
+ Return the text of the script expression.
+ */
+QByteArray QmlBasicScript::expression() const
+{
+ if (!d)
+ return QByteArray();
+ else
+ return QByteArray(d->expr());
+}
+
+/*!
+ Destroy the script instance.
+*/
+QmlBasicScript::~QmlBasicScript()
+{
+ clear();
+}
+
+/*!
+ Clear this script. The object will then be in its initial state, as though
+ it were freshly constructed with default constructor.
+*/
+void QmlBasicScript::clear()
+{
+ if (flags & QmlBasicScriptPrivate::OwnData)
+ free(d);
+ if (rc) rc->release();
+ d = 0;
+ rc = 0;
+ flags = 0;
+}
+
+/*!
+ Dump the script instructions to stderr for debugging.
+ */
+void QmlBasicScript::dump()
+{
+ if (!d)
+ return;
+
+ qWarning() << d->instructionCount << "instructions:";
+ for (int ii = 0; ii < d->instructionCount; ++ii) {
+ const ScriptInstruction &instr = d->instructions()[ii];
+
+ switch(instr.type) {
+ case ScriptInstruction::LoadIdObject:
+ qWarning().nospace() << "LOAD_ID_OBJECT";
+ break;
+ case ScriptInstruction::FetchConstant:
+ qWarning().nospace() << "FETCH_CONSTANT";
+ break;
+ case ScriptInstruction::FetchContextConstant:
+ qWarning().nospace() << "FETCH_CONTEXT_CONSTANT";
+ break;
+ case ScriptInstruction::FetchRootConstant:
+ qWarning().nospace() << "FETCH_ROOT_CONSTANT";
+ break;
+ case ScriptInstruction::Equals:
+ qWarning().nospace() << "EQUALS";
+ break;
+ case ScriptInstruction::Int:
+ qWarning().nospace() << "INT\t\t" << instr.integer.value;
+ break;
+ case ScriptInstruction::Bool:
+ qWarning().nospace() << "BOOL\t\t" << instr.boolean.value;
+ break;
+ default:
+ qWarning().nospace() << "UNKNOWN";
+ break;
+ }
+ }
+}
+
+/*!
+ Return true if this is a valid script binding, otherwise returns false.
+ */
+bool QmlBasicScript::isValid() const
+{
+ return d != 0;
+}
+
+bool QmlBasicScript::compile(const Expression &expression)
+{
+ if (!expression.expression.asAST()) return false;
+
+ QByteArray expr = expression.expression.asScript().toUtf8();
+ const char *src = expr.constData();
+
+ QmlBasicScriptCompiler bsc;
+ bsc.script = this;
+ bsc.context = expression.context;
+ bsc.component = expression.component;
+ bsc.ids = expression.ids;
+
+ if (d) {
+ if (flags & QmlBasicScriptPrivate::OwnData)
+ free(d);
+ d = 0;
+ flags = 0;
+ }
+
+ if (bsc.compile(expression.expression.asAST())) {
+ int len = ::strlen(src);
+ flags = QmlBasicScriptPrivate::OwnData;
+ int size = sizeof(QmlBasicScriptPrivate) +
+ bsc.bytecode.count() * sizeof(ScriptInstruction) +
+ QmlBasicScriptPrivate::alignRound(bsc.data.count() + len + 1);
+ d = (QmlBasicScriptPrivate *) malloc(size);
+ d->size = size;
+ d->stateSize = bsc.stateSize;
+ d->instructionCount = bsc.bytecode.count();
+ d->exprLen = len;
+ ::memcpy((char *)d->expr(), src, len + 1);
+ for (int ii = 0; ii < d->instructionCount; ++ii)
+ d->instructions()[ii] = bsc.bytecode.at(ii);
+ ::memcpy((char *)d->data(), bsc.data.constData(), bsc.data.count());
+ }
+
+ if (d && qmlBasicScriptDump())
+ dump();
+ return d != 0;
+}
+
+bool QmlBasicScriptCompiler::compile(QmlJS::AST::Node *node)
+{
+ return compileExpression(node);
+}
+
+bool QmlBasicScriptCompiler::tryConstant(QmlJS::AST::Node *node)
+{
+ if (node->kind == AST::Node::Kind_TrueLiteral ||
+ node->kind == AST::Node::Kind_FalseLiteral)
+ return true;
+
+ if (node->kind == AST::Node::Kind_NumericLiteral) {
+ AST::NumericLiteral *lit = static_cast<AST::NumericLiteral *>(node);
+
+ return double(int(lit->value)) == lit->value;
+ }
+
+ return false;
+}
+
+bool QmlBasicScriptCompiler::parseConstant(QmlJS::AST::Node *node)
+{
+ ScriptInstruction instr;
+
+ if (node->kind == AST::Node::Kind_NumericLiteral) {
+ AST::NumericLiteral *lit = static_cast<AST::NumericLiteral *>(node);
+ instr.type = ScriptInstruction::Int;
+ instr.integer.value = int(lit->value);
+ } else {
+ instr.type = ScriptInstruction::Bool;
+ instr.boolean.value = node->kind == AST::Node::Kind_TrueLiteral;
+ }
+
+ bytecode.append(instr);
+
+ return true;
+}
+
+bool QmlBasicScriptCompiler::tryName(QmlJS::AST::Node *node)
+{
+ return node->kind == AST::Node::Kind_IdentifierExpression ||
+ node->kind == AST::Node::Kind_FieldMemberExpression;
+}
+
+bool QmlBasicScriptCompiler::buildName(QStringList &name,
+ QmlJS::AST::Node *node)
+{
+ if (node->kind == AST::Node::Kind_IdentifierExpression) {
+ name << static_cast<AST::IdentifierExpression*>(node)->name->asString();
+ } else if (node->kind == AST::Node::Kind_FieldMemberExpression) {
+ AST::FieldMemberExpression *expr =
+ static_cast<AST::FieldMemberExpression *>(node);
+
+ if (!buildName(name, expr->base))
+ return false;
+
+ name << expr->name->asString();
+ } else {
+ return false;
+ }
+
+ return true;
+}
+
+const QMetaObject *
+QmlBasicScriptCompiler::fetch(int type, const QMetaObject *mo, int idx)
+{
+ ScriptInstruction instr;
+ (int &)instr.type = type;
+ instr.constant.idx = idx;
+ QMetaProperty prop = mo->property(idx);
+ if (prop.isConstant())
+ instr.constant.notify = 0;
+ else
+ instr.constant.notify = prop.notifySignalIndex();
+ instr.constant.type = prop.userType();
+ bytecode << instr;
+ return QmlMetaType::metaObjectForType(prop.userType());
+}
+
+bool QmlBasicScriptCompiler::parseName(AST::Node *node)
+{
+ QStringList nameParts;
+ if (!buildName(nameParts, node))
+ return false;
+
+ QmlParser::Object *absType = 0;
+ const QMetaObject *metaType = 0;
+
+ for (int ii = 0; ii < nameParts.count(); ++ii) {
+ const QString &name = nameParts.at(ii);
+
+ // We don't handle signal properties
+ if (name.length() > 2 && name.startsWith(QLatin1String("on")) &&
+ name.at(2).isUpper())
+ return false;
+
+ if (ii == 0) {
+
+ if (0) {
+ // ### - Must test for an attached type name
+ } else if (ids.contains(name)) {
+ ScriptInstruction instr;
+ instr.type = ScriptInstruction::LoadIdObject;
+ instr.fetch.idx = ids.value(name)->idIndex;
+ bytecode << instr;
+ absType = ids.value(name);
+ } else if(name.at(0).isLower()) {
+
+ QByteArray utf8Name = name.toUtf8();
+ const char *cname = utf8Name.constData();
+
+ int d0Idx = context->metaObject()->indexOfProperty(cname);
+ int d1Idx = -1;
+ if (d0Idx == -1)
+ d1Idx = component->metaObject()->indexOfProperty(cname);
+
+ if (d0Idx != -1) {
+ metaType = fetch(ScriptInstruction::FetchContextConstant,
+ context->metaObject(), d0Idx);
+ } else if(d1Idx != -1) {
+ metaType = fetch(ScriptInstruction::FetchRootConstant,
+ component->metaObject(), d1Idx);
+ } else {
+ return false;
+ }
+
+ } else {
+ return false;
+ }
+ } else {
+
+ if (!name.at(0).isLower())
+ return false;
+
+ const QMetaObject *mo = 0;
+ if (absType)
+ mo = absType->metaObject();
+ else if(metaType)
+ mo = metaType;
+ else
+ return false;
+
+ QByteArray utf8Name = name.toUtf8();
+ const char *cname = utf8Name.constData();
+ int idx = mo->indexOfProperty(cname);
+ if (idx == -1)
+ return false;
+
+ if (absType || mo->property(idx).isFinal()) {
+ absType = 0; metaType = 0;
+ metaType = fetch(ScriptInstruction::FetchConstant, mo, idx);
+ } else {
+ return false;
+ }
+
+ }
+ }
+
+ return true;
+}
+
+bool QmlBasicScriptCompiler::compileExpression(QmlJS::AST::Node *node)
+{
+ if (tryBinaryExpression(node))
+ return compileBinaryExpression(node);
+ else if (tryConstant(node))
+ return parseConstant(node);
+ else if (tryName(node))
+ return parseName(node);
+ else
+ return false;
+}
+
+bool QmlBasicScriptCompiler::tryBinaryExpression(AST::Node *node)
+{
+ if (node->kind == AST::Node::Kind_BinaryExpression) {
+ AST::BinaryExpression *expr =
+ static_cast<AST::BinaryExpression *>(node);
+
+ if (expr->op == QSOperator::Equal)
+ return true;
+ }
+ return false;
+}
+
+bool QmlBasicScriptCompiler::compileBinaryExpression(AST::Node *node)
+{
+ if (node->kind == AST::Node::Kind_BinaryExpression) {
+ AST::BinaryExpression *expr =
+ static_cast<AST::BinaryExpression *>(node);
+
+ if (!compileExpression(expr->left)) return false;
+ if (!compileExpression(expr->right)) return false;
+
+ ScriptInstruction instr;
+ switch (expr->op) {
+ case QSOperator::Equal:
+ instr.type = ScriptInstruction::Equals;
+ break;
+ default:
+ return false;
+ }
+
+ bytecode.append(instr);
+ return true;
+ }
+ return false;
+}
+
+/*!
+ Run the script in \a context and return the result.
+ */
+QVariant QmlBasicScript::run(QmlContext *context, QObject *me)
+{
+ if (!isValid())
+ return QVariant();
+
+ QmlContextPrivate *contextPrivate = context->d_func();
+ QmlEnginePrivate *enginePrivate = QmlEnginePrivate::get(context->engine());
+
+ QStack<QVariant> stack;
+
+ for (int idx = 0; idx < d->instructionCount; ++idx) {
+ const ScriptInstruction &instr = d->instructions()[idx];
+
+ switch(instr.type) {
+ case ScriptInstruction::LoadIdObject:
+ {
+ stack.push(QVariant::fromValue(contextPrivate->idValues[instr.fetch.idx].data()));
+ enginePrivate->capturedProperties <<
+ QmlEnginePrivate::CapturedProperty(context, -1, contextPrivate->notifyIndex + instr.fetch.idx);
+ }
+ break;
+
+ case ScriptInstruction::FetchContextConstant:
+ {
+ stack.push(fetch_value(me, instr.constant.idx, instr.constant.type));
+ if (me && instr.constant.notify != 0)
+ enginePrivate->capturedProperties <<
+ QmlEnginePrivate::CapturedProperty(me, instr.constant.idx, instr.constant.notify);
+ }
+ break;
+
+ case ScriptInstruction::FetchRootConstant:
+ {
+ QObject *obj = contextPrivate->defaultObjects.last();
+
+ stack.push(fetch_value(obj, instr.constant.idx, instr.constant.type));
+ if (obj && instr.constant.notify != 0)
+ enginePrivate->capturedProperties <<
+ QmlEnginePrivate::CapturedProperty(obj, instr.constant.idx, instr.constant.notify);
+ }
+ break;
+
+ case ScriptInstruction::FetchConstant:
+ {
+ QVariant o = stack.pop();
+ QObject *obj = *(QObject **)o.constData();
+
+ stack.push(fetch_value(obj, instr.constant.idx, instr.constant.type));
+ if (obj && instr.constant.notify != 0)
+ enginePrivate->capturedProperties <<
+ QmlEnginePrivate::CapturedProperty(obj, instr.constant.idx, instr.constant.notify);
+ }
+ break;
+
+ case ScriptInstruction::Int:
+ stack.push(QVariant(instr.integer.value));
+ break;
+
+ case ScriptInstruction::Bool:
+ stack.push(QVariant(instr.boolean.value));
+ break;
+
+ case ScriptInstruction::Equals:
+ {
+ QVariant rhs = stack.pop();
+ QVariant lhs = stack.pop();
+
+ stack.push(rhs == lhs);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (stack.isEmpty())
+ return QVariant();
+ else
+ return stack.top();
+}
+
+bool QmlBasicScript::isSingleIdFetch() const
+{
+ if (!isValid())
+ return false;
+
+ return d->instructionCount == 1 &&
+ d->instructions()[0].type == ScriptInstruction::LoadIdObject;
+}
+
+int QmlBasicScript::singleIdFetchIndex() const
+{
+ if (!isSingleIdFetch())
+ return -1;
+
+ return d->instructions()[0].fetch.idx;
+}
+
+bool QmlBasicScript::isSingleContextProperty() const
+{
+ if (!isValid())
+ return false;
+
+ return d->instructionCount == 1 &&
+ d->instructions()[0].type == ScriptInstruction::FetchContextConstant;
+}
+
+int QmlBasicScript::singleContextPropertyIndex() const
+{
+ if (!isSingleContextProperty())
+ return -1;
+
+ return d->instructions()[0].constant.idx;
+}
+
+/*!
+ Return a pointer to the script's compile data, or null if there is no data.
+ */
+const char *QmlBasicScript::compileData() const
+{
+ return (const char *)d;
+}
+
+/*!
+ Return the size of the script's compile data, or zero if there is no data.
+ The size will always be a multiple of 4.
+ */
+unsigned int QmlBasicScript::compileDataSize() const
+{
+ if (d)
+ return d->size;
+ else
+ return 0;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlbasicscript_p.h b/src/declarative/qml/qmlbasicscript_p.h
new file mode 100644
index 0000000..5ad7735
--- /dev/null
+++ b/src/declarative/qml/qmlbasicscript_p.h
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** 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 QMLBASICSCRIPT_P_H
+#define QMLBASICSCRIPT_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/QList>
+#include <QtCore/QByteArray>
+#include <QtCore/QVariant>
+#include <private/qmlparser_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QmlRefCount;
+class QmlContext;
+class QmlBasicScriptPrivate;
+class QmlBasicScriptNodeCache;
+class QmlBasicScript
+{
+public:
+ QmlBasicScript();
+ ~QmlBasicScript();
+
+ void load(const char *, QmlRefCount * = 0);
+
+ // Always 4-byte aligned
+ const char *compileData() const;
+ unsigned int compileDataSize() const;
+
+ QByteArray expression() const;
+
+ struct Expression
+ {
+ QmlParser::Object *component;
+ QmlParser::Object *context;
+ QmlParser::Property *property;
+ QmlParser::Variant expression;
+ QHash<QString, QmlParser::Object *> ids;
+ };
+
+ bool compile(const Expression &);
+ bool isValid() const;
+
+ void clear();
+
+ void dump();
+
+ QVariant run(QmlContext *, QObject *);
+
+ bool isSingleIdFetch() const;
+ int singleIdFetchIndex() const;
+
+ bool isSingleContextProperty() const;
+ int singleContextPropertyIndex() const;
+private:
+ int flags;
+ QmlBasicScriptPrivate *d;
+ QmlRefCount *rc;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLBASICSCRIPT_P_H
diff --git a/src/declarative/qml/qmlbinding.cpp b/src/declarative/qml/qmlbinding.cpp
new file mode 100644
index 0000000..65ff789
--- /dev/null
+++ b/src/declarative/qml/qmlbinding.cpp
@@ -0,0 +1,251 @@
+/****************************************************************************
+**
+** 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 <qml.h>
+#include "qmlbinding.h"
+#include "qmlbinding_p.h"
+#include <qmlcontext.h>
+#include <qmlinfo.h>
+#include <QVariant>
+#include <private/qfxperf_p.h>
+#include <QtCore/qdebug.h>
+#include <private/qmlcontext_p.h>
+#include <private/qmldeclarativedata_p.h>
+#include <private/qmlstringconverters_p.h>
+
+Q_DECLARE_METATYPE(QList<QObject *>);
+
+QT_BEGIN_NAMESPACE
+
+QML_DEFINE_NOCREATE_TYPE(QmlBinding);
+
+QmlBindingData::QmlBindingData()
+: updating(false), enabled(false)
+{
+}
+
+QmlBindingPrivate::QmlBindingPrivate()
+: QmlExpressionPrivate(new QmlBindingData)
+{
+}
+
+QmlBinding::QmlBinding(void *data, QmlRefCount *rc, QObject *obj, QmlContext *ctxt, const QUrl &url, int lineNumber, QObject *parent)
+: QmlExpression(ctxt, data, rc, obj, url, lineNumber, *new QmlBindingPrivate)
+{
+ setParent(parent);
+}
+
+QmlBinding::QmlBinding(const QString &str, QObject *obj, QmlContext *ctxt, QObject *parent)
+: QmlExpression(ctxt, str, obj, *new QmlBindingPrivate)
+{
+ setParent(parent);
+}
+
+QmlBinding::~QmlBinding()
+{
+}
+
+void QmlBinding::setTarget(const QmlMetaProperty &prop)
+{
+ Q_D(QmlBinding);
+ d->bindingData()->property = prop;
+
+ update();
+}
+
+QmlMetaProperty QmlBinding::property() const
+{
+ Q_D(const QmlBinding);
+ return d->bindingData()->property;
+}
+
+void QmlBinding::update(QmlMetaProperty::WriteFlags flags)
+{
+ Q_D(QmlBinding);
+
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::BindableValueUpdate> bu;
+#endif
+ QmlBindingData *data = d->bindingData();
+
+ if (!data->enabled)
+ return;
+
+ data->addref();
+
+ if (!data->updating) {
+ data->updating = true;
+
+ if (data->property.propertyCategory() == QmlMetaProperty::Bindable) {
+
+ int idx = data->property.coreIndex();
+ Q_ASSERT(idx != -1);
+
+
+ QmlBinding *t = this;
+ int status = -1;
+ void *a[] = { &t, 0, &status, &flags };
+ QMetaObject::metacall(data->property.object(),
+ QMetaObject::WriteProperty,
+ idx, a);
+
+ } else {
+ bool undefined = false;
+ QVariant value = this->value(&undefined);
+
+ if (!undefined && data->property.object() && !data->property.write(value, flags)) {
+ QString fileName = data->fileName;
+ int line = data->line;
+ if (fileName.isEmpty()) fileName = QLatin1String("<Unknown File>");
+
+ const char *valueType = 0;
+ if (value.userType() == QVariant::Invalid) valueType = "null";
+ else valueType = QMetaType::typeName(value.userType());
+ qWarning().nospace() << qPrintable(fileName) << ":" << line
+ << " Unable to assign " << valueType << " to "
+ << QMetaType::typeName(data->property.propertyType());
+ }
+ }
+
+ data->updating = false;
+ } else {
+ qmlInfo(tr("Binding loop detected for property \"%1\"").arg(data->property.name()), data->property.object());
+ }
+
+ data->release();
+}
+
+void QmlBinding::valueChanged()
+{
+ update();
+}
+
+void QmlBinding::setEnabled(bool e, QmlMetaProperty::WriteFlags flags)
+{
+ Q_D(QmlBinding);
+ d->bindingData()->enabled = e;
+ setTrackChange(e);
+
+ QmlAbstractBinding::setEnabled(e, flags);
+
+ if (e) {
+ addToObject(d->bindingData()->property.object());
+ update(flags);
+ } else {
+ removeFromObject();
+ }
+}
+
+int QmlBinding::propertyIndex()
+{
+ Q_D(QmlBinding);
+ return d->bindingData()->property.coreIndex();
+}
+
+bool QmlBinding::enabled() const
+{
+ Q_D(const QmlBinding);
+
+ return d->bindingData()->enabled;
+}
+
+QString QmlBinding::expression() const
+{
+ return QmlExpression::expression();
+}
+
+QmlAbstractBinding::QmlAbstractBinding()
+: m_object(0), m_mePtr(0), m_prevBinding(0), m_nextBinding(0)
+{
+}
+
+QmlAbstractBinding::~QmlAbstractBinding()
+{
+ removeFromObject();
+ if (m_mePtr)
+ *m_mePtr = 0;
+}
+
+void QmlAbstractBinding::addToObject(QObject *object)
+{
+ Q_ASSERT(object);
+
+ removeFromObject();
+
+ Q_ASSERT(!m_prevBinding);
+
+ QmlDeclarativeData *data = QmlDeclarativeData::get(object, true);
+ m_nextBinding = data->bindings;
+ if (m_nextBinding) m_nextBinding->m_prevBinding = &m_nextBinding;
+ m_prevBinding = &data->bindings;
+ data->bindings = this;
+ m_object = object;
+
+ data->setBindingBit(m_object, propertyIndex());
+}
+
+void QmlAbstractBinding::removeFromObject()
+{
+ if (m_prevBinding) {
+ Q_ASSERT(m_object);
+
+ *m_prevBinding = m_nextBinding;
+ if (m_nextBinding) m_nextBinding->m_prevBinding = m_prevBinding;
+ m_prevBinding = 0;
+ m_nextBinding = 0;
+
+ QmlDeclarativeData *data = QmlDeclarativeData::get(m_object, false);
+ if (data) data->clearBindingBit(propertyIndex());
+ m_object = 0;
+ }
+}
+
+QString QmlAbstractBinding::expression() const
+{
+ return QLatin1String("<Unknown>");
+}
+
+void QmlAbstractBinding::setEnabled(bool e, QmlMetaProperty::WriteFlags)
+{
+ if (e) m_mePtr = 0;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlbinding.h b/src/declarative/qml/qmlbinding.h
new file mode 100644
index 0000000..6a3e92a
--- /dev/null
+++ b/src/declarative/qml/qmlbinding.h
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** 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 QMLBINDING_H
+#define QMLBINDING_H
+
+#include <QtCore/QObject>
+#include <QtDeclarative/qfxglobal.h>
+#include <QtDeclarative/qml.h>
+#include <QtDeclarative/qmlpropertyvaluesource.h>
+#include <QtDeclarative/qmlexpression.h>
+#include <QtCore/QMetaProperty>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlAbstractBinding
+{
+public:
+ QmlAbstractBinding();
+ virtual ~QmlAbstractBinding();
+
+ virtual QString expression() const;
+
+ void setEnabled(bool e) { setEnabled(e, QmlMetaProperty::DontRemoveBinding); }
+ virtual void setEnabled(bool, QmlMetaProperty::WriteFlags) = 0;
+ virtual int propertyIndex() = 0;
+
+ void update() { update(QmlMetaProperty::DontRemoveBinding); }
+ virtual void update(QmlMetaProperty::WriteFlags) = 0;
+
+ void addToObject(QObject *);
+ void removeFromObject();
+
+private:
+ friend class QmlDeclarativeData;
+ friend class QmlMetaProperty;
+ friend class QmlMetaPropertyPrivate;
+ friend class QmlVME;
+
+ QObject *m_object;
+ QmlAbstractBinding **m_mePtr;
+ QmlAbstractBinding **m_prevBinding;
+ QmlAbstractBinding *m_nextBinding;
+};
+
+class QmlContext;
+class QmlBindingPrivate;
+class Q_DECLARATIVE_EXPORT QmlBinding : public QmlExpression,
+ public QmlAbstractBinding
+{
+Q_OBJECT
+public:
+ QmlBinding(const QString &, QObject *, QmlContext *, QObject *parent=0);
+ QmlBinding(void *, QmlRefCount *, QObject *, QmlContext *, const QUrl &, int,
+ QObject *parent);
+ ~QmlBinding();
+
+ void setTarget(const QmlMetaProperty &);
+ QmlMetaProperty property() const;
+
+ bool enabled() const;
+
+ // Inherited from QmlAbstractBinding
+ virtual void setEnabled(bool, QmlMetaProperty::WriteFlags flags);
+ virtual int propertyIndex();
+ virtual void update(QmlMetaProperty::WriteFlags flags);
+ virtual QString expression() const;
+
+public Q_SLOTS:
+ void update() { update(QmlMetaProperty::DontRemoveBinding); }
+
+protected:
+ virtual void valueChanged();
+
+private:
+ Q_DECLARE_PRIVATE(QmlBinding)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlBinding);
+
+QT_END_HEADER
+
+#endif // QMLBINDING_H
diff --git a/src/declarative/qml/qmlbinding_p.h b/src/declarative/qml/qmlbinding_p.h
new file mode 100644
index 0000000..2c0c6b9
--- /dev/null
+++ b/src/declarative/qml/qmlbinding_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** 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 QMLBINDING_P_H
+#define QMLBINDING_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 <QtDeclarative/qmlbinding.h>
+#include <QtDeclarative/qmlmetaproperty.h>
+#include "qmlexpression_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QmlBindingData : public QmlExpressionData
+{
+public:
+ QmlBindingData();
+
+ bool updating:1;
+ bool enabled:1;
+
+ 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/qmlbindingoptimizations.cpp b/src/declarative/qml/qmlbindingoptimizations.cpp
new file mode 100644
index 0000000..6dc221e
--- /dev/null
+++ b/src/declarative/qml/qmlbindingoptimizations.cpp
@@ -0,0 +1,205 @@
+/****************************************************************************
+**
+** 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 "qmlbindingoptimizations_p.h"
+#include <private/qmlcontext_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*
+ The QmlBinding_Id optimization handles expressions of the type:
+
+ property: id
+
+ where id is a local context id, and property is an object property.
+ Coercian between id and property must be checked outside the QmlBinding_Id -
+ it assumes that they coerce successfully.
+
+ The QmlBinding_Id class avoids any signal slot connections, through the
+ special "bindings" linked list maintained in the
+ QmlContextPrivate::ContextGuard instance for each id object.
+*/
+QmlBinding_Id::QmlBinding_Id(QObject *object, int propertyIdx,
+ QmlContext *context, int id)
+: m_prev(0), m_next(0), m_object(object), m_propertyIdx(propertyIdx), m_id(id)
+{
+ QmlAbstractExpression::setContext(context);
+}
+
+QmlBinding_Id::~QmlBinding_Id()
+{
+ removeFromContext();
+}
+
+void QmlBinding_Id::setEnabled(bool e, QmlMetaProperty::WriteFlags flags)
+{
+ if (e) {
+ addToObject(m_object);
+ update(flags);
+ } else {
+ removeFromObject();
+ }
+
+ QmlAbstractBinding::setEnabled(e, flags);
+}
+
+int QmlBinding_Id::propertyIndex()
+{
+ return m_propertyIdx;
+}
+
+void QmlBinding_Id::update(QmlMetaProperty::WriteFlags flags)
+{
+ QmlContextPrivate *ctxtPriv =
+ static_cast<QmlContextPrivate *>(QObjectPrivate::get(context()));
+
+ if (ctxtPriv) {
+
+ if (!m_prev) {
+ m_next = ctxtPriv->idValues[m_id].bindings;
+ if (m_next) m_next->m_prev = &m_next;
+
+ m_prev = &ctxtPriv->idValues[m_id].bindings;
+ ctxtPriv->idValues[m_id].bindings = this;
+ }
+
+ QObject *o = ctxtPriv->idValues[m_id].data();
+ int status = -1;
+ void *a[] = { &o, 0, &status, &flags };
+ QMetaObject::metacall(m_object, QMetaObject::WriteProperty,
+ m_propertyIdx, a);
+ }
+}
+
+void QmlBinding_Id::removeFromContext()
+{
+ if (m_prev) {
+ *m_prev = m_next;
+ if (m_next) m_next->m_prev = m_prev;
+ m_next = 0;
+ m_prev = 0;
+ }
+}
+
+void QmlBinding_Id::reset()
+{
+ removeFromContext();
+
+ QObject *o = 0;
+ int status = -1;
+ QmlMetaProperty::WriteFlags flags = QmlMetaProperty::DontRemoveBinding;
+ void *a[] = { &o, 0, &status, &flags };
+ QMetaObject::metacall(m_object, QMetaObject::WriteProperty,
+ m_propertyIdx, a);
+}
+
+/*
+ The QmlBinding_ObjectProperty optimization handles expressions of the type:
+
+ property: objectProperty
+
+ where both property and objectProperty are object properties on the target
+ object. Coercian between the two must be checked outside the
+ QmlBinding_ObjectProperty - it assumes that they coerce successfully.
+
+ Due to dot properties, property does not have to be on the same object as
+ objectProperty. For example:
+
+ anchors.fill: parent
+*/
+QmlBinding_ObjProperty::QmlBinding_ObjProperty(QObject *object, int propertyIdx,
+ QObject *context, int contextIdx,
+ int notifyIdx)
+: m_enabled(false), m_object(object), m_propertyIdx(propertyIdx),
+ m_context(context), m_contextIdx(contextIdx), m_notifyIdx(notifyIdx)
+{
+}
+
+void QmlBinding_ObjProperty::setEnabled(bool e, QmlMetaProperty::WriteFlags flags)
+{
+ m_enabled = e;
+ if (e) {
+ addToObject(m_object);
+ update(flags);
+ } else {
+ removeFromObject();
+ }
+
+ QmlAbstractBinding::setEnabled(e, flags);
+}
+
+int QmlBinding_ObjProperty::propertyIndex()
+{
+ return m_propertyIdx;
+}
+
+void QmlBinding_ObjProperty::update(QmlMetaProperty::WriteFlags flags)
+{
+ if (!m_enabled)
+ return;
+
+ QObject *value = 0;
+ int status = -1;
+ void *ra[] = { &value, 0, &status };
+
+ // Read
+ QMetaObject::metacall(m_context, QMetaObject::ReadProperty,
+ m_contextIdx, ra);
+
+ void *wa[] = { &value, 0, &status, &flags };
+
+ // Write
+ QMetaObject::metacall(m_object, QMetaObject::WriteProperty,
+ m_propertyIdx, wa);
+
+ // Connect notify if needed. Only need to connect once, so we set
+ // m_notifyIdx back to -1 afterwards
+ static int slotIdx = -1;
+ if (m_notifyIdx != -1) {
+ if (slotIdx == -1)
+ slotIdx = QmlBinding_ObjProperty::staticMetaObject.indexOfMethod("update()");
+
+ QMetaObject::connect(m_context, m_notifyIdx, this, slotIdx);
+ m_notifyIdx = -1;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlbindingoptimizations_p.h b/src/declarative/qml/qmlbindingoptimizations_p.h
new file mode 100644
index 0000000..d0a4df4
--- /dev/null
+++ b/src/declarative/qml/qmlbindingoptimizations_p.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** 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 QMLBINDINGOPTIMIZATIONS_P_H
+#define QMLBINDINGOPTIMIZATIONS_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/qmlexpression_p.h>
+#include <QtDeclarative/qmlbinding.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QmlBinding_Id : public QmlAbstractExpression,
+ public QmlAbstractBinding
+{
+public:
+ QmlBinding_Id(QObject *object, int propertyIdx,
+ QmlContext *context, int id);
+ virtual ~QmlBinding_Id();
+
+ // Inherited from QmlAbstractBinding
+ virtual void setEnabled(bool, QmlMetaProperty::WriteFlags flags);
+ virtual int propertyIndex();
+ virtual void update(QmlMetaProperty::WriteFlags flags);
+
+ void reset();
+
+private:
+ void removeFromContext();
+
+ QmlBinding_Id **m_prev;
+ QmlBinding_Id *m_next;
+
+ QObject *m_object;
+ int m_propertyIdx;
+ int m_id;
+};
+
+class QmlBinding_ObjProperty : public QObject,
+ public QmlAbstractExpression,
+ public QmlAbstractBinding
+{
+ Q_OBJECT
+public:
+ QmlBinding_ObjProperty(QObject *object, int propertyIdx,
+ QObject *context, int contextIdx, int notifyIdx);
+
+ // Inherited from QmlAbstractBinding
+ virtual void setEnabled(bool, QmlMetaProperty::WriteFlags flags);
+ virtual int propertyIndex();
+ virtual void update(QmlMetaProperty::WriteFlags flags);
+
+private Q_SLOTS:
+ void update() { update(QmlMetaProperty::DontRemoveBinding); }
+
+private:
+ bool m_enabled;
+ QObject *m_object;
+ int m_propertyIdx;
+ QObject *m_context;
+ int m_contextIdx;
+ int m_notifyIdx;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLBINDINGOPTIMIZATIONS_P_H
+
diff --git a/src/declarative/qml/qmlboundsignal.cpp b/src/declarative/qml/qmlboundsignal.cpp
new file mode 100644
index 0000000..ce591e8
--- /dev/null
+++ b/src/declarative/qml/qmlboundsignal.cpp
@@ -0,0 +1,259 @@
+/****************************************************************************
+**
+** 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 "qmlboundsignal_p.h"
+#include "private/qmetaobjectbuilder_p.h"
+#include "private/qmlengine_p.h"
+#include "private/qmlexpression_p.h"
+#include "private/qmlcontext_p.h"
+#include <qfxglobal.h>
+#include <qmlmetatype.h>
+#include <qml.h>
+#include <qmlcontext.h>
+#include <QDebug>
+
+QT_BEGIN_NAMESPACE
+
+class QmlBoundSignalParameters : public QObject
+{
+Q_OBJECT
+public:
+ QmlBoundSignalParameters(const QMetaMethod &, QObject * = 0);
+ ~QmlBoundSignalParameters();
+
+ void setValues(void **);
+ void clearValues();
+
+private:
+ friend class MetaObject;
+ int metaCall(QMetaObject::Call, int _id, void **);
+ struct MetaObject : public QAbstractDynamicMetaObject {
+ MetaObject(QmlBoundSignalParameters *b)
+ : parent(b) {}
+
+ int metaCall(QMetaObject::Call c, int id, void **a) {
+ return parent->metaCall(c, id, a);
+ }
+ QmlBoundSignalParameters *parent;
+ };
+
+ int *types;
+ void **values;
+ QMetaObject *myMetaObject;
+};
+
+static int evaluateIdx = -1;
+
+QmlAbstractBoundSignal::QmlAbstractBoundSignal(QObject *parent)
+: QObject(parent)
+{
+}
+
+QmlAbstractBoundSignal::~QmlAbstractBoundSignal()
+{
+}
+
+QmlBoundSignal::QmlBoundSignal(QObject *scope, const QMetaMethod &signal,
+ QObject *parent)
+: m_expression(0), m_idx(signal.methodIndex()), m_params(0)
+{
+ // A cached evaluation of the QmlExpression::value() slot index.
+ //
+ // This is thread safe. Although it may be updated by two threads, they
+ // will both set it to the same value - so the worst thing that can happen
+ // is that they both do the work to figure it out. Boo hoo.
+ if (evaluateIdx == -1) evaluateIdx = metaObject()->methodCount();
+
+ QFx_setParent_noEvent(this, parent);
+ QMetaObject::connect(scope, m_idx, this, evaluateIdx);
+
+ if (!signal.parameterTypes().isEmpty())
+ m_params = new QmlBoundSignalParameters(signal, this);
+}
+
+QmlBoundSignal::QmlBoundSignal(QmlContext *ctxt, const QString &val,
+ QObject *scope, const QMetaMethod &signal,
+ QObject *parent)
+: m_expression(0), m_idx(signal.methodIndex()), m_params(0)
+{
+ // A cached evaluation of the QmlExpression::value() slot index.
+ //
+ // This is thread safe. Although it may be updated by two threads, they
+ // will both set it to the same value - so the worst thing that can happen
+ // is that they both do the work to figure it out. Boo hoo.
+ if (evaluateIdx == -1) evaluateIdx = metaObject()->methodCount();
+
+ QFx_setParent_noEvent(this, parent);
+ QMetaObject::connect(scope, m_idx, this, evaluateIdx);
+
+ m_expression = new QmlExpression(ctxt, val, scope);
+ m_expression->setTrackChange(false);
+
+ if (!signal.parameterTypes().isEmpty())
+ m_params = new QmlBoundSignalParameters(signal, this);
+}
+
+QmlBoundSignal::~QmlBoundSignal()
+{
+ delete m_expression;
+ m_expression = 0;
+}
+
+int QmlBoundSignal::index() const
+{
+ return m_idx;
+}
+
+/*!
+ Returns the signal expression.
+*/
+QmlExpression *QmlBoundSignal::expression() const
+{
+ return m_expression;
+}
+
+/*!
+ Sets the signal expression to \a e. Returns the current signal expression,
+ or null if there is no signal expression.
+
+ The QmlBoundSignal instance takes ownership of \a e. The caller is
+ assumes ownership of the returned QmlExpression.
+*/
+QmlExpression *QmlBoundSignal::setExpression(QmlExpression *e)
+{
+ QmlExpression *rv = m_expression;
+ m_expression = e;
+ if (m_expression) m_expression->setTrackChange(false);
+ return rv;
+}
+
+QmlBoundSignal *QmlBoundSignal::cast(QObject *o)
+{
+ QmlAbstractBoundSignal *s = qobject_cast<QmlAbstractBoundSignal*>(o);
+ return static_cast<QmlBoundSignal *>(s);
+}
+
+int QmlBoundSignal::qt_metacall(QMetaObject::Call c, int id, void **a)
+{
+ if (c == QMetaObject::InvokeMetaMethod && id == evaluateIdx) {
+ if (m_params) m_params->setValues(a);
+ if (m_expression)
+ QmlExpressionPrivate::get(m_expression)->value(m_params);
+ if (m_params) m_params->clearValues();
+ return -1;
+ } else {
+ return QObject::qt_metacall(c, id, a);
+ }
+}
+
+QmlBoundSignalParameters::QmlBoundSignalParameters(const QMetaMethod &method,
+ QObject *parent)
+: QObject(parent), types(0), values(0)
+{
+ MetaObject *mo = new MetaObject(this);
+
+ // ### Optimize!
+ // ### Ensure only supported types are allowed, otherwise it might crash
+ QMetaObjectBuilder mob;
+ mob.setSuperClass(&QmlBoundSignalParameters::staticMetaObject);
+ mob.setClassName("QmlBoundSignalParameters");
+
+ QList<QByteArray> paramTypes = method.parameterTypes();
+ QList<QByteArray> paramNames = method.parameterNames();
+ types = new int[paramTypes.count()];
+ for (int ii = 0; ii < paramTypes.count(); ++ii) {
+ const QByteArray &type = paramTypes.at(ii);
+ const QByteArray &name = paramNames.at(ii);
+
+ if (name.isEmpty() || type.isEmpty()) {
+ types[ii] = 0;
+ continue;
+ }
+
+ QVariant::Type t = (QVariant::Type)QMetaType::type(type.constData());
+ if (QmlMetaType::isObject(t)) {
+ types[ii] = QMetaType::QObjectStar;
+ QMetaPropertyBuilder prop = mob.addProperty(name, "QObject*");
+ prop.setWritable(false);
+ } else {
+ types[ii] = t;
+ QMetaPropertyBuilder prop = mob.addProperty(name, type);
+ prop.setWritable(false);
+ }
+ }
+ myMetaObject = mob.toMetaObject();
+ *static_cast<QMetaObject *>(mo) = *myMetaObject;
+
+ d_ptr->metaObject = mo;
+}
+
+QmlBoundSignalParameters::~QmlBoundSignalParameters()
+{
+ delete [] types;
+ qFree(myMetaObject);
+}
+
+void QmlBoundSignalParameters::setValues(void **v)
+{
+ values = v;
+}
+
+void QmlBoundSignalParameters::clearValues()
+{
+ values = 0;
+}
+
+int QmlBoundSignalParameters::metaCall(QMetaObject::Call c, int id, void **a)
+{
+ if (!values)
+ return -1;
+
+ if (c == QMetaObject::ReadProperty && id >= 1) {
+ QmlMetaType::copy(types[id - 1], a[0], values[id]);
+ return -1;
+ } else {
+ return qt_metacall(c, id, a);
+ }
+}
+
+QT_END_NAMESPACE
+
+#include "qmlboundsignal.moc"
diff --git a/src/declarative/qml/qmlboundsignal_p.h b/src/declarative/qml/qmlboundsignal_p.h
new file mode 100644
index 0000000..51c7155
--- /dev/null
+++ b/src/declarative/qml/qmlboundsignal_p.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** 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 QMLBOUNDSIGNAL_P_H
+#define QMLBOUNDSIGNAL_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 <QtDeclarative/qmlexpression.h>
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlAbstractBoundSignal : public QObject
+{
+ Q_OBJECT
+public:
+ QmlAbstractBoundSignal(QObject *parent = 0);
+ virtual ~QmlAbstractBoundSignal() = 0;
+};
+
+class QmlBoundSignalParameters;
+class QmlBoundSignal : public QmlAbstractBoundSignal
+{
+public:
+ QmlBoundSignal(QObject *scope, const QMetaMethod &signal, QObject *parent);
+ QmlBoundSignal(QmlContext *ctxt, const QString &val, QObject *scope,
+ const QMetaMethod &signal, QObject *parent);
+ virtual ~QmlBoundSignal();
+
+ int index() const;
+
+ QmlExpression *expression() const;
+ QmlExpression *setExpression(QmlExpression *);
+
+ static QmlBoundSignal *cast(QObject *);
+
+protected:
+ virtual int qt_metacall(QMetaObject::Call c, int id, void **a);
+
+private:
+ QmlExpression *m_expression;
+ int m_idx;
+ QmlBoundSignalParameters *m_params;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLBOUNDSIGNAL_P_H
diff --git a/src/declarative/qml/qmlclassfactory.cpp b/src/declarative/qml/qmlclassfactory.cpp
new file mode 100644
index 0000000..ddfbd78
--- /dev/null
+++ b/src/declarative/qml/qmlclassfactory.cpp
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** 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 "qmlclassfactory_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QmlClassFactory::~QmlClassFactory()
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlclassfactory_p.h b/src/declarative/qml/qmlclassfactory_p.h
new file mode 100644
index 0000000..cd80ffc
--- /dev/null
+++ b/src/declarative/qml/qmlclassfactory_p.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** 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 QMLCLASSFACTORY_P_H
+#define QMLCLASSFACTORY_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/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlEngine;
+class QByteArray;
+class QUrl;
+class QmlComponent;
+
+class QmlClassFactory
+{
+public:
+ virtual ~QmlClassFactory();
+ virtual QmlComponent *create(const QByteArray &, const QUrl& baseUrl, QmlEngine*) = 0;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLCLASSFACTORY_P_H
diff --git a/src/declarative/qml/qmlcleanup.cpp b/src/declarative/qml/qmlcleanup.cpp
new file mode 100644
index 0000000..7799cfc
--- /dev/null
+++ b/src/declarative/qml/qmlcleanup.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$
+**
+****************************************************************************/
+
+#include "qmlcleanup_p.h"
+#include <private/qmlengine_p.h>
+
+/*!
+\internal
+\class QmlCleanup
+\brief The QmlCleanup provides a callback when a QmlEngine is deleted.
+
+Any object that needs cleanup to occur before the QmlEngine's QScriptEngine is
+destroyed should inherit from QmlCleanup. The clear() virtual method will be
+called by QmlEngine just before it deletes the QScriptEngine.
+*/
+
+/*!
+\internal
+
+Create a QmlCleanup for \a engine
+*/
+QmlCleanup::QmlCleanup(QmlEngine *engine)
+: prev(0), next(0)
+{
+ Q_ASSERT(engine);
+ QmlEnginePrivate *p = QmlEnginePrivate::get(engine);
+
+ if (p->cleanup) next = p->cleanup;
+ p->cleanup = this;
+ prev = &p->cleanup;
+ if (next) next->prev = &next;
+}
+
+/*!
+\internal
+*/
+QmlCleanup::~QmlCleanup()
+{
+ if (prev) *prev = next;
+ if (next) next->prev = prev;
+ prev = 0;
+ next = 0;
+}
+
diff --git a/src/declarative/qml/qmlcleanup_p.h b/src/declarative/qml/qmlcleanup_p.h
new file mode 100644
index 0000000..e9196a3
--- /dev/null
+++ b/src/declarative/qml/qmlcleanup_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** 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 QMLCLEANUP_P_H
+#define QMLCLEANUP_P_H
+
+#include <QtCore/qglobal.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_NAMESPACE
+
+class QmlEngine;
+class QmlCleanup
+{
+public:
+ QmlCleanup(QmlEngine *);
+ virtual ~QmlCleanup();
+
+protected:
+ virtual void clear() = 0;
+
+private:
+ friend class QmlEnginePrivate;
+ QmlCleanup **prev;
+ QmlCleanup *next;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLCLEANUP_P_H
+
diff --git a/src/declarative/qml/qmlcompileddata.cpp b/src/declarative/qml/qmlcompileddata.cpp
new file mode 100644
index 0000000..7032a3b
--- /dev/null
+++ b/src/declarative/qml/qmlcompileddata.cpp
@@ -0,0 +1,209 @@
+/****************************************************************************
+**
+** 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 "qmlcompiler_p.h"
+#include "qmlengine.h"
+#include "qmlcomponent.h"
+#include "qmlcomponent_p.h"
+#include "qmlcontext.h"
+#include "qmlcontext_p.h"
+#include <private/qobject_p.h>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+int QmlCompiledData::pack(const char *data, size_t size)
+{
+ const char *p = packData.constData();
+ unsigned int ps = packData.size();
+
+ for (unsigned int ii = 0; (ii + size) <= ps; ii += sizeof(int)) {
+ if (0 == ::memcmp(p + ii, data, size))
+ return ii;
+ }
+
+ int rv = packData.size();
+ packData.append(data, size);
+ return rv;
+}
+
+int QmlCompiledData::indexForString(const QString &data)
+{
+ int idx = primitives.indexOf(data);
+ if (idx == -1) {
+ idx = primitives.count();
+ primitives << data;
+ }
+ return idx;
+}
+
+int QmlCompiledData::indexForByteArray(const QByteArray &data)
+{
+ int idx = datas.indexOf(data);
+ if (idx == -1) {
+ idx = datas.count();
+ datas << data;
+ }
+ return idx;
+}
+
+int QmlCompiledData::indexForFloat(float *data, int count)
+{
+ Q_ASSERT(count > 0);
+
+ for (int ii = 0; ii <= floatData.count() - count; ++ii) {
+ bool found = true;
+ for (int jj = 0; jj < count; ++jj) {
+ if (floatData.at(ii + jj) != data[jj]) {
+ found = false;
+ break;
+ }
+ }
+
+ if (found)
+ return ii;
+ }
+
+ int idx = floatData.count();
+ for (int ii = 0; ii < count; ++ii)
+ floatData << data[ii];
+
+ return idx;
+}
+
+int QmlCompiledData::indexForInt(int *data, int count)
+{
+ Q_ASSERT(count > 0);
+
+ for (int ii = 0; ii <= intData.count() - count; ++ii) {
+ bool found = true;
+ for (int jj = 0; jj < count; ++jj) {
+ if (intData.at(ii + jj) != data[jj]) {
+ found = false;
+ break;
+ }
+ }
+
+ if (found)
+ return ii;
+ }
+
+ int idx = intData.count();
+ for (int ii = 0; ii < count; ++ii)
+ intData << data[ii];
+
+ return idx;
+}
+
+int QmlCompiledData::indexForLocation(const QmlParser::Location &l)
+{
+ // ### FIXME
+ int rv = locations.count();
+ locations << l;
+ return rv;
+}
+
+int QmlCompiledData::indexForLocation(const QmlParser::LocationSpan &l)
+{
+ // ### FIXME
+ int rv = locations.count();
+ locations << l.start << l.end;
+ return rv;
+}
+
+QmlCompiledData::QmlCompiledData()
+: importCache(0), root(0)
+{
+}
+
+QmlCompiledData::~QmlCompiledData()
+{
+ for (int ii = 0; ii < types.count(); ++ii) {
+ 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
+{
+ if (type) {
+ QObject *rv = type->create();
+ if (rv)
+ QmlEngine::setContextForObject(rv, ctxt);
+ return rv;
+ } else {
+ Q_ASSERT(component);
+ return QmlComponentPrivate::get(component)->create(ctxt, bindings);
+ }
+}
+
+const QMetaObject *QmlCompiledData::TypeReference::metaObject() const
+{
+ if (type) {
+ return type->metaObject();
+ } else {
+ Q_ASSERT(component);
+ return static_cast<QmlComponentPrivate *>(QObjectPrivate::get(component))->cc->root;
+ }
+}
+
+void QmlCompiledData::dumpInstructions()
+{
+ if (!name.isEmpty())
+ qWarning() << name;
+ qWarning() << "Index\tLine\tOperation\t\tData1\tData2\t\tComments";
+ qWarning() << "-------------------------------------------------------------------------------";
+ for (int ii = 0; ii < bytecode.count(); ++ii) {
+ dump(&bytecode[ii], ii);
+ }
+ qWarning() << "-------------------------------------------------------------------------------";
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp
new file mode 100644
index 0000000..69ebf9c
--- /dev/null
+++ b/src/declarative/qml/qmlcompiler.cpp
@@ -0,0 +1,2565 @@
+/****************************************************************************
+**
+** 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 "private/qmlcompiler_p.h"
+#include "private/qmlcompositetypedata_p.h"
+#include <private/qfxperf_p.h>
+#include "qmlparser_p.h"
+#include "private/qmlscriptparser_p.h"
+#include <qmlpropertyvaluesource.h>
+#include <qmlcomponent.h>
+#include "private/qmetaobjectbuilder_p.h"
+#include "qmlbasicscript_p.h"
+#include <QColor>
+#include <QDebug>
+#include <QPointF>
+#include <QSizeF>
+#include <QRectF>
+#include <QAtomicInt>
+#include <private/qmlstringconverters_p.h>
+#include <private/qmlengine_p.h>
+#include <qmlengine.h>
+#include <qmlcontext.h>
+#include <qmlmetatype.h>
+#include <QtCore/qdebug.h>
+#include <QtGui/qapplication.h>
+#include "private/qmlcustomparser_p_p.h"
+#include <private/qmlcontext_p.h>
+#include <private/qmlcomponent_p.h>
+#include "parser/qmljsast_p.h"
+#include <private/qmlvmemetaobject_p.h>
+#include <private/qmlexpression_p.h>
+#include "qmlmetaproperty_p.h"
+#include "qmlrewrite_p.h"
+#include <QtDeclarative/qmlscriptstring.h>
+
+#include "qmlscriptparser_p.h"
+
+QT_BEGIN_NAMESPACE
+
+DEFINE_BOOL_CONFIG_OPTION(compilerDump, QML_COMPILER_DUMP);
+
+using namespace QmlParser;
+
+/*!
+ Instantiate a new QmlCompiler.
+*/
+QmlCompiler::QmlCompiler()
+: output(0), engine(0)
+{
+}
+
+/*!
+ Returns true if the last call to compile() caused errors.
+
+ \sa errors()
+*/
+bool QmlCompiler::isError() const
+{
+ return !exceptions.isEmpty();
+}
+
+/*!
+ Return the list of errors from the last call to compile(), or an empty list
+ if there were no errors.
+*/
+QList<QmlError> QmlCompiler::errors() const
+{
+ return exceptions;
+}
+
+/*!
+ Returns true if \a val is a legal object id, false otherwise.
+
+ Legal ids must start with a letter or underscore, and contain only
+ letters, numbers and underscores.
+*/
+bool QmlCompiler::isValidId(const QString &val)
+{
+ if (val.isEmpty())
+ return false;
+
+ QChar u(QLatin1Char('_'));
+ for (int ii = 0; ii < val.count(); ++ii)
+ if (val.at(ii) != u &&
+ ((ii == 0 && !val.at(ii).isLetter()) ||
+ (ii != 0 && !val.at(ii).isLetterOrNumber())) )
+ return false;
+
+ return true;
+}
+
+/*!
+ Returns true if \a name refers to an attached property, false otherwise.
+
+ Attached property names are those that start with a capital letter.
+*/
+bool QmlCompiler::isAttachedPropertyName(const QByteArray &name)
+{
+ return !name.isEmpty() && name.at(0) >= 'A' && name.at(0) <= 'Z';
+}
+
+/*!
+ Returns true if \a name refers to a signal property, false otherwise.
+
+ Signal property names are those that start with "on", followed by a capital
+ letter.
+*/
+bool QmlCompiler::isSignalPropertyName(const QByteArray &name)
+{
+ return name.length() >= 3 && name.startsWith("on") &&
+ 'A' <= name.at(2) && 'Z' >= name.at(2);
+}
+
+/*!
+ Inserts an error into the QmlCompiler error list, and returns false
+ (failure).
+
+ \a token is used to source the error line and column, and \a desc is the
+ error itself. \a desc can be an expression that can be piped into QDebug.
+
+ For example:
+
+ \code
+ COMPILE_EXCEPTION(property, qApp->translate("QmlCompiler","Error for property \"%1\"").arg(QString::fromUtf8(property->name)));
+ \endcode
+*/
+#define COMPILE_EXCEPTION(token, desc) \
+ { \
+ QString exceptionDescription; \
+ QmlError error; \
+ error.setUrl(output->url); \
+ error.setLine((token)->location.start.line); \
+ error.setColumn((token)->location.start.column); \
+ error.setDescription(desc.trimmed()); \
+ exceptions << error; \
+ return false; \
+ }
+
+/*!
+ Returns false if \a is false, otherwise does nothing.
+*/
+#define COMPILE_CHECK(a) \
+ { \
+ if (!a) return false; \
+ }
+
+/*!
+ Returns true if literal \a v can be assigned to property \a prop, otherwise
+ false.
+
+ This test corresponds to action taken by genLiteralAssignment(). Any change
+ made here, must have a corresponding action in genLiteralAssigment().
+*/
+bool QmlCompiler::testLiteralAssignment(const QMetaProperty &prop,
+ QmlParser::Value *v)
+{
+ QString string = v->value.asScript();
+
+ if (!prop.isWritable())
+ COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Invalid property assignment: \"%1\" is a read-only property").arg(QString::fromUtf8(prop.name())));
+
+ if (prop.isEnumType()) {
+ int value;
+ if (prop.isFlagType()) {
+ value = prop.enumerator().keysToValue(string.toUtf8().constData());
+ } else
+ value = prop.enumerator().keyToValue(string.toUtf8().constData());
+ if (value == -1)
+ COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Invalid property assignment: unknown enumeration"));
+ return true;
+ }
+ int type = prop.userType();
+ switch(type) {
+ case -1:
+ break;
+ case QVariant::String:
+ if (!v->value.isString()) COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Invalid property assignment: string expected"));
+ break;
+ case QVariant::Url:
+ if (!v->value.isString()) COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Invalid property assignment: url expected"));
+ break;
+ case QVariant::UInt:
+ {
+ bool ok;
+ string.toUInt(&ok);
+ if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Invalid property assignment: unsigned int expected"));
+ }
+ break;
+ case QVariant::Int:
+ {
+ bool ok;
+ string.toInt(&ok);
+ if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Invalid property assignment: int expected"));
+ }
+ break;
+ case QMetaType::Float:
+ {
+ bool ok;
+ string.toFloat(&ok);
+ if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Invalid property assignment: float expected"));
+ }
+ break;
+ case QVariant::Double:
+ {
+ bool ok;
+ string.toDouble(&ok);
+ if (!v->value.isNumber() || !ok) COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Invalid property assignment: double expected"));
+ }
+ break;
+ case QVariant::Color:
+ {
+ QColor c = QmlStringConverters::colorFromString(string);
+ if (!c.isValid()) COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Invalid property assignment: color expected"));
+ }
+ break;
+ case QVariant::Date:
+ {
+ QDate d = QDate::fromString(string, Qt::ISODate);
+ if (!d.isValid()) COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Invalid property assignment: date expected"));
+ }
+ break;
+ case QVariant::Time:
+ {
+ QTime time = QTime::fromString(string, Qt::ISODate);
+ if (!time.isValid()) COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Invalid property assignment: time expected"));
+ }
+ break;
+ case QVariant::DateTime:
+ {
+ QDateTime dateTime = QDateTime::fromString(string, Qt::ISODate);
+ if (!dateTime.isValid()) COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Invalid property assignment: datetime expected"));
+ }
+ break;
+ case QVariant::Point:
+ case QVariant::PointF:
+ {
+ bool ok;
+ QPointF point = QmlStringConverters::pointFFromString(string, &ok);
+ if (!ok) COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Invalid property assignment: point expected"));
+ }
+ break;
+ case QVariant::Size:
+ case QVariant::SizeF:
+ {
+ bool ok;
+ QSizeF size = QmlStringConverters::sizeFFromString(string, &ok);
+ if (!ok) COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Invalid property assignment: size expected"));
+ }
+ break;
+ case QVariant::Rect:
+ case QVariant::RectF:
+ {
+ bool ok;
+ QRectF rect = QmlStringConverters::rectFFromString(string, &ok);
+ if (!ok) COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Invalid property assignment: rect expected"));
+ }
+ break;
+ case QVariant::Bool:
+ {
+ if (!v->value.isBoolean()) COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Invalid property assignment: boolean expected"));
+ }
+ break;
+ case QVariant::Vector3D:
+ {
+ bool ok;
+ QVector3D point = QmlStringConverters::vector3DFromString(string, &ok);
+ if (!ok) COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Invalid property assignment: 3D vector expected"));
+ }
+ break;
+ default:
+ {
+ int t = prop.type();
+ if (t == QVariant::UserType)
+ t = prop.userType();
+ QmlMetaType::StringConverter converter =
+ QmlMetaType::customStringConverter(t);
+ if (!converter)
+ COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Invalid property assignment: unsupported type \"%1\"").arg(QString::fromLatin1(QVariant::typeToName(prop.type()))));
+ }
+ break;
+ }
+ return true;
+}
+
+/*!
+ Generate a store instruction for assigning literal \a v to property \a prop.
+
+ Any literal assignment that is approved in testLiteralAssignment() must have
+ a corresponding action in this method.
+*/
+void QmlCompiler::genLiteralAssignment(const QMetaProperty &prop,
+ QmlParser::Value *v)
+{
+ QString string = v->value.asScript();
+
+ QmlInstruction instr;
+ instr.line = v->location.start.line;
+ if (prop.isEnumType()) {
+ int value;
+ if (prop.isFlagType()) {
+ value = prop.enumerator().keysToValue(string.toUtf8().constData());
+ } else
+ value = prop.enumerator().keyToValue(string.toUtf8().constData());
+
+ instr.type = QmlInstruction::StoreInteger;
+ instr.storeInteger.propertyIndex = prop.propertyIndex();
+ instr.storeInteger.value = value;
+ output->bytecode << instr;
+ return;
+ }
+
+ int type = prop.userType();
+ switch(type) {
+ case -1:
+ {
+ instr.type = QmlInstruction::StoreVariant;
+ instr.storeString.propertyIndex = prop.propertyIndex();
+ instr.storeString.value = output->indexForString(string);
+ }
+ break;
+ case QVariant::String:
+ {
+ instr.type = QmlInstruction::StoreString;
+ instr.storeString.propertyIndex = prop.propertyIndex();
+ instr.storeString.value = output->indexForString(string);
+ }
+ break;
+ case QVariant::Url:
+ {
+ instr.type = QmlInstruction::StoreUrl;
+ QUrl u = string.isEmpty() ? QUrl() : output->url.resolved(QUrl(string));
+ instr.storeUrl.propertyIndex = prop.propertyIndex();
+ instr.storeUrl.value = output->indexForString(u.toString());
+ }
+ break;
+ case QVariant::UInt:
+ {
+ instr.type = QmlInstruction::StoreInteger;
+ instr.storeInteger.propertyIndex = prop.propertyIndex();
+ instr.storeInteger.value = string.toUInt();
+ }
+ break;
+ case QVariant::Int:
+ {
+ instr.type = QmlInstruction::StoreInteger;
+ instr.storeInteger.propertyIndex = prop.propertyIndex();
+ instr.storeInteger.value = string.toInt();
+ }
+ break;
+ case QMetaType::Float:
+ {
+ instr.type = QmlInstruction::StoreFloat;
+ instr.storeFloat.propertyIndex = prop.propertyIndex();
+ instr.storeFloat.value = string.toFloat();
+ }
+ break;
+ case QVariant::Double:
+ {
+ instr.type = QmlInstruction::StoreDouble;
+ instr.storeDouble.propertyIndex = prop.propertyIndex();
+ instr.storeDouble.value = string.toDouble();
+ }
+ break;
+ case QVariant::Color:
+ {
+ QColor c = QmlStringConverters::colorFromString(string);
+ instr.type = QmlInstruction::StoreColor;
+ instr.storeColor.propertyIndex = prop.propertyIndex();
+ instr.storeColor.value = c.rgba();
+ }
+ break;
+ case QVariant::Date:
+ {
+ QDate d = QDate::fromString(string, Qt::ISODate);
+ instr.type = QmlInstruction::StoreDate;
+ instr.storeDate.propertyIndex = prop.propertyIndex();
+ instr.storeDate.value = d.toJulianDay();
+ }
+ break;
+ case QVariant::Time:
+ {
+ QTime time = QTime::fromString(string, Qt::ISODate);
+ int data[] = { time.hour(), time.minute(),
+ time.second(), time.msec() };
+ int index = output->indexForInt(data, 4);
+ instr.type = QmlInstruction::StoreTime;
+ instr.storeTime.propertyIndex = prop.propertyIndex();
+ instr.storeTime.valueIndex = index;
+ }
+ break;
+ case QVariant::DateTime:
+ {
+ QDateTime dateTime = QDateTime::fromString(string, Qt::ISODate);
+ int data[] = { dateTime.date().toJulianDay(),
+ dateTime.time().hour(),
+ dateTime.time().minute(),
+ dateTime.time().second(),
+ dateTime.time().msec() };
+ int index = output->indexForInt(data, 5);
+ instr.type = QmlInstruction::StoreDateTime;
+ instr.storeDateTime.propertyIndex = prop.propertyIndex();
+ instr.storeDateTime.valueIndex = index;
+ }
+ break;
+ case QVariant::Point:
+ case QVariant::PointF:
+ {
+ bool ok;
+ QPointF point =
+ QmlStringConverters::pointFFromString(string, &ok);
+ float data[] = { point.x(), point.y() };
+ int index = output->indexForFloat(data, 2);
+ if (type == QVariant::PointF)
+ instr.type = QmlInstruction::StorePointF;
+ else
+ instr.type = QmlInstruction::StorePoint;
+ instr.storeRealPair.propertyIndex = prop.propertyIndex();
+ instr.storeRealPair.valueIndex = index;
+ }
+ break;
+ case QVariant::Size:
+ case QVariant::SizeF:
+ {
+ bool ok;
+ QSizeF size = QmlStringConverters::sizeFFromString(string, &ok);
+ float data[] = { size.width(), size.height() };
+ int index = output->indexForFloat(data, 2);
+ if (type == QVariant::SizeF)
+ instr.type = QmlInstruction::StoreSizeF;
+ else
+ instr.type = QmlInstruction::StoreSize;
+ instr.storeRealPair.propertyIndex = prop.propertyIndex();
+ instr.storeRealPair.valueIndex = index;
+ }
+ break;
+ case QVariant::Rect:
+ case QVariant::RectF:
+ {
+ bool ok;
+ QRectF rect = QmlStringConverters::rectFFromString(string, &ok);
+ float data[] = { rect.x(), rect.y(),
+ rect.width(), rect.height() };
+ int index = output->indexForFloat(data, 4);
+ if (type == QVariant::RectF)
+ instr.type = QmlInstruction::StoreRectF;
+ else
+ instr.type = QmlInstruction::StoreRect;
+ instr.storeRect.propertyIndex = prop.propertyIndex();
+ instr.storeRect.valueIndex = index;
+ }
+ break;
+ case QVariant::Bool:
+ {
+ bool b = v->value.asBoolean();
+ instr.type = QmlInstruction::StoreBool;
+ instr.storeBool.propertyIndex = prop.propertyIndex();
+ instr.storeBool.value = b;
+ }
+ break;
+ case QVariant::Vector3D:
+ {
+ bool ok;
+ QVector3D vector =
+ QmlStringConverters::vector3DFromString(string, &ok);
+ float data[] = { vector.x(), vector.y(), vector.z() };
+ int index = output->indexForFloat(data, 3);
+ instr.type = QmlInstruction::StoreVector3D;
+ instr.storeRealPair.propertyIndex = prop.propertyIndex();
+ instr.storeRealPair.valueIndex = index;
+ }
+ break;
+ default:
+ {
+ int t = prop.type();
+ if (t == QVariant::UserType)
+ t = prop.userType();
+ int index = output->customTypeData.count();
+ instr.type = QmlInstruction::AssignCustomType;
+ instr.assignCustomType.propertyIndex = prop.propertyIndex();
+ instr.assignCustomType.valueIndex = index;
+
+ QmlCompiledData::CustomTypeData data;
+ data.index = output->indexForString(string);
+ data.type = t;
+ output->customTypeData << data;
+ }
+ break;
+ }
+ output->bytecode << instr;
+}
+
+/*!
+ Resets data by clearing the lists that the QmlCompiler modifies.
+*/
+void QmlCompiler::reset(QmlCompiledData *data)
+{
+ data->types.clear();
+ data->primitives.clear();
+ data->floatData.clear();
+ data->intData.clear();
+ data->customTypeData.clear();
+ data->datas.clear();
+ data->bytecode.clear();
+}
+
+/*!
+ Compile \a unit, and store the output in \a out. \a engine is the QmlEngine
+ with which the QmlCompiledData will be associated.
+
+ Returns true on success, false on failure. On failure, the compile errors
+ are available from errors().
+
+ If the environment variant QML_COMPILER_DUMP is set
+ (eg. QML_COMPILER_DUMP=1) the compiled instructions will be dumped to stderr
+ on a successful compiler.
+*/
+bool QmlCompiler::compile(QmlEngine *engine,
+ QmlCompositeTypeData *unit,
+ QmlCompiledData *out)
+{
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::Compilation> pc;
+#endif
+ exceptions.clear();
+
+ Q_ASSERT(out);
+ reset(out);
+
+ output = out;
+
+ // Compile types
+ for (int ii = 0; ii < unit->types.count(); ++ii) {
+ QmlCompositeTypeData::TypeReference &tref = unit->types[ii];
+ QmlCompiledData::TypeReference ref;
+ QmlScriptParser::TypeReference *parserRef = unit->data.referencedTypes().at(ii);
+ if (tref.type)
+ ref.type = tref.type;
+ else if (tref.unit) {
+ ref.component = tref.unit->toComponent(engine);
+
+ if (ref.component->isError()) {
+ QmlError error;
+ error.setUrl(output->url);
+ error.setDescription(QLatin1String("Unable to create type ") +
+ parserRef->name);
+ if (!parserRef->refObjects.isEmpty()) {
+ QmlParser::Object *parserObject = parserRef->refObjects.first();
+ error.setLine(parserObject->location.start.line);
+ error.setColumn(parserObject->location.start.column);
+ }
+
+ exceptions << error;
+ exceptions << ref.component->errors();
+ reset(out);
+ return false;
+ }
+ ref.ref = tref.unit;
+ ref.ref->addref();
+ }
+ ref.className = parserRef->name.toUtf8();
+ out->types << ref;
+ }
+
+ Object *root = unit->data.tree();
+ Q_ASSERT(root);
+
+ this->engine = engine;
+ this->unit = unit;
+ compileTree(root);
+
+ if (!isError()) {
+ if (compilerDump())
+ out->dumpInstructions();
+ } else {
+ reset(out);
+ }
+
+ compileState = ComponentCompileState();
+ savedCompileStates.clear();
+ output = 0;
+ this->engine = 0;
+
+ return !isError();
+}
+
+void QmlCompiler::compileTree(Object *tree)
+{
+ compileState.root = tree;
+
+ if (!buildObject(tree, BindingContext()) || !completeComponentBuild())
+ return;
+
+ QmlInstruction init;
+ init.type = QmlInstruction::Init;
+ init.line = 0;
+ init.init.bindingsSize = compileState.bindings.count();
+ init.init.parserStatusSize = compileState.parserStatusCount;
+ init.init.contextCache = genContextCache();
+ output->bytecode << init;
+
+ genObject(tree);
+
+ QmlInstruction def;
+ init.line = 0;
+ def.type = QmlInstruction::SetDefault;
+ output->bytecode << def;
+
+ output->imports = unit->imports;
+ output->importCache = output->imports.cache(engine);
+
+ Q_ASSERT(tree->metatype);
+
+ if (tree->metadata.isEmpty()) {
+ output->root = tree->metatype;
+ } else {
+ static_cast<QMetaObject &>(output->rootData) = *tree->metaObject();
+ output->root = &output->rootData;
+ }
+ if (!tree->metadata.isEmpty())
+ QmlEnginePrivate::get(engine)->registerCompositeType(output);
+}
+
+bool QmlCompiler::buildObject(Object *obj, const BindingContext &ctxt)
+{
+ Q_ASSERT (obj->type != -1);
+ const QmlCompiledData::TypeReference &tr =
+ output->types.at(obj->type);
+ obj->metatype = tr.metaObject();
+
+ if (tr.component)
+ obj->url = tr.component->url();
+ if (tr.type)
+ obj->typeName = tr.type->qmlTypeName();
+ obj->className = tr.className;
+
+ // This object is a "Component" element
+ if (tr.type && 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);
+
+ // Create the synthesized meta object, ignoring aliases
+ COMPILE_CHECK(mergeDynamicMetaProperties(obj));
+ COMPILE_CHECK(buildDynamicMeta(obj, IgnoreAliases));
+
+ // Find the native type and check for the QmlParserStatus interface
+ QmlType *type = toQmlType(obj);
+ Q_ASSERT(type);
+ obj->parserStatusCast = type->parserStatusCast();
+ if (obj->parserStatusCast != -1)
+ compileState.parserStatusCount++;
+
+ // Check if this is a custom parser type. Custom parser types allow
+ // assignments to non-existant properties. These assignments are then
+ // compiled by the type.
+ bool isCustomParser = output->types.at(obj->type).type &&
+ output->types.at(obj->type).type->customParser() != 0;
+ QList<QmlCustomParserProperty> customProps;
+
+ // Fetch the list of deferred properties
+ QStringList deferredList = deferredProperties(obj);
+
+ // Must do id property first. This is to ensure that the id given to any
+ // id reference created matches the order in which the objects are
+ // instantiated
+ foreach(Property *prop, obj->properties) {
+ if (prop->name == "id") {
+ COMPILE_CHECK(buildProperty(prop, obj, objCtxt));
+ break;
+ }
+ }
+
+ // Build all explicit properties specified
+ foreach(Property *prop, obj->properties) {
+
+ if (prop->name == "id")
+ continue;
+
+ bool canDefer = false;
+ if (isCustomParser) {
+ if (doesPropertyExist(prop, obj)) {
+ int ids = compileState.ids.count();
+ COMPILE_CHECK(buildProperty(prop, obj, objCtxt));
+ canDefer = ids == compileState.ids.count();
+ } else {
+ customProps << QmlCustomParserNodePrivate::fromProperty(prop);
+ }
+ } else {
+ if (isSignalPropertyName(prop->name)) {
+ COMPILE_CHECK(buildSignal(prop,obj,objCtxt));
+ } else {
+ int ids = compileState.ids.count();
+ COMPILE_CHECK(buildProperty(prop, obj, objCtxt));
+ canDefer = ids == compileState.ids.count();
+ }
+ }
+
+ if (canDefer && !deferredList.isEmpty() &&
+ deferredList.contains(QString::fromUtf8(prop->name)))
+ prop->isDeferred = true;
+
+ }
+
+ // Build the default property
+ if (obj->defaultProperty) {
+ Property *prop = obj->defaultProperty;
+
+ bool canDefer = false;
+ if (isCustomParser) {
+ if (doesPropertyExist(prop, obj)) {
+ int ids = compileState.ids.count();
+ COMPILE_CHECK(buildProperty(prop, obj, objCtxt));
+ canDefer = ids == compileState.ids.count();
+ } else {
+ customProps << QmlCustomParserNodePrivate::fromProperty(prop);
+ }
+ } else {
+ int ids = compileState.ids.count();
+ COMPILE_CHECK(buildProperty(prop, obj, objCtxt));
+ canDefer = ids == compileState.ids.count();
+ }
+
+ if (canDefer && !deferredList.isEmpty() &&
+ deferredList.contains(QString::fromUtf8(prop->name)))
+ prop->isDeferred = true;
+ }
+
+ // Compile custom parser parts
+ if (isCustomParser && !customProps.isEmpty()) {
+ QmlCustomParser *cp = output->types.at(obj->type).type->customParser();
+ cp->clearErrors();
+ obj->custom = cp->compile(customProps);
+ foreach (QmlError err, cp->errors()) {
+ err.setUrl(output->url);
+ exceptions << err;
+ }
+ }
+
+ return true;
+}
+
+void QmlCompiler::genObject(QmlParser::Object *obj)
+{
+ const QmlCompiledData::TypeReference &tr =
+ output->types.at(obj->type);
+ if (tr.type && obj->metatype == &QmlComponent::staticMetaObject) {
+ genComponent(obj);
+ return;
+ }
+
+ // Create the object
+ QmlInstruction create;
+ create.type = QmlInstruction::CreateObject;
+ create.line = obj->location.start.line;
+ create.create.column = obj->location.start.column;
+ create.create.data = -1;
+ if (!obj->custom.isEmpty())
+ create.create.data = output->indexForByteArray(obj->custom);
+ create.create.type = obj->type;
+ if (!output->types.at(create.create.type).type &&
+ !obj->bindingBitmask.isEmpty()) {
+ while (obj->bindingBitmask.size() % 4)
+ obj->bindingBitmask.append(char(0));
+ create.create.bindingBits =
+ output->indexForByteArray(obj->bindingBitmask);
+ } else {
+ create.create.bindingBits = -1;
+ }
+ output->bytecode << create;
+
+ // Setup the synthesized meta object if necessary
+ if (!obj->metadata.isEmpty()) {
+ QmlInstruction meta;
+ meta.type = QmlInstruction::StoreMetaObject;
+ meta.line = 0;
+ meta.storeMeta.data = output->indexForByteArray(obj->metadata);
+ meta.storeMeta.aliasData = output->indexForByteArray(obj->synthdata);
+ 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;
+ }
+
+ // Set the object id
+ if (!obj->id.isEmpty()) {
+ QmlInstruction id;
+ id.type = QmlInstruction::SetId;
+ id.line = 0;
+ id.setId.value = output->indexForString(obj->id);
+ id.setId.index = obj->idIndex;
+ output->bytecode << id;
+ }
+
+ // Set any script blocks
+ for (int ii = 0; ii < obj->scriptBlocks.count(); ++ii) {
+ QmlInstruction script;
+ script.type = QmlInstruction::StoreScript;
+ script.line = 0; // ###
+ script.storeScript.fileName = output->indexForString(obj->scriptBlocksFile.at(ii));
+ script.storeScript.lineNumber = obj->scriptBlocksLineNumber.at(ii);
+ script.storeScript.value = output->indexForString(obj->scriptBlocks.at(ii));
+ output->bytecode << script;
+ }
+
+ // Begin the class
+ if (obj->parserStatusCast != -1) {
+ QmlInstruction begin;
+ begin.type = QmlInstruction::BeginObject;
+ begin.begin.castValue = obj->parserStatusCast;
+ begin.line = obj->location.start.line;
+ output->bytecode << begin;
+ }
+
+ genObjectBody(obj);
+}
+
+void QmlCompiler::genObjectBody(QmlParser::Object *obj)
+{
+ typedef QPair<Property *, int> PropPair;
+ foreach(const PropPair &prop, obj->scriptStringProperties) {
+ QmlInstruction ss;
+ ss.type = QmlInstruction::StoreScriptString;
+ ss.storeScriptString.propertyIndex = prop.first->index;
+ ss.storeScriptString.value =
+ output->indexForString(prop.first->values.at(0)->value.asScript());
+ ss.storeScriptString.scope = prop.second;
+ output->bytecode << ss;
+ }
+
+ bool seenDefer = false;
+ foreach(Property *prop, obj->valueProperties) {
+ if (prop->isDeferred) {
+ seenDefer = true;
+ continue;
+ }
+ genValueProperty(prop, obj);
+ }
+ if (seenDefer) {
+ QmlInstruction defer;
+ defer.type = QmlInstruction::Defer;
+ defer.line = 0;
+ defer.defer.deferCount = 0;
+ int deferIdx = output->bytecode.count();
+ output->bytecode << defer;
+
+ foreach(Property *prop, obj->valueProperties) {
+ if (!prop->isDeferred)
+ continue;
+ genValueProperty(prop, obj);
+ }
+
+ output->bytecode[deferIdx].defer.deferCount =
+ output->bytecode.count() - deferIdx - 1;
+ }
+
+ foreach(Property *prop, obj->signalProperties) {
+
+ QmlParser::Value *v = prop->values.at(0);
+
+ if (v->type == Value::SignalObject) {
+
+ genObject(v->object);
+
+ QmlInstruction assign;
+ assign.type = QmlInstruction::AssignSignalObject;
+ assign.line = v->location.start.line;
+ assign.assignSignalObject.signal =
+ output->indexForByteArray(prop->name);
+ output->bytecode << assign;
+
+ } else if (v->type == Value::SignalExpression) {
+
+ QmlInstruction store;
+ store.type = QmlInstruction::StoreSignal;
+ store.line = v->location.start.line;
+ store.storeSignal.signalIndex = prop->index;
+ store.storeSignal.value =
+ output->indexForString(v->value.asScript().trimmed());
+ output->bytecode << store;
+
+ }
+
+ }
+
+ foreach(Property *prop, obj->attachedProperties) {
+ QmlInstruction fetch;
+ fetch.type = QmlInstruction::FetchAttached;
+ fetch.line = prop->location.start.line;
+ fetch.fetchAttached.id = prop->index;
+ output->bytecode << fetch;
+
+ genObjectBody(prop->value);
+
+ QmlInstruction pop;
+ pop.type = QmlInstruction::PopFetchedObject;
+ pop.line = prop->location.start.line;
+ output->bytecode << pop;
+ }
+
+ foreach(Property *prop, obj->groupedProperties) {
+ QmlInstruction fetch;
+ fetch.type = QmlInstruction::FetchObject;
+ fetch.fetch.property = prop->index;
+ fetch.line = prop->location.start.line;
+ output->bytecode << fetch;
+
+ genObjectBody(prop->value);
+
+ QmlInstruction pop;
+ pop.type = QmlInstruction::PopFetchedObject;
+ pop.line = prop->location.start.line;
+ output->bytecode << pop;
+ }
+
+ foreach(Property *prop, obj->valueTypeProperties) {
+ QmlInstruction fetch;
+ fetch.type = QmlInstruction::FetchValueType;
+ fetch.fetchValue.property = prop->index;
+ fetch.fetchValue.type = prop->type;
+ fetch.line = prop->location.start.line;
+
+ output->bytecode << fetch;
+
+ foreach(Property *vprop, prop->value->valueProperties) {
+ genPropertyAssignment(vprop, prop->value, prop);
+ }
+
+ QmlInstruction pop;
+ pop.type = QmlInstruction::PopValueType;
+ pop.fetchValue.property = prop->index;
+ pop.fetchValue.type = prop->type;
+ pop.line = prop->location.start.line;
+ output->bytecode << pop;
+ }
+}
+
+void QmlCompiler::genComponent(QmlParser::Object *obj)
+{
+ QmlParser::Object *root = obj->defaultProperty->values.at(0)->object;
+ Q_ASSERT(root);
+
+ QmlInstruction create;
+ create.type = QmlInstruction::CreateComponent;
+ create.line = root->location.start.line;
+ create.createComponent.column = root->location.start.column;
+ create.createComponent.endLine = root->location.end.line;
+ output->bytecode << create;
+ int count = output->bytecode.count();
+
+ ComponentCompileState oldCompileState = compileState;
+ compileState = componentState(root);
+
+ QmlInstruction init;
+ init.type = QmlInstruction::Init;
+ init.init.bindingsSize = compileState.bindings.count();
+ init.init.parserStatusSize = compileState.parserStatusCount;
+ init.init.contextCache = genContextCache();
+ init.line = obj->location.start.line;
+ output->bytecode << init;
+
+ genObject(root);
+
+ QmlInstruction def;
+ init.line = 0;
+ def.type = QmlInstruction::SetDefault;
+ output->bytecode << def;
+
+ output->bytecode[count - 1].createComponent.count =
+ output->bytecode.count() - count;
+
+ compileState = oldCompileState;
+
+ if (!obj->id.isEmpty()) {
+ QmlInstruction id;
+ id.type = QmlInstruction::SetId;
+ id.line = 0;
+ id.setId.value = output->indexForString(obj->id);
+ id.setId.index = obj->idIndex;
+ output->bytecode << id;
+ }
+}
+
+bool QmlCompiler::buildComponent(QmlParser::Object *obj,
+ const BindingContext &ctxt)
+{
+ // The special "Component" element can only have the id property and a
+ // default property, that actually defines the component's tree
+
+ // 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->scriptBlockObjects.isEmpty())
+ COMPILE_EXCEPTION(obj, qApp->translate("QmlCompiler","Invalid component specification"));
+
+ if (obj->properties.count())
+ idProp = *obj->properties.begin();
+ if (idProp && (idProp->value || idProp->values.count() > 1 || !isValidId(idProp->values.first()->primitive())))
+ COMPILE_EXCEPTION(obj, qApp->translate("QmlCompiler","Invalid component id specification"));
+
+ if (idProp) {
+ QString idVal = idProp->values.first()->primitive();
+
+ if (compileState.ids.contains(idVal))
+ COMPILE_EXCEPTION(obj, qApp->translate("QmlCompiler","id is not unique"));
+
+ obj->id = idVal;
+ addId(idVal, obj);
+ }
+
+ // Check the Component tree is well formed
+ if (obj->defaultProperty &&
+ (obj->defaultProperty->value || obj->defaultProperty->values.count() > 1 ||
+ (obj->defaultProperty->values.count() == 1 && !obj->defaultProperty->values.first()->object)))
+ COMPILE_EXCEPTION(obj, qApp->translate("QmlCompiler","Invalid component body specification"));
+
+ Object *root = 0;
+ if (obj->defaultProperty && obj->defaultProperty->values.count())
+ root = obj->defaultProperty->values.first()->object;
+
+ if (!root)
+ COMPILE_EXCEPTION(obj, qApp->translate("QmlCompiler","Cannot create empty component specification"));
+
+ // Build the component tree
+ COMPILE_CHECK(buildComponentFromRoot(root, ctxt));
+
+ return true;
+}
+
+bool QmlCompiler::buildScript(QmlParser::Object *obj, QmlParser::Object *script)
+{
+ QString scriptCode;
+ QString sourceUrl;
+ int lineNumber = 1;
+
+ if (script->properties.count() == 1 &&
+ script->properties.begin().key() == QByteArray("source")) {
+
+ Property *source = *script->properties.begin();
+ if (script->defaultProperty)
+ COMPILE_EXCEPTION(source, qApp->translate("QmlCompiler","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, qApp->translate("QmlCompiler","Invalid Script source value"));
+
+ 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(), qApp->translate("QmlCompiler","Properties cannot be set on Script block"));
+ } else if (script->defaultProperty) {
+ sourceUrl = output->url.toString();
+
+ QmlParser::Location currentLocation;
+
+ for (int ii = 0; ii < script->defaultProperty->values.count(); ++ii) {
+ Value *v = script->defaultProperty->values.at(ii);
+ if (lineNumber == 1)
+ lineNumber = v->location.start.line;
+ if (v->object || !v->value.isString())
+ COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","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);
+ obj->scriptBlocksFile.append(sourceUrl);
+ obj->scriptBlocksLineNumber.append(lineNumber);
+ }
+
+ return true;
+}
+
+bool QmlCompiler::buildComponentFromRoot(QmlParser::Object *obj,
+ const BindingContext &ctxt)
+{
+ ComponentCompileState oldComponentCompileState = compileState;
+ compileState = ComponentCompileState();
+ compileState.root = obj;
+
+ if (obj)
+ COMPILE_CHECK(buildObject(obj, ctxt));
+
+ COMPILE_CHECK(completeComponentBuild());
+
+ compileState = oldComponentCompileState;
+
+ return true;
+}
+
+
+// Build a sub-object. A sub-object is one that was not created directly by
+// QML - such as a grouped property object, or an attached object. Sub-object's
+// can't have an id, involve a custom parser, have attached properties etc.
+bool QmlCompiler::buildSubObject(Object *obj, const BindingContext &ctxt)
+{
+ Q_ASSERT(obj->metatype);
+ Q_ASSERT(ctxt.isSubContext()); // sub-objects must always be in a binding
+ // sub-context
+
+ if (obj->defaultProperty)
+ COMPILE_CHECK(buildProperty(obj->defaultProperty, obj, ctxt));
+
+ foreach(Property *prop, obj->properties) {
+ if (isSignalPropertyName(prop->name)) {
+ COMPILE_CHECK(buildSignal(prop, obj, ctxt));
+ } else {
+ COMPILE_CHECK(buildProperty(prop, obj, ctxt));
+ }
+ }
+
+ return true;
+}
+
+int QmlCompiler::componentTypeRef()
+{
+ QmlType *t = QmlMetaType::qmlType("Qt/Component",4,6);
+ for (int ii = output->types.count() - 1; ii >= 0; --ii) {
+ if (output->types.at(ii).type == t)
+ return ii;
+ }
+ QmlCompiledData::TypeReference ref;
+ ref.className = "Component";
+ ref.type = t;
+ output->types << ref;
+ return output->types.count() - 1;
+}
+
+int QmlCompiler::findSignalByName(const QMetaObject *mo, const QByteArray &name)
+{
+ int methods = mo->methodCount();
+ for (int ii = methods - 1; ii >= 0; --ii) {
+ QMetaMethod method = mo->method(ii);
+ QByteArray methodName = method.signature();
+ int idx = methodName.indexOf('(');
+ methodName = methodName.left(idx);
+
+ if (methodName == name)
+ return ii;
+ }
+ return -1;
+}
+
+bool QmlCompiler::buildSignal(QmlParser::Property *prop, QmlParser::Object *obj,
+ const BindingContext &ctxt)
+{
+ Q_ASSERT(obj->metaObject());
+
+ if (prop->isEmpty())
+ COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","Empty property assignment"));
+
+ QByteArray name = prop->name;
+ Q_ASSERT(name.startsWith("on"));
+ name = name.mid(2);
+ if(name[0] >= 'A' && name[0] <= 'Z')
+ name[0] = name[0] - 'A' + 'a';
+
+ int sigIdx = findSignalByName(obj->metaObject(), name);
+
+ if (sigIdx == -1) {
+
+ // If the "on<Signal>" name doesn't resolve into a signal, try it as a
+ // property.
+ COMPILE_CHECK(buildProperty(prop, obj, ctxt));
+
+ } else {
+
+ if (prop->value || prop->values.count() > 1)
+ COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","Incorrectly specified signal"));
+
+ prop->index = sigIdx;
+ obj->addSignalProperty(prop);
+
+ if (prop->values.at(0)->object) {
+ COMPILE_CHECK(buildObject(prop->values.at(0)->object, ctxt));
+ prop->values.at(0)->type = Value::SignalObject;
+ } else {
+ prop->values.at(0)->type = Value::SignalExpression;
+ }
+ }
+
+ return true;
+}
+
+
+/*!
+ Returns true if (value) property \a prop exists on obj, false otherwise.
+*/
+bool QmlCompiler::doesPropertyExist(QmlParser::Property *prop,
+ QmlParser::Object *obj)
+{
+ if(isAttachedPropertyName(prop->name) || prop->name == "id")
+ return true;
+
+ const QMetaObject *mo = obj->metaObject();
+ if (mo) {
+ if (prop->isDefault) {
+ QMetaProperty p = QmlMetaType::defaultProperty(mo);
+ return p.name() != 0;
+ } else {
+ int idx = mo->indexOfProperty(prop->name.constData());
+ return idx != -1;
+ }
+ }
+
+ return false;
+}
+
+bool QmlCompiler::buildProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ const BindingContext &ctxt)
+{
+ if (prop->isEmpty())
+ COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","Empty property assignment"));
+
+ const QMetaObject *metaObject = obj->metaObject();
+ Q_ASSERT(metaObject);
+
+ if (isAttachedPropertyName(prop->name)) {
+ // Setup attached property data
+
+ if (ctxt.isSubContext()) {
+ // Attached properties cannot be used on sub-objects. Sub-objects
+ // always exist in a binding sub-context, which is what we test
+ // for here.
+ COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","Attached properties cannot be used here"));
+ }
+
+ QmlType *type = 0;
+ QmlEnginePrivate::ImportedNamespace *typeNamespace = 0;
+ QmlEnginePrivate::get(engine)->resolveType(unit->imports, prop->name,
+ &type, 0, 0, 0, &typeNamespace);
+
+ if (typeNamespace) {
+ // ### We might need to indicate that this property is a namespace
+ // for the DOM API
+ COMPILE_CHECK(buildPropertyInNamespace(typeNamespace, prop, obj,
+ ctxt));
+ return true;
+ } else if (!type || !type->attachedPropertiesType()) {
+ COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","Non-existant attached object"));
+ }
+
+ if (!prop->value)
+ COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","Invalid attached object assignment"));
+
+ Q_ASSERT(type->attachedPropertiesFunction());
+ prop->index = type->index();
+ prop->value->metatype = type->attachedPropertiesType();
+ } else {
+ // Setup regular property data
+ QMetaProperty p;
+
+ if (prop->isDefault) {
+ p = QmlMetaType::defaultProperty(metaObject);
+
+ if (p.name()) {
+ prop->index = p.propertyIndex();
+ prop->name = p.name();
+ }
+
+ } else {
+ prop->index = metaObject->indexOfProperty(prop->name.constData());
+
+ if (prop->index != -1) {
+ p = metaObject->property(prop->index);
+ Q_ASSERT(p.name());
+ }
+ }
+
+ // We can't error here as the "id" property does not require a
+ // successful index resolution
+ if (p.name()) {
+ int t = p.type();
+
+ if (t == QVariant::UserType)
+ t = p.userType();
+
+ prop->type = t;
+ }
+ }
+
+ if (prop->index != -1)
+ prop->parent->setBindingBit(prop->index);
+
+ if (!prop->isDefault && prop->name == "id" && !ctxt.isSubContext()) {
+
+ // The magic "id" behavior doesn't apply when "id" is resolved as a
+ // default property or to sub-objects (which are always in binding
+ // sub-contexts)
+ COMPILE_CHECK(buildIdProperty(prop, obj));
+ if (prop->type == QVariant::String &&
+ prop->values.at(0)->value.isString())
+ COMPILE_CHECK(buildPropertyAssignment(prop, obj, ctxt));
+
+ } else if (isAttachedPropertyName(prop->name)) {
+
+ COMPILE_CHECK(buildAttachedProperty(prop, obj, ctxt));
+
+ } else if (prop->index == -1) {
+
+ if (prop->isDefault) {
+ COMPILE_EXCEPTION(prop->values.first(), qApp->translate("QmlCompiler","Cannot assign to non-existant default property"));
+ } else {
+ COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","Cannot assign to non-existant property \"%1\"").arg(QString::fromUtf8(prop->name)));
+ }
+
+ } else if (prop->value) {
+
+ COMPILE_CHECK(buildGroupedProperty(prop, obj, ctxt));
+
+ } else if (QmlEnginePrivate::get(engine)->isQmlList(prop->type) ||
+ QmlMetaType::isList(prop->type)) {
+
+ COMPILE_CHECK(buildListProperty(prop, obj, ctxt));
+
+ } else if (prop->type == qMetaTypeId<QmlScriptString>()) {
+
+ COMPILE_CHECK(buildScriptStringProperty(prop, obj, ctxt));
+
+ } else {
+
+ COMPILE_CHECK(buildPropertyAssignment(prop, obj, ctxt));
+
+ }
+
+ return true;
+}
+
+bool
+QmlCompiler::buildPropertyInNamespace(QmlEnginePrivate::ImportedNamespace *ns,
+ QmlParser::Property *nsProp,
+ QmlParser::Object *obj,
+ const BindingContext &ctxt)
+{
+ if (!nsProp->value)
+ COMPILE_EXCEPTION(nsProp, qApp->translate("QmlCompiler","Invalid use of namespace"));
+
+ foreach (Property *prop, nsProp->value->properties) {
+
+ if (!isAttachedPropertyName(prop->name))
+ COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","Not an attached property name"));
+
+ // Setup attached property data
+
+ QmlType *type = 0;
+ QmlEnginePrivate::get(engine)->resolveTypeInNamespace(ns, prop->name,
+ &type, 0, 0, 0);
+
+ if (!type || !type->attachedPropertiesType())
+ COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","Non-existant attached object"));
+
+ if (!prop->value)
+ COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","Invalid attached object assignment"));
+
+ Q_ASSERT(type->attachedPropertiesFunction());
+ prop->index = type->index();
+ prop->value->metatype = type->attachedPropertiesType();
+
+ COMPILE_CHECK(buildAttachedProperty(prop, obj, ctxt));
+ }
+
+ return true;
+}
+
+void QmlCompiler::genValueProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj)
+{
+ if (QmlEnginePrivate::get(engine)->isQmlList(prop->type) ||
+ QmlMetaType::isList(prop->type)) {
+ genListProperty(prop, obj);
+ } else {
+ genPropertyAssignment(prop, obj);
+ }
+}
+
+void QmlCompiler::genListProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj)
+{
+ QmlInstruction::Type fetchType;
+ QmlInstruction::Type storeType;
+ int listType;
+
+ if (QmlEnginePrivate::get(engine)->isQmlList(prop->type)) {
+ fetchType = QmlInstruction::FetchQmlList;
+ storeType = QmlInstruction::StoreObjectQmlList;
+ listType = QmlEnginePrivate::get(engine)->qmlListType(prop->type);
+ } else {
+ fetchType = QmlInstruction::FetchQList;
+ storeType = QmlInstruction::StoreObjectQList;
+ listType = QmlMetaType::listType(prop->type);
+ }
+
+ QmlInstruction fetch;
+ fetch.type = fetchType;
+ fetch.line = prop->location.start.line;
+ fetch.fetchQmlList.property = prop->index;
+ bool listTypeIsInterface = QmlMetaType::isInterface(listType);
+ fetch.fetchQmlList.type = listType;
+ output->bytecode << fetch;
+
+ for (int ii = 0; ii < prop->values.count(); ++ii) {
+ Value *v = prop->values.at(ii);
+
+ if (v->type == Value::CreatedObject) {
+
+ genObject(v->object);
+ if (listTypeIsInterface) {
+ QmlInstruction assign;
+ assign.type = QmlInstruction::AssignObjectList;
+ assign.line = prop->location.start.line;
+ output->bytecode << assign;
+ } else {
+ QmlInstruction store;
+ store.type = storeType;
+ store.line = prop->location.start.line;
+ output->bytecode << store;
+ }
+
+ } else if (v->type == Value::PropertyBinding) {
+
+ genBindingAssignment(v, prop, obj);
+
+ }
+
+ }
+
+ QmlInstruction pop;
+ pop.type = QmlInstruction::PopQList;
+ pop.line = prop->location.start.line;
+ output->bytecode << pop;
+}
+
+void QmlCompiler::genPropertyAssignment(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ QmlParser::Property *valueTypeProperty)
+{
+ for (int ii = 0; ii < prop->values.count(); ++ii) {
+ QmlParser::Value *v = prop->values.at(ii);
+
+ if (v->type == Value::CreatedObject) {
+
+ genObject(v->object);
+
+ if (QmlMetaType::isInterface(prop->type)) {
+
+ QmlInstruction store;
+ store.type = QmlInstruction::StoreInterface;
+ store.line = v->object->location.start.line;
+ store.storeObject.propertyIndex = prop->index;
+ output->bytecode << store;
+
+ } else if (prop->type == -1) {
+
+ QmlInstruction store;
+ store.type = QmlInstruction::StoreVariantObject;
+ store.line = v->object->location.start.line;
+ store.storeObject.propertyIndex = prop->index;
+ output->bytecode << store;
+
+ } else {
+
+ QmlInstruction store;
+ store.type = QmlInstruction::StoreObject;
+ store.line = v->object->location.start.line;
+ store.storeObject.propertyIndex = prop->index;
+ output->bytecode << store;
+
+ }
+ } else if (v->type == Value::ValueSource) {
+ genObject(v->object);
+
+ QmlInstruction store;
+ store.type = QmlInstruction::StoreValueSource;
+ store.line = v->object->location.start.line;
+ if (valueTypeProperty) {
+ store.assignValueSource.property = QmlMetaPropertyPrivate::saveValueType(valueTypeProperty->index, prop->index);
+ store.assignValueSource.owner = 1;
+ } else {
+ store.assignValueSource.property =
+ QmlMetaPropertyPrivate::saveProperty(prop->index);
+ store.assignValueSource.owner = 0;
+ }
+ QmlType *valueType = QmlMetaType::qmlType(v->object->metatype);
+ store.assignValueSource.castValue = valueType->propertyValueSourceCast();
+ output->bytecode << store;
+
+ } else if (v->type == Value::ValueInterceptor) {
+ genObject(v->object);
+
+ QmlInstruction store;
+ store.type = QmlInstruction::StoreValueInterceptor;
+ store.line = v->object->location.start.line;
+ if (valueTypeProperty) {
+ store.assignValueInterceptor.property = QmlMetaPropertyPrivate::saveValueType(valueTypeProperty->index, prop->index);
+ store.assignValueInterceptor.owner = 1;
+ } else {
+ store.assignValueInterceptor.property =
+ QmlMetaPropertyPrivate::saveProperty(prop->index);
+ store.assignValueInterceptor.owner = 0;
+ }
+ QmlType *valueType = QmlMetaType::qmlType(v->object->metatype);
+ store.assignValueInterceptor.castValue = valueType->propertyValueInterceptorCast();
+ output->bytecode << store;
+
+ } else if (v->type == Value::PropertyBinding) {
+
+ genBindingAssignment(v, prop, obj, valueTypeProperty);
+
+ } else if (v->type == Value::Literal) {
+
+ QMetaProperty mp = obj->metaObject()->property(prop->index);
+ genLiteralAssignment(mp, v);
+
+ }
+
+ }
+}
+
+bool QmlCompiler::buildIdProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj)
+{
+ if (prop->value ||
+ prop->values.count() > 1 ||
+ prop->values.at(0)->object)
+ COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","Invalid use of id property"));
+
+ QmlParser::Value *idValue = prop->values.at(0);
+ QString val = idValue->primitive();
+
+ if (!isValidId(val))
+ COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","\"%1\" is not a valid object id").arg(val));
+
+ // We disallow id's that conflict with import prefixes and types
+ QmlEnginePrivate::ImportedNamespace *ns = 0;
+ QmlType *type = 0;
+ QmlEnginePrivate::get(engine)->resolveType(unit->imports, val.toUtf8(),
+ &type, 0, 0, 0, &ns);
+ if (type)
+ COMPILE_EXCEPTION(idValue, qApp->translate("QmlCompiler","id conflicts with type name"));
+ if (ns)
+ COMPILE_EXCEPTION(idValue, qApp->translate("QmlCompiler","id conflicts with namespace prefix"));
+
+ if (compileState.ids.contains(val))
+ COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","id is not unique"));
+
+ prop->values.at(0)->type = Value::Id;
+
+ obj->id = val;
+ addId(val, obj);
+
+ return true;
+}
+
+void QmlCompiler::addId(const QString &id, QmlParser::Object *obj)
+{
+ Q_ASSERT(!compileState.ids.contains(id));
+ Q_ASSERT(obj->id == id);
+ obj->idIndex = compileState.ids.count();
+ compileState.ids.insert(id, obj);
+ compileState.idIndexes.insert(obj->idIndex, obj);
+}
+
+void QmlCompiler::addBindingReference(const BindingReference &ref)
+{
+ Q_ASSERT(ref.value && !compileState.bindings.contains(ref.value));
+ compileState.bindings.insert(ref.value, ref);
+}
+
+void QmlCompiler::saveComponentState()
+{
+ Q_ASSERT(compileState.root);
+ Q_ASSERT(!savedCompileStates.contains(compileState.root));
+
+ savedCompileStates.insert(compileState.root, compileState);
+}
+
+QmlCompiler::ComponentCompileState
+QmlCompiler::componentState(QmlParser::Object *obj)
+{
+ Q_ASSERT(savedCompileStates.contains(obj));
+ return savedCompileStates.value(obj);
+}
+
+// Build attached property object. In this example,
+// Text {
+// GridView.row: 10
+// }
+// GridView is an attached property object.
+bool QmlCompiler::buildAttachedProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ const BindingContext &ctxt)
+{
+ Q_ASSERT(prop->value);
+ Q_ASSERT(prop->index != -1); // This is set in buildProperty()
+
+ obj->addAttachedProperty(prop);
+
+ COMPILE_CHECK(buildSubObject(prop->value, ctxt.incr()));
+
+ return true;
+}
+
+
+// Build "grouped" properties. In this example:
+// Text {
+// font.pointSize: 12
+// font.family: "Helvetica"
+// }
+// font is a nested property. pointSize and family are not.
+bool QmlCompiler::buildGroupedProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ const BindingContext &ctxt)
+{
+ Q_ASSERT(prop->type != 0);
+ Q_ASSERT(prop->index != -1);
+
+ if (prop->type < (int)QVariant::UserType) {
+ QmlEnginePrivate *ep =
+ static_cast<QmlEnginePrivate *>(QObjectPrivate::get(engine));
+ if (ep->valueTypes[prop->type]) {
+ COMPILE_CHECK(buildValueTypeProperty(ep->valueTypes[prop->type],
+ prop->value, obj, ctxt.incr()));
+ obj->addValueTypeProperty(prop);
+ } else {
+ COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","Invalid property access"));
+ }
+
+ } else {
+ // Load the nested property's meta type
+ prop->value->metatype =
+ QmlEnginePrivate::get(engine)->metaObjectForType(prop->type);
+ if (!prop->value->metatype)
+ COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","Cannot nest non-QObject property \"%1\"").arg(QString::fromUtf8(prop->name)));
+
+ obj->addGroupedProperty(prop);
+
+ COMPILE_CHECK(buildSubObject(prop->value, ctxt.incr()));
+ }
+
+ return true;
+}
+
+bool QmlCompiler::buildValueTypeProperty(QObject *type,
+ QmlParser::Object *obj,
+ QmlParser::Object *baseObj,
+ const BindingContext &ctxt)
+{
+ if (obj->defaultProperty)
+ COMPILE_EXCEPTION(obj, qApp->translate("QmlCompiler","Invalid property use"));
+ obj->metatype = type->metaObject();
+
+ foreach (Property *prop, obj->properties) {
+ int idx = type->metaObject()->indexOfProperty(prop->name.constData());
+ if (idx == -1)
+ COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","Cannot assign to non-existant property \"%1\"").arg(QString::fromUtf8(prop->name)));
+ QMetaProperty p = type->metaObject()->property(idx);
+ prop->index = idx;
+ prop->type = p.userType();
+
+ if (prop->value || prop->values.count() != 1)
+ COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","Invalid property use"));
+
+ Value *value = prop->values.at(0);
+
+ if (value->object) {
+ bool isPropertyValue = output->types.at(value->object->type).type->propertyValueSourceCast() != -1;
+ bool isPropertyInterceptor = output->types.at(value->object->type).type->propertyValueInterceptorCast() != -1;
+ if (!isPropertyValue && !isPropertyInterceptor) {
+ COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","Invalid property use"));
+ } else {
+ COMPILE_CHECK(buildObject(value->object, ctxt));
+
+ if (isPropertyInterceptor && baseObj->synthdata.isEmpty())
+ buildDynamicMeta(baseObj, ForceCreation);
+ value->type = isPropertyValue ? Value::ValueSource : Value::ValueInterceptor;
+ }
+ } else if (value->value.isScript()) {
+ // ### Check for writability
+ BindingReference reference;
+ reference.expression = value->value;
+ reference.property = prop;
+ reference.value = value;
+ reference.bindingContext = ctxt;
+ reference.bindingContext.owner++;
+ addBindingReference(reference);
+ value->type = Value::PropertyBinding;
+ } else {
+ COMPILE_CHECK(testLiteralAssignment(p, value));
+ value->type = Value::Literal;
+ }
+ obj->addValueProperty(prop);
+ }
+
+ return true;
+}
+
+// Build assignments to QML lists. QML lists are properties of type
+// QList<T *> * and QmlList<T *> *.
+//
+// QList<T *> * types can accept a list of objects, or a single binding
+// QmlList<T *> * types can accept a list of objects
+bool QmlCompiler::buildListProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ const BindingContext &ctxt)
+{
+ Q_ASSERT(QmlMetaType::isList(prop->type) ||
+ QmlEnginePrivate::get(engine)->isQmlList(prop->type));
+
+ int t = prop->type;
+
+ obj->addValueProperty(prop);
+
+ if (QmlEnginePrivate::get(engine)->isQmlList(t)) {
+ int listType = QmlEnginePrivate::get(engine)->qmlListType(t);
+ bool listTypeIsInterface = QmlMetaType::isInterface(listType);
+
+ for (int ii = 0; ii < prop->values.count(); ++ii) {
+ Value *v = prop->values.at(ii);
+ if (v->object) {
+ v->type = Value::CreatedObject;
+ COMPILE_CHECK(buildObject(v->object, ctxt));
+
+ // We check object coercian here. We check interface assignment
+ // at runtime.
+ if (!listTypeIsInterface) {
+ if (!canCoerce(listType, v->object)) {
+ COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Cannot assign object to list"));
+ }
+ }
+
+ } else {
+ COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Cannot assign primitives to lists"));
+ }
+ }
+
+ } else {
+ int listType = QmlMetaType::listType(t);
+ bool listTypeIsInterface = QmlMetaType::isInterface(listType);
+
+ bool assignedBinding = false;
+ for (int ii = 0; ii < prop->values.count(); ++ii) {
+ Value *v = prop->values.at(ii);
+ if (v->object) {
+ v->type = Value::CreatedObject;
+ COMPILE_CHECK(buildObject(v->object, ctxt));
+
+ // We check object coercian here. We check interface assignment
+ // at runtime.
+ if (!listTypeIsInterface) {
+ if (!canCoerce(listType, v->object)) {
+ COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Cannot assign object to list"));
+ }
+ }
+
+ } else if (v->value.isScript()) {
+ if (assignedBinding)
+ COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Can only assign one binding to lists"));
+
+ assignedBinding = true;
+ COMPILE_CHECK(buildBinding(v, prop, ctxt));
+ v->type = Value::PropertyBinding;
+ } else {
+ COMPILE_EXCEPTION(v, qApp->translate("QmlCompiler","Cannot assign primitives to lists"));
+ }
+ }
+
+ }
+
+ return true;
+}
+
+// Compiles an assignment to a QmlScriptString property
+bool QmlCompiler::buildScriptStringProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ const BindingContext &ctxt)
+{
+ if (prop->values.count() > 1)
+ COMPILE_EXCEPTION(prop->values.at(1), qApp->translate("QmlCompiler", "Cannot assign multiple values to a script property"));
+
+ if (prop->values.at(0)->object || !prop->values.at(0)->value.isScript())
+ COMPILE_EXCEPTION(prop->values.at(0), qApp->translate("QmlCompiler", "Invalid property assignment: script expected"));
+
+ obj->addScriptStringProperty(prop, ctxt.stack);
+
+ return true;
+}
+
+// Compile regular property assignments of the form "property: <value>"
+//
+// ### The following problems exist
+//
+// There is no distinction between how "lists" of values are specified. This
+// Item {
+// children: Item {}
+// children: Item {}
+// }
+// is identical to
+// Item {
+// children: [ Item {}, Item {} ]
+// }
+//
+// We allow assignming multiple values to single value properties
+bool QmlCompiler::buildPropertyAssignment(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ const BindingContext &ctxt)
+{
+ obj->addValueProperty(prop);
+
+ for (int ii = 0; ii < prop->values.count(); ++ii) {
+ Value *v = prop->values.at(ii);
+ if (v->object) {
+
+ COMPILE_CHECK(buildPropertyObjectAssignment(prop, obj, v, ctxt));
+
+ } else {
+
+ COMPILE_CHECK(buildPropertyLiteralAssignment(prop, obj, v, ctxt));
+
+ }
+ }
+
+ return true;
+}
+
+// Compile assigning a single object instance to a regular property
+bool QmlCompiler::buildPropertyObjectAssignment(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ QmlParser::Value *v,
+ const BindingContext &ctxt)
+{
+ Q_ASSERT(prop->index != -1);
+ Q_ASSERT(v->object->type != -1);
+
+ if (QmlMetaType::isInterface(prop->type)) {
+
+ // Assigning an object to an interface ptr property
+ COMPILE_CHECK(buildObject(v->object, ctxt));
+
+ v->type = Value::CreatedObject;
+
+ } else if (prop->type == -1) {
+
+ // Assigning an object to a QVariant
+ COMPILE_CHECK(buildObject(v->object, ctxt));
+
+ v->type = Value::CreatedObject;
+ } else {
+ // Normally buildObject() will set this up, but we need the static
+ // meta object earlier to test for assignability. It doesn't matter
+ // that there may still be outstanding synthesized meta object changes
+ // on this type, as they are not relevant for assignability testing
+ v->object->metatype = output->types.at(v->object->type).metaObject();
+ Q_ASSERT(v->object->metaObject());
+
+ // Will be true if the assigned type inherits QmlPropertyValueSource
+ bool isPropertyValue = false;
+ // Will be true if the assigned type inherits QmlPropertyValueInterceptor
+ bool isPropertyInterceptor = false;
+ if (QmlType *valueType = QmlMetaType::qmlType(v->object->metatype)) {
+ isPropertyValue = valueType->propertyValueSourceCast() != -1;
+ isPropertyInterceptor = valueType->propertyValueInterceptorCast() != -1;
+ }
+
+ // We want to raw metaObject here as the raw metaobject is the
+ // actual property type before we applied any extensions that might
+ // effect the properties on the type, but don't effect assignability
+ const QMetaObject *propertyMetaObject =
+ QmlEnginePrivate::get(engine)->rawMetaObjectForType(prop->type);
+
+ // Will be true if the assgned type inherits propertyMetaObject
+ bool isAssignable = false;
+ // Determine isAssignable value
+ if (propertyMetaObject) {
+ const QMetaObject *c = v->object->metatype;
+ while(c) {
+ isAssignable |= (QmlMetaPropertyPrivate::equal(c, propertyMetaObject));
+ c = c->superClass();
+ }
+ }
+
+ if (isAssignable) {
+ // Simple assignment
+ COMPILE_CHECK(buildObject(v->object, ctxt));
+
+ v->type = Value::CreatedObject;
+ } else if (propertyMetaObject == &QmlComponent::staticMetaObject) {
+ // Automatic "Component" insertion
+ QmlParser::Object *root = v->object;
+ QmlParser::Object *component = new QmlParser::Object;
+ component->type = componentTypeRef();
+ component->typeName = "Qt/Component";
+ component->metatype = &QmlComponent::staticMetaObject;
+ component->location = root->location;
+ QmlParser::Value *componentValue = new QmlParser::Value;
+ componentValue->object = root;
+ component->getDefaultProperty()->addValue(componentValue);
+ v->object = component;
+ COMPILE_CHECK(buildPropertyObjectAssignment(prop, obj, v, ctxt));
+ } else if (isPropertyValue || isPropertyInterceptor) {
+ // Assign as a property value source
+ COMPILE_CHECK(buildObject(v->object, ctxt));
+
+ if (isPropertyInterceptor && prop->parent->synthdata.isEmpty())
+ buildDynamicMeta(prop->parent, ForceCreation);
+ v->type = isPropertyValue ? Value::ValueSource : Value::ValueInterceptor;
+ } else {
+ COMPILE_EXCEPTION(v->object, qApp->translate("QmlCompiler","Cannot assign object to property"));
+ }
+ }
+
+ return true;
+}
+
+// Compile assigning a literal or binding to a regular property
+bool QmlCompiler::buildPropertyLiteralAssignment(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ QmlParser::Value *v,
+ const BindingContext &ctxt)
+{
+ Q_ASSERT(prop->index != -1);
+
+ if (v->value.isScript()) {
+
+ COMPILE_CHECK(buildBinding(v, prop, ctxt));
+
+ v->type = Value::PropertyBinding;
+
+ } else {
+
+ COMPILE_CHECK(testLiteralAssignment(obj->metaObject()->property(prop->index), v));
+
+ v->type = Value::Literal;
+ }
+
+ return true;
+}
+
+// Ensures that the dynamic meta specification on obj is valid
+bool QmlCompiler::checkDynamicMeta(QmlParser::Object *obj)
+{
+ QSet<QByteArray> propNames;
+ QSet<QByteArray> methodNames;
+ bool seenDefaultProperty = false;
+
+ // Check properties
+ for (int ii = 0; ii < obj->dynamicProperties.count(); ++ii) {
+ const QmlParser::Object::DynamicProperty &prop =
+ obj->dynamicProperties.at(ii);
+
+ if (prop.isDefaultProperty) {
+ if (seenDefaultProperty)
+ COMPILE_EXCEPTION(obj, qApp->translate("QmlCompiler","Duplicate default property"));
+ seenDefaultProperty = true;
+ }
+
+ if (propNames.contains(prop.name))
+ COMPILE_EXCEPTION(obj, qApp->translate("QmlCompiler","Duplicate property name"));
+
+ propNames.insert(prop.name);
+ }
+
+ for (int ii = 0; ii < obj->dynamicSignals.count(); ++ii) {
+ QByteArray name = obj->dynamicSignals.at(ii).name;
+ if (methodNames.contains(name))
+ COMPILE_EXCEPTION(obj, qApp->translate("QmlCompiler","Duplicate signal name"));
+ methodNames.insert(name);
+ }
+ for (int ii = 0; ii < obj->dynamicSlots.count(); ++ii) {
+ QByteArray name = obj->dynamicSlots.at(ii).name;
+ if (methodNames.contains(name))
+ COMPILE_EXCEPTION(obj, qApp->translate("QmlCompiler","Duplicate method name"));
+ methodNames.insert(name);
+ }
+
+ return true;
+}
+
+bool QmlCompiler::mergeDynamicMetaProperties(QmlParser::Object *obj)
+{
+ for (int ii = 0; ii < obj->dynamicProperties.count(); ++ii) {
+ const Object::DynamicProperty &p = obj->dynamicProperties.at(ii);
+
+ if (!p.defaultValue || p.type == Object::DynamicProperty::Alias)
+ continue;
+
+ Property *property = 0;
+ if (p.isDefaultProperty)
+ property = obj->getDefaultProperty();
+ else
+ property = obj->getProperty(p.name);
+
+ if (property->value)
+ COMPILE_EXCEPTION(property, qApp->translate("QmlCompiler","Invalid property nesting"));
+
+ for (int ii = 0; ii < p.defaultValue->values.count(); ++ii) {
+ Value *v = p.defaultValue->values.at(ii);
+ v->addref();
+ property->values.append(v);
+ }
+ }
+ return true;
+}
+
+Q_GLOBAL_STATIC(QAtomicInt, classIndexCounter)
+
+bool QmlCompiler::buildDynamicMeta(QmlParser::Object *obj, DynamicMetaMode mode)
+{
+ Q_ASSERT(obj);
+ Q_ASSERT(obj->metatype);
+
+ if (mode != ForceCreation &&
+ obj->dynamicProperties.isEmpty() &&
+ obj->dynamicSignals.isEmpty() &&
+ obj->dynamicSlots.isEmpty())
+ return true;
+
+ COMPILE_CHECK(checkDynamicMeta(obj));
+
+ QByteArray dynamicData(sizeof(QmlVMEMetaData), (char)0);
+
+ QByteArray newClassName = obj->metatype->className();
+ newClassName.append("_QML_");
+ int idx = classIndexCounter()->fetchAndAddRelaxed(1);
+ newClassName.append(QByteArray::number(idx));
+
+ QMetaObjectBuilder builder;
+ builder.setClassName(newClassName);
+ builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
+
+ bool hasAlias = false;
+ for (int ii = 0; ii < obj->dynamicProperties.count(); ++ii) {
+ const Object::DynamicProperty &p = obj->dynamicProperties.at(ii);
+
+ int propIdx =
+ obj->metaObject()->indexOfProperty(p.name.constData());
+ if (-1 != propIdx) {
+ QMetaProperty prop = obj->metaObject()->property(propIdx);
+ if (prop.isFinal())
+ COMPILE_EXCEPTION(&p, qApp->translate("QmlCompiler","Cannot override FINAL property"));
+ }
+
+ if (p.isDefaultProperty &&
+ (p.type != Object::DynamicProperty::Alias ||
+ mode == ResolveAliases))
+ builder.addClassInfo("DefaultProperty", p.name);
+
+ QByteArray type;
+ int propertyType = 0;
+ bool readonly = false;
+ switch(p.type) {
+ case Object::DynamicProperty::Alias:
+ hasAlias = true;
+ continue;
+ break;
+ case Object::DynamicProperty::CustomList:
+ case Object::DynamicProperty::Custom:
+ {
+ QByteArray customTypeName;
+ QmlType *qmltype = 0;
+ QUrl url;
+ QmlEnginePrivate *priv = QmlEnginePrivate::get(engine);
+ if (!priv->resolveType(unit->imports, p.customType, &qmltype,
+ &url, 0, 0, 0))
+ COMPILE_EXCEPTION(&p, qApp->translate("QmlCompiler","Invalid property type"));
+
+ if (!qmltype) {
+ QmlCompositeTypeData *tdata = priv->typeManager.get(url);
+ Q_ASSERT(tdata);
+ Q_ASSERT(tdata->status == QmlCompositeTypeData::Complete);
+
+ QmlCompiledData *data = tdata->toCompiledComponent(engine);
+ customTypeName = data->root->className();
+ } else {
+ customTypeName = qmltype->typeName();
+ }
+
+ if (p.type == Object::DynamicProperty::Custom) {
+ type = customTypeName + "*";
+ propertyType = QMetaType::QObjectStar;
+ } else {
+ readonly = true;
+ type = "QmlList<";
+ type.append(customTypeName);
+ type.append("*>*");
+ propertyType = qMetaTypeId<QmlList<QObject*>* >();
+ }
+ }
+ break;
+ case Object::DynamicProperty::Variant:
+ propertyType = -1;
+ type = "QVariant";
+ break;
+ case Object::DynamicProperty::Int:
+ propertyType = QVariant::Int;
+ type = "int";
+ break;
+ case Object::DynamicProperty::Bool:
+ propertyType = QVariant::Bool;
+ type = "bool";
+ break;
+ case Object::DynamicProperty::Real:
+ propertyType = QVariant::Double;
+ type = "double";
+ break;
+ case Object::DynamicProperty::String:
+ propertyType = QVariant::String;
+ type = "QString";
+ break;
+ case Object::DynamicProperty::Url:
+ propertyType = QVariant::Url;
+ type = "QUrl";
+ break;
+ case Object::DynamicProperty::Color:
+ propertyType = QVariant::Color;
+ type = "QColor";
+ break;
+ case Object::DynamicProperty::Date:
+ propertyType = QVariant::Date;
+ type = "QDate";
+ break;
+ }
+
+ ((QmlVMEMetaData *)dynamicData.data())->propertyCount++;
+ QmlVMEMetaData::PropertyData propertyData = { propertyType };
+ dynamicData.append((char *)&propertyData, sizeof(propertyData));
+
+ builder.addSignal(p.name + "Changed()");
+ QMetaPropertyBuilder propBuilder =
+ builder.addProperty(p.name, type, builder.methodCount() - 1);
+ propBuilder.setScriptable(true);
+ propBuilder.setWritable(!readonly);
+ }
+
+ if (mode == ResolveAliases) {
+ for (int ii = 0; ii < obj->dynamicProperties.count(); ++ii) {
+ const Object::DynamicProperty &p = obj->dynamicProperties.at(ii);
+
+ if (p.type == Object::DynamicProperty::Alias) {
+ ((QmlVMEMetaData *)dynamicData.data())->aliasCount++;
+ compileAlias(builder, dynamicData, obj, p);
+ }
+ }
+ }
+
+ for (int ii = 0; ii < obj->dynamicSignals.count(); ++ii) {
+ const Object::DynamicSignal &s = obj->dynamicSignals.at(ii);
+ QByteArray sig(s.name + "(");
+ for (int jj = 0; jj < s.parameterTypes.count(); ++jj) {
+ if (jj) sig.append(",");
+ sig.append(s.parameterTypes.at(jj));
+ }
+ sig.append(")");
+ QMetaMethodBuilder b = builder.addSignal(sig);
+ b.setParameterNames(s.parameterNames);
+ ((QmlVMEMetaData *)dynamicData.data())->signalCount++;
+ }
+
+ for (int ii = 0; ii < obj->dynamicSlots.count(); ++ii) {
+ const Object::DynamicSlot &s = obj->dynamicSlots.at(ii);
+ QByteArray sig(s.name + "(");
+ for (int jj = 0; jj < s.parameterNames.count(); ++jj) {
+ if (jj) sig.append(",");
+ sig.append("QVariant");
+ }
+ sig.append(")");
+ QMetaMethodBuilder b = builder.addSlot(sig);
+ b.setParameterNames(s.parameterNames);
+
+ ((QmlVMEMetaData *)dynamicData.data())->methodCount++;
+ QmlVMEMetaData::MethodData methodData =
+ { s.parameterNames.count(), 0, s.body.length(), 0 };
+
+ dynamicData.append((char *)&methodData, sizeof(methodData));
+ }
+
+ for (int ii = 0; ii < obj->dynamicSlots.count(); ++ii) {
+ const Object::DynamicSlot &s = obj->dynamicSlots.at(ii);
+ QmlVMEMetaData::MethodData *data =
+ ((QmlVMEMetaData *)dynamicData.data())->methodData() + ii;
+
+ data->bodyOffset = dynamicData.size();
+
+ dynamicData.append((const char *)s.body.constData(),
+ (s.body.length() * sizeof(QChar)));
+ }
+
+ obj->metadata = builder.toRelocatableData();
+ builder.fromRelocatableData(&obj->extObject, obj->metatype, obj->metadata);
+
+ if (mode == IgnoreAliases && hasAlias)
+ compileState.aliasingObjects << obj;
+
+ obj->synthdata = dynamicData;
+
+ return true;
+}
+
+#include <private/qmljsparser_p.h>
+static QStringList astNodeToStringList(QmlJS::AST::Node *node)
+{
+ if (node->kind == QmlJS::AST::Node::Kind_IdentifierExpression) {
+ QString name =
+ static_cast<QmlJS::AST::IdentifierExpression *>(node)->name->asString();
+ return QStringList() << name;
+ } else if (node->kind == QmlJS::AST::Node::Kind_FieldMemberExpression) {
+ QmlJS::AST::FieldMemberExpression *expr = static_cast<QmlJS::AST::FieldMemberExpression *>(node);
+
+ QStringList rv = astNodeToStringList(expr->base);
+ if (rv.isEmpty())
+ return rv;
+ rv.append(expr->name->asString());
+ return rv;
+ }
+ return QStringList();
+}
+
+bool QmlCompiler::compileAlias(QMetaObjectBuilder &builder,
+ QByteArray &data,
+ Object *obj,
+ const Object::DynamicProperty &prop)
+{
+ if (!prop.defaultValue)
+ COMPILE_EXCEPTION(obj, qApp->translate("QmlCompiler","No property alias location"));
+
+ if (prop.defaultValue->values.count() != 1 ||
+ prop.defaultValue->values.at(0)->object ||
+ !prop.defaultValue->values.at(0)->value.isScript())
+ COMPILE_EXCEPTION(prop.defaultValue, qApp->translate("QmlCompiler","Invalid alias location"));
+
+ QmlJS::AST::Node *node = prop.defaultValue->values.at(0)->value.asAST();
+ if (!node)
+ COMPILE_EXCEPTION(obj, qApp->translate("QmlCompiler","No property alias location")); // ### Can this happen?
+
+ QStringList alias = astNodeToStringList(node);
+
+ if (alias.count() != 1 && alias.count() != 2)
+ COMPILE_EXCEPTION(prop.defaultValue, qApp->translate("QmlCompiler","Invalid alias location"));
+
+ if (!compileState.ids.contains(alias.at(0)))
+ COMPILE_EXCEPTION(prop.defaultValue, qApp->translate("QmlCompiler","Invalid alias location"));
+
+ Object *idObject = compileState.ids[alias.at(0)];
+
+ QByteArray typeName;
+
+ int propIdx = -1;
+ bool writable = false;
+ if (alias.count() == 2) {
+ propIdx = idObject->metaObject()->indexOfProperty(alias.at(1).toUtf8().constData());
+
+ if (-1 == propIdx)
+ COMPILE_EXCEPTION(prop.defaultValue, qApp->translate("QmlCompiler","Invalid alias location"));
+
+ QMetaProperty aliasProperty = idObject->metaObject()->property(propIdx);
+ writable = aliasProperty.isWritable();
+
+ if (aliasProperty.isEnumType())
+ typeName = "int"; // Avoid introducing a dependency on the aliased metaobject
+ else
+ typeName = aliasProperty.typeName();
+ } else {
+ typeName = idObject->metaObject()->className();
+ typeName += "*";
+ }
+
+ data.append((const char *)&idObject->idIndex, sizeof(idObject->idIndex));
+ data.append((const char *)&propIdx, sizeof(propIdx));
+
+ builder.addSignal(prop.name + "Changed()");
+ QMetaPropertyBuilder propBuilder =
+ builder.addProperty(prop.name, typeName.constData(), builder.methodCount() - 1);
+ propBuilder.setScriptable(true);
+ propBuilder.setWritable(writable);
+ return true;
+}
+
+bool QmlCompiler::buildBinding(QmlParser::Value *value,
+ QmlParser::Property *prop,
+ const BindingContext &ctxt)
+{
+ Q_ASSERT(prop->index);
+ Q_ASSERT(prop->parent);
+ Q_ASSERT(prop->parent->metaObject());
+
+ QMetaProperty mp = prop->parent->metaObject()->property(prop->index);
+ if (!mp.isWritable() && !QmlMetaType::isList(prop->type))
+ COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","Invalid property assignment: \"%1\" is a read-only property").arg(QString::fromUtf8(prop->name)));
+
+ BindingReference reference;
+ reference.expression = value->value;
+ reference.property = prop;
+ reference.value = value;
+ reference.bindingContext = ctxt;
+ addBindingReference(reference);
+
+ return true;
+}
+
+void QmlCompiler::genBindingAssignment(QmlParser::Value *binding,
+ QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ QmlParser::Property *valueTypeProperty)
+{
+ Q_UNUSED(obj);
+ Q_ASSERT(compileState.bindings.contains(binding));
+
+ const BindingReference &ref = compileState.bindings.value(binding);
+
+ QmlInstruction store;
+
+ QmlBasicScript bs;
+ if (ref.isBasicScript)
+ bs.load(ref.compiledData.constData() + sizeof(quint32));
+
+ if (bs.isSingleIdFetch()) {
+ int idIndex = bs.singleIdFetchIndex();
+ QmlParser::Object *idObj = compileState.idIndexes.value(idIndex);
+ if (canCoerce(prop->type, idObj)) {
+ store.type = QmlInstruction::StoreIdOptBinding;
+ store.assignIdOptBinding.id = idIndex;
+ store.assignIdOptBinding.property = prop->index;
+ output->bytecode << store;
+ return;
+ }
+ } else if (bs.isSingleContextProperty()) {
+ int propIndex = bs.singleContextPropertyIndex();
+
+ QMetaProperty p =
+ ref.bindingContext.object->metaObject()->property(propIndex);
+ if ((p.notifySignalIndex() != -1 || p.isConstant()) &&
+ canCoerce(prop->type, p.userType())) {
+
+ store.type = QmlInstruction::StoreObjPropBinding;
+ store.assignObjPropBinding.property = prop->index;
+ store.assignObjPropBinding.contextIdx = propIndex;
+ store.assignObjPropBinding.context = ref.bindingContext.stack;
+ store.assignObjPropBinding.notifyIdx = p.notifySignalIndex();
+
+ output->bytecode << store;
+ return;
+ }
+ }
+
+ store.type = QmlInstruction::StoreBinding;
+ store.assignBinding.value = output->indexForByteArray(ref.compiledData);
+ store.assignBinding.context = ref.bindingContext.stack;
+ store.assignBinding.owner = ref.bindingContext.owner;
+ store.line = binding->location.start.line;
+
+ Q_ASSERT(ref.bindingContext.owner == 0 ||
+ (ref.bindingContext.owner != 0 && valueTypeProperty));
+ if (ref.bindingContext.owner) {
+ store.assignBinding.property =
+ QmlMetaPropertyPrivate::saveValueType(valueTypeProperty->index,
+ prop->index);
+ } else {
+ store.assignBinding.property =
+ QmlMetaPropertyPrivate::saveProperty(prop->index);
+ }
+
+ 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) {
+ Object *aliasObject = compileState.aliasingObjects.at(ii);
+ COMPILE_CHECK(buildDynamicMeta(aliasObject, ResolveAliases));
+ }
+
+ QmlBasicScript::Expression expr;
+ expr.component = compileState.root;
+ expr.ids = compileState.ids;
+
+ for (QHash<QmlParser::Value*,BindingReference>::Iterator iter = compileState.bindings.begin(); iter != compileState.bindings.end(); ++iter) {
+ BindingReference &binding = *iter;
+
+ QmlBasicScript bs;
+ expr.context = binding.bindingContext.object;
+ expr.property = binding.property;
+ expr.expression = binding.expression;
+
+ bs.compile(expr);
+ quint32 type;
+ if (bs.isValid()) {
+ binding.compiledData =
+ QByteArray(bs.compileData(), bs.compileDataSize());
+ type = QmlExpressionPrivate::BasicScriptEngineData;
+ binding.isBasicScript = true;
+ } else {
+ type = QmlExpressionPrivate::PreTransformedQtScriptData;
+
+ // Pre-rewrite the expression
+ QString expression = binding.expression.asScript();
+ QmlRewrite::RewriteBinding rewriteBinding;
+ 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));
+ binding.isBasicScript = false;
+ }
+ binding.compiledData.prepend(QByteArray((const char *)&type,
+ sizeof(quint32)));
+ }
+
+ saveComponentState();
+
+ return true;
+}
+
+/*!
+ Returns true if from can be assigned to a (QObject) property of type
+ to.
+*/
+bool QmlCompiler::canCoerce(int to, QmlParser::Object *from)
+{
+ const QMetaObject *toMo =
+ QmlEnginePrivate::get(engine)->rawMetaObjectForType(to);
+ const QMetaObject *fromMo = from->metaObject();
+
+ while (fromMo) {
+ if (QmlMetaPropertyPrivate::equal(fromMo, toMo))
+ return true;
+ fromMo = fromMo->superClass();
+ }
+ return false;
+}
+
+/*!
+ Returns true if from can be assigned to a (QObject) property of type
+ to.
+*/
+bool QmlCompiler::canCoerce(int to, int from)
+{
+ const QMetaObject *toMo =
+ QmlEnginePrivate::get(engine)->rawMetaObjectForType(to);
+ const QMetaObject *fromMo =
+ QmlEnginePrivate::get(engine)->rawMetaObjectForType(from);
+
+ while (fromMo) {
+ if (QmlMetaPropertyPrivate::equal(fromMo, toMo))
+ return true;
+ fromMo = fromMo->superClass();
+ }
+ return false;
+}
+
+QmlType *QmlCompiler::toQmlType(QmlParser::Object *from)
+{
+ // ### Optimize
+ const QMetaObject *mo = from->metatype;
+ QmlType *type = 0;
+ while (!type && mo) {
+ type = QmlMetaType::qmlType(mo);
+ mo = mo->superClass();
+ }
+ return type;
+}
+
+QStringList QmlCompiler::deferredProperties(QmlParser::Object *obj)
+{
+ const QMetaObject *mo = obj->metatype;
+
+ int idx = mo->indexOfClassInfo("DeferredPropertyNames");
+ if (idx == -1)
+ return QStringList();
+
+ QMetaClassInfo classInfo = mo->classInfo(idx);
+ QStringList rv = QString::fromUtf8(classInfo.value()).split(QLatin1Char(','));
+ return rv;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h
new file mode 100644
index 0000000..8a9ca9c
--- /dev/null
+++ b/src/declarative/qml/qmlcompiler_p.h
@@ -0,0 +1,294 @@
+/****************************************************************************
+**
+** 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 QMLCOMPILER_P_H
+#define QMLCOMPILER_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/qbytearray.h>
+#include <QtCore/qset.h>
+#include <QtDeclarative/qml.h>
+#include <QtDeclarative/qmlerror.h>
+#include <private/qmlinstruction_p.h>
+#include <private/qmlcompositetypemanager_p.h>
+#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
+
+class QmlEngine;
+class QmlComponent;
+class QmlContext;
+
+class QScriptProgram;
+class QmlCompiledData : public QmlRefCount
+{
+public:
+ QmlCompiledData();
+ virtual ~QmlCompiledData();
+
+ QByteArray name;
+ QUrl url;
+ QmlEnginePrivate::Imports imports;
+ QmlTypeNameCache *importCache;
+
+ struct TypeReference
+ {
+ TypeReference()
+ : type(0), component(0), ref(0) {}
+
+ QByteArray className;
+ QmlType *type;
+ QmlComponent *component;
+
+ QmlRefCount *ref;
+ QObject *createInstance(QmlContext *, const QBitField &) const;
+ const QMetaObject *metaObject() const;
+ };
+ QList<TypeReference> types;
+ struct CustomTypeData
+ {
+ int index;
+ int type;
+ };
+
+ const QMetaObject *root;
+ QAbstractDynamicMetaObject rootData;
+ QList<QString> primitives;
+ QList<float> floatData;
+ QList<int> intData;
+ QList<CustomTypeData> customTypeData;
+ QList<QByteArray> datas;
+ QList<QmlParser::Location> locations;
+ QList<QmlInstruction> bytecode;
+ QList<QScriptProgram *> programs;
+ QList<QmlPropertyCache *> propertyCaches;
+ QList<QmlIntegerCache *> contextCaches;
+
+ void dumpInstructions();
+private:
+ void dump(QmlInstruction *, int idx = -1);
+ QmlCompiledData(const QmlCompiledData &other);
+ QmlCompiledData &operator=(const QmlCompiledData &other);
+ QByteArray packData;
+ friend class QmlCompiler;
+ int pack(const char *, size_t);
+
+ int indexForString(const QString &);
+ int indexForByteArray(const QByteArray &);
+ int indexForFloat(float *, int);
+ int indexForInt(int *, int);
+ int indexForLocation(const QmlParser::Location &);
+ int indexForLocation(const QmlParser::LocationSpan &);
+};
+
+class QMetaObjectBuilder;
+class Q_DECLARATIVE_EXPORT QmlCompiler
+{
+public:
+ QmlCompiler();
+
+ bool compile(QmlEngine *, QmlCompositeTypeData *, QmlCompiledData *);
+
+ bool isError() const;
+ QList<QmlError> errors() const;
+
+ static bool isValidId(const QString &);
+ static bool isAttachedPropertyName(const QByteArray &);
+ static bool isSignalPropertyName(const QByteArray &);
+
+private:
+ static void reset(QmlCompiledData *);
+
+ struct BindingContext {
+ BindingContext()
+ : stack(0), owner(0), object(0) {}
+ BindingContext(QmlParser::Object *o)
+ : stack(0), owner(0), object(o) {}
+ BindingContext incr() const {
+ BindingContext rv(object);
+ rv.stack = stack + 1;
+ return rv;
+ }
+ bool isSubContext() const { return stack != 0; }
+ int stack;
+ int owner;
+ QmlParser::Object *object;
+ };
+
+ void compileTree(QmlParser::Object *tree);
+
+
+ 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,
+ const BindingContext &);
+ bool buildProperty(QmlParser::Property *prop, QmlParser::Object *obj,
+ const BindingContext &);
+ bool buildPropertyInNamespace(QmlEnginePrivate::ImportedNamespace *ns,
+ QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ const BindingContext &);
+ bool buildIdProperty(QmlParser::Property *prop, QmlParser::Object *obj);
+ bool buildAttachedProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ const BindingContext &ctxt);
+ bool buildGroupedProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ const BindingContext &ctxt);
+ bool buildValueTypeProperty(QObject *type,
+ QmlParser::Object *obj,
+ QmlParser::Object *baseObj,
+ const BindingContext &ctxt);
+ bool buildListProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ const BindingContext &ctxt);
+ bool buildScriptStringProperty(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ const BindingContext &ctxt);
+ bool buildPropertyAssignment(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ const BindingContext &ctxt);
+ bool buildPropertyObjectAssignment(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ QmlParser::Value *value,
+ const BindingContext &ctxt);
+ bool buildPropertyLiteralAssignment(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ QmlParser::Value *value,
+ const BindingContext &ctxt);
+ bool doesPropertyExist(QmlParser::Property *prop, QmlParser::Object *obj);
+ bool testLiteralAssignment(const QMetaProperty &prop,
+ QmlParser::Value *value);
+ enum DynamicMetaMode { IgnoreAliases, ResolveAliases, ForceCreation };
+ bool mergeDynamicMetaProperties(QmlParser::Object *obj);
+ bool buildDynamicMeta(QmlParser::Object *obj, DynamicMetaMode mode);
+ bool checkDynamicMeta(QmlParser::Object *obj);
+ bool buildBinding(QmlParser::Value *, QmlParser::Property *prop,
+ const BindingContext &ctxt);
+ bool buildComponentFromRoot(QmlParser::Object *obj, const BindingContext &);
+ bool compileAlias(QMetaObjectBuilder &,
+ QByteArray &data,
+ QmlParser::Object *obj,
+ const QmlParser::Object::DynamicProperty &);
+ bool completeComponentBuild();
+
+
+ void genObject(QmlParser::Object *obj);
+ void genObjectBody(QmlParser::Object *obj);
+ void genComponent(QmlParser::Object *obj);
+ void genValueProperty(QmlParser::Property *prop, QmlParser::Object *obj);
+ void genListProperty(QmlParser::Property *prop, QmlParser::Object *obj);
+ void genPropertyAssignment(QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ QmlParser::Property *valueTypeProperty = 0);
+ void genLiteralAssignment(const QMetaProperty &prop,
+ QmlParser::Value *value);
+ void genBindingAssignment(QmlParser::Value *binding,
+ QmlParser::Property *prop,
+ QmlParser::Object *obj,
+ QmlParser::Property *valueTypeProperty = 0);
+ int genContextCache();
+
+ int componentTypeRef();
+
+ static int findSignalByName(const QMetaObject *, const QByteArray &name);
+ static QmlType *toQmlType(QmlParser::Object *from);
+ bool canCoerce(int to, QmlParser::Object *from);
+ bool canCoerce(int to, int from);
+
+ QStringList deferredProperties(QmlParser::Object *);
+
+ void addId(const QString &, QmlParser::Object *);
+
+ struct BindingReference {
+ QmlParser::Variant expression;
+ QmlParser::Property *property;
+ QmlParser::Value *value;
+ bool isBasicScript;
+ QByteArray compiledData;
+ BindingContext bindingContext;
+ };
+ void addBindingReference(const BindingReference &);
+
+ struct ComponentCompileState
+ {
+ ComponentCompileState()
+ : parserStatusCount(0), pushedProperties(0), root(0) {}
+ QHash<QString, QmlParser::Object *> ids;
+ QHash<int, QmlParser::Object *> idIndexes;
+ int parserStatusCount;
+ int pushedProperties;
+
+ QHash<QmlParser::Value *, BindingReference> bindings;
+ QList<QmlParser::Object *> aliasingObjects;
+ QmlParser::Object *root;
+ };
+ ComponentCompileState compileState;
+
+ void saveComponentState();
+ ComponentCompileState componentState(QmlParser::Object *);
+ QHash<QmlParser::Object *, ComponentCompileState> savedCompileStates;
+
+ QList<QmlError> exceptions;
+ QmlCompiledData *output;
+ QmlEngine *engine;
+ QmlCompositeTypeData *unit;
+};
+QT_END_NAMESPACE
+
+#endif // QMLCOMPILER_P_H
diff --git a/src/declarative/qml/qmlcomponent.cpp b/src/declarative/qml/qmlcomponent.cpp
new file mode 100644
index 0000000..12fb120
--- /dev/null
+++ b/src/declarative/qml/qmlcomponent.cpp
@@ -0,0 +1,682 @@
+/****************************************************************************
+**
+** 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 "qmlcomponent.h"
+#include "qmlcomponent_p.h"
+#include "qmlcompiler_p.h"
+#include "private/qmlcontext_p.h"
+#include "private/qmlcompositetypedata_p.h"
+#include "private/qmlengine_p.h"
+#include "qmlvme_p.h"
+#include "qml.h"
+#include <QStack>
+#include <private/qfxperf_p.h>
+#include <QStringList>
+#include <qmlengine.h>
+#include <QFileInfo>
+#include "qmlbinding.h"
+#include <QtCore/qdebug.h>
+#include <QApplication>
+
+#include "qmlscriptparser_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QByteArray;
+int statusId = qRegisterMetaType<QmlComponent::Status>("QmlComponent::Status");
+
+/*!
+ \class QmlComponent
+ \brief The QmlComponent class encapsulates a QML component description.
+ \mainclass
+*/
+
+/*!
+ \qmlclass Component QmlComponent
+ \brief The Component element encapsulates a QML component description.
+
+ Components are reusable, encapsulated Qml element with a well-defined interface.
+ They are often defined in \l {components}{Component Files}.
+
+ The \e Component element allows defining components within a QML file.
+ This can be useful for reusing a small component within a single QML
+ file, or for defining a component that logically belongs with the
+ file containing it.
+
+ \qml
+Item {
+ Component {
+ id: redSquare
+ Rectangle {
+ color: "red"
+ width: 10
+ height: 10
+ }
+ }
+ Loader { sourceComponent: redSquare }
+ Loader { sourceComponent: redSquare; x: 20 }
+}
+ \endqml
+
+ \section1 Attached Properties
+
+ \e onCompleted
+
+ Emitted after component "startup" has completed. This can be used to
+ execute script code at startup, once the full QML environment has been
+ established.
+
+ The \c {Component::onCompleted} attached property can be applied to
+ any element. The order of running the \c onCompleted scripts is
+ undefined.
+
+ \qml
+ Rectangle {
+ Component.onCompleted: print("Completed Running!")
+ Rectangle {
+ Component.onCompleted: print("Nested Completed Running!")
+ }
+ }
+ \endqml
+*/
+QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,Component,QmlComponent);
+
+/*!
+ \enum QmlComponent::Status
+
+ Specifies the loading status of the QmlComponent.
+
+ \value Null This QmlComponent has no data. Call loadUrl() or setData() to add QML content.
+ \value Ready This QmlComponent is ready and create() may be called.
+ \value Loading This QmlComponent is loading network data.
+ \value Error An error has occured. Calling errorDescription() to retrieve a description.
+*/
+
+void QmlComponentPrivate::typeDataReady()
+{
+ Q_Q(QmlComponent);
+
+ Q_ASSERT(typeData);
+
+ fromTypeData(typeData);
+ typeData = 0;
+
+ emit q->statusChanged(q->status());
+}
+
+void QmlComponentPrivate::updateProgress(qreal p)
+{
+ Q_Q(QmlComponent);
+
+ progress = p;
+ emit q->progressChanged(p);
+}
+
+void QmlComponentPrivate::fromTypeData(QmlCompositeTypeData *data)
+{
+ url = data->imports.baseUrl();
+ QmlCompiledData *c = data->toCompiledComponent(engine);
+
+ if (!c) {
+ Q_ASSERT(data->status == QmlCompositeTypeData::Error);
+
+ errors = data->errors;
+
+ } else {
+
+ cc = c;
+
+ }
+
+ data->release();
+}
+
+void QmlComponentPrivate::clear()
+{
+ if (typeData) {
+ typeData->remWaiter(this);
+ typeData->release();
+ typeData = 0;
+ }
+
+ if (cc) {
+ cc->release();
+ cc = 0;
+ }
+}
+
+/*!
+ \internal
+*/
+QmlComponent::QmlComponent(QObject *parent)
+ : QObject(*(new QmlComponentPrivate), parent)
+{
+}
+
+/*!
+ Destruct the QmlComponent.
+*/
+QmlComponent::~QmlComponent()
+{
+ Q_D(QmlComponent);
+ if (d->typeData) {
+ d->typeData->remWaiter(d);
+ d->typeData->release();
+ }
+ if (d->cc)
+ d->cc->release();
+
+ for(int ii = 0; ii < d->bindValues.count(); ++ii)
+ QmlEnginePrivate::clear(d->bindValues[ii]);
+ for(int ii = 0; ii < d->parserStatus.count(); ++ii)
+ QmlEnginePrivate::clear(d->parserStatus[ii]);
+}
+
+/*!
+ Returns the component's current \l{QmlComponent::Status} {status}.
+ */
+QmlComponent::Status QmlComponent::status() const
+{
+ Q_D(const QmlComponent);
+
+ if (d->typeData)
+ return Loading;
+ else if (!d->errors.isEmpty())
+ return Error;
+ else if (d->engine && d->cc)
+ return Ready;
+ else
+ return Null;
+}
+
+/*!
+ Returns true if the component is in the Null state, false otherwise.
+
+ Equivalent to status() == QmlComponent::Null.
+*/
+bool QmlComponent::isNull() const
+{
+ return status() == Null;
+}
+
+/*!
+ Returns true if the component is in the Ready state, false otherwise.
+
+ Equivalent to status() == QmlComponent::Ready.
+*/
+bool QmlComponent::isReady() const
+{
+ return status() == Ready;
+}
+
+/*!
+ Returns true if the component is in the Error state, false otherwise.
+
+ Equivalent to status() == QmlComponent::Error.
+*/
+bool QmlComponent::isError() const
+{
+ return status() == Error;
+}
+
+/*!
+ Returns true if the component is in the Loading state, false otherwise.
+
+ Equivalent to status() == QmlComponent::Loading.
+*/
+bool QmlComponent::isLoading() const
+{
+ return status() == Loading;
+}
+
+qreal QmlComponent::progress() const
+{
+ Q_D(const QmlComponent);
+ return d->progress;
+}
+
+/*!
+ \fn void QmlComponent::statusChanged(QmlComponent::Status status)
+
+ Emitted whenever the component's status changes. \a status will be the
+ new status.
+*/
+
+/*!
+ Create a QmlComponent with no data and give it the specified
+ \a engine and \a parent. Set the data with setData().
+*/
+QmlComponent::QmlComponent(QmlEngine *engine, QObject *parent)
+ : QObject(*(new QmlComponentPrivate), parent)
+{
+ Q_D(QmlComponent);
+ d->engine = engine;
+}
+
+/*!
+ Create a QmlComponent from the given \a url and give it the
+ specified \a parent and \a engine.
+
+ \sa loadUrl()
+*/
+QmlComponent::QmlComponent(QmlEngine *engine, const QUrl &url, QObject *parent)
+: QObject(*(new QmlComponentPrivate), parent)
+{
+ Q_D(QmlComponent);
+ d->engine = engine;
+ loadUrl(url);
+}
+
+/*!
+ Create a QmlComponent from the given \a fileName and give it the specified
+ \a parent and \a engine.
+
+ \sa loadUrl()
+*/
+QmlComponent::QmlComponent(QmlEngine *engine, const QString &fileName,
+ QObject *parent)
+: QObject(*(new QmlComponentPrivate), parent)
+{
+ Q_D(QmlComponent);
+ d->engine = engine;
+ loadUrl(QUrl::fromLocalFile(fileName));
+}
+
+/*!
+ Create a QmlComponent from the given QML \a data and give it the
+ specified \a parent and \a engine. \a url is used to provide a base path
+ for items resolved by this component, and may be an empty url if the
+ component contains no items to resolve.
+
+ \sa setData()
+*/
+QmlComponent::QmlComponent(QmlEngine *engine, const QByteArray &data, const QUrl &url, QObject *parent)
+ : QObject(*(new QmlComponentPrivate), parent)
+{
+ Q_D(QmlComponent);
+ d->engine = engine;
+ setData(data,url);
+}
+
+/*!
+ \internal
+*/
+QmlComponent::QmlComponent(QmlEngine *engine, QmlCompiledData *cc, int start, int count, QObject *parent)
+ : QObject(*(new QmlComponentPrivate), parent)
+{
+ Q_D(QmlComponent);
+ d->engine = engine;
+ d->cc = cc;
+ cc->addref();
+ d->start = start;
+ d->count = count;
+ d->url = cc->url;
+ d->progress = 1.0;
+}
+
+/*!
+ Sets the QmlComponent to use the given QML \a data. If \a url
+ is provided, it is used to set the component name and to provide
+ a base path for items resolved by this component.
+*/
+void QmlComponent::setData(const QByteArray &data, const QUrl &url)
+{
+ Q_D(QmlComponent);
+
+ d->clear();
+
+ d->url = url;
+
+ QmlCompositeTypeData *typeData =
+ QmlEnginePrivate::get(d->engine)->typeManager.getImmediate(data, url);
+
+ if (typeData->status == QmlCompositeTypeData::Waiting) {
+
+ d->typeData = typeData;
+ d->typeData->addWaiter(d);
+
+ } else {
+
+ d->fromTypeData(typeData);
+
+ }
+
+ d->progress = 1.0;
+ emit statusChanged(status());
+ emit progressChanged(d->progress);
+}
+
+/*!
+Returns the QmlContext the component was created in. This is only
+valid for components created directly from QML.
+*/
+QmlContext *QmlComponent::creationContext() const
+{
+ Q_D(const QmlComponent);
+
+ QmlDeclarativeData *ddata = QmlDeclarativeData::get(this);
+ if (ddata)
+ return ddata->context;
+ else
+ return 0;
+}
+
+/*!
+ Load the QmlComponent from the provided \a url.
+*/
+void QmlComponent::loadUrl(const QUrl &url)
+{
+ Q_D(QmlComponent);
+
+ d->clear();
+
+ if (url.isRelative() && !url.isEmpty())
+ d->url = d->engine->baseUrl().resolved(url);
+ else
+ d->url = url;
+
+ QmlCompositeTypeData *data =
+ QmlEnginePrivate::get(d->engine)->typeManager.get(d->url);
+
+ if (data->status == QmlCompositeTypeData::Waiting) {
+ d->typeData = data;
+ d->typeData->addWaiter(d);
+ d->progress = data->progress;
+ } else {
+ d->fromTypeData(data);
+ d->progress = 1.0;
+ }
+
+ emit statusChanged(status());
+ emit progressChanged(d->progress);
+}
+
+/*!
+ Return the list of errors that occured during the last compile or create
+ operation. An empty list is returned if isError() is not set.
+*/
+QList<QmlError> QmlComponent::errors() const
+{
+ Q_D(const QmlComponent);
+ if (isError())
+ return d->errors;
+ else
+ return QList<QmlError>();
+}
+
+/*!
+ Return the component URL. This is the URL passed to either the constructor,
+ or the loadUrl() or setData() methods.
+*/
+QUrl QmlComponent::url() const
+{
+ Q_D(const QmlComponent);
+ return d->url;
+}
+
+/*!
+ \internal
+*/
+QmlComponent::QmlComponent(QmlComponentPrivate &dd, QObject *parent)
+ : QObject(dd, parent)
+{
+}
+
+
+/*!
+ Create an object instance from this component. Returns 0 if creation
+ failed. \a context specifies the context within which to create the object
+ instance.
+
+ If \a context is 0 (the default), it will create the instance in the
+ engine' s \l {QmlEngine::rootContext()}{root context}.
+*/
+QObject *QmlComponent::create(QmlContext *context)
+{
+ Q_D(QmlComponent);
+
+ return d->create(context, QBitField());
+}
+
+QObject *QmlComponentPrivate::create(QmlContext *context,
+ const QBitField &bindings)
+{
+ QObject *create(QmlContext *context, const QBitField &);
+ if (!context)
+ context = engine->rootContext();
+
+ if (context->engine() != engine) {
+ qWarning("QmlComponent::create(): Must create component in context from the same QmlEngine");
+ return 0;
+ }
+
+ QObject *rv = beginCreate(context, bindings);
+ completeCreate();
+ return rv;
+}
+
+/*!
+ This method provides more advanced control over component instance creation.
+ In general, programmers should use QmlComponent::create() to create a
+ component.
+
+ Create an object instance from this component. Returns 0 if creation
+ failed. \a context specifies the context within which to create the object
+ instance.
+
+ When QmlComponent constructs an instance, it occurs in three steps:
+ \list 1
+ \i The object hierarchy is created, and constant values are assigned.
+ \i Property bindings are evaluated for the the first time.
+ \i If applicable, QmlParserStatus::componentComplete() is called on objects.
+ \endlist
+ QmlComponent::beginCreate() differs from QmlComponent::create() in that it
+ only performs step 1. QmlComponent::completeCreate() must be called to
+ complete steps 2 and 3.
+
+ This breaking point is sometimes useful when using attached properties to
+ communicate information to an instantiated component, as it allows their
+ initial values to be configured before property bindings take effect.
+*/
+QObject *QmlComponent::beginCreate(QmlContext *context)
+{
+ Q_D(QmlComponent);
+ return d->beginCreate(context, QBitField());
+}
+
+QObject *
+QmlComponentPrivate::beginCreate(QmlContext *context, const QBitField &bindings)
+{
+ Q_Q(QmlComponent);
+ if (!context) {
+ qWarning("QmlComponent::beginCreate(): Cannot create a component in a null context");
+ return 0;
+ }
+
+ if (context->engine() != engine) {
+ qWarning("QmlComponent::beginCreate(): Must create component in context from the same QmlEngine");
+ return 0;
+ }
+
+ if (completePending) {
+ qWarning("QmlComponent: Cannot create new component instance before completing the previous");
+ return 0;
+ }
+
+ if (!q->isReady()) {
+ qWarning("QmlComponent: Component is not ready");
+ return 0;
+ }
+
+ if (!QmlEnginePrivate::get(engine)->rootComponent)
+ QmlEnginePrivate::get(engine)->rootComponent = q;
+
+ QmlContextPrivate *contextPriv =
+ 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->importCache;
+ cc->importCache->addref();
+
+ QmlVME vme;
+ QObject *rv = vme.run(ctxt, cc, start, count, bindings);
+
+ if (vme.isError())
+ errors = vme.errors();
+
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
+ if (ep->rootComponent == q) {
+ ep->rootComponent = 0;
+
+ bindValues = ep->bindValues;
+ parserStatus = ep->parserStatus;
+ componentAttacheds = ep->componentAttacheds;
+ if (componentAttacheds)
+ componentAttacheds->prev = &componentAttacheds;
+
+ ep->componentAttacheds = 0;
+ ep->bindValues.clear();
+ ep->parserStatus.clear();
+ completePending = true;
+ }
+
+ if (rv) {
+ QFx_setParent_noEvent(ctxt, rv);
+ } else {
+ delete ctxt;
+ }
+
+ if (rv && !contextPriv->isInternal && ep->isDebugging)
+ contextPriv->instances.append(rv);
+ return rv;
+}
+
+/*!
+ This method provides more advanced control over component instance creation.
+ In general, programmers should use QmlComponent::create() to create a
+ component.
+
+ Complete a component creation begin with QmlComponent::beginCreate().
+*/
+void QmlComponent::completeCreate()
+{
+ Q_D(QmlComponent);
+ d->completeCreate();
+}
+
+void QmlComponentPrivate::completeCreate()
+{
+ if (completePending) {
+ {
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::BindInit> bi;
+#endif
+ for (int ii = 0; ii < bindValues.count(); ++ii) {
+ QmlEnginePrivate::SimpleList<QmlAbstractBinding> bv =
+ bindValues.at(ii);
+ for (int jj = 0; jj < bv.count; ++jj) {
+ if(bv.at(jj))
+ bv.at(jj)->setEnabled(true, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding);
+ }
+ QmlEnginePrivate::clear(bv);
+ }
+ }
+
+ for (int ii = 0; ii < parserStatus.count(); ++ii) {
+ QmlEnginePrivate::SimpleList<QmlParserStatus> ps =
+ parserStatus.at(ii);
+
+ for (int jj = 0; jj < ps.count; ++jj) {
+ QmlParserStatus *status = ps.at(jj);
+ if (status && status->d) {
+ status->d = 0;
+ status->componentComplete();
+ }
+ }
+ QmlEnginePrivate::clear(ps);
+ }
+
+ while (componentAttacheds) {
+ QmlComponentAttached *a = componentAttacheds;
+ if (a->next) a->next->prev = &componentAttacheds;
+ componentAttacheds = a->next;
+ a->prev = 0; a->next = 0;
+ emit a->completed();
+ }
+
+ bindValues.clear();
+ parserStatus.clear();
+ completePending = false;
+ }
+}
+
+QmlComponentAttached::QmlComponentAttached(QObject *parent)
+: QObject(parent), prev(0), next(0)
+{
+}
+
+QmlComponentAttached::~QmlComponentAttached()
+{
+ if (prev) *prev = next;
+ if (next) next->prev = prev;
+ prev = 0;
+ next = 0;
+}
+
+QmlComponentAttached *QmlComponent::qmlAttachedProperties(QObject *obj)
+{
+ QmlComponentAttached *a = new QmlComponentAttached(obj);
+
+ QmlEngine *engine = qmlEngine(obj);
+ if (!engine || !QmlEnginePrivate::get(engine)->rootComponent)
+ return a;
+
+ QmlEnginePrivate *p = QmlEnginePrivate::get(engine);
+
+ a->next = p->componentAttacheds;
+ a->prev = &p->componentAttacheds;
+ if (a->next) a->next->prev = &a->next;
+ p->componentAttacheds = a;
+
+ return a;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcomponent.h b/src/declarative/qml/qmlcomponent.h
new file mode 100644
index 0000000..a72aa4e
--- /dev/null
+++ b/src/declarative/qml/qmlcomponent.h
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** 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 QMLCOMPONENT_H
+#define QMLCOMPONENT_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qstring.h>
+#include <QtScript/qscriptvalue.h>
+#include <QtDeclarative/qfxglobal.h>
+#include <QtDeclarative/qml.h>
+#include <QtDeclarative/qmlerror.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlCompiledData;
+class QByteArray;
+class QmlComponentPrivate;
+class QmlEngine;
+class QmlComponentAttached;
+class Q_DECLARATIVE_EXPORT QmlComponent : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlComponent)
+
+public:
+ QmlComponent(QObject *parent = 0);
+ QmlComponent(QmlEngine *, QObject *parent=0);
+ QmlComponent(QmlEngine *, const QString &url, QObject *parent = 0);
+ QmlComponent(QmlEngine *, const QUrl &url, QObject *parent = 0);
+ QmlComponent(QmlEngine *, const QByteArray &data,
+ const QUrl &baseUrl, QObject *parent=0);
+ virtual ~QmlComponent();
+
+ Q_ENUMS(Status)
+ enum Status { Null, Ready, Loading, Error };
+ Status status() const;
+
+ bool isNull() const;
+ bool isReady() const;
+ bool isError() const;
+ bool isLoading() const;
+
+ QList<QmlError> errors() const;
+
+ qreal progress() const;
+
+ QUrl url() const;
+
+ virtual QObject *create(QmlContext *context = 0);
+ virtual QObject *beginCreate(QmlContext *);
+ virtual void completeCreate();
+
+ void loadUrl(const QUrl &url);
+ void setData(const QByteArray &, const QUrl &baseUrl);
+
+ QmlContext *creationContext() const;
+
+ static QmlComponentAttached *qmlAttachedProperties(QObject *);
+
+Q_SIGNALS:
+ void statusChanged(QmlComponent::Status);
+ void progressChanged(qreal);
+
+protected:
+ QmlComponent(QmlComponentPrivate &dd, QObject* parent);
+
+private:
+ QmlComponent(QmlEngine *, QmlCompiledData *, int, int, QObject *parent);
+
+ friend class QmlVME;
+ friend class QmlCompositeTypeData;
+};
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QmlComponent::Status)
+QML_DECLARE_TYPE(QmlComponent)
+QML_DECLARE_TYPEINFO(QmlComponent, QML_HAS_ATTACHED_PROPERTIES)
+
+QT_END_HEADER
+
+#endif // QMLCOMPONENT_H
diff --git a/src/declarative/qml/qmlcomponent_p.h b/src/declarative/qml/qmlcomponent_p.h
new file mode 100644
index 0000000..7eedfbd
--- /dev/null
+++ b/src/declarative/qml/qmlcomponent_p.h
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** 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 QMLCOMPONENT_P_H
+#define QMLCOMPONENT_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/QString>
+#include <QtCore/QStringList>
+#include <QtCore/QList>
+#include <private/qobject_p.h>
+#include <private/qmlengine_p.h>
+#include <private/qmlcompositetypemanager_p.h>
+#include <private/qbitfield_p.h>
+#include <QtDeclarative/qmlerror.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <QtDeclarative/qml.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlComponent;
+class QmlEngine;
+class QmlCompiledData;
+
+class QmlComponentAttached;
+class QmlComponentPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlComponent)
+
+public:
+ QmlComponentPrivate() : typeData(0), progress(0.), start(-1), count(-1), cc(0), completePending(false), componentAttacheds(0), engine(0) {}
+
+
+ QObject *create(QmlContext *context, const QBitField &);
+ QObject *beginCreate(QmlContext *, const QBitField &);
+ void completeCreate();
+
+ QmlCompositeTypeData *typeData;
+ void typeDataReady();
+ void updateProgress(qreal);
+
+ void fromTypeData(QmlCompositeTypeData *data);
+
+ QList<QmlError> errors;
+ QUrl url;
+ qreal progress;
+
+ int start;
+ int count;
+ QmlCompiledData *cc;
+
+ QList<QmlEnginePrivate::SimpleList<QmlAbstractBinding> > bindValues;
+ QList<QmlEnginePrivate::SimpleList<QmlParserStatus> > parserStatus;
+ QmlComponentAttached *componentAttacheds;
+
+ bool completePending;
+
+ QmlEngine *engine;
+
+ void clear();
+
+ static QmlComponentPrivate *get(QmlComponent *c) {
+ return static_cast<QmlComponentPrivate *>(QObjectPrivate::get(c));
+ }
+};
+
+class QmlComponentAttached : public QObject
+{
+ Q_OBJECT
+public:
+ QmlComponentAttached(QObject *parent = 0);
+ ~QmlComponentAttached();
+
+ QmlComponentAttached **prev;
+ QmlComponentAttached *next;
+
+signals:
+ void completed();
+
+private:
+ friend class QmlComponentPrivate;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLCOMPONENT_P_H
diff --git a/src/declarative/qml/qmlcomponentjs.cpp b/src/declarative/qml/qmlcomponentjs.cpp
new file mode 100644
index 0000000..df3e834
--- /dev/null
+++ b/src/declarative/qml/qmlcomponentjs.cpp
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** 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 "qmlcomponentjs_p.h"
+#include "qmlcomponentjs_p_p.h"
+#include "qmlengine_p.h"
+#include "qmlcomponent.h"
+
+QT_BEGIN_NAMESPACE
+
+QmlComponentJS::QmlComponentJS(QmlEngine *engine, QObject *parent)
+ : QmlComponent(*(new QmlComponentJSPrivate), parent)
+{
+ Q_D(QmlComponentJS);
+ d->engine = engine;
+ connect(this, SIGNAL(statusChanged(QmlComponent::Status)),
+ this, SLOT(statusChange(QmlComponent::Status)));
+}
+
+QmlComponentJS::QmlComponentJS(QmlEngine *engine, const QUrl &url, QObject *parent)
+ : QmlComponent(*(new QmlComponentJSPrivate), parent)
+{
+ Q_D(QmlComponentJS);
+ d->engine = engine;
+ loadUrl(url);
+ connect(this, SIGNAL(statusChanged(QmlComponent::Status)),
+ this, SLOT(statusChange(QmlComponent::Status)));
+}
+
+void QmlComponentJS::setContext(QmlContext* c)
+{
+ Q_D(QmlComponentJS);
+ d->ctxt =c;
+}
+/*!
+ Create a script object instance from this component. Returns a null
+ script object if creation failed. It will create the instance in the
+ same context that it was created it. QmlComponentJS is only
+ meant to be created from with script - C++ developers should just use
+ QmlComponent directly.
+
+ Similar to QmlComponent::create(), but creates an object suitable
+ for usage within scripts.
+*/
+QScriptValue QmlComponentJS::createObject()
+{
+ Q_D(QmlComponentJS);
+ QObject* ret = create(d->ctxt);
+ return QmlEnginePrivate::qmlScriptObject(ret, d->engine);
+}
+
+/*!
+ Return the list of errors that occured during the last compile or create
+ operation, as a single string. An empty string is returned if isError()
+ is not set.
+
+ This function is similar to errors(), except more useful when called from
+ QML. C++ code should usually use errors().
+
+ \sa errors()
+*/
+QString QmlComponentJS::errorsString() const
+{
+ Q_D(const QmlComponentJS);
+ QString ret;
+ if(!isError())
+ return ret;
+ foreach(const QmlError &e, d->errors) {
+ ret += e.url().toString() + QLatin1String(":") +
+ QString::number(e.line()) + QLatin1String(" ") +
+ e.description() + QLatin1String("\n");
+ }
+ return ret;
+}
+
+
+void QmlComponentJS::statusChange(QmlComponent::Status newStatus)
+{
+ Q_D(QmlComponentJS);
+ if(newStatus == d->prevStatus)
+ return;
+ if(newStatus == QmlComponent::Null || d->prevStatus == QmlComponent::Null)
+ emit isNullChanged();
+ if(newStatus == QmlComponent::Ready || d->prevStatus == QmlComponent::Ready)
+ emit isReadyChanged();
+ if(newStatus == QmlComponent::Loading || d->prevStatus == QmlComponent::Loading)
+ emit isLoadingChanged();
+ if(newStatus == QmlComponent::Error || d->prevStatus == QmlComponent::Error)
+ emit isErrorChanged();
+ d->prevStatus = newStatus;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcomponentjs_p.h b/src/declarative/qml/qmlcomponentjs_p.h
new file mode 100644
index 0000000..3213929
--- /dev/null
+++ b/src/declarative/qml/qmlcomponentjs_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 QMLCOMPONENTJS_P_H
+#define QMLCOMPONENTJS_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/qobject.h>
+#include <QtCore/qstring.h>
+#include <QtDeclarative/qfxglobal.h>
+#include <QtDeclarative/qml.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <QtDeclarative/qmlerror.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlComponentJSPrivate;
+class QmlEngine;
+class QmlContext;
+class Q_DECLARATIVE_EXPORT QmlComponentJS : public QmlComponent
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlComponentJS)
+ 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;
+
+ void setContext(QmlContext* c);
+Q_SIGNALS:
+ void isNullChanged();
+ void isErrorChanged();
+ void isReadyChanged();
+ void isLoadingChanged();
+private Q_SLOTS:
+ void statusChange(QmlComponent::Status newStatus);
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QmlComponentJS)
+
+#endif // QMLCOMPONENTJS_P_H
diff --git a/src/declarative/qml/qmlcomponentjs_p_p.h b/src/declarative/qml/qmlcomponentjs_p_p.h
new file mode 100644
index 0000000..47ce491
--- /dev/null
+++ b/src/declarative/qml/qmlcomponentjs_p_p.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** 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 QMLCOMPONENTJS_P_P_H
+#define QMLCOMPONENTJS_P_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 "qmlcomponent.h"
+#include "qmlcomponentjs_p.h"
+#include "qmlcomponent_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QmlContext;
+class QmlComponentJSPrivate : public QmlComponentPrivate
+{
+ Q_DECLARE_PUBLIC(QmlComponentJS)
+public:
+ QmlComponentJSPrivate() : QmlComponentPrivate(),
+ prevStatus(QmlComponentJS::Null), ctxt(0)
+ { }
+
+ QmlComponent::Status prevStatus;
+ QmlContext* ctxt;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLCOMPONENTJS_P_P_H
diff --git a/src/declarative/qml/qmlcompositetypedata_p.h b/src/declarative/qml/qmlcompositetypedata_p.h
new file mode 100644
index 0000000..fa11137
--- /dev/null
+++ b/src/declarative/qml/qmlcompositetypedata_p.h
@@ -0,0 +1,148 @@
+/****************************************************************************
+**
+** 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 QMLCOMPOSITETYPEDATA_P_H
+#define QMLCOMPOSITETYPEDATA_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/qglobal.h>
+#include <private/qmlengine_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlCompositeTypeResource;
+class QmlCompositeTypeData : public QmlRefCount
+{
+public:
+ QmlCompositeTypeData();
+ virtual ~QmlCompositeTypeData();
+
+ enum Status {
+ Invalid,
+ Complete,
+ Error,
+ Waiting
+ };
+ Status status;
+ enum ErrorType {
+ NoError,
+ AccessError,
+ GeneralError
+ };
+ ErrorType errorType;
+
+ QList<QmlError> errors;
+
+ QmlEnginePrivate::Imports imports;
+
+ QList<QmlCompositeTypeData *> dependants;
+
+ // Return a QmlComponent if the QmlCompositeTypeData is not in the Waiting
+ // state. The QmlComponent is owned by the QmlCompositeTypeData, so a
+ // reference should be kept to keep the QmlComponent alive.
+ QmlComponent *toComponent(QmlEngine *);
+ // Return a QmlCompiledData if possible, or 0 if an error
+ // occurs
+ QmlCompiledData *toCompiledComponent(QmlEngine *);
+
+ struct TypeReference
+ {
+ TypeReference();
+
+ QmlType *type;
+ QmlCompositeTypeData *unit;
+ };
+
+ 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
+ // p. The waiter is automatically removed when the typeDataReady() method
+ // is invoked, so there is no need to call remWaiter() in this case.
+ void addWaiter(QmlComponentPrivate *p);
+ void remWaiter(QmlComponentPrivate *p);
+
+ qreal progress;
+
+private:
+ friend class QmlCompositeTypeManager;
+ friend class QmlCompiler;
+ friend class QmlDomDocument;
+
+ QmlScriptParser data;
+ QList<QmlComponentPrivate *> waiters;
+ QmlComponent *component;
+ 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
new file mode 100644
index 0000000..3c76344
--- /dev/null
+++ b/src/declarative/qml/qmlcompositetypemanager.cpp
@@ -0,0 +1,590 @@
+/****************************************************************************
+**
+** 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 <private/qmlcompositetypedata_p.h>
+#include <private/qmlcompositetypemanager_p.h>
+#include <private/qmlscriptparser_p.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtNetwork/qnetworkreply.h>
+#include <private/qmlengine_p.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qfile.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <private/qmlcomponent_p.h>
+#include <private/qmlcompiler_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QmlCompositeTypeData::QmlCompositeTypeData()
+: status(Invalid), errorType(NoError), component(0), compiledComponent(0)
+{
+}
+
+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();
+
+ if (component)
+ 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;
+}
+
+void QmlCompositeTypeData::remWaiter(QmlComponentPrivate *p)
+{
+ waiters.removeAll(p);
+}
+
+QmlComponent *QmlCompositeTypeData::toComponent(QmlEngine *engine)
+{
+ if (!component) {
+
+ QmlCompiledData *cc = toCompiledComponent(engine);
+ if (cc) {
+ component = new QmlComponent(engine, cc, -1, -1, 0);
+ cc->release();
+ } else {
+ component = new QmlComponent(engine, 0);
+ component->d_func()->url = imports.baseUrl();
+ component->d_func()->errors = errors;
+ }
+
+ }
+
+ return component;
+}
+
+QmlCompiledData *
+QmlCompositeTypeData::toCompiledComponent(QmlEngine *engine)
+{
+ if (status == Complete && !compiledComponent) {
+
+ compiledComponent = new QmlCompiledData;
+ compiledComponent->url = imports.baseUrl();
+ compiledComponent->name = compiledComponent->url.toString().toUtf8();
+
+ QmlCompiler compiler;
+ if (!compiler.compile(engine, this, compiledComponent)) {
+ status = Error;
+ errors = compiler.errors();
+ compiledComponent->release();
+ compiledComponent = 0;
+ }
+
+ // Data is no longer needed once we have a compiled component
+ data.clear();
+ }
+
+ if (compiledComponent)
+ compiledComponent->addref();
+
+ return compiledComponent;
+}
+
+QmlCompositeTypeData::TypeReference::TypeReference()
+: type(0), unit(0)
+{
+}
+
+QmlCompositeTypeManager::QmlCompositeTypeManager(QmlEngine *e)
+: engine(e)
+{
+}
+
+QmlCompositeTypeManager::~QmlCompositeTypeManager()
+{
+ for (Components::Iterator iter = components.begin(); iter != components.end();) {
+ (*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)
+{
+ QmlCompositeTypeData *unit = components.value(url.toString());
+
+ if (!unit) {
+ unit = new QmlCompositeTypeData;
+ unit->status = QmlCompositeTypeData::Waiting;
+ unit->imports.setBaseUrl(url);
+ components.insert(url.toString(), unit);
+
+ loadSource(unit);
+ }
+
+ unit->addref();
+ return unit;
+}
+
+QmlCompositeTypeData *
+QmlCompositeTypeManager::getImmediate(const QByteArray &data, const QUrl &url)
+{
+ QmlCompositeTypeData *unit = new QmlCompositeTypeData;
+ unit->status = QmlCompositeTypeData::Waiting;
+ unit->imports.setBaseUrl(url);
+ setData(unit, data, url);
+ return unit;
+}
+
+void QmlCompositeTypeManager::clearCache()
+{
+ for (Components::Iterator iter = components.begin(); iter != components.end();) {
+ if ((*iter)->status != QmlCompositeTypeData::Waiting) {
+ (*iter)->release();
+ iter = components.erase(iter);
+ } else {
+ ++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()
+{
+ QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
+
+ QmlCompositeTypeData *unit = components.value(reply->url().toString());
+ Q_ASSERT(unit);
+
+ if (reply->error() != QNetworkReply::NoError) {
+
+ QString errorDescription;
+ // ### - Fill in error
+ errorDescription = QLatin1String("Network error for URL ") +
+ reply->url().toString();
+
+ unit->status = QmlCompositeTypeData::Error;
+ // ### FIXME
+ QmlError error;
+ error.setDescription(errorDescription);
+ unit->errorType = QmlCompositeTypeData::AccessError;
+ unit->errors << error;
+ doComplete(unit);
+
+ } else {
+ QByteArray data = reply->readAll();
+
+ setData(unit, data, reply->url());
+ }
+
+ 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();
+}
+
+static QString toLocalFileOrQrc(const QUrl& url)
+{
+ QString r = url.toLocalFile();
+ if (r.isEmpty() && url.scheme() == QLatin1String("qrc"))
+ r = QLatin1Char(':') + url.path();
+ return r;
+}
+
+void QmlCompositeTypeManager::loadResource(QmlCompositeTypeResource *resource)
+{
+ QUrl url(resource->url);
+
+ QString lf = toLocalFileOrQrc(url);
+ if (!lf.isEmpty()) {
+
+ QFile file(lf);
+ 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());
+
+ QString lf = toLocalFileOrQrc(url);
+ if (!lf.isEmpty()) {
+
+ QFile file(lf);
+ if (file.open(QFile::ReadOnly)) {
+ QByteArray data = file.readAll();
+ setData(unit, data, url);
+ } else {
+ QString errorDescription;
+ // ### - Fill in error
+ errorDescription = QLatin1String("File error for URL ") + url.toString();
+ unit->status = QmlCompositeTypeData::Error;
+ // ### FIXME
+ QmlError error;
+ error.setDescription(errorDescription);
+ unit->errorType = QmlCompositeTypeData::AccessError;
+ unit->errors << error;
+ doComplete(unit);
+ }
+
+ } else {
+ QNetworkReply *reply =
+ engine->networkAccessManager()->get(QNetworkRequest(url));
+ QObject::connect(reply, SIGNAL(finished()),
+ this, SLOT(replyFinished()));
+ QObject::connect(reply, SIGNAL(downloadProgress(qint64,qint64)),
+ this, SLOT(requestProgress(qint64,qint64)));
+ }
+}
+
+void QmlCompositeTypeManager::requestProgress(qint64 received, qint64 total)
+{
+ if (total <= 0)
+ return;
+ QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
+
+ QmlCompositeTypeData *unit = components.value(reply->url().toString());
+ Q_ASSERT(unit);
+
+ unit->progress = qreal(received)/total;
+
+ foreach (QmlComponentPrivate *comp, unit->waiters)
+ comp->updateProgress(unit->progress);
+}
+
+void QmlCompositeTypeManager::setData(QmlCompositeTypeData *unit,
+ const QByteArray &data,
+ const QUrl &url)
+{
+ bool ok = true;
+ if (!unit->data.parse(data, url)) {
+ ok = false;
+ unit->errors << unit->data.errors();
+ } else {
+ foreach (QmlScriptParser::Import imp, unit->data.imports()) {
+ int dot = imp.version.indexOf(QLatin1Char('.'));
+ if (dot < 0) dot = imp.version.length();
+ if (!QmlEnginePrivate::get(engine)->addToImport(&unit->imports, imp.uri, imp.qualifier, imp.version.left(dot).toInt(), imp.version.mid(dot+1).toInt(), imp.type)) {
+ QmlError error;
+ error.setUrl(url);
+ error.setDescription(tr("Import %1 unavailable").arg(imp.uri));
+ unit->errors << error;
+ ok = false;
+ }
+ }
+ }
+
+ if (ok) {
+ compile(unit);
+ } else {
+ unit->status = QmlCompositeTypeData::Error;
+ unit->errorType = QmlCompositeTypeData::GeneralError;
+ doComplete(unit);
+ }
+}
+
+void QmlCompositeTypeManager::doComplete(QmlCompositeTypeData *unit)
+{
+ for (int ii = 0; ii < unit->dependants.count(); ++ii) {
+ checkComplete(unit->dependants.at(ii));
+ unit->dependants.at(ii)->release();
+ }
+ unit->dependants.clear();
+
+ while(!unit->waiters.isEmpty()) {
+ QmlComponentPrivate *p = unit->waiters.takeFirst();
+ p->typeDataReady();
+ }
+}
+
+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)
+ return;
+
+ int waiting = 0;
+ for (int ii = 0; ii < unit->types.count(); ++ii) {
+ QmlCompositeTypeData *u = unit->types.at(ii).unit;
+
+ if (!u)
+ continue;
+
+ if (u->status == QmlCompositeTypeData::Error) {
+ unit->status = QmlCompositeTypeData::Error;
+ unit->errors = u->errors;
+ doComplete(unit);
+ return;
+ } else if (u->status == QmlCompositeTypeData::Waiting) {
+ 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();
+
+ int waiting = 0;
+ for (int ii = 0; ii < types.count(); ++ii) {
+ QmlScriptParser::TypeReference *parserRef = types.at(ii);
+ QByteArray typeName = parserRef->name.toUtf8();
+
+ QmlCompositeTypeData::TypeReference ref;
+
+ QUrl url;
+ int majorVersion;
+ int minorVersion;
+ QmlEnginePrivate::ImportedNamespace *typeNamespace = 0;
+ if (!QmlEnginePrivate::get(engine)->resolveType(unit->imports, typeName, &ref.type, &url, &majorVersion, &minorVersion, &typeNamespace)) {
+ // XXX could produce error message here.
+ }
+
+ if (typeNamespace) {
+ QmlError error;
+ error.setUrl(unit->imports.baseUrl());
+ error.setDescription(tr("Namespace %1 cannot be used as a type").arg(QString::fromUtf8(typeName)));
+ if (!parserRef->refObjects.isEmpty()) {
+ QmlParser::Object *obj = parserRef->refObjects.first();
+ error.setLine(obj->location.start.line);
+ error.setColumn(obj->location.start.column);
+ }
+ unit->status = QmlCompositeTypeData::Error;
+ unit->errorType = QmlCompositeTypeData::GeneralError;
+ unit->errors << error;
+ doComplete(unit);
+ return;
+ }
+
+ if (ref.type) {
+ foreach (QmlParser::Object *obj, parserRef->refObjects) {
+ // store namespace for DOM
+ obj->majorVersion = majorVersion;
+ obj->minorVersion = minorVersion;
+ }
+ unit->types << ref;
+ continue;
+ }
+
+ QmlCompositeTypeData *urlUnit = components.value(url.toString());
+
+ if (!urlUnit) {
+ urlUnit = new QmlCompositeTypeData;
+ urlUnit->status = QmlCompositeTypeData::Waiting;
+ urlUnit->imports.setBaseUrl(url);
+ components.insert(url.toString(), urlUnit);
+
+ loadSource(urlUnit);
+ }
+
+ ref.unit = urlUnit;
+ switch(urlUnit->status) {
+ case QmlCompositeTypeData::Invalid:
+ case QmlCompositeTypeData::Error:
+ unit->status = QmlCompositeTypeData::Error;
+ {
+ QmlError error;
+ error.setUrl(unit->imports.baseUrl());
+ error.setDescription(tr("Type %1 unavailable").arg(QString::fromUtf8(typeName)));
+ if (!parserRef->refObjects.isEmpty()) {
+ QmlParser::Object *obj = parserRef->refObjects.first();
+ error.setLine(obj->location.start.line);
+ error.setColumn(obj->location.start.column);
+ }
+ unit->errors << error;
+ }
+ if (urlUnit->errorType != QmlCompositeTypeData::AccessError)
+ unit->errors << urlUnit->errors;
+ doComplete(unit);
+ return;
+
+ case QmlCompositeTypeData::Complete:
+ break;
+
+ case QmlCompositeTypeData::Waiting:
+ unit->addref();
+ ref.unit->dependants << unit;
+ waiting++;
+ break;
+ }
+
+ 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 {
+ unit->status = QmlCompositeTypeData::Complete;
+ doComplete(unit);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcompositetypemanager_p.h b/src/declarative/qml/qmlcompositetypemanager_p.h
new file mode 100644
index 0000000..843a9cf
--- /dev/null
+++ b/src/declarative/qml/qmlcompositetypemanager_p.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** 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 QMLCOMPOSITETYPEMANAGER_P_H
+#define QMLCOMPOSITETYPEMANAGER_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/qglobal.h>
+#include <private/qmlscriptparser_p.h>
+#include <private/qmlrefcount_p.h>
+#include <QtDeclarative/qmlerror.h>
+#include <QtDeclarative/qmlengine.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlCompiledData;
+class QmlComponentPrivate;
+class QmlComponent;
+class QmlDomDocument;
+
+class QmlCompositeTypeData;
+class QmlCompositeTypeResource;
+
+class QmlCompositeTypeManager : public QObject
+{
+ Q_OBJECT
+public:
+ QmlCompositeTypeManager(QmlEngine *);
+ ~QmlCompositeTypeManager();
+
+ // Return a QmlCompositeTypeData for url. The QmlCompositeTypeData may be
+ // cached.
+ QmlCompositeTypeData *get(const QUrl &url);
+ // Return a QmlCompositeTypeData for data, with the provided base url. The
+ // QmlCompositeTypeData will not be cached.
+ QmlCompositeTypeData *getImmediate(const QByteArray &data, const QUrl &url);
+
+ // Clear cached types. Only types that aren't in the Waiting state will
+ // be cleared.
+ void clearCache();
+
+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
+
+#endif // QMLCOMPOSITETYPEMANAGER_P_H
+
diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp
new file mode 100644
index 0000000..31d4e1f
--- /dev/null
+++ b/src/declarative/qml/qmlcontext.cpp
@@ -0,0 +1,502 @@
+/****************************************************************************
+**
+** 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 <qmlcontext.h>
+#include <private/qmlcontext_p.h>
+#include <private/qmlexpression_p.h>
+#include <private/qmlengine_p.h>
+#include <qmlengine.h>
+#include <qscriptengine.h>
+#include <QtCore/qvarlengtharray.h>
+#include <QtCore/qdebug.h>
+#include <private/qmlbindingoptimizations_p.h>
+#include <QtDeclarative/qmlinfo.h>
+
+// 6-bits
+#define MAXIMUM_DEFAULT_OBJECTS 63
+
+QT_BEGIN_NAMESPACE
+
+QmlContextPrivate::QmlContextPrivate()
+: 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,
+ const QString &fileName, int lineNumber)
+{
+ Q_Q(QmlContext);
+
+ if (!engine)
+ return;
+
+ QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine);
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+
+ QScriptContext *scriptContext = scriptEngine->pushCleanContext();
+ scriptContext->pushScope(enginePriv->contextClass->newContext(q, scopeObject));
+
+ QScriptValue scope = scriptEngine->newObject();
+ scriptContext->setActivationObject(scope);
+
+ QScriptValue val = scriptEngine->evaluate(script, fileName, lineNumber);
+
+ if (scriptEngine->hasUncaughtException())
+ QmlExpressionPrivate::printException(scriptEngine);
+
+ scriptEngine->popContext();
+
+ scripts.append(scope);
+}
+
+void QmlContextPrivate::dump()
+{
+ dump(0);
+}
+
+void QmlContextPrivate::dump(int depth)
+{
+ QByteArray ba(depth * 4, ' ');
+ if (parent)
+ parent->d_func()->dump(depth + 1);
+}
+
+void QmlContextPrivate::destroyed(ContextGuard *guard)
+{
+ Q_Q(QmlContext);
+
+ // process of being deleted (which is *probably* why obj has been destroyed
+ // anyway), as we're about to get deleted which will invalidate all the
+ // expressions that could depend on us
+ QObject *parent = q->parent();
+ if (parent && QObjectPrivate::get(parent)->wasDeleted)
+ return;
+
+ while(guard->bindings)
+ guard->bindings->reset();
+
+ for (int ii = 0; ii < idValueCount; ++ii) {
+ if (&idValues[ii] == guard) {
+ QMetaObject::activate(q, ii + notifyIndex, 0);
+ return;
+ }
+ }
+}
+
+void QmlContextPrivate::init()
+{
+ Q_Q(QmlContext);
+
+ if (parent)
+ parent->d_func()->childContexts.insert(q);
+}
+
+void QmlContextPrivate::addDefaultObject(QObject *object, Priority priority)
+{
+ if (defaultObjects.count() >= (MAXIMUM_DEFAULT_OBJECTS - 1)) {
+ qWarning("QmlContext: Cannot have more than %d default objects on "
+ "one bind context.", MAXIMUM_DEFAULT_OBJECTS - 1);
+ return;
+ }
+
+ if (priority == HighPriority) {
+ defaultObjects.insert(highPriorityCount++, object);
+ } else {
+ defaultObjects.append(object);
+ }
+}
+
+
+/*!
+ \class QmlContext
+ \brief The QmlContext class defines a context within a QML engine.
+ \mainclass
+
+ Contexts allow data to be exposed to the QML components instantiated by the
+ QML engine.
+
+ Each QmlContext contains a set of properties, distinct from
+ its QObject properties, that allow data to be
+ explicitly bound to a context by name. The context properties are defined or
+ updated by calling QmlContext::setContextProperty(). The following example shows
+ a Qt model being bound to a context and then accessed from a QML file.
+
+ \code
+ QmlEngine engine;
+ QmlContext context(engine.rootContext());
+ context.setContextProperty("myModel", modelData);
+
+ QmlComponent component(&engine, "ListView { model=myModel }");
+ component.create(&context);
+ \endcode
+
+ To simplify binding and maintaining larger data sets, QObject's can be
+ added to a QmlContext. These objects are known as the context's default
+ objects. In this case all the properties of the QObject are
+ made available by name in the context, as though they were all individually
+ added by calling QmlContext::setContextProperty(). Changes to the property's
+ values are detected through the property's notify signal. This method is
+ also slightly more faster than manually adding property values.
+
+ The following example has the same effect as the one above, but it is
+ achieved using a default object.
+
+ \code
+ class MyDataSet : ... {
+ ...
+ Q_PROPERTY(QAbstractItemModel *myModel READ model NOTIFY modelChanged)
+ ...
+ };
+
+ MyDataSet myDataSet;
+ QmlEngine engine;
+ QmlContext context(engine.rootContext());
+ context.addDefaultObject(&myDataSet);
+
+ QmlComponent component(&engine, "ListView { model=myModel }");
+ component.create(&context);
+ \endcode
+
+ Each context may have up to 32 default objects, and objects added first take
+ precedence over those added later. All properties added explicitly by
+ QmlContext::setContextProperty() take precedence over default object properties.
+
+ Contexts are hierarchal, with the \l {QmlEngine::rootContext()}{root context}
+ being created by the QmlEngine. A component instantiated in a given context
+ has access to that context's data, as well as the data defined by its
+ ancestor contexts. Data values (including those added implicitly by the
+ default objects) in a context override those in ancestor contexts. Data
+ that should be available to all components instantiated by the QmlEngine
+ should be added to the \l {QmlEngine::rootContext()}{root context}.
+
+ In the following example,
+
+ \code
+ QmlEngine engine;
+ QmlContext context1(engine.rootContext());
+ QmlContext context2(&context1);
+ QmlContext context3(&context2);
+
+ context1.setContextProperty("a", 12);
+ context2.setContextProperty("b", 13);
+ context3.setContextProperty("a", 14);
+ context3.setContextProperty("c", 14);
+ \endcode
+
+ a QML component instantiated in context1 would have access to the "a" data,
+ a QML component instantiated in context2 would have access to the "a" and
+ "b" data, and a QML component instantiated in context3 would have access to
+ the "a", "b" and "c" data - although its "a" data would return 14, unlike
+ that in context1 or context2.
+*/
+
+/*! \internal */
+QmlContext::QmlContext(QmlEngine *e, bool)
+: QObject(*(new QmlContextPrivate))
+{
+ Q_D(QmlContext);
+ d->engine = e;
+ d->init();
+}
+
+/*!
+ Create a new QmlContext as a child of \a engine's root context, and the
+ QObject \a parent.
+*/
+QmlContext::QmlContext(QmlEngine *engine, QObject *parent)
+: QObject(*(new QmlContextPrivate), parent)
+{
+ Q_D(QmlContext);
+ QmlContext *parentContext = engine?engine->rootContext():0;
+ d->parent = parentContext;
+ d->engine = parentContext->engine();
+ d->init();
+}
+
+/*!
+ Create a new QmlContext with the given \a parentContext, and the
+ QObject \a parent.
+*/
+QmlContext::QmlContext(QmlContext *parentContext, QObject *parent)
+: QObject(*(new QmlContextPrivate), parent)
+{
+ Q_D(QmlContext);
+ d->parent = parentContext;
+ d->engine = parentContext->engine();
+ d->init();
+}
+
+/*!
+ \internal
+*/
+QmlContext::QmlContext(QmlContext *parentContext, QObject *parent, bool)
+: QObject(*(new QmlContextPrivate), parent)
+{
+ Q_D(QmlContext);
+ d->parent = parentContext;
+ d->engine = parentContext->engine();
+ d->isInternal = true;
+ d->init();
+}
+
+/*!
+ Destroys the QmlContext.
+
+ Any expressions, or sub-contexts dependent on this context will be
+ invalidated, but not destroyed (unless they are parented to the QmlContext
+ object).
+ */
+QmlContext::~QmlContext()
+{
+ Q_D(QmlContext);
+ if (d->parent)
+ d->parent->d_func()->childContexts.remove(this);
+
+ for (QSet<QmlContext *>::ConstIterator iter = d->childContexts.begin();
+ iter != d->childContexts.end();
+ ++iter) {
+ (*iter)->d_func()->invalidateEngines();
+ (*iter)->d_func()->parent = 0;
+ }
+
+ QmlAbstractExpression *expression = d->expressions;
+ while (expression) {
+ QmlAbstractExpression *nextExpression = expression->m_nextExpression;
+
+ expression->m_context = 0;
+ expression->m_prevExpression = 0;
+ expression->m_nextExpression = 0;
+
+ expression = nextExpression;
+ }
+
+ for (int ii = 0; ii < d->contextObjects.count(); ++ii) {
+ QObjectPrivate *p = QObjectPrivate::get(d->contextObjects.at(ii));
+ QmlDeclarativeData *data =
+ static_cast<QmlDeclarativeData *>(p->declarativeData);
+ if(data)
+ data->context = 0;
+ }
+ d->contextObjects.clear();
+
+ delete [] d->idValues;
+
+ if (d->propertyNames)
+ d->propertyNames->release();
+
+ if (d->imports)
+ d->imports->release();
+}
+
+void QmlContextPrivate::invalidateEngines()
+{
+ if (!engine)
+ return;
+ engine = 0;
+ for (QSet<QmlContext *>::ConstIterator iter = childContexts.begin();
+ iter != childContexts.end();
+ ++iter) {
+ (*iter)->d_func()->invalidateEngines();
+ }
+}
+
+/*!
+ Return the context's QmlEngine, or 0 if the context has no QmlEngine or the
+ QmlEngine was destroyed.
+*/
+QmlEngine *QmlContext::engine() const
+{
+ Q_D(const QmlContext);
+ return d->engine;
+}
+
+/*!
+ Return the context's parent QmlContext, or 0 if this context has no
+ parent or if the parent has been destroyed.
+*/
+QmlContext *QmlContext::parentContext() const
+{
+ Q_D(const QmlContext);
+ return d->parent;
+}
+
+/*!
+ Add \a defaultObject to this context. The object will be added after
+ any existing default objects.
+*/
+void QmlContext::addDefaultObject(QObject *defaultObject)
+{
+ Q_D(QmlContext);
+ d->addDefaultObject(defaultObject, QmlContextPrivate::NormalPriority);
+}
+
+/*!
+ Set a the \a value of the \a name property on this context.
+*/
+void QmlContext::setContextProperty(const QString &name, const QVariant &value)
+{
+ Q_D(QmlContext);
+ if (d->notifyIndex == -1)
+ d->notifyIndex = this->metaObject()->methodCount();
+
+ if (QmlMetaType::isObject(value.userType())) {
+ QObject *o = QmlMetaType::toQObject(value);
+ setContextProperty(name, o);
+ } else {
+
+ 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[idx] = value;
+ QMetaObject::activate(this, idx + d->notifyIndex, 0);
+ }
+ }
+}
+
+void QmlContextPrivate::setIdProperty(const QString &name, int idx,
+ QObject *obj)
+{
+ if (notifyIndex == -1) {
+ Q_Q(QmlContext);
+ notifyIndex = q->metaObject()->methodCount();
+ }
+
+ idValues[idx].priv = this;
+ idValues[idx] = obj;
+}
+
+void QmlContextPrivate::setIdPropertyData(QmlIntegerCache *data)
+{
+ Q_ASSERT(!propertyNames);
+ propertyNames = data;
+ propertyNames->addref();
+
+ idValueCount = data->count();
+ idValues = new ContextGuard[idValueCount];
+}
+
+/*!
+ Set a the \a value of the \a name property on this context.
+
+ QmlContext does \b not take ownership of \a value.
+*/
+void QmlContext::setContextProperty(const QString &name, QObject *value)
+{
+ Q_D(QmlContext);
+ if (d->notifyIndex == -1)
+ d->notifyIndex = this->metaObject()->methodCount();
+
+ 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 {
+ d->propertyValues[idx] = QVariant::fromValue(value);
+ QMetaObject::activate(this, idx + d->notifyIndex, 0);
+ }
+}
+
+/*!
+ Resolves the URL \a src relative to the URL of the
+ containing component.
+
+ \sa QmlEngine::baseUrl(), setBaseUrl()
+*/
+QUrl QmlContext::resolvedUrl(const QUrl &src)
+{
+ QmlContext *ctxt = this;
+ if (src.isRelative() && !src.isEmpty()) {
+ if (ctxt) {
+ while(ctxt) {
+ if(ctxt->d_func()->url.isValid())
+ break;
+ else
+ ctxt = ctxt->parentContext();
+ }
+
+ if (ctxt)
+ return ctxt->d_func()->url.resolved(src);
+ }
+ return QUrl();
+ } else {
+ return src;
+ }
+}
+
+/*!
+ Explicitly sets the url resolvedUrl() will use for relative references to \a baseUrl.
+
+ Calling this function will override the url of the containing
+ component used by default.
+
+ \sa resolvedUrl()
+*/
+void QmlContext::setBaseUrl(const QUrl &baseUrl)
+{
+ d_func()->url = baseUrl;
+}
+
+/*!
+ Returns the base url of the component, or the containing component
+ if none is set.
+*/
+QUrl QmlContext::baseUrl() const
+{
+ Q_D(const QmlContext);
+ const QmlContext* p = this;
+ while (p && p->d_func()->url.isEmpty()) {
+ p = p->parentContext();
+ }
+ if (p)
+ return p->d_func()->url;
+ else
+ return QUrl();
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcontext.h b/src/declarative/qml/qmlcontext.h
new file mode 100644
index 0000000..03baafa
--- /dev/null
+++ b/src/declarative/qml/qmlcontext.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** 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 QMLCONTEXT_H
+#define QMLCONTEXT_H
+
+#include <QtCore/qurl.h>
+#include <QtCore/qobject.h>
+#include <QtScript/qscriptvalue.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QString;
+class QmlEngine;
+class QmlRefCount;
+class QmlContextPrivate;
+class QmlCompositeTypeData;
+
+class Q_DECLARATIVE_EXPORT QmlContext : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlContext)
+
+public:
+ QmlContext(QmlEngine *parent, QObject *objParent=0);
+ QmlContext(QmlContext *parent, QObject *objParent=0);
+ virtual ~QmlContext();
+
+ QmlEngine *engine() const;
+ QmlContext *parentContext() const;
+
+ void addDefaultObject(QObject *);
+ void setContextProperty(const QString &, QObject *);
+ void setContextProperty(const QString &, const QVariant &);
+
+ QUrl resolvedUrl(const QUrl &);
+
+ void setBaseUrl(const QUrl &);
+ QUrl baseUrl() const;
+
+private:
+ friend class QmlVME;
+ friend class QmlEngine;
+ friend class QmlEnginePrivate;
+ friend class QmlExpression;
+ friend class QmlExpressionPrivate;
+ friend class QmlBasicScript;
+ friend class QmlContextScriptClass;
+ friend class QmlObjectScriptClass;
+ friend class QmlComponent;
+ friend class QmlComponentPrivate;
+ friend class QmlScriptPrivate;
+ friend class QmlBoundSignalProxy;
+ QmlContext(QmlContext *parent, QObject *objParent, bool);
+ QmlContext(QmlEngine *, bool);
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLCONTEXT_H
diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h
new file mode 100644
index 0000000..9a77e94
--- /dev/null
+++ b/src/declarative/qml/qmlcontext_p.h
@@ -0,0 +1,146 @@
+/****************************************************************************
+**
+** 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 QMLCONTEXT_P_H
+#define QMLCONTEXT_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 <QtDeclarative/qmlcontext.h>
+#include <private/qobject_p.h>
+#include <private/qmldeclarativedata_p.h>
+#include <QtCore/qhash.h>
+#include <QtScript/qscriptvalue.h>
+#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
+
+class QmlContext;
+class QmlExpression;
+class QmlEngine;
+class QmlExpression;
+class QmlExpressionPrivate;
+class QmlAbstractExpression;
+class QmlBinding_Id;
+
+class QmlContextPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlContext)
+public:
+ QmlContextPrivate();
+
+ QmlContext *parent;
+ QmlEngine *engine;
+ bool isInternal;
+
+ QmlIntegerCache *propertyNames;
+ QList<QVariant> propertyValues;
+ int notifyIndex;
+
+ QObjectList defaultObjects;
+ int highPriorityCount;
+
+ QList<QScriptValue> scripts;
+ void addScript(const QString &script, QObject *scope,
+ const QString &fileName = QString(), int lineNumber = 1);
+
+ QUrl url;
+
+ QmlTypeNameCache *imports;
+
+ void init();
+
+ void dump();
+ void dump(int depth);
+
+ enum Priority {
+ HighPriority,
+ NormalPriority
+ };
+ void addDefaultObject(QObject *, Priority);
+
+ void invalidateEngines();
+ QSet<QmlContext *> childContexts;
+
+ QmlAbstractExpression *expressions;
+
+ QObjectList contextObjects;
+
+ struct ContextGuard : public QGuard<QObject>
+ {
+ ContextGuard() : priv(0), bindings(0) {}
+ QmlContextPrivate *priv;
+ QmlBinding_Id *bindings;
+ ContextGuard &operator=(QObject *obj) {
+ (QGuard<QObject>&)*this = obj; return *this;
+ }
+ void objectDestroyed(QObject *) { priv->destroyed(this); }
+ };
+ ContextGuard *idValues;
+ int idValueCount;
+ void setIdProperty(const QString &, int, QObject *);
+ 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;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLCONTEXT_P_H
diff --git a/src/declarative/qml/qmlcontextscriptclass.cpp b/src/declarative/qml/qmlcontextscriptclass.cpp
new file mode 100644
index 0000000..4df23f0
--- /dev/null
+++ b/src/declarative/qml/qmlcontextscriptclass.cpp
@@ -0,0 +1,238 @@
+/****************************************************************************
+**
+** 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, QObject *o) : context(c), scopeObject(o) {}
+ QGuard<QmlContext> context;
+ QGuard<QObject> scopeObject;
+};
+
+/*
+ The QmlContextScriptClass handles property access for a QmlContext
+ via QtScript.
+ */
+QmlContextScriptClass::QmlContextScriptClass(QmlEngine *bindEngine)
+: QScriptDeclarativeClass(QmlEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine),
+ lastScopeObject(0), lastContext(0), lastData(0), lastPropertyIndex(-1), lastDefaultObject(-1)
+{
+}
+
+QmlContextScriptClass::~QmlContextScriptClass()
+{
+}
+
+QScriptValue QmlContextScriptClass::newContext(QmlContext *context, QObject *scopeObject)
+{
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+
+ return newObject(scriptEngine, this, new ContextData(context, scopeObject));
+}
+
+QmlContext *QmlContextScriptClass::contextFromValue(const QScriptValue &v)
+{
+ if (scriptClass(v) != this)
+ return 0;
+
+ ContextData *data = (ContextData *)object(v);
+ return data->context;
+}
+
+QScriptClass::QueryFlags
+QmlContextScriptClass::queryProperty(Object *object, const Identifier &name,
+ QScriptClass::QueryFlags flags)
+{
+ Q_UNUSED(flags);
+
+ lastScopeObject = 0;
+ lastContext = 0;
+ lastData = 0;
+ lastPropertyIndex = -1;
+ lastDefaultObject = -1;
+
+ QmlContext *bindContext = ((ContextData *)object)->context.data();
+ QObject *scopeObject = ((ContextData *)object)->scopeObject.data();
+ if (!bindContext)
+ return 0;
+
+ bool includeTypes = true;
+ while (bindContext) {
+ QScriptClass::QueryFlags rv =
+ queryProperty(bindContext, scopeObject, name, flags, includeTypes);
+ scopeObject = 0; // Only applies to the first context
+ includeTypes = false; // Only applies to the first context
+ if (rv) return rv;
+ bindContext = bindContext->parentContext();
+ }
+
+ return 0;
+}
+
+QScriptClass::QueryFlags
+QmlContextScriptClass::queryProperty(QmlContext *bindContext, QObject *scopeObject,
+ const Identifier &name,
+ QScriptClass::QueryFlags flags,
+ bool includeTypes)
+{
+ 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 (includeTypes && cp->imports) {
+ QmlTypeNameCache::Data *data = cp->imports->data(name);
+
+ if (data) {
+ lastData = data;
+ lastContext = bindContext;
+ return QScriptClass::HandlesReadAccess;
+ }
+ }
+
+ 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;
+ }
+ }
+
+ if (scopeObject) {
+ QScriptClass::QueryFlags rv =
+ ep->objectClass->queryProperty(scopeObject, name, flags, bindContext);
+ if (rv) {
+ lastScopeObject = scopeObject;
+ lastContext = bindContext;
+ return rv;
+ }
+ }
+
+ for (int ii = 0; ii < cp->defaultObjects.count(); ++ii) {
+ QScriptClass::QueryFlags rv =
+ ep->objectClass->queryProperty(cp->defaultObjects.at(ii), name, flags, bindContext);
+
+ if (rv) {
+ lastDefaultObject = ii;
+ lastContext = bindContext;
+ return rv;
+ }
+ }
+
+ 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 (lastScopeObject) {
+
+ return ep->objectClass->property(lastScopeObject, name);
+
+ } else 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(lastScopeObject || lastDefaultObject != -1);
+
+ QmlContext *bindContext = lastContext;
+ Q_ASSERT(bindContext);
+
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
+ QmlContextPrivate *cp = QmlContextPrivate::get(bindContext);
+
+ if (lastScopeObject) {
+ ep->objectClass->setProperty(lastScopeObject, name, value, bindContext);
+ } else {
+ ep->objectClass->setProperty(cp->defaultObjects.at(lastDefaultObject), name, value,
+ bindContext);
+ }
+}
+
+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..95dff5b
--- /dev/null
+++ b/src/declarative/qml/qmlcontextscriptclass_p.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** 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 *, QObject * = 0);
+
+ 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 *, QObject *scopeObject,
+ const Identifier &,
+ QScriptClass::QueryFlags flags,
+ bool includeTypes);
+
+ QmlEngine *engine;
+
+ QObject *lastScopeObject;
+ 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/qmlcustomparser.cpp b/src/declarative/qml/qmlcustomparser.cpp
new file mode 100644
index 0000000..dbcbeb1
--- /dev/null
+++ b/src/declarative/qml/qmlcustomparser.cpp
@@ -0,0 +1,276 @@
+/****************************************************************************
+**
+** 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 "qmlcustomparser_p.h"
+#include "qmlcustomparser_p_p.h"
+#include "qmlparser_p.h"
+
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QmlParser;
+
+/*!
+ \class QmlCustomParser
+ \brief The QmlCustomParser class allows you to add new arbitrary types to QML.
+ \internal
+
+ By subclassing QmlCustomParser, you can add an XML parser for
+ building a particular type.
+
+ The subclass must implement compile() and create(), and define
+ itself in the meta type system with one of the macros:
+
+ \code
+ QML_DEFINE_CUSTOM_PARSER(Name, parserClass)
+ \endcode
+
+ \code
+ QML_DEFINE_CUSTOM_PARSER_NS("XmlNamespaceUri", Name, parserClass)
+ \endcode
+*/
+
+/*
+ \fn QByteArray QmlCustomParser::compile(QXmlStreamReader& reader)
+
+ Upon entry to this function, \a reader is positioned on a
+ QXmlStreamReader::StartElement with the name specified when the
+ class was defined with the QML_DEFINE_CUSTOM_PARSER macro.
+
+ The custom parser must consume tokens from \a reader until the
+ EndElement matching the initial start element is reached, or until
+ error.
+
+ Errors must be reported via the error() functions.
+
+ The returned QByteArray contains data meaningful only to the
+ custom parser; the type engine will pass this same data to
+ create() when making an instance of the data.
+
+ The QByteArray may be cached between executions of the system, so
+ it must contain correctly-serialized data (not, for example,
+ pointers to stack objects).
+*/
+
+/*
+ \fn QVariant QmlCustomParser::create(const QByteArray &data)
+
+ This function returns a QVariant containing the value represented
+ by \a data, which is a block of data previously returned by a call
+ to compile().
+
+ If the compile is for a type, the variant should be a pointer to
+ the correctly-named QObject subclass (i.e. the one defined by
+ QML_DEFINE_TYPE for the same-named type as this custom parser is
+ defined for).
+*/
+
+QmlCustomParserNode
+QmlCustomParserNodePrivate::fromObject(QmlParser::Object *root)
+{
+ QmlCustomParserNode rootNode;
+ rootNode.d->name = root->typeName;
+ rootNode.d->location = root->location.start;
+
+ for(QHash<QByteArray, Property *>::Iterator iter = root->properties.begin();
+ iter != root->properties.end();
+ ++iter) {
+
+ Property *p = *iter;
+
+ rootNode.d->properties << fromProperty(p);
+ }
+
+ return rootNode;
+}
+
+QmlCustomParserProperty
+QmlCustomParserNodePrivate::fromProperty(QmlParser::Property *p)
+{
+ QmlCustomParserProperty prop;
+ prop.d->name = p->name;
+ prop.d->isList = (p->values.count() > 1);
+ prop.d->location = p->location.start;
+
+ if (p->value) {
+ QmlCustomParserNode node = fromObject(p->value);
+ QList<QmlCustomParserProperty> props = node.properties();
+ for (int ii = 0; ii < props.count(); ++ii)
+ prop.d->values << QVariant::fromValue(props.at(ii));
+ } else {
+ for(int ii = 0; ii < p->values.count(); ++ii) {
+ Value *v = p->values.at(ii);
+ v->type = QmlParser::Value::Literal;
+
+ if(v->object) {
+ QmlCustomParserNode node = fromObject(v->object);
+ prop.d->values << QVariant::fromValue(node);
+ } else {
+ prop.d->values << QVariant::fromValue(v->value);
+ }
+
+ }
+ }
+
+ return prop;
+}
+
+QmlCustomParserNode::QmlCustomParserNode()
+: d(new QmlCustomParserNodePrivate)
+{
+}
+
+QmlCustomParserNode::QmlCustomParserNode(const QmlCustomParserNode &other)
+: d(new QmlCustomParserNodePrivate)
+{
+ *this = other;
+}
+
+QmlCustomParserNode &QmlCustomParserNode::operator=(const QmlCustomParserNode &other)
+{
+ d->name = other.d->name;
+ d->properties = other.d->properties;
+ d->location = other.d->location;
+ return *this;
+}
+
+QmlCustomParserNode::~QmlCustomParserNode()
+{
+ delete d; d = 0;
+}
+
+QByteArray QmlCustomParserNode::name() const
+{
+ return d->name;
+}
+
+QList<QmlCustomParserProperty> QmlCustomParserNode::properties() const
+{
+ return d->properties;
+}
+
+QmlParser::Location QmlCustomParserNode::location() const
+{
+ return d->location;
+}
+
+QmlCustomParserProperty::QmlCustomParserProperty()
+: d(new QmlCustomParserPropertyPrivate)
+{
+}
+
+QmlCustomParserProperty::QmlCustomParserProperty(const QmlCustomParserProperty &other)
+: d(new QmlCustomParserPropertyPrivate)
+{
+ *this = other;
+}
+
+QmlCustomParserProperty &QmlCustomParserProperty::operator=(const QmlCustomParserProperty &other)
+{
+ d->name = other.d->name;
+ d->isList = other.d->isList;
+ d->values = other.d->values;
+ d->location = other.d->location;
+ return *this;
+}
+
+QmlCustomParserProperty::~QmlCustomParserProperty()
+{
+ delete d; d = 0;
+}
+
+QByteArray QmlCustomParserProperty::name() const
+{
+ return d->name;
+}
+
+bool QmlCustomParserProperty::isList() const
+{
+ return d->isList;
+}
+
+QmlParser::Location QmlCustomParserProperty::location() const
+{
+ return d->location;
+}
+
+QList<QVariant> QmlCustomParserProperty::assignedValues() const
+{
+ return d->values;
+}
+
+void QmlCustomParser::clearErrors()
+{
+ exceptions.clear();
+}
+
+/*!
+ Reports an error in parsing \a prop, with the given \a description.
+
+ An error is generated referring to the position of \a node in the source file.
+*/
+void QmlCustomParser::error(const QmlCustomParserProperty& prop, const QString& description)
+{
+ QmlError error;
+ QString exceptionDescription;
+ error.setLine(prop.location().line);
+ error.setColumn(prop.location().column);
+ error.setDescription(description);
+ exceptions << error;
+}
+
+/*!
+ Reports an error in parsing \a node, with the given \a description.
+
+ An error is generated referring to the position of \a node in the source file.
+*/
+void QmlCustomParser::error(const QmlCustomParserNode& node, const QString& description)
+{
+ QmlError error;
+ QString exceptionDescription;
+ error.setLine(node.location().line);
+ error.setColumn(node.location().column);
+ error.setDescription(description);
+ exceptions << error;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcustomparser_p.h b/src/declarative/qml/qmlcustomparser_p.h
new file mode 100644
index 0000000..eb3e579
--- /dev/null
+++ b/src/declarative/qml/qmlcustomparser_p.h
@@ -0,0 +1,146 @@
+/****************************************************************************
+**
+** 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 QMLCUSTOMPARSER_H
+#define QMLCUSTOMPARSER_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/qbytearray.h>
+#include <QtCore/qxmlstream.h>
+#include <QtDeclarative/qfxglobal.h>
+#include <QtDeclarative/qmlmetatype.h>
+#include <QtDeclarative/qmlerror.h>
+#include <private/qmlparser_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlCustomParserPropertyPrivate;
+class Q_DECLARATIVE_EXPORT QmlCustomParserProperty
+{
+public:
+ QmlCustomParserProperty();
+ QmlCustomParserProperty(const QmlCustomParserProperty &);
+ QmlCustomParserProperty &operator=(const QmlCustomParserProperty &);
+ ~QmlCustomParserProperty();
+
+ QByteArray name() const;
+ QmlParser::Location location() const;
+
+ bool isList() const;
+ // Will be one of QmlParser::Variant, QmlCustomParserProperty or
+ // QmlCustomParserNode
+ QList<QVariant> assignedValues() const;
+
+private:
+ friend class QmlCustomParserNodePrivate;
+ friend class QmlCustomParserPropertyPrivate;
+ QmlCustomParserPropertyPrivate *d;
+};
+
+class QmlCustomParserNodePrivate;
+class Q_DECLARATIVE_EXPORT QmlCustomParserNode
+{
+public:
+ QmlCustomParserNode();
+ QmlCustomParserNode(const QmlCustomParserNode &);
+ QmlCustomParserNode &operator=(const QmlCustomParserNode &);
+ ~QmlCustomParserNode();
+
+ QByteArray name() const;
+ QmlParser::Location location() const;
+
+ QList<QmlCustomParserProperty> properties() const;
+
+private:
+ friend class QmlCustomParserNodePrivate;
+ QmlCustomParserNodePrivate *d;
+};
+
+class Q_DECLARATIVE_EXPORT QmlCustomParser
+{
+public:
+ virtual ~QmlCustomParser() {}
+
+ void clearErrors();
+
+ virtual QByteArray compile(const QList<QmlCustomParserProperty> &)=0;
+ virtual void setCustomData(QObject *, const QByteArray &)=0;
+
+ QList<QmlError> errors() const { return exceptions; }
+
+protected:
+ void error(const QmlCustomParserProperty&, const QString& description);
+ void error(const QmlCustomParserNode&, const QString& description);
+
+private:
+ QList<QmlError> exceptions;
+};
+
+#if defined(Q_OS_SYMBIAN)
+# define QML_DEFINE_CUSTOM_TYPE(URI, VERSION_MAJ, VERSION_MIN_FROM, VERSION_MAJ_TO, NAME, TYPE, CUSTOMTYPE) \
+ static int defineCustomType##NAME = qmlRegisterCustomType<TYPE>(#URI, VERSION_MAJ, VERSION_MIN_FROM, VERSION_MAJ_TO, #NAME, #TYPE, new CUSTOMTYPE);
+#else
+# define QML_DEFINE_CUSTOM_TYPE(URI, VERSION_MAJ, VERSION_MIN_FROM, VERSION_MAJ_TO, NAME, TYPE, CUSTOMTYPE) \
+ template<> QmlPrivate::InstanceType QmlPrivate::Define<TYPE *,(VERSION_MAJ), (VERSION_MIN_FROM), (VERSION_MAJ_TO)>::instance(qmlRegisterCustomType<TYPE>(#URI, VERSION_MAJ, VERSION_MIN_FROM, VERSION_MAJ_TO, #NAME, #TYPE, new CUSTOMTYPE));
+#endif
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QmlCustomParserProperty)
+Q_DECLARE_METATYPE(QmlCustomParserNode)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/declarative/qml/qmlcustomparser_p_p.h b/src/declarative/qml/qmlcustomparser_p_p.h
new file mode 100644
index 0000000..25023d3
--- /dev/null
+++ b/src/declarative/qml/qmlcustomparser_p_p.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** 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 QMLCUSTOMPARSER_P_H
+#define QMLCUSTOMPARSER_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/qglobal.h>
+#include "qmlcustomparser_p.h"
+#include "qmlparser_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QmlCustomParserNodePrivate
+{
+public:
+ QByteArray name;
+ QList<QmlCustomParserProperty> properties;
+ QmlParser::Location location;
+
+ static QmlCustomParserNode fromObject(QmlParser::Object *);
+ static QmlCustomParserProperty fromProperty(QmlParser::Property *);
+};
+
+class QmlCustomParserPropertyPrivate
+{
+public:
+ QmlCustomParserPropertyPrivate()
+ : isList(false) {}
+
+ QByteArray name;
+ bool isList;
+ QmlParser::Location location;
+ QList<QVariant> values;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLCUSTOMPARSER_P_H
diff --git a/src/declarative/qml/qmldeclarativedata_p.h b/src/declarative/qml/qmldeclarativedata_p.h
new file mode 100644
index 0000000..f6ecc3d
--- /dev/null
+++ b/src/declarative/qml/qmldeclarativedata_p.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** 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 QMLDECLARATIVEDATA_P_H
+#define QMLDECLARATIVEDATA_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/qobject_p.h>
+#include <QtScript/qscriptvalue.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlCompiledData;
+class QmlAbstractBinding;
+class QmlContext;
+class QmlPropertyCache;
+class QmlDeclarativeData : public QDeclarativeData
+{
+public:
+ QmlDeclarativeData(QmlContext *context = 0);
+
+ virtual void destroyed(QObject *);
+
+ QmlContext *context;
+ QmlAbstractBinding *bindings;
+
+ int bindingBitsSize;
+ quint32 *bindingBits;
+ bool hasBindingBit(int) const;
+ void clearBindingBit(int);
+ void setBindingBit(QObject *obj, int);
+
+ QmlContext *outerContext; // Can't this be found from context?
+ ushort lineNumber;
+ ushort columnNumber;
+
+ QmlCompiledData *deferredComponent; // Can't this be found from the context?
+ unsigned int deferredIdx;
+
+ 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));
+ if (priv && priv->declarativeData) {
+ return static_cast<QmlDeclarativeData *>(priv->declarativeData);
+ } else if (create && priv) {
+ priv->declarativeData = new QmlDeclarativeData;
+ return static_cast<QmlDeclarativeData *>(priv->declarativeData);
+ } else {
+ return 0;
+ }
+ }
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLDECLARATIVEDATA_P_H
diff --git a/src/declarative/qml/qmldom.cpp b/src/declarative/qml/qmldom.cpp
new file mode 100644
index 0000000..a0601d7
--- /dev/null
+++ b/src/declarative/qml/qmldom.cpp
@@ -0,0 +1,1770 @@
+/****************************************************************************
+**
+** 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 "qmldom.h"
+#include "qmldom_p.h"
+#include "private/qmlcompositetypedata_p.h"
+#include "private/qmlcompiler_p.h"
+#include "private/qmlengine_p.h"
+#include <QtCore/QByteArray>
+#include <QtCore/QDebug>
+#include <QtCore/QString>
+#include "qmlscriptparser_p.h"
+
+QT_BEGIN_NAMESPACE
+
+DEFINE_BOOL_CONFIG_OPTION(compilerDump, QML_COMPILER_DUMP)
+
+QmlDomDocumentPrivate::QmlDomDocumentPrivate()
+: root(0)
+{
+}
+
+QmlDomDocumentPrivate::QmlDomDocumentPrivate(const QmlDomDocumentPrivate &other)
+: QSharedData(other), root(0)
+{
+ root = other.root;
+ if (root) root->addref();
+}
+
+QmlDomDocumentPrivate::~QmlDomDocumentPrivate()
+{
+ if (root) root->release();
+}
+
+/*!
+ \class QmlDomDocument
+ \internal
+ \brief The QmlDomDocument class represents the root of a QML document
+
+ A QML document is a self-contained snippet of QML, usually contained in a
+ single file. Each document has a root object, accessible through
+ QmlDomDocument::rootObject().
+
+ The QmlDomDocument class allows the programmer to inspect a QML document by
+ calling QmlDomDocument::load().
+
+ The following example loads a QML file from disk, and prints out its root
+ object type and the properties assigned in the root object.
+ \code
+ QFile file(inputFileName);
+ file.open(QIODevice::ReadOnly);
+ QByteArray xmlData = file.readAll();
+
+ QmlDomDocument document;
+ document.load(qmlengine, xmlData);
+
+ QmlDomObject rootObject = document.rootObject();
+ qDebug() << rootObject.objectType();
+ foreach(QmlDomProperty property, rootObject.properties())
+ qDebug() << property.propertyName();
+ \endcode
+*/
+
+/*!
+ Construct an empty QmlDomDocument.
+*/
+QmlDomDocument::QmlDomDocument()
+: d(new QmlDomDocumentPrivate)
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomDocument.
+*/
+QmlDomDocument::QmlDomDocument(const QmlDomDocument &other)
+: d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomDocument
+*/
+QmlDomDocument::~QmlDomDocument()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomDocument.
+*/
+QmlDomDocument &QmlDomDocument::operator=(const QmlDomDocument &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Returns all import statements in qml.
+*/
+QList<QmlDomImport> QmlDomDocument::imports() const
+{
+ return d->imports;
+}
+
+/*!
+ Loads a QmlDomDocument from \a data. \a data should be valid QML
+ data. On success, true is returned. If the \a data is malformed, false
+ is returned and QmlDomDocument::loadError() contains an error description.
+
+ \sa QmlDomDocument::loadError()
+*/
+bool QmlDomDocument::load(QmlEngine *engine, const QByteArray &data, const QUrl &url)
+{
+ d->errors.clear();
+ d->imports.clear();
+
+ QmlCompiledData *component = new QmlCompiledData;
+ QmlCompiler compiler;
+
+ QmlCompositeTypeData *td = ((QmlEnginePrivate *)QmlEnginePrivate::get(engine))->typeManager.getImmediate(data, url);
+
+ if(td->status == QmlCompositeTypeData::Error) {
+ d->errors = td->errors;
+ td->release();
+ component->release();
+ return false;
+ } else if(td->status == QmlCompositeTypeData::Waiting) {
+ QmlError error;
+ error.setDescription(QLatin1String("QmlDomDocument supports local types only"));
+ d->errors << error;
+ td->release();
+ component->release();
+ return false;
+ }
+
+ compiler.compile(engine, td, component);
+
+ if (compiler.isError()) {
+ d->errors = compiler.errors();
+ td->release();
+ component->release();
+ return false;
+ }
+
+ for (int i = 0; i < td->data.imports().size(); ++i) {
+ QmlScriptParser::Import parserImport = td->data.imports().at(i);
+ QmlDomImport domImport;
+ domImport.d->type = static_cast<QmlDomImportPrivate::Type>(parserImport.type);
+ domImport.d->uri = parserImport.uri;
+ domImport.d->qualifier = parserImport.qualifier;
+ domImport.d->version = parserImport.version;
+ d->imports += domImport;
+ }
+
+ if (td->data.tree()) {
+ if (compilerDump()) {
+ qWarning() << "-AST------------------------------------------------------------------------------";
+ td->data.tree()->dump();
+ qWarning() << "----------------------------------------------------------------------------------";
+ }
+ d->root = td->data.tree();
+ d->root->addref();
+ }
+
+ component->release();
+ return true;
+}
+
+/*!
+ Returns the last load errors. The load errors will be reset after a
+ successful call to load().
+
+ \sa load()
+*/
+QList<QmlError> QmlDomDocument::errors() const
+{
+ return d->errors;
+}
+
+/*!
+ Returns the document's root object, or an invalid QmlDomObject if the
+ document has no root.
+
+ In the sample QML below, the root object will be the QFxItem type.
+ \qml
+Item {
+ Text {
+ text: "Hello World"
+ }
+}
+ \endqml
+*/
+QmlDomObject QmlDomDocument::rootObject() const
+{
+ QmlDomObject rv;
+ rv.d->object = d->root;
+ if (rv.d->object) rv.d->object->addref();
+ return rv;
+}
+
+QmlDomPropertyPrivate::QmlDomPropertyPrivate()
+: property(0)
+{
+}
+
+QmlDomPropertyPrivate::QmlDomPropertyPrivate(const QmlDomPropertyPrivate &other)
+: QSharedData(other), property(0)
+{
+ property = other.property;
+ if (property) property->addref();
+}
+
+QmlDomPropertyPrivate::~QmlDomPropertyPrivate()
+{
+ if (property) property->release();
+}
+
+QmlDomDynamicPropertyPrivate::QmlDomDynamicPropertyPrivate():
+ valid(false)
+{
+}
+
+QmlDomDynamicPropertyPrivate::QmlDomDynamicPropertyPrivate(const QmlDomDynamicPropertyPrivate &other)
+: QSharedData(other), valid(other.valid)
+{
+ property = other.property;
+ if (valid && property.defaultValue) property.defaultValue->addref();
+}
+
+QmlDomDynamicPropertyPrivate::~QmlDomDynamicPropertyPrivate()
+{
+ if (valid && property.defaultValue) property.defaultValue->release();
+}
+
+/*!
+ \class QmlDomProperty
+ \internal
+ \brief The QmlDomProperty class represents one property assignment in the
+ QML DOM tree
+
+ Properties in QML can be assigned QML \l {QmlDomValue}{values}.
+
+ \sa QmlDomObject
+*/
+
+/*!
+ Construct an invalid QmlDomProperty.
+*/
+QmlDomProperty::QmlDomProperty()
+: d(new QmlDomPropertyPrivate)
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomProperty.
+*/
+QmlDomProperty::QmlDomProperty(const QmlDomProperty &other)
+: d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomProperty.
+*/
+QmlDomProperty::~QmlDomProperty()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomProperty.
+*/
+QmlDomProperty &QmlDomProperty::operator=(const QmlDomProperty &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Return the name of this property.
+
+ \qml
+Text {
+ x: 10
+ y: 10
+ font.bold: true
+}
+ \endqml
+
+ As illustrated above, a property name can be a simple string, such as "x" or
+ "y", or a more complex "dot property", such as "font.bold". In both cases
+ the full name is returned ("x", "y" and "font.bold") by this method.
+
+ For dot properties, a split version of the name can be accessed by calling
+ QmlDomProperty::propertyNameParts().
+
+ \sa QmlDomProperty::propertyNameParts()
+*/
+QByteArray QmlDomProperty::propertyName() const
+{
+ return d->propertyName;
+}
+
+/*!
+ Return the name of this property, split into multiple parts in the case
+ of dot properties.
+
+ \qml
+Text {
+ x: 10
+ y: 10
+ font.bold: true
+}
+ \endqml
+
+ For each of the properties shown above, this method would return ("x"),
+ ("y") and ("font", "bold").
+
+ \sa QmlDomProperty::propertyName()
+*/
+QList<QByteArray> QmlDomProperty::propertyNameParts() const
+{
+ if (d->propertyName.isEmpty()) return QList<QByteArray>();
+ else return d->propertyName.split('.');
+}
+
+/*!
+ Return true if this property is used as a default property in the QML
+ document.
+
+ \qml
+<Text text="hello"/>
+<Text>hello</Text>
+ \endqml
+
+ The above two examples return the same DOM tree, except that the second has
+ the default property flag set on the text property. Observe that whether
+ or not a property has isDefaultProperty set is determined by how the
+ property is used, and not only by whether the property is the types default
+ property.
+*/
+bool QmlDomProperty::isDefaultProperty() const
+{
+ return d->property && d->property->isDefault;
+}
+
+/*!
+ Returns the QmlDomValue that is assigned to this property, or an invalid
+ QmlDomValue if no value is assigned.
+*/
+QmlDomValue QmlDomProperty::value() const
+{
+ QmlDomValue rv;
+ if (d->property) {
+ rv.d->property = d->property;
+ rv.d->value = d->property->values.at(0);
+ rv.d->property->addref();
+ rv.d->value->addref();
+ }
+ return rv;
+}
+
+/*!
+ Returns the position in the input data where the property ID startd, or -1 if
+ the property is invalid.
+*/
+int QmlDomProperty::position() const
+{
+ if (d && d->property) {
+ return d->property->location.range.offset;
+ } else
+ return -1;
+}
+
+/*!
+ Returns the length in the input data from where the property ID started upto
+ the end of it, or -1 if the property is invalid.
+*/
+int QmlDomProperty::length() const
+{
+ if (d && d->property)
+ return d->property->location.range.length;
+ else
+ return -1;
+}
+
+/*!
+ Construct an invalid QmlDomDynamicProperty.
+*/
+QmlDomDynamicProperty::QmlDomDynamicProperty():
+ d(new QmlDomDynamicPropertyPrivate)
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomDynamicProperty.
+*/
+QmlDomDynamicProperty::QmlDomDynamicProperty(const QmlDomDynamicProperty &other):
+ d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomDynamicProperty.
+*/
+QmlDomDynamicProperty::~QmlDomDynamicProperty()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomDynamicProperty.
+*/
+QmlDomDynamicProperty &QmlDomDynamicProperty::operator=(const QmlDomDynamicProperty &other)
+{
+ d = other.d;
+ return *this;
+}
+
+bool QmlDomDynamicProperty::isValid() const
+{
+ return d && d->valid;
+}
+
+/*!
+ Return the name of this dynamic property.
+
+ \qml
+Item {
+ property int count: 10;
+}
+ \endqml
+
+ As illustrated above, a dynamic property name can have a name and a
+ default value ("10").
+*/
+QByteArray QmlDomDynamicProperty::propertyName() const
+{
+ if (isValid())
+ return d->property.name;
+ else
+ return QByteArray();
+}
+
+int QmlDomDynamicProperty::propertyType() const
+{
+ if (isValid()) {
+ switch (d->property.type) {
+ case QmlParser::Object::DynamicProperty::Bool:
+ return QMetaType::type("bool");
+
+ case QmlParser::Object::DynamicProperty::Color:
+ return QMetaType::type("QColor");
+
+ case QmlParser::Object::DynamicProperty::Date:
+ return QMetaType::type("QDateTime");
+
+ case QmlParser::Object::DynamicProperty::Int:
+ return QMetaType::type("int");
+
+ case QmlParser::Object::DynamicProperty::Real:
+ return QMetaType::type("double");
+
+ case QmlParser::Object::DynamicProperty::String:
+ return QMetaType::type("QString");
+
+ case QmlParser::Object::DynamicProperty::Url:
+ return QMetaType::type("QUrl");
+
+ case QmlParser::Object::DynamicProperty::Variant:
+ return QMetaType::type("QVariant");
+
+ default:
+ break;
+ }
+ }
+
+ return -1;
+}
+
+/*!
+ Return true if this property is used as a default property in the QML
+ document.
+
+ \qml
+<Text text="hello"/>
+<Text>hello</Text>
+ \endqml
+
+ The above two examples return the same DOM tree, except that the second has
+ the default property flag set on the text property. Observe that whether
+ or not a property has isDefaultProperty set is determined by how the
+ property is used, and not only by whether the property is the types default
+ property.
+*/
+bool QmlDomDynamicProperty::isDefaultProperty() const
+{
+ if (isValid())
+ return d->property.isDefaultProperty;
+ else
+ return false;
+}
+
+/*!
+ Returns the default value as a QmlDomProperty.
+*/
+QmlDomProperty QmlDomDynamicProperty::defaultValue() const
+{
+ QmlDomProperty rp;
+
+ if (isValid() && d->property.defaultValue) {
+ rp.d->property = d->property.defaultValue;
+ rp.d->property->addref();
+ }
+
+ return rp;
+}
+
+/*!
+ Returns the position in the input data where the property ID startd, or 0 if
+ the property is invalid.
+*/
+int QmlDomDynamicProperty::position() const
+{
+ if (isValid()) {
+ return d->property.location.range.offset;
+ } else
+ return -1;
+}
+
+/*!
+ Returns the length in the input data from where the property ID started upto
+ the end of it, or 0 if the property is invalid.
+*/
+int QmlDomDynamicProperty::length() const
+{
+ if (isValid())
+ return d->property.location.range.length;
+ else
+ return -1;
+}
+
+QmlDomObjectPrivate::QmlDomObjectPrivate()
+: object(0), isVirtualComponent(false)
+{
+}
+
+QmlDomObjectPrivate::QmlDomObjectPrivate(const QmlDomObjectPrivate &other)
+: QSharedData(other), object(0), isVirtualComponent(false)
+{
+ object = other.object;
+ if (object) object->addref();
+ isVirtualComponent = other.isVirtualComponent;
+}
+
+QmlDomObjectPrivate::~QmlDomObjectPrivate()
+{
+ if (object) object->release();
+}
+
+QmlDomObjectPrivate::Properties
+QmlDomObjectPrivate::properties() const
+{
+ Properties rv;
+
+ for (QHash<QByteArray, QmlParser::Property *>::ConstIterator iter =
+ object->properties.begin();
+ iter != object->properties.end();
+ ++iter) {
+
+ rv << properties(*iter);
+
+ }
+ return rv;
+}
+
+QmlDomObjectPrivate::Properties
+QmlDomObjectPrivate::properties(QmlParser::Property *property) const
+{
+ Properties rv;
+
+ if (property->value) {
+
+ for (QHash<QByteArray, QmlParser::Property *>::ConstIterator iter =
+ property->value->properties.begin();
+ iter != property->value->properties.end();
+ ++iter) {
+
+ rv << properties(*iter);
+
+ }
+
+ QByteArray name(property->name + ".");
+ for (Properties::Iterator iter = rv.begin(); iter != rv.end(); ++iter)
+ iter->second.prepend(name);
+
+ } else {
+ rv << qMakePair(property, property->name);
+ }
+
+ return rv;
+}
+
+/*!
+ \class QmlDomObject
+ \internal
+ \brief The QmlDomObject class represents an object instantiation.
+
+ Each object instantiated in a QML file has a corresponding QmlDomObject
+ node in the QML DOM.
+
+ In addition to the type information that determines the object to
+ instantiate, QmlDomObject's also have a set of associated QmlDomProperty's.
+ Each QmlDomProperty represents a QML property assignment on the instantiated
+ object. For example,
+
+ \qml
+QGraphicsWidget {
+ opacity: 0.5
+ size: "100x100"
+}
+ \endqml
+
+ describes a single QmlDomObject - "QGraphicsWidget" - with two properties,
+ "opacity" and "size". Obviously QGraphicsWidget has many more properties than just
+ these two, but the QML DOM representation only contains those assigned
+ values (or bindings) in the QML file.
+*/
+
+/*!
+ Construct an invalid QmlDomObject.
+*/
+QmlDomObject::QmlDomObject()
+: d(new QmlDomObjectPrivate)
+{
+}
+
+/*!
+ Construct a new QmlDomObject with the specified \a objectType.
+*/
+QmlDomObject::QmlDomObject(const QByteArray &objectType)
+: d(new QmlDomObjectPrivate)
+{
+ Q_UNUSED(objectType);
+ qWarning("QmlDomObject::QmlDomObject(const QByteArray &): Not implemented");
+}
+
+/*!
+ Create a copy of \a other QmlDomObject.
+*/
+QmlDomObject::QmlDomObject(const QmlDomObject &other)
+: d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomObject.
+*/
+QmlDomObject::~QmlDomObject()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomObject.
+*/
+QmlDomObject &QmlDomObject::operator=(const QmlDomObject &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Returns true if this is a valid QmlDomObject, false otherwise.
+*/
+bool QmlDomObject::isValid() const
+{
+ return d->object != 0;
+}
+
+/*!
+ Returns the fully-qualified type name of this object.
+
+ For example, the type of this object would be "Qt/4.6/Rectangle".
+ \qml
+Rectangle { }
+ \endqml
+*/
+QByteArray QmlDomObject::objectType() const
+{
+ if (d->object) return d->object->typeName;
+ else return QByteArray();
+}
+
+/*!
+ Returns the type name as referenced in the qml file.
+
+ For example, the type of this object would be "Rectangle".
+ \qml
+Rectangle { }
+ \endqml
+*/
+QByteArray QmlDomObject::objectClassName() const
+{
+ if (d->object)
+ return d->object->className;
+ else
+ return QByteArray();
+}
+
+int QmlDomObject::objectTypeMajorVersion() const
+{
+ if (d->object)
+ return d->object->majorVersion;
+ else
+ return -1;
+}
+
+int QmlDomObject::objectTypeMinorVersion() const
+{
+ if (d->object)
+ return d->object->minorVersion;
+ else
+ return -1;
+}
+
+/*!
+ Returns the QML id assigned to this object, or an empty QByteArray if no id
+ has been assigned.
+
+ For example, the object id of this object would be "MyText".
+ \qml
+Text { id: myText }
+ \endqml
+*/
+QString QmlDomObject::objectId() const
+{
+ if (d->object) {
+ return d->object->id;
+ } else {
+ return QString();
+ }
+}
+
+/*!
+ Returns the list of assigned properties on this object.
+
+ In the following example, "text" and "x" properties would be returned.
+ \qml
+Text {
+ text: "Hello world!"
+ x: 100
+}
+ \endqml
+*/
+QList<QmlDomProperty> QmlDomObject::properties() const
+{
+ QList<QmlDomProperty> rv;
+
+ if (!d->object)
+ return rv;
+
+ QmlDomObjectPrivate::Properties properties = d->properties();
+ for (int ii = 0; ii < properties.count(); ++ii) {
+
+ QmlDomProperty domProperty;
+ domProperty.d->property = properties.at(ii).first;
+ domProperty.d->property->addref();
+ domProperty.d->propertyName = properties.at(ii).second;
+ rv << domProperty;
+
+ }
+
+ if (d->object->defaultProperty) {
+ QmlDomProperty domProperty;
+ domProperty.d->property = d->object->defaultProperty;
+ domProperty.d->property->addref();
+ domProperty.d->propertyName = d->object->defaultProperty->name;
+ rv << domProperty;
+ }
+
+ return rv;
+}
+
+/*!
+ Returns the object's \a name property if a value has been assigned to
+ it, or an invalid QmlDomProperty otherwise.
+
+ In the example below, \c {object.property("source")} would return a valid
+ QmlDomProperty, and \c {object.property("tile")} an invalid QmlDomProperty.
+
+ \qml
+Image { source: "sample.jpg" }
+ \endqml
+*/
+QmlDomProperty QmlDomObject::property(const QByteArray &name) const
+{
+ QList<QmlDomProperty> props = properties();
+ for (int ii = 0; ii < props.count(); ++ii)
+ if (props.at(ii).propertyName() == name)
+ return props.at(ii);
+ return QmlDomProperty();
+}
+
+QList<QmlDomDynamicProperty> QmlDomObject::dynamicProperties() const
+{
+ QList<QmlDomDynamicProperty> properties;
+
+ for (int i = 0; i < d->object->dynamicProperties.size(); ++i) {
+ QmlDomDynamicProperty p;
+ p.d = new QmlDomDynamicPropertyPrivate;
+ p.d->property = d->object->dynamicProperties.at(i);
+ p.d->valid = true;
+
+ if (p.d->property.defaultValue)
+ p.d->property.defaultValue->addref();
+
+ properties.append(p);
+ }
+
+ return properties;
+}
+
+QmlDomDynamicProperty QmlDomObject::dynamicProperty(const QByteArray &name) const
+{
+ QmlDomDynamicProperty p;
+
+ for (int i = 0; i < d->object->dynamicProperties.size(); ++i) {
+ if (d->object->dynamicProperties.at(i).name == name) {
+ p.d = new QmlDomDynamicPropertyPrivate;
+ p.d->property = d->object->dynamicProperties.at(i);
+ if (p.d->property.defaultValue) p.d->property.defaultValue->addref();
+ p.d->valid = true;
+ }
+ }
+
+ return p;
+}
+
+/*!
+ Returns true if this object is a custom type. Custom types are special
+ types that allow embeddeding non-QML data, such as SVG or HTML data,
+ directly into QML files.
+
+ \note Currently this method will always return false, and is a placekeeper
+ for future functionality.
+
+ \sa QmlDomObject::customTypeData()
+*/
+bool QmlDomObject::isCustomType() const
+{
+ return false;
+}
+
+/*!
+ If this object represents a custom type, returns the data associated with
+ the custom type, otherwise returns an empty QByteArray().
+ QmlDomObject::isCustomType() can be used to check if this object represents
+ a custom type.
+*/
+QByteArray QmlDomObject::customTypeData() const
+{
+ return QByteArray();
+}
+
+/*!
+ Returns true if this object is a sub-component object. Sub-component
+ objects can be converted into QmlDomComponent instances by calling
+ QmlDomObject::toComponent().
+
+ \sa QmlDomObject::toComponent()
+*/
+bool QmlDomObject::isComponent() const
+{
+ return d->isVirtualComponent ||
+ (d->object && d->object->typeName == "Qt/Component");
+}
+
+/*!
+ Returns a QmlDomComponent for this object if it is a sub-component, or
+ an invalid QmlDomComponent if not. QmlDomObject::isComponent() can be used
+ to check if this object represents a sub-component.
+
+ \sa QmlDomObject::isComponent()
+*/
+QmlDomComponent QmlDomObject::toComponent() const
+{
+ QmlDomComponent rv;
+ if (isComponent())
+ rv.d = d;
+ return rv;
+}
+
+/*!
+ Returns the position in the input data where the property assignment started
+, or -1 if the property is invalid.
+*/
+int QmlDomObject::position() const
+{
+ if (d && d->object)
+ return d->object->location.range.offset;
+ else
+ return -1;
+}
+
+/*!
+ Returns the length in the input data from where the property assignment star
+ted upto the end of it, or -1 if the property is invalid.
+*/
+int QmlDomObject::length() const
+{
+ if (d && d->object)
+ return d->object->location.range.length;
+ else
+ return -1;
+}
+
+// Returns the URL of the type, if it is an external type, or an empty URL if
+// not
+QUrl QmlDomObject::url() const
+{
+ if (d && d->object)
+ return d->object->url;
+ else
+ return QUrl();
+}
+
+QmlDomBasicValuePrivate::QmlDomBasicValuePrivate()
+: value(0)
+{
+}
+
+QmlDomBasicValuePrivate::QmlDomBasicValuePrivate(const QmlDomBasicValuePrivate &other)
+: QSharedData(other), value(0)
+{
+ value = other.value;
+ if (value) value->addref();
+}
+
+QmlDomBasicValuePrivate::~QmlDomBasicValuePrivate()
+{
+ if (value) value->release();
+}
+
+/*!
+ \class QmlDomValueLiteral
+ \internal
+ \brief The QmlDomValueLiteral class represents a literal value.
+
+ A literal value is a simple value, written inline with the QML. In the
+ example below, the "x", "y" and "color" properties are being assigned
+ literal values.
+
+ \qml
+Rectangle {
+ x: 10
+ y: 10
+ color: "red"
+}
+ \endqml
+*/
+
+/*!
+ Construct an empty QmlDomValueLiteral.
+*/
+QmlDomValueLiteral::QmlDomValueLiteral():
+ d(new QmlDomBasicValuePrivate)
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomValueLiteral.
+*/
+QmlDomValueLiteral::QmlDomValueLiteral(const QmlDomValueLiteral &other)
+: d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomValueLiteral.
+*/
+QmlDomValueLiteral::~QmlDomValueLiteral()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomValueLiteral.
+*/
+QmlDomValueLiteral &QmlDomValueLiteral::operator=(const QmlDomValueLiteral &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Return the literal value.
+
+ In the example below, the literal value will be the string "10".
+ \qml
+Rectangle { x: 10 }
+ \endqml
+*/
+QString QmlDomValueLiteral::literal() const
+{
+ if (d->value) return d->value->primitive();
+ else return QString();
+}
+
+/*!
+ \class QmlDomValueBinding
+ \internal
+ \brief The QmlDomValueBinding class represents a property binding.
+
+ A property binding is an ECMAScript expression assigned to a property. In
+ the example below, the "x" property is being assigned a property binding.
+
+ \qml
+Rectangle { x: Other.x }
+ \endqml
+*/
+
+/*!
+ Construct an empty QmlDomValueBinding.
+*/
+QmlDomValueBinding::QmlDomValueBinding():
+ d(new QmlDomBasicValuePrivate)
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomValueBinding.
+*/
+QmlDomValueBinding::QmlDomValueBinding(const QmlDomValueBinding &other)
+: d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomValueBinding.
+*/
+QmlDomValueBinding::~QmlDomValueBinding()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomValueBinding.
+*/
+QmlDomValueBinding &QmlDomValueBinding::operator=(const QmlDomValueBinding &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Return the binding expression.
+
+ In the example below, the string "Other.x" will be returned.
+ \qml
+Rectangle { x: Other.x }
+ \endqml
+*/
+QString QmlDomValueBinding::binding() const
+{
+ if (d->value)
+ return d->value->value.asScript();
+ else
+ return QString();
+}
+
+/*!
+ \class QmlDomValueValueSource
+ \internal
+ \brief The QmlDomValueValueSource class represents a value source assignment value.
+
+ In QML, value sources are special value generating types that may be
+ assigned to properties. Value sources inherit the QmlPropertyValueSource
+ class. In the example below, the "x" property is being assigned the
+ NumberAnimation value source.
+
+ \qml
+Rectangle {
+ x: NumberAnimation {
+ from: 0
+ to: 100
+ repeat: true
+ running: true
+ }
+}
+ \endqml
+*/
+
+/*!
+ Construct an empty QmlDomValueValueSource.
+*/
+QmlDomValueValueSource::QmlDomValueValueSource():
+ d(new QmlDomBasicValuePrivate)
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomValueValueSource.
+*/
+QmlDomValueValueSource::QmlDomValueValueSource(const QmlDomValueValueSource &other)
+: d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomValueValueSource.
+*/
+QmlDomValueValueSource::~QmlDomValueValueSource()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomValueValueSource.
+*/
+QmlDomValueValueSource &QmlDomValueValueSource::operator=(const QmlDomValueValueSource &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Return the value source object.
+
+ In the example below, an object representing the NumberAnimation will be
+ returned.
+ \qml
+Rectangle {
+ x: NumberAnimation {
+ from: 0
+ to: 100
+ repeat: true
+ running: true
+ }
+}
+ \endqml
+*/
+QmlDomObject QmlDomValueValueSource::object() const
+{
+ QmlDomObject rv;
+ if (d->value) {
+ rv.d->object = d->value->object;
+ rv.d->object->addref();
+ }
+ return rv;
+}
+
+
+QmlDomValuePrivate::QmlDomValuePrivate()
+: property(0), value(0)
+{
+}
+
+QmlDomValuePrivate::QmlDomValuePrivate(const QmlDomValuePrivate &other)
+: QSharedData(other), property(0), value(0)
+{
+ property = other.property;
+ value = other.value;
+ if (property) property->addref();
+ if (value) value->addref();
+}
+
+QmlDomValuePrivate::~QmlDomValuePrivate()
+{
+ if (property) property->release();
+ if (value) value->release();
+}
+
+/*!
+ \class QmlDomValue
+ \internal
+ \brief The QmlDomValue class represents a generic Qml value.
+
+ QmlDomValue's can be assigned to QML \l {QmlDomProperty}{properties}. In
+ QML, properties can be assigned various different values, including basic
+ literals, property bindings, property value sources, objects and lists of
+ values. The QmlDomValue class allows a programmer to determine the specific
+ value type being assigned and access more detailed information through a
+ corresponding value type class.
+
+ For example, in the following example,
+
+ \qml
+Text {
+ text: "Hello World!"
+ y: Other.y
+}
+ \endqml
+
+ The text property is being assigned a literal, and the y property a property
+ binding. To output the values assigned to the text and y properties in the
+ above example from C++,
+
+ \code
+ QmlDomDocument document;
+ QmlDomObject root = document.rootObject();
+
+ QmlDomProperty text = root.property("text");
+ if (text.value().isLiteral()) {
+ QmlDomValueLiteral literal = text.value().toLiteral();
+ qDebug() << literal.literal();
+ }
+
+ QmlDomProperty y = root.property("y");
+ if (y.value().isBinding()) {
+ QmlDomValueBinding binding = y.value().toBinding();
+ qDebug() << binding.binding();
+ }
+ \endcode
+*/
+
+/*!
+ Construct an invalid QmlDomValue.
+*/
+QmlDomValue::QmlDomValue()
+: d(new QmlDomValuePrivate)
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomValue.
+*/
+QmlDomValue::QmlDomValue(const QmlDomValue &other)
+: d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomValue
+*/
+QmlDomValue::~QmlDomValue()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomValue.
+*/
+QmlDomValue &QmlDomValue::operator=(const QmlDomValue &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ \enum QmlDomValue::Type
+
+ The type of the QmlDomValue node.
+
+ \value Invalid The QmlDomValue is invalid.
+ \value Literal The QmlDomValue is a literal value assignment. Use QmlDomValue::toLiteral() to access the type instance.
+ \value PropertyBinding The QmlDomValue is a property binding. Use QmlDomValue::toBinding() to access the type instance.
+ \value ValueSource The QmlDomValue is a property value source. Use QmlDomValue::toValueSource() to access the type instance.
+ \value Object The QmlDomValue is an object assignment. Use QmlDomValue::toObject() to access the type instnace.
+ \value List The QmlDomValue is a list of other values. Use QmlDomValue::toList() to access the type instance.
+*/
+
+/*!
+ Returns the type of this QmlDomValue.
+*/
+QmlDomValue::Type QmlDomValue::type() const
+{
+ if (d->property)
+ if (QmlMetaType::isList(d->property->type) ||
+ QmlMetaType::isQmlList(d->property->type) ||
+ (d->property && d->property->values.count() > 1))
+ return List;
+
+ QmlParser::Value *value = d->value;
+ if (!value && !d->property)
+ return Invalid;
+
+ switch(value->type) {
+ case QmlParser::Value::Unknown:
+ return Invalid;
+ case QmlParser::Value::Literal:
+ return Literal;
+ case QmlParser::Value::PropertyBinding:
+ return PropertyBinding;
+ case QmlParser::Value::ValueSource:
+ return ValueSource;
+ case QmlParser::Value::CreatedObject:
+ return Object;
+ case QmlParser::Value::SignalObject:
+ return Invalid;
+ case QmlParser::Value::SignalExpression:
+ return Literal;
+ case QmlParser::Value::Id:
+ return Literal;
+ }
+ return Invalid;
+}
+
+/*!
+ Returns true if this is an invalid value, otherwise false.
+*/
+bool QmlDomValue::isInvalid() const
+{
+ return type() == Invalid;
+}
+
+/*!
+ Returns true if this is a literal value, otherwise false.
+*/
+bool QmlDomValue::isLiteral() const
+{
+ return type() == Literal;
+}
+
+/*!
+ Returns true if this is a property binding value, otherwise false.
+*/
+bool QmlDomValue::isBinding() const
+{
+ return type() == PropertyBinding;
+}
+
+/*!
+ Returns true if this is a value source value, otherwise false.
+*/
+bool QmlDomValue::isValueSource() const
+{
+ return type() == ValueSource;
+}
+
+/*!
+ Returns true if this is an object value, otherwise false.
+*/
+bool QmlDomValue::isObject() const
+{
+ return type() == Object;
+}
+
+/*!
+ Returns true if this is a list value, otherwise false.
+*/
+bool QmlDomValue::isList() const
+{
+ return type() == List;
+}
+
+/*!
+ Returns a QmlDomValueLiteral if this value is a literal type, otherwise
+ returns an invalid QmlDomValueLiteral.
+
+ \sa QmlDomValue::type()
+*/
+QmlDomValueLiteral QmlDomValue::toLiteral() const
+{
+ QmlDomValueLiteral rv;
+ if (type() == Literal) {
+ rv.d->value = d->value;
+ rv.d->value->addref();
+ }
+ return rv;
+}
+
+/*!
+ Returns a QmlDomValueBinding if this value is a property binding type,
+ otherwise returns an invalid QmlDomValueBinding.
+
+ \sa QmlDomValue::type()
+*/
+QmlDomValueBinding QmlDomValue::toBinding() const
+{
+ QmlDomValueBinding rv;
+ if (type() == PropertyBinding) {
+ rv.d->value = d->value;
+ rv.d->value->addref();
+ }
+ return rv;
+}
+
+/*!
+ Returns a QmlDomValueValueSource if this value is a property value source
+ type, otherwise returns an invalid QmlDomValueValueSource.
+
+ \sa QmlDomValue::type()
+*/
+QmlDomValueValueSource QmlDomValue::toValueSource() const
+{
+ QmlDomValueValueSource rv;
+ if (type() == ValueSource) {
+ rv.d->value = d->value;
+ rv.d->value->addref();
+ }
+ return rv;
+}
+
+/*!
+ Returns a QmlDomObject if this value is an object assignment type, otherwise
+ returns an invalid QmlDomObject.
+
+ \sa QmlDomValue::type()
+*/
+QmlDomObject QmlDomValue::toObject() const
+{
+ QmlDomObject rv;
+ if (type() == Object) {
+ rv.d->object = d->value->object;
+ rv.d->object->addref();
+ }
+ return rv;
+}
+
+/*!
+ Returns a QmlDomList if this value is a list type, otherwise returns an
+ invalid QmlDomList.
+
+ \sa QmlDomValue::type()
+*/
+QmlDomList QmlDomValue::toList() const
+{
+ QmlDomList rv;
+ if (type() == List) {
+ rv.d = d;
+ }
+ return rv;
+}
+
+/*!
+ Returns the position in the input data where the property value startd, or -1
+ if the value is invalid.
+*/
+int QmlDomValue::position() const
+{
+ if (type() == Invalid)
+ return -1;
+ else
+ return d->value->location.range.offset;
+}
+
+/*!
+ Returns the length in the input data from where the property value started u
+pto the end of it, or -1 if the value is invalid.
+*/
+int QmlDomValue::length() const
+{
+ if (type() == Invalid)
+ return -1;
+ else
+ return d->value->location.range.length;
+}
+
+/*!
+ \class QmlDomList
+ \internal
+ \brief The QmlDomList class represents a list of values assigned to a QML property.
+
+ Lists of values can be assigned to properties. For example, the following
+ example assigns multiple objects to Item's "children" property
+ \qml
+Item {
+ children: [
+ Text { },
+ Rectangle { }
+ ]
+}
+ \endqml
+
+ Lists can also be implicitly created by assigning multiple
+ \l {QmlDomValueValueSource}{value sources} or constants to a property.
+ \qml
+Item {
+ x: 10
+ x: NumberAnimation {
+ running: false
+ from: 0
+ to: 100
+ }
+}
+ \endqml
+*/
+
+/*!
+ Construct an empty QmlDomList.
+*/
+QmlDomList::QmlDomList()
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomList.
+*/
+QmlDomList::QmlDomList(const QmlDomList &other)
+: d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomList.
+*/
+QmlDomList::~QmlDomList()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomList.
+*/
+QmlDomList &QmlDomList::operator=(const QmlDomList &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Returns the list of QmlDomValue's.
+*/
+QList<QmlDomValue> QmlDomList::values() const
+{
+ QList<QmlDomValue> rv;
+ if (!d->property)
+ return rv;
+
+ for (int ii = 0; ii < d->property->values.count(); ++ii) {
+ QmlDomValue v;
+ v.d->value = d->property->values.at(ii);
+ v.d->value->addref();
+ rv << v;
+ }
+
+ return rv;
+}
+
+/*!
+ Returns the position in the input data where the list started, or -1 if
+ the property is invalid.
+*/
+int QmlDomList::position() const
+{
+ if (d && d->property) {
+ return d->property->listValueRange.offset;
+ } else
+ return -1;
+}
+
+/*!
+ Returns the length in the input data from where the list started upto
+ the end of it, or 0 if the property is invalid.
+*/
+int QmlDomList::length() const
+{
+ if (d && d->property)
+ return d->property->listValueRange.length;
+ else
+ return -1;
+}
+
+/*!
+ Returns a list of positions of the commas in the QML file.
+*/
+QList<int> QmlDomList:: commaPositions() const
+{
+ if (d && d->property)
+ return d->property->listCommaPositions;
+ else
+ return QList<int>();
+}
+
+/*!
+ \class QmlDomComponent
+ \internal
+ \brief The QmlDomComponent class represents sub-component within a QML document.
+
+ Sub-components are QmlComponents defined within a QML document. The
+ following example shows the definition of a sub-component with the id
+ "listDelegate".
+
+ \qml
+Item {
+ Component {
+ id: listDelegate
+ Text {
+ text: modelData.text
+ }
+ }
+}
+ \endqml
+
+ Like QmlDomDocument's, components contain a single root object.
+*/
+
+/*!
+ Construct an empty QmlDomComponent.
+*/
+QmlDomComponent::QmlDomComponent()
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomComponent.
+*/
+QmlDomComponent::QmlDomComponent(const QmlDomComponent &other)
+: QmlDomObject(other)
+{
+}
+
+/*!
+ Destroy the QmlDomComponent.
+*/
+QmlDomComponent::~QmlDomComponent()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomComponent.
+*/
+QmlDomComponent &QmlDomComponent::operator=(const QmlDomComponent &other)
+{
+ static_cast<QmlDomObject &>(*this) = other;
+ return *this;
+}
+
+/*!
+ Returns the component's root object.
+
+ In the example below, the root object is the "Text" object.
+ \qml
+Item {
+ Component {
+ id: listDelegate
+ Text {
+ text: modelData.text
+ }
+ }
+}
+ \endqml
+*/
+QmlDomObject QmlDomComponent::componentRoot() const
+{
+ QmlDomObject rv;
+ if (d->isVirtualComponent) {
+ rv.d->object = d->object;
+ rv.d->object->addref();
+ } else if (d->object) {
+ QmlParser::Object *obj = 0;
+ if (d->object->defaultProperty &&
+ d->object->defaultProperty->values.count() == 1 &&
+ d->object->defaultProperty->values.at(0)->object)
+ obj = d->object->defaultProperty->values.at(0)->object;
+
+ if (obj) {
+ rv.d->object = obj;
+ rv.d->object->addref();
+ }
+ }
+
+ return rv;
+}
+
+QmlDomImportPrivate::QmlDomImportPrivate()
+: type(File)
+{
+}
+
+QmlDomImportPrivate::QmlDomImportPrivate(const QmlDomImportPrivate &other)
+: QSharedData(other)
+{
+}
+
+QmlDomImportPrivate::~QmlDomImportPrivate()
+{
+}
+
+/*!
+ \class QmlDomImport
+ \internal
+ \brief The QmlDomImport class represents an import statement.
+*/
+
+/*!
+ Construct an empty QmlDomImport.
+*/
+QmlDomImport::QmlDomImport()
+: d(new QmlDomImportPrivate)
+{
+}
+
+/*!
+ Create a copy of \a other QmlDomImport.
+*/
+QmlDomImport::QmlDomImport(const QmlDomImport &other)
+: d(other.d)
+{
+}
+
+/*!
+ Destroy the QmlDomImport.
+*/
+QmlDomImport::~QmlDomImport()
+{
+}
+
+/*!
+ Assign \a other to this QmlDomImport.
+*/
+QmlDomImport &QmlDomImport::operator=(const QmlDomImport &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Returns the type of the import.
+ */
+QmlDomImport::Type QmlDomImport::type() const
+{
+ return static_cast<QmlDomImport::Type>(d->type);
+}
+
+/*!
+ Returns the URI of the import (e.g. 'subdir' or 'com.nokia.Qt')
+ */
+QString QmlDomImport::uri() const
+{
+ return d->uri;
+}
+
+/*!
+ Returns the version specified by the import. An empty string if no version was specified.
+ */
+QString QmlDomImport::version() const
+{
+ return d->version;
+}
+
+/*!
+ Returns the (optional) qualifier string (the token following the 'as' keyword) of the import.
+ */
+QString QmlDomImport::qualifier() const
+{
+ return d->qualifier;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmldom.h b/src/declarative/qml/qmldom.h
new file mode 100644
index 0000000..f344bb2
--- /dev/null
+++ b/src/declarative/qml/qmldom.h
@@ -0,0 +1,325 @@
+/****************************************************************************
+**
+** 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 QMLDOM_H
+#define QMLDOM_H
+
+#include <QtCore/qlist.h>
+#include <QtCore/qshareddata.h>
+#include <QtDeclarative/qmlerror.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QString;
+class QByteArray;
+class QmlDomObject;
+class QmlDomList;
+class QmlDomValue;
+class QmlEngine;
+class QmlDomComponent;
+class QmlDomImport;
+class QIODevice;
+
+class QmlDomDocumentPrivate;
+
+class Q_DECLARATIVE_EXPORT QmlDomDocument
+{
+public:
+ QmlDomDocument();
+ QmlDomDocument(const QmlDomDocument &);
+ ~QmlDomDocument();
+ QmlDomDocument &operator=(const QmlDomDocument &);
+
+ QList<QmlDomImport> imports() const;
+
+ QList<QmlError> errors() const;
+ bool load(QmlEngine *, const QByteArray &, const QUrl & = QUrl());
+
+ QmlDomObject rootObject() const;
+
+private:
+ QSharedDataPointer<QmlDomDocumentPrivate> d;
+};
+
+class QmlDomPropertyPrivate;
+class Q_DECLARATIVE_EXPORT QmlDomProperty
+{
+public:
+ QmlDomProperty();
+ QmlDomProperty(const QmlDomProperty &);
+ ~QmlDomProperty();
+ QmlDomProperty &operator=(const QmlDomProperty &);
+
+ QByteArray propertyName() const;
+ QList<QByteArray> propertyNameParts() const;
+
+ bool isDefaultProperty() const;
+
+ QmlDomValue value() const;
+
+ int position() const;
+ int length() const;
+
+private:
+ friend class QmlDomObject;
+ friend class QmlDomDynamicProperty;
+ QSharedDataPointer<QmlDomPropertyPrivate> d;
+};
+
+class QmlDomDynamicPropertyPrivate;
+class Q_DECLARATIVE_EXPORT QmlDomDynamicProperty
+{
+public:
+ QmlDomDynamicProperty();
+ QmlDomDynamicProperty(const QmlDomDynamicProperty &);
+ ~QmlDomDynamicProperty();
+ QmlDomDynamicProperty &operator=(const QmlDomDynamicProperty &);
+
+ bool isValid() const;
+
+ QByteArray propertyName() const;
+ int propertyType() const;
+
+ bool isDefaultProperty() const;
+
+ QmlDomProperty defaultValue() const;
+
+ int position() const;
+ int length() const;
+
+private:
+ friend class QmlDomObject;
+ QSharedDataPointer<QmlDomDynamicPropertyPrivate> d;
+};
+
+class QmlDomObjectPrivate;
+class Q_DECLARATIVE_EXPORT QmlDomObject
+{
+public:
+ QmlDomObject();
+ QmlDomObject(const QByteArray &);
+ QmlDomObject(const QmlDomObject &);
+ ~QmlDomObject();
+ QmlDomObject &operator=(const QmlDomObject &);
+
+ bool isValid() const;
+
+ QByteArray objectType() const;
+ QByteArray objectClassName() const;
+
+ int objectTypeMajorVersion() const;
+ int objectTypeMinorVersion() const;
+
+ QString objectId() const;
+
+ QList<QmlDomProperty> properties() const;
+ QmlDomProperty property(const QByteArray &) const;
+
+ QList<QmlDomDynamicProperty> dynamicProperties() const;
+ QmlDomDynamicProperty dynamicProperty(const QByteArray &) const;
+
+ bool isCustomType() const;
+ QByteArray customTypeData() const;
+
+ bool isComponent() const;
+ QmlDomComponent toComponent() const;
+
+ int position() const;
+ int length() const;
+
+ QUrl url() const;
+private:
+ friend class QmlDomDocument;
+ friend class QmlDomComponent;
+ friend class QmlDomValue;
+ friend class QmlDomValueValueSource;
+ QSharedDataPointer<QmlDomObjectPrivate> d;
+};
+
+class QmlDomValuePrivate;
+class QmlDomBasicValuePrivate;
+class Q_DECLARATIVE_EXPORT QmlDomValueLiteral
+{
+public:
+ QmlDomValueLiteral();
+ QmlDomValueLiteral(const QmlDomValueLiteral &);
+ ~QmlDomValueLiteral();
+ QmlDomValueLiteral &operator=(const QmlDomValueLiteral &);
+
+ QString literal() const;
+
+private:
+ friend class QmlDomValue;
+ QSharedDataPointer<QmlDomBasicValuePrivate> d;
+};
+
+class Q_DECLARATIVE_EXPORT QmlDomValueBinding
+{
+public:
+ QmlDomValueBinding();
+ QmlDomValueBinding(const QmlDomValueBinding &);
+ ~QmlDomValueBinding();
+ QmlDomValueBinding &operator=(const QmlDomValueBinding &);
+
+ QString binding() const;
+
+private:
+ friend class QmlDomValue;
+ QSharedDataPointer<QmlDomBasicValuePrivate> d;
+};
+
+class Q_DECLARATIVE_EXPORT QmlDomValueValueSource
+{
+public:
+ QmlDomValueValueSource();
+ QmlDomValueValueSource(const QmlDomValueValueSource &);
+ ~QmlDomValueValueSource();
+ QmlDomValueValueSource &operator=(const QmlDomValueValueSource &);
+
+ QmlDomObject object() const;
+
+private:
+ friend class QmlDomValue;
+ QSharedDataPointer<QmlDomBasicValuePrivate> d;
+};
+
+class Q_DECLARATIVE_EXPORT QmlDomComponent : public QmlDomObject
+{
+public:
+ QmlDomComponent();
+ QmlDomComponent(const QmlDomComponent &);
+ ~QmlDomComponent();
+ QmlDomComponent &operator=(const QmlDomComponent &);
+
+ QmlDomObject componentRoot() const;
+};
+
+class Q_DECLARATIVE_EXPORT QmlDomValue
+{
+public:
+ enum Type {
+ Invalid,
+ Literal,
+ PropertyBinding,
+ ValueSource,
+ Object,
+ List
+ };
+
+ QmlDomValue();
+ QmlDomValue(const QmlDomValue &);
+ ~QmlDomValue();
+ QmlDomValue &operator=(const QmlDomValue &);
+
+ Type type() const;
+
+ bool isInvalid() const;
+ bool isLiteral() const;
+ bool isBinding() const;
+ bool isValueSource() const;
+ bool isObject() const;
+ bool isList() const;
+
+ QmlDomValueLiteral toLiteral() const;
+ QmlDomValueBinding toBinding() const;
+ QmlDomValueValueSource toValueSource() const;
+ QmlDomObject toObject() const;
+ QmlDomList toList() const;
+
+ int position() const;
+ int length() const;
+
+private:
+ friend class QmlDomProperty;
+ friend class QmlDomList;
+ QSharedDataPointer<QmlDomValuePrivate> d;
+};
+
+class Q_DECLARATIVE_EXPORT QmlDomList
+{
+public:
+ QmlDomList();
+ QmlDomList(const QmlDomList &);
+ ~QmlDomList();
+ QmlDomList &operator=(const QmlDomList &);
+
+ QList<QmlDomValue> values() const;
+
+ int position() const;
+ int length() const;
+
+ QList<int> commaPositions() const;
+
+private:
+ friend class QmlDomValue;
+ QSharedDataPointer<QmlDomValuePrivate> d;
+};
+
+class QmlDomImportPrivate;
+class Q_DECLARATIVE_EXPORT QmlDomImport
+{
+public:
+ enum Type { Library, File };
+
+ QmlDomImport();
+ QmlDomImport(const QmlDomImport &);
+ ~QmlDomImport();
+ QmlDomImport &operator=(const QmlDomImport &);
+
+ Type type() const;
+ QString uri() const;
+ QString version() const;
+ QString qualifier() const;
+
+private:
+ friend class QmlDomDocument;
+ QSharedDataPointer<QmlDomImportPrivate> d;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLDOM_H
diff --git a/src/declarative/qml/qmldom_p.h b/src/declarative/qml/qmldom_p.h
new file mode 100644
index 0000000..b15844a
--- /dev/null
+++ b/src/declarative/qml/qmldom_p.h
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** 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 QMLDOM_P_H
+#define QMLDOM_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/QtGlobal>
+#include "qmlparser_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QmlDomDocumentPrivate : public QSharedData
+{
+public:
+ QmlDomDocumentPrivate();
+ QmlDomDocumentPrivate(const QmlDomDocumentPrivate &);
+ ~QmlDomDocumentPrivate();
+
+ QList<QmlError> errors;
+ QList<QmlDomImport> imports;
+ QmlParser::Object *root;
+ QList<int> automaticSemicolonOffsets;
+};
+
+class QmlDomObjectPrivate : public QSharedData
+{
+public:
+ QmlDomObjectPrivate();
+ QmlDomObjectPrivate(const QmlDomObjectPrivate &);
+ ~QmlDomObjectPrivate();
+
+ typedef QList<QPair<QmlParser::Property *, QByteArray> > Properties;
+ Properties properties() const;
+ Properties properties(QmlParser::Property *) const;
+
+ QmlParser::Object *object;
+ bool isVirtualComponent;
+};
+
+class QmlDomPropertyPrivate : public QSharedData
+{
+public:
+ QmlDomPropertyPrivate();
+ QmlDomPropertyPrivate(const QmlDomPropertyPrivate &);
+ ~QmlDomPropertyPrivate();
+
+ QByteArray propertyName;
+ QmlParser::Property *property;
+};
+
+class QmlDomDynamicPropertyPrivate : public QSharedData
+{
+public:
+ QmlDomDynamicPropertyPrivate();
+ QmlDomDynamicPropertyPrivate(const QmlDomDynamicPropertyPrivate &);
+ ~QmlDomDynamicPropertyPrivate();
+
+ bool valid;
+ QmlParser::Object::DynamicProperty property;
+};
+
+class QmlDomValuePrivate : public QSharedData
+{
+public:
+ QmlDomValuePrivate();
+ QmlDomValuePrivate(const QmlDomValuePrivate &);
+ ~QmlDomValuePrivate();
+
+ QmlParser::Property *property;
+ QmlParser::Value *value;
+};
+
+class QmlDomBasicValuePrivate : public QSharedData
+{
+public:
+ QmlDomBasicValuePrivate();
+ QmlDomBasicValuePrivate(const QmlDomBasicValuePrivate &);
+ ~QmlDomBasicValuePrivate();
+
+ QmlParser::Value *value;
+};
+
+class QmlDomImportPrivate : public QSharedData
+{
+public:
+ QmlDomImportPrivate();
+ QmlDomImportPrivate(const QmlDomImportPrivate &);
+ ~QmlDomImportPrivate();
+
+ enum Type { Library, File };
+
+ Type type;
+ QString uri;
+ QString version;
+ QString qualifier;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLDOM_P_H
+
diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp
new file mode 100644
index 0000000..4f3b2ba
--- /dev/null
+++ b/src/declarative/qml/qmlengine.cpp
@@ -0,0 +1,1510 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#undef QT3_SUPPORT // don't want it here - it just causes bugs (which is why we removed it)
+
+#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>
+#endif
+
+#include <QScriptClass>
+#include <QNetworkReply>
+#include <QNetworkRequest>
+#include <QNetworkAccessManager>
+#include <QDesktopServices>
+#include <QTimer>
+#include <QList>
+#include <QPair>
+#include <QDebug>
+#include <QMetaObject>
+#include "qml.h"
+#include <private/qfxperf_p.h>
+#include <QStack>
+#include "private/qmlbasicscript_p.h"
+#include "qmlengine.h"
+#include "qmlcontext.h"
+#include "qmlexpression.h"
+#include <QtCore/qthreadstorage.h>
+#include <QtCore/qthread.h>
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qdir.h>
+#include <QtGui/qcolor.h>
+#include <QtGui/qvector3d.h>
+#include <QtGui/qsound.h>
+#include <qmlcomponent.h>
+#include <private/qmlcomponentjs_p.h>
+#include <private/qmlmetaproperty_p.h>
+#include <private/qmlbinding_p.h>
+#include <private/qmlvme_p.h>
+#include <private/qmlenginedebug_p.h>
+#include <private/qmlstringconverters_p.h>
+#include <private/qmlxmlhttprequest_p.h>
+#include <private/qmlsqldatabase_p.h>
+#include <private/qmltypenamescriptclass_p.h>
+#include <private/qmllistscriptclass_p.h>
+#include <QtDeclarative/qmlscriptstring.h>
+
+#ifdef Q_OS_WIN // for %APPDATA%
+#include "qt_windows.h"
+#include "qlibrary.h"
+#define CSIDL_APPDATA 0x001a // <username>\Application Data
+#endif
+
+Q_DECLARE_METATYPE(QmlMetaProperty)
+Q_DECLARE_METATYPE(QList<QObject *>);
+
+QT_BEGIN_NAMESPACE
+
+DEFINE_BOOL_CONFIG_OPTION(qmlDebugger, QML_DEBUGGER)
+DEFINE_BOOL_CONFIG_OPTION(qmlImportTrace, QML_IMPORT_TRACE)
+
+QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,Object,QObject)
+
+struct StaticQtMetaObject : public QObject
+{
+ static const QMetaObject *get()
+ { return &static_cast<StaticQtMetaObject*> (0)->staticQtMetaObject; }
+};
+
+QScriptValue desktopOpenUrl(QScriptContext *ctxt, QScriptEngine *e)
+{
+ if(!ctxt->argumentCount())
+ return e->newVariant(QVariant(false));
+ bool ret = QDesktopServices::openUrl(QUrl(ctxt->argument(0).toString()));
+ return e->newVariant(QVariant(ret));
+}
+
+static QString userLocalDataPath(const QString& app)
+{
+ return QDesktopServices::storageLocation(QDesktopServices::DataLocation) + QLatin1String("/") + app;
+}
+
+QmlEnginePrivate::QmlEnginePrivate(QmlEngine *e)
+: rootContext(0), currentExpression(0),
+ isDebugging(false), contextClass(0), objectClass(0), valueTypeClass(0), globalClass(0),
+ nodeListClass(0), namedNodeMapClass(0), sqlQueryClass(0), cleanup(0), scriptEngine(this),
+ componentAttacheds(0), rootComponent(0), networkAccessManager(0), typeManager(e), uniqueId(1)
+{
+ QScriptValue qtObject =
+ scriptEngine.newQMetaObject(StaticQtMetaObject::get());
+ QScriptValue desktopObject = scriptEngine.newObject();
+ desktopObject.setProperty(QLatin1String("openUrl"),scriptEngine.newFunction(desktopOpenUrl, 1));
+ qtObject.setProperty(QLatin1String("DesktopServices"), desktopObject);
+ scriptEngine.globalObject().setProperty(QLatin1String("Qt"), qtObject);
+
+ offlineStoragePath = userLocalDataPath(QLatin1String("QML/OfflineStorage"));
+ qt_add_qmlxmlhttprequest(&scriptEngine);
+ qt_add_qmlsqldatabase(&scriptEngine);
+
+ //types
+ qtObject.setProperty(QLatin1String("rgba"), scriptEngine.newFunction(QmlEnginePrivate::rgba, 4));
+ qtObject.setProperty(QLatin1String("hsla"), scriptEngine.newFunction(QmlEnginePrivate::hsla, 4));
+ qtObject.setProperty(QLatin1String("rect"), scriptEngine.newFunction(QmlEnginePrivate::rect, 4));
+ qtObject.setProperty(QLatin1String("point"), scriptEngine.newFunction(QmlEnginePrivate::point, 2));
+ qtObject.setProperty(QLatin1String("size"), scriptEngine.newFunction(QmlEnginePrivate::size, 2));
+ qtObject.setProperty(QLatin1String("vector3d"), scriptEngine.newFunction(QmlEnginePrivate::vector, 3));
+
+ //color helpers
+ 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));
+
+ //misc methods
+ qtObject.setProperty(QLatin1String("playSound"), scriptEngine.newFunction(QmlEnginePrivate::playSound, 1));
+
+ scriptEngine.globalObject().setProperty(QLatin1String("createQmlObject"),
+ scriptEngine.newFunction(QmlEnginePrivate::createQmlObject, 1));
+ scriptEngine.globalObject().setProperty(QLatin1String("createComponent"),
+ scriptEngine.newFunction(QmlEnginePrivate::createComponent, 1));
+
+ globalClass = new QmlGlobalScriptClass(&scriptEngine);
+}
+
+QmlEnginePrivate::~QmlEnginePrivate()
+{
+ while (cleanup) {
+ QmlCleanup *c = cleanup;
+ cleanup = c->next;
+ if (cleanup) cleanup->prev = &cleanup;
+ c->next = 0;
+ c->prev = 0;
+ c->clear();
+ }
+
+ delete rootContext;
+ rootContext = 0;
+ delete contextClass;
+ contextClass = 0;
+ delete objectClass;
+ objectClass = 0;
+ delete valueTypeClass;
+ valueTypeClass = 0;
+ delete typeNameClass;
+ typeNameClass = 0;
+ delete listClass;
+ listClass = 0;
+ delete networkAccessManager;
+ networkAccessManager = 0;
+ delete nodeListClass;
+ nodeListClass = 0;
+ delete namedNodeMapClass;
+ namedNodeMapClass = 0;
+ delete sqlQueryClass;
+ sqlQueryClass = 0;
+
+ for(int ii = 0; ii < bindValues.count(); ++ii)
+ clear(bindValues[ii]);
+ for(int ii = 0; ii < parserStatus.count(); ++ii)
+ 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)
+{
+ bvs.clear();
+}
+
+void QmlEnginePrivate::clear(SimpleList<QmlParserStatus> &pss)
+{
+ for (int ii = 0; ii < pss.count; ++ii) {
+ QmlParserStatus *ps = pss.at(ii);
+ if(ps)
+ ps->d = 0;
+ }
+ pss.clear();
+}
+
+Q_GLOBAL_STATIC(QmlEngineDebugServer, qmlEngineDebugServer);
+
+void QmlEnginePrivate::init()
+{
+ Q_Q(QmlEngine);
+ qRegisterMetaType<QVariant>("QVariant");
+ qRegisterMetaType<QmlScriptString>("QmlScriptString");
+
+ scriptEngine.installTranslatorFunctions();
+ contextClass = new QmlContextScriptClass(q);
+ objectClass = new QmlObjectScriptClass(q);
+ valueTypeClass = new QmlValueTypeScriptClass(q);
+ typeNameClass = new QmlTypeNameScriptClass(q);
+ listClass = new QmlListScriptClass(q);
+ rootContext = new QmlContext(q,true);
+#ifdef QT_SCRIPTTOOLS_LIB
+ if (qmlDebugger()){
+ debugger = new QScriptEngineDebugger(q);
+ debugger->attachTo(&scriptEngine);
+ }
+#endif
+
+ if (QCoreApplication::instance()->thread() == q->thread() &&
+ QmlEngineDebugServer::isDebuggingEnabled()) {
+ qmlEngineDebugServer();
+ isDebugging = true;
+ QmlEngineDebugServer::addEngine(q);
+
+ qmlEngineDebugServer()->waitForClients();
+ }
+}
+
+QmlEnginePrivate::CapturedProperty::CapturedProperty(const QmlMetaProperty &p)
+: object(p.object()), coreIndex(p.coreIndex()), notifyIndex(p.property().notifySignalIndex())
+{
+}
+
+/*!
+ \class QmlEngine
+ \brief The QmlEngine class provides an environment for instantiating QML components.
+ \mainclass
+
+ Each QML component is instantiated in a QmlContext. QmlContext's are
+ essential for passing data to QML components. In QML, contexts are arranged
+ hierarchically and this hierarchy is managed by the QmlEngine.
+
+ Prior to creating any QML components, an application must have created a
+ QmlEngine to gain access to a QML context. The following example shows how
+ to create a simple Text item.
+
+ \code
+ QmlEngine engine;
+ QmlComponent component(&engine, "Text { text: \"Hello world!\" }");
+ QFxItem *item = qobject_cast<QFxItem *>(component.create());
+
+ //add item to view, etc
+ ...
+ \endcode
+
+ In this case, the Text item will be created in the engine's
+ \l {QmlEngine::rootContext()}{root context}.
+
+ \sa QmlComponent QmlContext
+*/
+
+/*!
+ Create a new QmlEngine with the given \a parent.
+*/
+QmlEngine::QmlEngine(QObject *parent)
+: QObject(*new QmlEnginePrivate(this), parent)
+{
+ Q_D(QmlEngine);
+ d->init();
+}
+
+/*!
+ Destroys the QmlEngine.
+
+ Any QmlContext's created on this engine will be invalidated, but not
+ destroyed (unless they are parented to the QmlEngine object).
+*/
+QmlEngine::~QmlEngine()
+{
+ Q_D(QmlEngine);
+ if (d->isDebugging)
+ QmlEngineDebugServer::remEngine(this);
+}
+
+/*!
+ Clears the engine's internal component cache.
+
+ Normally the QmlEngine caches components loaded from qml files. This method
+ clears this cache and forces the component to be reloaded.
+ */
+void QmlEngine::clearComponentCache()
+{
+ Q_D(QmlEngine);
+ d->typeManager.clearCache();
+}
+
+/*!
+ Returns the engine's root context.
+
+ The root context is automatically created by the QmlEngine. Data that
+ should be available to all QML component instances instantiated by the
+ engine should be put in the root context.
+
+ Additional data that should only be available to a subset of component
+ instances should be added to sub-contexts parented to the root context.
+*/
+QmlContext *QmlEngine::rootContext()
+{
+ Q_D(QmlEngine);
+ return d->rootContext;
+}
+
+/*!
+ Sets the common QNetworkAccessManager, \a network, used by all QML elements
+ instantiated by this engine.
+
+ Any previously set manager is deleted and \a network is owned by the
+ QmlEngine. This method should only be called before any QmlComponents are
+ instantiated.
+*/
+void QmlEngine::setNetworkAccessManager(QNetworkAccessManager *network)
+{
+ Q_D(QmlEngine);
+ delete d->networkAccessManager;
+ d->networkAccessManager = network;
+}
+
+/*!
+ Returns the common QNetworkAccessManager used by all QML elements
+ instantiated by this engine.
+
+ The default implements no caching, cookiejar, etc., just a default
+ QNetworkAccessManager.
+*/
+QNetworkAccessManager *QmlEngine::networkAccessManager() const
+{
+ Q_D(const QmlEngine);
+ if (!d->networkAccessManager)
+ d->networkAccessManager = new QNetworkAccessManager;
+ return d->networkAccessManager;
+}
+
+/*!
+ Return the base URL for this engine. The base URL is only used to resolve
+ components when a relative URL is passed to the QmlComponent constructor.
+
+ If a base URL has not been explicitly set, this method returns the
+ application's current working directory.
+
+ \sa setBaseUrl()
+*/
+QUrl QmlEngine::baseUrl() const
+{
+ Q_D(const QmlEngine);
+ if (d->baseUrl.isEmpty()) {
+ return QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
+ } else {
+ return d->baseUrl;
+ }
+}
+
+/*!
+ Set the base URL for this engine to \a url.
+
+ \sa baseUrl()
+*/
+void QmlEngine::setBaseUrl(const QUrl &url)
+{
+ Q_D(QmlEngine);
+ d->baseUrl = url;
+}
+
+/*!
+ Returns the QmlContext for the \a object, or 0 if no context has been set.
+
+ When the QmlEngine instantiates a QObject, the context is set automatically.
+ */
+QmlContext *QmlEngine::contextForObject(const QObject *object)
+{
+ if(!object)
+ return 0;
+
+ QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
+
+ QmlDeclarativeData *data =
+ static_cast<QmlDeclarativeData *>(priv->declarativeData);
+
+ if (!data)
+ return 0;
+ else if (data->outerContext)
+ return data->outerContext;
+ else
+ return data->context;
+}
+
+/*!
+ Sets the QmlContext for the \a object to \a context.
+ If the \a object already has a context, a warning is
+ output, but the context is not changed.
+
+ When the QmlEngine instantiates a QObject, the context is set automatically.
+ */
+void QmlEngine::setContextForObject(QObject *object, QmlContext *context)
+{
+ QObjectPrivate *priv = QObjectPrivate::get(object);
+
+ QmlDeclarativeData *data =
+ static_cast<QmlDeclarativeData *>(priv->declarativeData);
+
+ if (data && data->context) {
+ qWarning("QmlEngine::setContextForObject(): Object already has a QmlContext");
+ return;
+ }
+
+ if (!data) {
+ priv->declarativeData = new QmlDeclarativeData(context);
+ } else {
+ data->context = context;
+ }
+
+ context->d_func()->contextObjects.append(object);
+}
+
+void qmlExecuteDeferred(QObject *object)
+{
+ QmlDeclarativeData *data = QmlDeclarativeData::get(object);
+
+ if (data && data->deferredComponent) {
+ QmlVME vme;
+ vme.runDeferred(object);
+
+ data->deferredComponent->release();
+ data->deferredComponent = 0;
+ }
+}
+
+QmlContext *qmlContext(const QObject *obj)
+{
+ return QmlEngine::contextForObject(obj);
+}
+
+QmlEngine *qmlEngine(const QObject *obj)
+{
+ QmlContext *context = QmlEngine::contextForObject(obj);
+ return context?context->engine():0;
+}
+
+QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
+{
+ QmlDeclarativeData *data = QmlDeclarativeData::get(object);
+
+ QObject *rv = data->attachedProperties?data->attachedProperties->value(id):0;
+ if (rv || !create)
+ return rv;
+
+ QmlAttachedPropertiesFunc pf = QmlMetaType::attachedPropertiesFuncById(id);
+ if (!pf)
+ return 0;
+
+ rv = pf(const_cast<QObject *>(object));
+
+ if (rv) {
+ if (!data->attachedProperties)
+ data->attachedProperties = new QHash<int, QObject *>();
+ data->attachedProperties->insert(id, rv);
+ }
+
+ return rv;
+}
+
+QmlDeclarativeData::QmlDeclarativeData(QmlContext *ctxt)
+: context(ctxt), bindings(0), bindingBitsSize(0), bindingBits(0),
+ outerContext(0), lineNumber(0), columnNumber(0), deferredComponent(0),
+ deferredIdx(0), attachedProperties(0), propertyCache(0)
+{
+}
+
+void QmlDeclarativeData::destroyed(QObject *object)
+{
+ if (deferredComponent)
+ deferredComponent->release();
+ if (attachedProperties)
+ delete attachedProperties;
+ if (context)
+ static_cast<QmlContextPrivate *>(QObjectPrivate::get(context))->contextObjects.removeAll(object);
+
+ QmlAbstractBinding *binding = bindings;
+ while (binding) {
+ QmlAbstractBinding *next = binding->m_nextBinding;
+ binding->m_prevBinding = 0;
+ binding->m_nextBinding = 0;
+ delete binding;
+ binding = next;
+ }
+
+ if (bindingBits)
+ free(bindingBits);
+
+ if (propertyCache)
+ propertyCache->release();
+
+ delete this;
+}
+
+bool QmlDeclarativeData::hasBindingBit(int bit) const
+{
+ if (bindingBitsSize > bit)
+ return bindingBits[bit / 32] & (1 << (bit % 32));
+ else
+ return false;
+}
+
+void QmlDeclarativeData::clearBindingBit(int bit)
+{
+ if (bindingBitsSize > bit)
+ bindingBits[bit / 32] &= ~(1 << (bit % 32));
+}
+
+void QmlDeclarativeData::setBindingBit(QObject *obj, int bit)
+{
+ if (bindingBitsSize <= bit) {
+ int props = obj->metaObject()->propertyCount();
+ Q_ASSERT(bit < props);
+
+ int arraySize = (props + 31) / 32;
+ int oldArraySize = bindingBitsSize / 32;
+
+ bindingBits = (quint32 *)realloc(bindingBits,
+ arraySize * sizeof(quint32));
+
+ memset(bindingBits + oldArraySize,
+ 0x00,
+ sizeof(quint32) * (arraySize - oldArraySize));
+
+ bindingBitsSize = arraySize * 32;
+ }
+
+ bindingBits[bit / 32] |= (1 << (bit % 32));
+}
+
+/*!
+ Creates a QScriptValue allowing you to use \a object in QML script.
+ \a engine is the QmlEngine it is to be created in.
+
+ The QScriptValue returned is a QtScript Object, not a QtScript QObject, due
+ to the special needs of QML requiring more functionality than a standard
+ QtScript QObject.
+*/
+QScriptValue QmlEnginePrivate::qmlScriptObject(QObject* object,
+ QmlEngine* engine)
+{
+ QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine);
+ return enginePriv->objectClass->newQObject(object);
+}
+
+/*!
+ Returns the QmlContext for the executing QScript \a ctxt.
+*/
+QmlContext *QmlEnginePrivate::getContext(QScriptContext *ctxt)
+{
+ QScriptValue scopeNode = QScriptDeclarativeClass::scopeChainValue(ctxt, -3);
+ Q_ASSERT(scopeNode.isValid());
+ Q_ASSERT(QScriptDeclarativeClass::scriptClass(scopeNode) == contextClass);
+ return contextClass->contextFromValue(scopeNode);
+}
+
+/*!
+ This function is intended for use inside QML only. In C++ just create a
+ component object as usual.
+
+ This function takes the URL of a QML file as its only argument. It returns
+ a component object which can be used to create and load that QML file.
+
+ Example QmlJS is below, remember that QML files that might be loaded
+ over the network cannot be expected to be ready immediately.
+ \code
+ var component;
+ var sprite;
+ function finishCreation(){
+ if(component.isReady()){
+ sprite = component.createObject();
+ if(sprite == 0){
+ // Error Handling
+ }else{
+ sprite.parent = page;
+ sprite.x = 200;
+ //...
+ }
+ }else if(component.isError()){
+ // Error Handling
+ }
+ }
+
+ component = createComponent("Sprite.qml");
+ if(component.isReady()){
+ finishCreation();
+ }else{
+ component.statusChanged.connect(finishCreation);
+ }
+ \endcode
+
+ If you are certain the files will be local, you could simplify to
+
+ \code
+ component = createComponent("Sprite.qml");
+ sprite = component.createObject();
+ if(sprite == 0){
+ // Error Handling
+ print(component.errorsString());
+ }else{
+ sprite.parent = page;
+ sprite.x = 200;
+ //...
+ }
+ \endcode
+
+ If you want to just create an arbitrary string of QML, instead of
+ loading a qml file, consider the createQmlObject() function.
+*/
+QScriptValue QmlEnginePrivate::createComponent(QScriptContext *ctxt,
+ QScriptEngine *engine)
+{
+ QmlComponentJS* c;
+
+ QmlEnginePrivate *activeEnginePriv =
+ static_cast<QmlScriptEngine*>(engine)->p;
+ QmlEngine* activeEngine = activeEnginePriv->q_func();
+
+ QmlContext* context = activeEnginePriv->getContext(ctxt);
+ if(ctxt->argumentCount() != 1) {
+ c = new QmlComponentJS(activeEngine);
+ }else{
+ QUrl url = QUrl(context->resolvedUrl(ctxt->argument(0).toString()));
+ if(!url.isValid())
+ url = QUrl(ctxt->argument(0).toString());
+ c = new QmlComponentJS(activeEngine, url, activeEngine);
+ }
+ c->setContext(context);
+ return engine->newQObject(c);
+}
+
+/*!
+ Creates a new object from the specified string of QML. It requires a
+ second argument, which is the id of an existing QML object to use as
+ the new object's parent. If a third argument is provided, this is used
+ as the filepath that the qml came from.
+
+ Example (where targetItem is the id of an existing QML item):
+ \code
+ newObject = createQmlObject('import Qt 4.6; Rectangle {color: "red"; width: 20; height: 20}',
+ targetItem, "dynamicSnippet1");
+ \endcode
+
+ This function is intended for use inside QML only. It is intended to behave
+ similarly to eval, but for creating QML elements.
+
+ Returns the created object, or null if there is an error. In the case of an
+ error, details of the error are output using qWarning().
+
+ Note that this function returns immediately, and therefore may not work if
+ the QML loads new components. If you are trying to load a new component,
+ for example from a QML file, consider the createComponent() function
+ instead. 'New components' refers to external QML files that have not yet
+ been loaded, and so it is safe to use createQmlObject to load built-in
+ components.
+*/
+QScriptValue QmlEnginePrivate::createQmlObject(QScriptContext *ctxt, QScriptEngine *engine)
+{
+ QmlEnginePrivate *activeEnginePriv =
+ static_cast<QmlScriptEngine*>(engine)->p;
+ QmlEngine* activeEngine = activeEnginePriv->q_func();
+
+ if(ctxt->argumentCount() < 2)
+ return engine->nullValue();
+
+ QString qml = ctxt->argument(0).toString();
+ QUrl url;
+ if(ctxt->argumentCount() > 2)
+ url = QUrl(ctxt->argument(2).toString());
+ else
+ url = QUrl(QLatin1String("DynamicQML"));
+ QObject *parentArg = activeEnginePriv->objectClass->toQObject(ctxt->argument(1));
+ QmlContext *qmlCtxt = qmlContext(parentArg);
+ if (url.isEmpty()) {
+ url = qmlCtxt->resolvedUrl(QUrl(QLatin1String("<Unknown File>")));
+ } else {
+ url = qmlCtxt->resolvedUrl(url);
+ }
+
+ QmlComponent component(activeEngine, qml.toUtf8(), url);
+ if(component.isError()) {
+ QList<QmlError> errors = component.errors();
+ qWarning() <<"QmlEngine::createQmlObject():";
+ foreach (const QmlError &error, errors)
+ qWarning() << " " << error;
+
+ return engine->nullValue();
+ }
+
+ QObject *obj = component.create(qmlCtxt);
+
+ if(component.isError()) {
+ QList<QmlError> errors = component.errors();
+ qWarning() <<"QmlEngine::createQmlObject():";
+ foreach (const QmlError &error, errors)
+ qWarning() << " " << error;
+
+ return engine->nullValue();
+ }
+
+ if(obj) {
+ obj->setParent(parentArg);
+ obj->setProperty("parent", QVariant::fromValue<QObject*>(parentArg));
+ return qmlScriptObject(obj, activeEngine);
+ }
+ return engine->nullValue();
+}
+
+/*!
+ This function is intended for use inside QML only. In C++ just create a
+ QVector3D as usual.
+
+ This function takes three numeric components and combines them into a
+ QVector3D value that can be used with any property that takes a
+ QVector3D argument. The following QML code:
+
+ \code
+ transform: Rotation {
+ id: rotation
+ origin.x: Container.width / 2;
+ axis: vector(0, 1, 1)
+ }
+ \endcode
+
+ is equivalent to:
+
+ \code
+ transform: Rotation {
+ id: rotation
+ origin.x: Container.width / 2;
+ axis.x: 0; axis.y: 1; axis.z: 0
+ }
+ \endcode
+*/
+QScriptValue QmlEnginePrivate::vector(QScriptContext *ctxt, QScriptEngine *engine)
+{
+ if(ctxt->argumentCount() < 3)
+ return engine->nullValue();
+ qsreal x = ctxt->argument(0).toNumber();
+ qsreal y = ctxt->argument(1).toNumber();
+ qsreal z = ctxt->argument(2).toNumber();
+ return engine->newVariant(qVariantFromValue(QVector3D(x, y, z)));
+}
+
+QScriptValue QmlEnginePrivate::rgba(QScriptContext *ctxt, QScriptEngine *engine)
+{
+ int argCount = ctxt->argumentCount();
+ if(argCount < 3)
+ return engine->nullValue();
+ qsreal r = ctxt->argument(0).toNumber();
+ qsreal g = ctxt->argument(1).toNumber();
+ qsreal b = ctxt->argument(2).toNumber();
+ qsreal a = (argCount == 4) ? ctxt->argument(3).toNumber() : 1;
+ return qScriptValueFromValue(engine, qVariantFromValue(QColor::fromRgbF(r, g, b, a)));
+}
+
+QScriptValue QmlEnginePrivate::hsla(QScriptContext *ctxt, QScriptEngine *engine)
+{
+ int argCount = ctxt->argumentCount();
+ if(argCount < 3)
+ return engine->nullValue();
+ qsreal h = ctxt->argument(0).toNumber();
+ qsreal s = ctxt->argument(1).toNumber();
+ qsreal l = ctxt->argument(2).toNumber();
+ qsreal a = (argCount == 4) ? ctxt->argument(3).toNumber() : 1;
+ return qScriptValueFromValue(engine, qVariantFromValue(QColor::fromHslF(h, s, l, a)));
+}
+
+QScriptValue QmlEnginePrivate::rect(QScriptContext *ctxt, QScriptEngine *engine)
+{
+ if(ctxt->argumentCount() < 4)
+ return engine->nullValue();
+ qsreal x = ctxt->argument(0).toNumber();
+ qsreal y = ctxt->argument(1).toNumber();
+ qsreal w = ctxt->argument(2).toNumber();
+ qsreal h = ctxt->argument(3).toNumber();
+ return qScriptValueFromValue(engine, qVariantFromValue(QRectF(x, y, w, h)));
+}
+
+QScriptValue QmlEnginePrivate::point(QScriptContext *ctxt, QScriptEngine *engine)
+{
+ if(ctxt->argumentCount() < 2)
+ return engine->nullValue();
+ qsreal x = ctxt->argument(0).toNumber();
+ qsreal y = ctxt->argument(1).toNumber();
+ return qScriptValueFromValue(engine, qVariantFromValue(QPointF(x, y)));
+}
+
+QScriptValue QmlEnginePrivate::size(QScriptContext *ctxt, QScriptEngine *engine)
+{
+ if(ctxt->argumentCount() < 2)
+ return engine->nullValue();
+ qsreal w = ctxt->argument(0).toNumber();
+ qsreal h = ctxt->argument(1).toNumber();
+ return qScriptValueFromValue(engine, qVariantFromValue(QSizeF(w, h)));
+}
+
+QScriptValue QmlEnginePrivate::lighter(QScriptContext *ctxt, QScriptEngine *engine)
+{
+ if(ctxt->argumentCount() < 1)
+ return engine->nullValue();
+ QVariant v = ctxt->argument(0).toVariant();
+ QColor color;
+ if (v.type() == QVariant::Color)
+ color = v.value<QColor>();
+ else if (v.type() == QVariant::String) {
+ bool ok;
+ color = QmlStringConverters::colorFromString(v.toString(), &ok);
+ if (!ok)
+ return engine->nullValue();
+ } else
+ return engine->nullValue();
+ color = color.lighter();
+ return qScriptValueFromValue(engine, qVariantFromValue(color));
+}
+
+QScriptValue QmlEnginePrivate::darker(QScriptContext *ctxt, QScriptEngine *engine)
+{
+ if(ctxt->argumentCount() < 1)
+ return engine->nullValue();
+ QVariant v = ctxt->argument(0).toVariant();
+ QColor color;
+ if (v.type() == QVariant::Color)
+ color = v.value<QColor>();
+ else if (v.type() == QVariant::String) {
+ bool ok;
+ color = QmlStringConverters::colorFromString(v.toString(), &ok);
+ if (!ok)
+ return engine->nullValue();
+ } else
+ return engine->nullValue();
+ color = color.darker();
+ return qScriptValueFromValue(engine, qVariantFromValue(color));
+}
+
+QScriptValue QmlEnginePrivate::playSound(QScriptContext *ctxt, QScriptEngine *engine)
+{
+ if (ctxt->argumentCount() < 1)
+ return engine->undefinedValue();
+
+ QUrl url(ctxt->argument(0).toString());
+
+ QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine);
+ if (url.isRelative()) {
+ QmlContext *context = enginePriv->getContext(ctxt);
+ if (!context)
+ return engine->undefinedValue();
+
+ url = context->resolvedUrl(url);
+ }
+
+ if (url.scheme() == QLatin1String("file")) {
+
+ QSound::play(url.toLocalFile());
+
+ }
+ return engine->undefinedValue();
+}
+
+/*!
+ This function allows tinting one color with another.
+
+ The tint color should usually be mostly transparent, or you will not be able to see the underlying color. The below example provides a slight red tint by having the tint color be pure red which is only 1/16th opaque.
+
+ \qml
+ Rectangle { x: 0; width: 80; height: 80; color: "lightsteelblue" }
+ Rectangle { x: 100; width: 80; height: 80; color: Qt.tint("lightsteelblue", "#10FF0000") }
+ \endqml
+ \image declarative-rect_tint.png
+
+ Tint is most useful when a subtle change is intended to be conveyed due to some event; you can then use tinting to more effectively tune the visible color.
+*/
+QScriptValue QmlEnginePrivate::tint(QScriptContext *ctxt, QScriptEngine *engine)
+{
+ if(ctxt->argumentCount() < 2)
+ return engine->nullValue();
+ //get color
+ QVariant v = ctxt->argument(0).toVariant();
+ QColor color;
+ if (v.type() == QVariant::Color)
+ color = v.value<QColor>();
+ else if (v.type() == QVariant::String) {
+ bool ok;
+ color = QmlStringConverters::colorFromString(v.toString(), &ok);
+ if (!ok)
+ return engine->nullValue();
+ } else
+ return engine->nullValue();
+
+ //get tint color
+ v = ctxt->argument(1).toVariant();
+ QColor tintColor;
+ if (v.type() == QVariant::Color)
+ tintColor = v.value<QColor>();
+ else if (v.type() == QVariant::String) {
+ bool ok;
+ tintColor = QmlStringConverters::colorFromString(v.toString(), &ok);
+ if (!ok)
+ return engine->nullValue();
+ } else
+ return engine->nullValue();
+
+ //tint
+ QColor finalColor;
+ int a = tintColor.alpha();
+ if (a == 0xFF)
+ finalColor = tintColor;
+ else if (a == 0x00)
+ finalColor = color;
+ else {
+ uint src = tintColor.rgba();
+ uint dest = color.rgba();
+
+ uint res = (((a * (src & 0xFF00FF)) +
+ ((0xFF - a) * (dest & 0xFF00FF))) >> 8) & 0xFF00FF;
+ res |= (((a * ((src >> 8) & 0xFF00FF)) +
+ ((0xFF - a) * ((dest >> 8) & 0xFF00FF)))) & 0xFF00FF00;
+ if ((src & 0xFF000000) == 0xFF000000)
+ res |= 0xFF000000;
+
+ finalColor = QColor::fromRgba(res);
+ }
+
+ return qScriptValueFromValue(engine, qVariantFromValue(finalColor));
+}
+
+
+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 QmlEnginePrivate::scriptValueToVariant(const QScriptValue &val)
+{
+ 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 == valueTypeClass) {
+ return valueTypeClass->toVariant(val);
+ } else {
+ return QVariant();
+ }
+}
+
+QmlScriptClass::QmlScriptClass(QmlEngine *bindengine)
+: QScriptClass(QmlEnginePrivate::getScriptEngine(bindengine)),
+ engine(bindengine)
+{
+}
+
+QVariant QmlScriptClass::toVariant(QmlEngine *engine, const QScriptValue &val)
+{
+ QmlEnginePrivate *ep =
+ static_cast<QmlEnginePrivate *>(QObjectPrivate::get(engine));
+
+ QScriptDeclarativeClass *dc = QScriptDeclarativeClass::scriptClass(val);
+ if (dc == ep->objectClass)
+ return QVariant::fromValue(ep->objectClass->toQObject(val));
+ else if (dc == ep->contextClass)
+ return QVariant();
+
+ QScriptClass *sc = val.scriptClass();
+ if (!sc) {
+ return val.toVariant();
+ } else if (sc == ep->valueTypeClass) {
+ return ep->valueTypeClass->toVariant(val);
+ }
+
+ return QVariant();
+}
+
+// XXX this beyonds in QUrl::toLocalFile()
+static QString toLocalFileOrQrc(const QUrl& url)
+{
+ QString r = url.toLocalFile();
+ if (r.isEmpty() && url.scheme() == QLatin1String("qrc"))
+ r = QLatin1Char(':') + url.path();
+ return r;
+}
+
+/////////////////////////////////////////////////////////////
+struct QmlEnginePrivate::ImportedNamespace {
+ QStringList urls;
+ QList<int> majversions;
+ QList<int> minversions;
+ QList<bool> isLibrary;
+ QList<bool> isBuiltin;
+
+ bool find(const QByteArray& type, int *vmajor, int *vminor, QmlType** type_return, QUrl* url_return) const
+ {
+ for (int i=0; i<urls.count(); ++i) {
+ int vmaj = majversions.at(i);
+ int vmin = minversions.at(i);
+
+ if (isBuiltin.at(i)) {
+ QByteArray qt = urls.at(i).toUtf8();
+ qt += "/";
+ qt += type;
+ QmlType *t = QmlMetaType::qmlType(qt,vmaj,vmin);
+ if (vmajor) *vmajor = vmaj;
+ if (vminor) *vminor = vmin;
+ if (t) {
+ if (type_return)
+ *type_return = t;
+ return true;
+ }
+ } else {
+ QUrl url = QUrl(urls.at(i) + QLatin1String("/") + QString::fromUtf8(type) + QLatin1String(".qml"));
+ if (vmaj || vmin) {
+ // Check version file - XXX cache these in QmlEngine!
+ QFile qmldir(toLocalFileOrQrc(QUrl(urls.at(i)+QLatin1String("/qmldir"))));
+ if (qmldir.open(QIODevice::ReadOnly)) {
+ do {
+ QByteArray lineba = qmldir.readLine();
+ if (lineba.at(0) == '#')
+ continue;
+ int space1 = lineba.indexOf(' ');
+ if (qstrncmp(lineba,type,space1)==0) {
+ // eg. 1.2-5
+ QString line = QString::fromUtf8(lineba);
+ space1 = line.indexOf(QLatin1Char(' ')); // refind in Unicode
+ int space2 = space1 >=0 ? line.indexOf(QLatin1Char(' '),space1+1) : -1;
+ QString mapversions = line.mid(space1+1,space2<0?line.length()-space1-2:space2-space1-1);
+ int dot = mapversions.indexOf(QLatin1Char('.'));
+ int dash = mapversions.indexOf(QLatin1Char('-'));
+ int mapvmaj = mapversions.left(dot).toInt();
+ if (mapvmaj==vmaj) {
+ int mapvmin_from = (dash <= 0 ? mapversions.mid(dot+1) : mapversions.mid(dot+1,dash-dot-1)).toInt();
+ int mapvmin_to = dash <= 0 ? mapvmin_from : mapversions.mid(dash+1).toInt();
+ if (vmin >= mapvmin_from && vmin <= mapvmin_to) {
+ QStringRef mapfile = space2<0 ? QStringRef() : line.midRef(space2+1,line.length()-space2-2);
+ if (url_return)
+ *url_return = url.resolved(mapfile.toString());
+ return true;
+ }
+ }
+ }
+ } while (!qmldir.atEnd());
+ }
+ } else {
+ // XXX search non-files too! (eg. zip files, see QT-524)
+ QFileInfo f(toLocalFileOrQrc(url));
+ if (f.exists()) {
+ if (url_return)
+ *url_return = url;
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+};
+
+class QmlImportsPrivate {
+public:
+ QmlImportsPrivate() : ref(1)
+ {
+ }
+
+ ~QmlImportsPrivate()
+ {
+ foreach (QmlEnginePrivate::ImportedNamespace* s, set.values())
+ delete s;
+ }
+
+ bool add(const QUrl& base, const QString& uri, const QString& prefix, int vmaj, int vmin, QmlScriptParser::Import::Type importType, const QStringList& importPath)
+ {
+ QmlEnginePrivate::ImportedNamespace *s;
+ if (prefix.isEmpty()) {
+ s = &unqualifiedset;
+ } else {
+ s = set.value(prefix);
+ if (!s)
+ set.insert(prefix,(s=new QmlEnginePrivate::ImportedNamespace));
+ }
+ QString url = uri;
+ bool isbuiltin = false;
+ if (importType == QmlScriptParser::Import::Library) {
+ url.replace(QLatin1Char('.'),QLatin1Char('/'));
+ bool found = false;
+ foreach (QString p, importPath) {
+ QString dir = p+QLatin1Char('/')+url;
+ QFileInfo fi(dir+QLatin1String("/qmldir"));
+ if (fi.isFile()) {
+ url = QUrl::fromLocalFile(fi.absolutePath()).toString();
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ // XXX assume it is a built-in type qualifier
+ isbuiltin = true;
+ }
+ } else {
+ url = base.resolved(QUrl(url)).toString();
+ }
+ s->urls.prepend(url);
+ s->majversions.prepend(vmaj);
+ s->minversions.prepend(vmin);
+ s->isLibrary.prepend(importType == QmlScriptParser::Import::Library);
+ s->isBuiltin.prepend(isbuiltin);
+ return true;
+ }
+
+ bool find(const QByteArray& type, int *vmajor, int *vminor, QmlType** type_return, QUrl* url_return)
+ {
+ QmlEnginePrivate::ImportedNamespace *s = 0;
+ int slash = type.indexOf('/');
+ if (slash >= 0) {
+ while (!s) {
+ s = set.value(QString::fromUtf8(type.left(slash)));
+ int nslash = type.indexOf('/',slash+1);
+ if (nslash > 0)
+ slash = nslash;
+ else
+ break;
+ }
+ } else {
+ s = &unqualifiedset;
+ }
+ QByteArray unqualifiedtype = slash < 0 ? type : type.mid(slash+1); // common-case opt (QString::mid works fine, but slower)
+ if (s) {
+ if (s->find(unqualifiedtype,vmajor,vminor,type_return,url_return))
+ return true;
+ if (s->urls.count() == 1 && !s->isBuiltin[0] && !s->isLibrary[0] && url_return) {
+ *url_return = QUrl(s->urls[0]+QLatin1String("/")).resolved(QUrl(QString::fromUtf8(unqualifiedtype) + QLatin1String(".qml")));
+ return true;
+ }
+ }
+ if (url_return) {
+ *url_return = base.resolved(QUrl(QString::fromUtf8(type + ".qml")));
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ QmlEnginePrivate::ImportedNamespace *findNamespace(const QString& type)
+ {
+ return set.value(type);
+ }
+
+ QUrl base;
+ int ref;
+
+private:
+ friend class QmlEnginePrivate::Imports;
+ QmlEnginePrivate::ImportedNamespace unqualifiedset;
+ QHash<QString,QmlEnginePrivate::ImportedNamespace* > set;
+};
+
+QmlEnginePrivate::Imports::Imports(const Imports &copy) :
+ d(copy.d)
+{
+ ++d->ref;
+}
+
+QmlEnginePrivate::Imports &QmlEnginePrivate::Imports::operator =(const Imports &copy)
+{
+ ++copy.d->ref;
+ if (--d->ref == 0)
+ delete d;
+ d = copy.d;
+ return *this;
+}
+
+QmlEnginePrivate::Imports::Imports() :
+ d(new QmlImportsPrivate)
+{
+}
+
+QmlEnginePrivate::Imports::~Imports()
+{
+ if (--d->ref == 0)
+ 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.
+*/
+void QmlEnginePrivate::Imports::setBaseUrl(const QUrl& url)
+{
+ d->base = url;
+}
+
+/*!
+ Returns the base URL to be used for all relative file imports added.
+*/
+QUrl QmlEnginePrivate::Imports::baseUrl() const
+{
+ return d->base;
+}
+
+/*!
+ Adds \a path as a directory where installed QML components are
+ defined in a URL-based directory structure.
+
+ For example, if you add \c /opt/MyApp/lib/qml and then load QML
+ that imports \c com.mycompany.Feature, then QmlEngine will look
+ in \c /opt/MyApp/lib/qml/com/mycompany/Feature/ for the components
+ provided by that module (and in the case of versioned imports,
+ for the \c qmldir file definiting the type version mapping.
+*/
+void QmlEngine::addImportPath(const QString& path)
+{
+ if (qmlImportTrace())
+ qDebug() << "QmlEngine::addImportPath" << path;
+ Q_D(QmlEngine);
+ d->fileImportPath.prepend(path);
+}
+
+/*!
+ \property QmlEngine::offlineStoragePath
+ \brief the directory for storing offline user data
+
+ Returns the directory where SQL and other offline
+ storage is placed.
+
+ QFxWebView and the SQL databases created with openDatabase()
+ are stored here.
+
+ The default is QML/OfflineStorage/ in the platform-standard
+ user application data directory.
+*/
+void QmlEngine::setOfflineStoragePath(const QString& dir)
+{
+ Q_D(QmlEngine);
+ d->offlineStoragePath = dir;
+}
+
+QString QmlEngine::offlineStoragePath() const
+{
+ Q_D(const QmlEngine);
+ return d->offlineStoragePath;
+}
+
+
+/*!
+ \internal
+
+ Adds information to \a imports such that subsequent calls to resolveType()
+ will resolve types qualified by \a prefix by considering types found at the given \a uri.
+
+ The uri is either a directory (if importType is FileImport), or a URI resolved using paths
+ added via addImportPath() (if importType is LibraryImport).
+
+ The \a prefix may be empty, in which case the import location is considered for
+ unqualified types.
+
+ The base URL must already have been set with Import::setBaseUrl().
+*/
+bool QmlEnginePrivate::addToImport(Imports* imports, const QString& uri, const QString& prefix, int vmaj, int vmin, QmlScriptParser::Import::Type importType) const
+{
+ bool ok = imports->d->add(imports->d->base,uri,prefix,vmaj,vmin,importType,fileImportPath);
+ if (qmlImportTrace())
+ qDebug() << "QmlEngine::addToImport(" << imports << uri << prefix << vmaj << "." << vmin << (importType==QmlScriptParser::Import::Library? "Library" : "File") << ": " << ok;
+ return ok;
+}
+
+/*!
+ \internal
+
+ Using the given \a imports, the given (namespace qualified) \a type is resolved to either
+ an ImportedNamespace stored at \a ns_return,
+ a QmlType stored at \a type_return, or
+ a component located at \a url_return.
+
+ If any return pointer is 0, the corresponding search is not done.
+
+ \sa addToImport()
+*/
+bool QmlEnginePrivate::resolveType(const Imports& imports, const QByteArray& type, QmlType** type_return, QUrl* url_return, int *vmaj, int *vmin, ImportedNamespace** ns_return) const
+{
+ ImportedNamespace* ns = imports.d->findNamespace(QString::fromUtf8(type));
+ if (ns) {
+ if (qmlImportTrace())
+ qDebug() << "QmlEngine::resolveType" << type << "is namespace for" << ns->urls;
+ if (ns_return)
+ *ns_return = ns;
+ return true;
+ }
+ if (type_return || url_return) {
+ if (imports.d->find(type,vmaj,vmin,type_return,url_return)) {
+ if (qmlImportTrace()) {
+ if (type_return && *type_return)
+ qDebug() << "QmlEngine::resolveType" << type << "=" << (*type_return)->typeName();
+ if (url_return)
+ qDebug() << "QmlEngine::resolveType" << type << "=" << *url_return;
+ }
+ return true;
+ }
+ if (qmlImportTrace())
+ qDebug() << "QmlEngine::resolveType" << type << "not found";
+ }
+ return false;
+}
+
+/*!
+ \internal
+
+ Searching \e only in the namespace \a ns (previously returned in a call to
+ resolveType(), \a type is found and returned to either
+ a QmlType stored at \a type_return, or
+ a component located at \a url_return.
+
+ If either return pointer is 0, the corresponding search is not done.
+*/
+void QmlEnginePrivate::resolveTypeInNamespace(ImportedNamespace* ns, const QByteArray& type, QmlType** type_return, QUrl* url_return, int *vmaj, int *vmin ) const
+{
+ ns->find(type,vmaj,vmin,type_return,url_return);
+}
+
+static void voidptr_destructor(void *v)
+{
+ void **ptr = (void **)v;
+ delete ptr;
+}
+
+static void *voidptr_constructor(const void *v)
+{
+ if (!v) {
+ return new void*;
+ } else {
+ return new void*(*(void **)v);
+ }
+}
+
+void QmlEnginePrivate::registerCompositeType(QmlCompiledData *data)
+{
+ QByteArray name = data->root->className();
+
+ QByteArray ptr = name + "*";
+ QByteArray lst = "QmlList<" + ptr + ">*";
+
+ int ptr_type = QMetaType::registerType(ptr.constData(), voidptr_destructor,
+ voidptr_constructor);
+ int lst_type = QMetaType::registerType(lst.constData(), voidptr_destructor,
+ voidptr_constructor);
+
+ m_qmlLists.insert(lst_type, ptr_type);
+ m_compositeTypes.insert(ptr_type, data);
+ data->addref();
+}
+
+bool QmlEnginePrivate::isQmlList(int t) const
+{
+ return m_qmlLists.contains(t) || QmlMetaType::isQmlList(t);
+}
+
+bool QmlEnginePrivate::isObject(int t)
+{
+ return m_compositeTypes.contains(t) || QmlMetaType::isObject(t);
+}
+
+int QmlEnginePrivate::qmlListType(int t) const
+{
+ QHash<int, int>::ConstIterator iter = m_qmlLists.find(t);
+ if (iter != m_qmlLists.end())
+ return *iter;
+ else
+ return QmlMetaType::qmlListType(t);
+}
+
+const QMetaObject *QmlEnginePrivate::rawMetaObjectForType(int t) const
+{
+ QHash<int, QmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
+ if (iter != m_compositeTypes.end()) {
+ return (*iter)->root;
+ } else {
+ return QmlMetaType::rawMetaObjectForType(t);
+ }
+}
+
+const QMetaObject *QmlEnginePrivate::metaObjectForType(int t) const
+{
+ QHash<int, QmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t);
+ if (iter != m_compositeTypes.end()) {
+ return (*iter)->root;
+ } else {
+ return QmlMetaType::metaObjectForType(t);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlengine.h b/src/declarative/qml/qmlengine.h
new file mode 100644
index 0000000..b4233e4
--- /dev/null
+++ b/src/declarative/qml/qmlengine.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** 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 QMLENGINE_H
+#define QMLENGINE_H
+
+#include <QtCore/qurl.h>
+#include <QtCore/qobject.h>
+#include <QtCore/qmap.h>
+#include <QtScript/qscriptvalue.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlComponent;
+class QmlEnginePrivate;
+class QmlImportsPrivate;
+class QmlExpression;
+class QmlContext;
+class QmlType;
+class QUrl;
+class QScriptEngine;
+class QScriptContext;
+class QNetworkAccessManager;
+class Q_DECLARATIVE_EXPORT QmlEngine : public QObject
+{
+ Q_PROPERTY(QString offlineStoragePath READ offlineStoragePath WRITE setOfflineStoragePath)
+ Q_OBJECT
+public:
+ QmlEngine(QObject *p = 0);
+ virtual ~QmlEngine();
+
+ QmlContext *rootContext();
+
+ void clearComponentCache();
+
+ void addImportPath(const QString& dir);
+
+ void setNetworkAccessManager(QNetworkAccessManager *);
+ QNetworkAccessManager *networkAccessManager() const;
+
+ void setOfflineStoragePath(const QString& dir);
+ QString offlineStoragePath() const;
+
+ QUrl baseUrl() const;
+ void setBaseUrl(const QUrl &);
+
+ static QmlContext *contextForObject(const QObject *);
+ static void setContextForObject(QObject *, QmlContext *);
+
+private:
+ Q_DECLARE_PRIVATE(QmlEngine)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLENGINE_H
diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h
new file mode 100644
index 0000000..29621c0
--- /dev/null
+++ b/src/declarative/qml/qmlengine_p.h
@@ -0,0 +1,288 @@
+/****************************************************************************
+**
+** 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 QMLENGINE_P_H
+#define QMLENGINE_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>
+#include <QtScript/QScriptValue>
+#include <QtScript/QScriptString>
+#include <QtCore/qstring.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qpair.h>
+#include <QtCore/qstack.h>
+#include <private/qobject_p.h>
+#include <private/qmlclassfactory_p.h>
+#include <private/qmlcompositetypemanager_p.h>
+#include <private/qpodvector_p.h>
+#include <QtDeclarative/qml.h>
+#include <private/qmlbasicscript_p.h>
+#include <private/qmlvaluetype_p.h>
+#include <QtDeclarative/qmlcontext.h>
+#include <QtDeclarative/qmlengine.h>
+#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
+
+class QmlContext;
+class QmlEngine;
+class QmlContextPrivate;
+class QmlExpression;
+class QmlBasicScriptNodeCache;
+class QmlContextScriptClass;
+class QmlObjectScriptClass;
+class QmlTypeNameScriptClass;
+class QmlValueTypeScriptClass;
+class QScriptEngineDebugger;
+class QNetworkReply;
+class QNetworkAccessManager;
+class QmlAbstractBinding;
+class QScriptDeclarativeClass;
+class QmlTypeNameScriptClass;
+class QmlTypeNameCache;
+class QmlComponentAttached;
+class QmlListScriptClass;
+class QmlCleanup;
+
+class QmlEnginePrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlEngine)
+public:
+ QmlEnginePrivate(QmlEngine *);
+ ~QmlEnginePrivate();
+
+ void init();
+
+ struct CapturedProperty {
+ CapturedProperty(QObject *o, int c, int n)
+ : object(o), coreIndex(c), notifyIndex(n) {}
+ CapturedProperty(const QmlMetaProperty &);
+
+ QObject *object;
+ int coreIndex;
+ int notifyIndex;
+ };
+ QPODVector<CapturedProperty> capturedProperties;
+
+ QmlContext *rootContext;
+ QmlExpression *currentExpression;
+ bool isDebugging;
+#ifdef QT_SCRIPTTOOLS_LIB
+ QScriptEngineDebugger *debugger;
+#endif
+
+ struct ImportedNamespace;
+ QmlContextScriptClass *contextClass;
+ QmlObjectScriptClass *objectClass;
+ QmlValueTypeScriptClass *valueTypeClass;
+ QmlTypeNameScriptClass *typeNameClass;
+ QmlListScriptClass *listClass;
+ // Global script class
+ QScriptClass *globalClass;
+ // Used by DOM Core 3 API
+ QScriptClass *nodeListClass;
+ QScriptClass *namedNodeMapClass;
+ // Used by SQL database API
+ QScriptClass *sqlQueryClass;
+
+ // Registered cleanup handlers
+ QmlCleanup *cleanup;
+
+ struct QmlScriptEngine : public QScriptEngine
+ {
+ QmlScriptEngine(QmlEnginePrivate *priv)
+ : p(priv) {}
+ QmlEnginePrivate *p;
+ };
+ QmlScriptEngine scriptEngine;
+
+ QUrl baseUrl;
+
+ template<class T>
+ struct SimpleList {
+ SimpleList()
+ : count(0), values(0) {}
+ SimpleList(int r)
+ : count(0), values(new T*[r]) {}
+
+ int count;
+ T **values;
+
+ void append(T *v) {
+ values[count++] = v;
+ }
+
+ T *at(int idx) const {
+ return values[idx];
+ }
+
+ void clear() {
+ delete [] values;
+ }
+ };
+
+ static void clear(SimpleList<QmlAbstractBinding> &);
+ static void clear(SimpleList<QmlParserStatus> &);
+
+ QList<SimpleList<QmlAbstractBinding> > bindValues;
+ QList<SimpleList<QmlParserStatus> > parserStatus;
+ QmlComponentAttached *componentAttacheds;
+
+ QmlComponent *rootComponent;
+ mutable QNetworkAccessManager *networkAccessManager;
+
+ QmlCompositeTypeManager typeManager;
+ QStringList fileImportPath;
+ QString offlineStoragePath;
+
+ mutable quint32 uniqueId;
+ quint32 getUniqueId() const {
+ return uniqueId++;
+ }
+
+ QmlValueTypeFactory valueTypes;
+
+ 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();
+ Imports(const Imports &copy);
+ Imports &operator =(const Imports &copy);
+
+ void setBaseUrl(const QUrl& url);
+ QUrl baseUrl() const;
+
+ QmlTypeNameCache *cache(QmlEngine *) const;
+
+ private:
+ friend class QmlEnginePrivate;
+ QmlImportsPrivate *d;
+ };
+
+ bool addToImport(Imports*, const QString& uri, const QString& prefix, int vmaj, int vmin, QmlScriptParser::Import::Type importType) const;
+ bool resolveType(const Imports&, const QByteArray& type,
+ QmlType** type_return, QUrl* url_return,
+ int *version_major, int *version_minor,
+ ImportedNamespace** ns_return) const;
+ void resolveTypeInNamespace(ImportedNamespace*, const QByteArray& type,
+ QmlType** type_return, QUrl* url_return,
+ int *version_major, int *version_minor ) const;
+
+
+ void registerCompositeType(QmlCompiledData *);
+ bool isQmlList(int) const;
+ bool isObject(int);
+ int qmlListType(int) const;
+ const QMetaObject *rawMetaObjectForType(int) const;
+ const QMetaObject *metaObjectForType(int) const;
+ 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*);
+ static QScriptValue vector(QScriptContext*, QScriptEngine*);
+ static QScriptValue rgba(QScriptContext*, QScriptEngine*);
+ static QScriptValue hsla(QScriptContext*, QScriptEngine*);
+ static QScriptValue point(QScriptContext*, QScriptEngine*);
+ static QScriptValue size(QScriptContext*, QScriptEngine*);
+ static QScriptValue rect(QScriptContext*, QScriptEngine*);
+
+ static QScriptValue lighter(QScriptContext*, QScriptEngine*);
+ static QScriptValue darker(QScriptContext*, QScriptEngine*);
+ static QScriptValue tint(QScriptContext*, QScriptEngine*);
+
+ static QScriptValue playSound(QScriptContext*, QScriptEngine*);
+
+ static QScriptEngine *getScriptEngine(QmlEngine *e) { return &e->d_func()->scriptEngine; }
+ static QmlEngine *getEngine(QScriptEngine *e) { return static_cast<QmlScriptEngine*>(e)->p->q_func(); }
+ static QmlEnginePrivate *get(QmlEngine *e) { return e->d_func(); }
+ static QmlEnginePrivate *get(QScriptEngine *e) { return static_cast<QmlScriptEngine*>(e)->p; }
+ QmlContext *getContext(QScriptContext *);
+};
+
+
+class QmlScriptClass : public QScriptClass
+{
+public:
+ QmlScriptClass(QmlEngine *);
+
+ static QVariant toVariant(QmlEngine *, const QScriptValue &);
+protected:
+ QmlEngine *engine;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLENGINE_P_H
diff --git a/src/declarative/qml/qmlenginedebug.cpp b/src/declarative/qml/qmlenginedebug.cpp
new file mode 100644
index 0000000..7178e6c
--- /dev/null
+++ b/src/declarative/qml/qmlenginedebug.cpp
@@ -0,0 +1,401 @@
+/****************************************************************************
+**
+** 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 "qmlenginedebug_p.h"
+#include "qmlboundsignal_p.h"
+#include <QtCore/qdebug.h>
+#include <QtCore/qmetaobject.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlmetatype.h>
+#include <qmlmetaproperty.h>
+#include <qmlbinding.h>
+#include "qmlcontext_p.h"
+#include "qmlwatcher_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QList<QmlEngine *> QmlEngineDebugServer::m_engines;
+QmlEngineDebugServer::QmlEngineDebugServer(QObject *parent)
+: QmlDebugService(QLatin1String("QmlEngine"), parent),
+ m_watch(new QmlWatcher(this))
+{
+ QObject::connect(m_watch, SIGNAL(propertyChanged(int,int,QByteArray,QVariant)),
+ this, SLOT(propertyChanged(int,int,QByteArray,QVariant)));
+}
+
+QDataStream &operator<<(QDataStream &ds,
+ const QmlEngineDebugServer::QmlObjectData &data)
+{
+ ds << data.url << data.lineNumber << data.columnNumber << data.objectName
+ << data.objectType << data.objectId << data.contextId;
+ return ds;
+}
+
+QDataStream &operator>>(QDataStream &ds,
+ QmlEngineDebugServer::QmlObjectData &data)
+{
+ ds >> data.url >> data.lineNumber >> data.columnNumber >> data.objectName
+ >> data.objectType >> data.objectId >> data.contextId;
+ return ds;
+}
+
+QDataStream &operator<<(QDataStream &ds,
+ const QmlEngineDebugServer::QmlObjectProperty &data)
+{
+ ds << (int)data.type << data.name << data.value << data.valueTypeName
+ << data.binding << data.hasNotifySignal;
+ return ds;
+}
+
+QDataStream &operator>>(QDataStream &ds,
+ QmlEngineDebugServer::QmlObjectProperty &data)
+{
+ int type;
+ ds >> type >> data.name >> data.value >> data.valueTypeName
+ >> data.binding >> data.hasNotifySignal;
+ data.type = (QmlEngineDebugServer::QmlObjectProperty::Type)type;
+ return ds;
+}
+
+QmlEngineDebugServer::QmlObjectProperty
+QmlEngineDebugServer::propertyData(QObject *obj, int propIdx)
+{
+ QmlObjectProperty rv;
+
+ QMetaProperty prop = obj->metaObject()->property(propIdx);
+
+ rv.type = QmlObjectProperty::Unknown;
+ rv.valueTypeName = QString::fromUtf8(prop.typeName());
+ rv.name = prop.name();
+ rv.hasNotifySignal = prop.hasNotifySignal();
+ QmlAbstractBinding *binding = QmlMetaProperty(obj, rv.name).binding();
+ if (binding)
+ rv.binding = binding->expression();
+
+ if (prop.type() < QVariant::UserType) {
+ rv.type = QmlObjectProperty::Basic;
+ rv.value = prop.read(obj);
+ } else if (QmlMetaType::isObject(prop.userType())) {
+ rv.type = QmlObjectProperty::Object;
+ } else if (QmlMetaType::isList(prop.userType()) ||
+ QmlMetaType::isQmlList(prop.userType())) {
+ rv.type = QmlObjectProperty::List;
+ }
+
+ return rv;
+}
+
+void QmlEngineDebugServer::buildObjectDump(QDataStream &message,
+ QObject *object, bool recur)
+{
+ message << objectData(object);
+ message << object->metaObject()->propertyCount();
+
+ for (int ii = 0; ii < object->metaObject()->propertyCount(); ++ii)
+ message << propertyData(object, ii);
+
+ QObjectList children = object->children();
+ message << children.count() << recur;
+
+ for (int ii = 0; ii < children.count(); ++ii) {
+ QObject *child = children.at(ii);
+ if (recur)
+ buildObjectDump(message, child, recur);
+ else
+ message << objectData(child);
+ }
+}
+
+void QmlEngineDebugServer::buildObjectList(QDataStream &message,
+ QmlContext *ctxt)
+{
+ QmlContextPrivate *p = (QmlContextPrivate *)QObjectPrivate::get(ctxt);
+
+ QString ctxtName = ctxt->objectName();
+ int ctxtId = QmlDebugService::idForObject(ctxt);
+
+ message << ctxtName << ctxtId;
+
+ int count = 0;
+
+ for (QSet<QmlContext *>::ConstIterator iter = p->childContexts.begin();
+ iter != p->childContexts.end(); ++iter) {
+ QmlContextPrivate *p = (QmlContextPrivate *)QObjectPrivate::get(*iter);
+ if (p->isInternal)
+ continue;
+ ++count;
+ }
+
+ message << count;
+
+ for (QSet<QmlContext *>::ConstIterator iter = p->childContexts.begin();
+ iter != p->childContexts.end(); ++iter) {
+ QmlContextPrivate *p = (QmlContextPrivate *)QObjectPrivate::get(*iter);
+ if (p->isInternal)
+ continue;
+ buildObjectList(message, *iter);
+ }
+
+ // Clean deleted objects
+ for (int ii = 0; ii < p->instances.count(); ++ii) {
+ if (!p->instances.at(ii)) {
+ p->instances.removeAt(ii);
+ --ii;
+ }
+ }
+
+ message << p->instances.count();
+ for (int ii = 0; ii < p->instances.count(); ++ii) {
+ message << objectData(p->instances.at(ii));
+ }
+}
+
+QVariant QmlEngineDebugServer::serializableVariant(const QVariant &value)
+{
+ if (value.type() < QVariant::UserType)
+ return value;
+
+ if (!value.toString().isEmpty())
+ return value.toString();
+
+ QVariant v;
+ if (value.type() == QVariant::UserType || QmlMetaType::isObject(value.userType())) {
+ QObject *o = QmlMetaType::toQObject(value);
+ if (o) {
+ QString objectName = o->objectName();
+ if (objectName.isEmpty())
+ objectName = QLatin1String("<unnamed>");
+ v = QString::fromUtf8(o->metaObject()->className()) +
+ QLatin1String(": ") + objectName;
+ }
+ }
+
+ if (v.isNull())
+ v = QString::fromUtf8(value.typeName());
+
+ return v;
+}
+
+QmlEngineDebugServer::QmlObjectData
+QmlEngineDebugServer::objectData(QObject *object)
+{
+ QmlDeclarativeData *ddata = QmlDeclarativeData::get(object);
+ QmlObjectData rv;
+ if (ddata) {
+ rv.url = ddata->outerContext->baseUrl();
+ rv.lineNumber = ddata->lineNumber;
+ rv.columnNumber = ddata->columnNumber;
+ } else {
+ rv.lineNumber = -1;
+ rv.columnNumber = -1;
+ }
+
+ rv.objectName = object->objectName();
+ rv.objectType = object->metaObject()->className();
+ rv.objectId = QmlDebugService::idForObject(object);
+ rv.contextId = QmlDebugService::idForObject(qmlContext(object));
+
+ return rv;
+}
+
+void QmlEngineDebugServer::messageReceived(const QByteArray &message)
+{
+ QDataStream ds(message);
+
+ QByteArray type;
+ ds >> type;
+
+ //qDebug() << "QmlEngineDebugServer::messageReceived()" << type;
+
+ if (type == "LIST_ENGINES") {
+ int queryId;
+ ds >> queryId;
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("LIST_ENGINES_R");
+ rs << queryId << m_engines.count();
+
+ for (int ii = 0; ii < m_engines.count(); ++ii) {
+ QmlEngine *engine = m_engines.at(ii);
+
+ QString engineName = engine->objectName();
+ int engineId = QmlDebugService::idForObject(engine);
+
+ rs << engineName << engineId;
+ }
+
+ sendMessage(reply);
+ } else if (type == "LIST_OBJECTS") {
+ int queryId;
+ int engineId = -1;
+ ds >> queryId >> engineId;
+
+ QmlEngine *engine =
+ qobject_cast<QmlEngine *>(QmlDebugService::objectForId(engineId));
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("LIST_OBJECTS_R") << queryId;
+
+ if (engine)
+ buildObjectList(rs, engine->rootContext());
+
+ sendMessage(reply);
+ } else if (type == "FETCH_OBJECT") {
+ int queryId;
+ int objectId;
+ bool recurse;
+
+ ds >> queryId >> objectId >> recurse;
+
+ QObject *object = QmlDebugService::objectForId(objectId);
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("FETCH_OBJECT_R") << queryId;
+
+ if (object)
+ buildObjectDump(rs, object, recurse);
+
+ sendMessage(reply);
+ } else if (type == "WATCH_OBJECT") {
+ int queryId;
+ int objectId;
+
+ ds >> queryId >> objectId;
+ bool ok = m_watch->addWatch(queryId, objectId);
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("WATCH_OBJECT_R") << queryId << objectId << ok;
+
+ sendMessage(reply);
+ } else if (type == "WATCH_PROPERTY") {
+ int queryId;
+ int objectId;
+ QByteArray property;
+
+ ds >> queryId >> objectId >> property;
+ bool ok = m_watch->addWatch(queryId, objectId, property);
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("WATCH_PROPERTY_R") << queryId << ok;
+
+ sendMessage(reply);
+ } else if (type == "WATCH_EXPR_OBJECT") {
+ int queryId;
+ int debugId;
+ QString expr;
+
+ ds >> queryId >> debugId >> expr;
+ bool ok = m_watch->addWatch(queryId, debugId, expr);
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("WATCH_EXPR_OBJECT_R") << queryId << ok;
+
+ sendMessage(reply);
+ } else if (type == "NO_WATCH") {
+ int queryId;
+
+ ds >> queryId;
+ m_watch->removeWatch(queryId);
+ } else if (type == "EVAL_EXPRESSION") {
+ int queryId;
+ int objectId;
+ QString expr;
+
+ ds >> queryId >> objectId >> expr;
+
+ QObject *object = QmlDebugService::objectForId(objectId);
+ QmlContext *context = qmlContext(object);
+ QVariant result;
+ if (object && context) {
+ QmlExpression *exprObj = new QmlExpression(context, expr, object);
+ bool undefined = false;
+ QVariant value = exprObj->value(&undefined);
+ if (undefined)
+ result = QLatin1String("<undefined>");
+ else
+ result = serializableVariant(value);
+ delete exprObj;
+ } else {
+ result = QLatin1String("<unknown context>");
+ }
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("EVAL_EXPRESSION_R") << queryId << result;
+
+ sendMessage(reply);
+ }
+}
+
+void QmlEngineDebugServer::propertyChanged(int id, int objectId, const QByteArray &property, const QVariant &value)
+{
+ QByteArray reply;
+ QVariant v = serializableVariant(value);
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+
+ rs << QByteArray("UPDATE_WATCH") << id << objectId << property << v;
+
+ sendMessage(reply);
+}
+
+void QmlEngineDebugServer::addEngine(QmlEngine *engine)
+{
+ Q_ASSERT(engine);
+ Q_ASSERT(!m_engines.contains(engine));
+
+ m_engines.append(engine);
+}
+
+void QmlEngineDebugServer::remEngine(QmlEngine *engine)
+{
+ Q_ASSERT(engine);
+ Q_ASSERT(m_engines.contains(engine));
+
+ m_engines.removeAll(engine);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlenginedebug_p.h b/src/declarative/qml/qmlenginedebug_p.h
new file mode 100644
index 0000000..075a711
--- /dev/null
+++ b/src/declarative/qml/qmlenginedebug_p.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** 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 QMLENGINEDEBUG_P_H
+#define QMLENGINEDEBUG_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 <QtDeclarative/qmldebugservice.h>
+#include <QtCore/qurl.h>
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlEngine;
+class QmlContext;
+class QmlWatcher;
+class QDataStream;
+
+class QmlEngineDebugServer : public QmlDebugService
+{
+ Q_OBJECT
+public:
+ QmlEngineDebugServer(QObject * = 0);
+
+ struct QmlObjectData {
+ QUrl url;
+ int lineNumber;
+ int columnNumber;
+ QString objectName;
+ QString objectType;
+ int objectId;
+ int contextId;
+ };
+
+ struct QmlObjectProperty {
+ enum Type { Unknown, Basic, Object, List };
+ Type type;
+ QString name;
+ QVariant value;
+ QString valueTypeName;
+ QString binding;
+ bool hasNotifySignal;
+ };
+
+ static void addEngine(QmlEngine *);
+ static void remEngine(QmlEngine *);
+
+protected:
+ virtual void messageReceived(const QByteArray &);
+
+private Q_SLOTS:
+ void propertyChanged(int id, int objectId, const QByteArray &property, const QVariant &value);
+
+private:
+ void buildObjectList(QDataStream &, QmlContext *);
+ void buildObjectDump(QDataStream &, QObject *, bool);
+ QmlObjectData objectData(QObject *);
+ QmlObjectProperty propertyData(QObject *, int);
+ QVariant serializableVariant(const QVariant &value);
+
+ static QList<QmlEngine *> m_engines;
+ QmlWatcher *m_watch;
+};
+Q_DECLARATIVE_EXPORT QDataStream &operator<<(QDataStream &, const QmlEngineDebugServer::QmlObjectData &);
+Q_DECLARATIVE_EXPORT QDataStream &operator>>(QDataStream &, QmlEngineDebugServer::QmlObjectData &);
+Q_DECLARATIVE_EXPORT QDataStream &operator<<(QDataStream &, const QmlEngineDebugServer::QmlObjectProperty &);
+Q_DECLARATIVE_EXPORT QDataStream &operator>>(QDataStream &, QmlEngineDebugServer::QmlObjectProperty &);
+
+QT_END_NAMESPACE
+
+#endif // QMLENGINEDEBUG_P_H
+
diff --git a/src/declarative/qml/qmlerror.cpp b/src/declarative/qml/qmlerror.cpp
new file mode 100644
index 0000000..514fe44
--- /dev/null
+++ b/src/declarative/qml/qmlerror.cpp
@@ -0,0 +1,234 @@
+/****************************************************************************
+**
+** 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 "qmlerror.h"
+#include <QtCore/qdebug.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qstringlist.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QmlError
+ \brief The QmlError class encapsulates a QML error
+*/
+class QmlErrorPrivate
+{
+public:
+ QmlErrorPrivate();
+
+ QUrl url;
+ QString description;
+ int line;
+ int column;
+};
+
+QmlErrorPrivate::QmlErrorPrivate()
+: line(-1), column(-1)
+{
+}
+
+/*!
+ Create an empty error object.
+*/
+QmlError::QmlError()
+: d(new QmlErrorPrivate)
+{
+}
+
+/*!
+ Create a copy of \a other.
+*/
+QmlError::QmlError(const QmlError &other)
+: d(new QmlErrorPrivate)
+{
+ *this = other;
+}
+
+/*!
+ Assign \a other to this error object.
+*/
+QmlError &QmlError::operator=(const QmlError &other)
+{
+ d->url = other.d->url;
+ d->description = other.d->description;
+ d->line = other.d->line;
+ d->column = other.d->column;
+ return *this;
+}
+
+/*!
+ \internal
+*/
+QmlError::~QmlError()
+{
+ delete d; d = 0;
+}
+
+/*!
+ Return the url for the file that caused this error.
+*/
+QUrl QmlError::url() const
+{
+ return d->url;
+}
+
+/*!
+ Set the \a url for the file that caused this error.
+*/
+void QmlError::setUrl(const QUrl &url)
+{
+ d->url = url;
+}
+
+/*!
+ Return the error description.
+*/
+QString QmlError::description() const
+{
+ return d->description;
+}
+
+/*!
+ Set the error \a description.
+*/
+void QmlError::setDescription(const QString &description)
+{
+ d->description = description;
+}
+
+/*!
+ Return the error line number.
+*/
+int QmlError::line() const
+{
+ return d->line;
+}
+
+/*!
+ Set the error \a line number.
+*/
+void QmlError::setLine(int line)
+{
+ d->line = line;
+}
+
+/*!
+ Return the error column number.
+*/
+int QmlError::column() const
+{
+ return d->column;
+}
+
+/*!
+ Set the error \a column number.
+*/
+void QmlError::setColumn(int column)
+{
+ d->column = column;
+}
+
+/*!
+ Return the error as a human readable string.
+*/
+QString QmlError::toString() const
+{
+ QString rv;
+ rv = url().toString() + QLatin1String(":") + QString::number(line());
+ if(column() != -1)
+ rv += QLatin1String(":") + QString::number(column());
+
+ rv += QLatin1String(": ") + description();
+
+ return rv;
+}
+
+/*!
+ \relates QmlError
+ \fn QDebug operator<<(QDebug debug, const QmlError &error)
+
+ Output a human readable version of \a error to \a debug.
+*/
+
+QDebug operator<<(QDebug debug, const QmlError &error)
+{
+ debug << qPrintable(error.toString());
+
+ QUrl url = error.url();
+
+ if (error.line() > 0 && url.scheme() == QLatin1String("file")) {
+ QString file = url.toLocalFile();
+ QFile f(file);
+ if (f.open(QIODevice::ReadOnly)) {
+ QByteArray data = f.readAll();
+ QTextStream stream(data, QIODevice::ReadOnly);
+ stream.setCodec("UTF-8");
+ const QString code = stream.readAll();
+ const QStringList lines = code.split(QLatin1Char('\n'));
+
+ if (lines.count() >= error.line()) {
+ const QString &line = lines.at(error.line() - 1);
+ debug << "\n " << qPrintable(line);
+
+ if(error.column() > 0) {
+ int column = qMax(0, error.column() - 1);
+ column = qMin(column, line.length());
+
+ QByteArray ind;
+ ind.reserve(column);
+ for (int i = 0; i < column; ++i) {
+ const QChar ch = line.at(i);
+ if (ch.isSpace())
+ ind.append(ch.unicode());
+ else
+ ind.append(' ');
+ }
+ ind.append('^');
+ debug << "\n " << ind.constData();
+ }
+ }
+ }
+ }
+ return debug;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlerror.h b/src/declarative/qml/qmlerror.h
new file mode 100644
index 0000000..c1a8720
--- /dev/null
+++ b/src/declarative/qml/qmlerror.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** 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 QMLERROR_H
+#define QMLERROR_H
+
+#include <QtCore/qurl.h>
+#include <QtCore/qstring.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDebug;
+class QmlErrorPrivate;
+class Q_DECLARATIVE_EXPORT QmlError
+{
+public:
+ QmlError();
+ QmlError(const QmlError &);
+ QmlError &operator=(const QmlError &);
+ ~QmlError();
+
+ QUrl url() const;
+ void setUrl(const QUrl &);
+ QString description() const;
+ void setDescription(const QString &);
+ int line() const;
+ void setLine(int);
+ int column() const;
+ void setColumn(int);
+
+ QString toString() const;
+private:
+ QmlErrorPrivate *d;
+};
+
+QDebug Q_DECLARATIVE_EXPORT operator<<(QDebug debug, const QmlError &error);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLERROR_H
diff --git a/src/declarative/qml/qmlexpression.cpp b/src/declarative/qml/qmlexpression.cpp
new file mode 100644
index 0000000..3f531a3
--- /dev/null
+++ b/src/declarative/qml/qmlexpression.cpp
@@ -0,0 +1,686 @@
+/****************************************************************************
+**
+** 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 "qmlexpression.h"
+#include "qmlexpression_p.h"
+#include "qmlengine_p.h"
+#include "qmlcontext_p.h"
+#include "qmlrewrite_p.h"
+#include "QtCore/qdebug.h"
+#include "qmlcompiler_p.h"
+
+Q_DECLARE_METATYPE(QList<QObject *>);
+
+QT_BEGIN_NAMESPACE
+
+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)
+{
+ data->expression = expr;
+
+ data->QmlAbstractExpression::setContext(ctxt);
+ data->me = me;
+}
+
+void QmlExpressionPrivate::init(QmlContext *ctxt, void *expr, QmlRefCount *rc,
+ QObject *me, const QUrl &url, int lineNumber)
+{
+ data->fileName = url.toString();
+ data->line = lineNumber;
+
+ quint32 *exprData = (quint32 *)expr;
+ Q_ASSERT(*exprData == BasicScriptEngineData ||
+ *exprData == PreTransformedQtScriptData);
+ if (*exprData == BasicScriptEngineData) {
+ data->sse.load((const char *)(exprData + 1), rc);
+ } else {
+ QmlCompiledData *dd = (QmlCompiledData *)rc;
+
+ data->expressionRewritten = true;
+ data->expression = QString::fromRawData((QChar *)(exprData + 3), exprData[2]);
+
+ int progIdx = *(exprData + 1);
+ QmlEngine *engine = ctxt->engine();
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+#if !defined(Q_OS_SYMBIAN) && !defined(Q_OS_WIN32) //XXX Why doesn't this work?
+ if (!dd->programs.at(progIdx)) {
+ dd->programs[progIdx] =
+ new QScriptProgram(scriptEngine->compile(data->expression, data->fileName, data->line));
+ }
+#endif
+
+ QScriptContext *scriptContext = scriptEngine->pushCleanContext();
+ scriptContext->pushScope(ep->contextClass->newContext(ctxt, me));
+
+#if !defined(Q_OS_SYMBIAN) && !defined(Q_OS_WIN32)
+ data->expressionFunction = scriptEngine->evaluate(*dd->programs[progIdx]);
+#else
+ data->expressionFunction = scriptEngine->evaluate(data->expression);
+#endif
+
+ data->expressionFunctionValid = true;
+ scriptEngine->popContext();
+ }
+
+ data->QmlAbstractExpression::setContext(ctxt);
+ data->me = me;
+}
+
+/*!
+ \class QmlExpression
+ \brief The QmlExpression class evaluates ECMAScript in a QML context.
+*/
+
+/*!
+ Create an invalid QmlExpression.
+
+ As the expression will not have an associated QmlContext, this will be a
+ null expression object and its value will always be an invalid QVariant.
+ */
+QmlExpression::QmlExpression()
+: QObject(*new QmlExpressionPrivate, 0)
+{
+}
+
+/*! \internal */
+QmlExpression::QmlExpression(QmlContext *ctxt, void *expr,
+ QmlRefCount *rc, QObject *me,
+ const QUrl &url, int lineNumber,
+ QmlExpressionPrivate &dd)
+: QObject(dd, 0)
+{
+ Q_D(QmlExpression);
+ d->init(ctxt, expr, rc, me, url, lineNumber);
+}
+
+/*!
+ Create a QmlExpression object.
+
+ The \a expression ECMAScript will be executed in the \a ctxt QmlContext.
+ If specified, the \a scope object's properties will also be in scope during
+ the expression's execution.
+*/
+QmlExpression::QmlExpression(QmlContext *ctxt, const QString &expression,
+ QObject *scope)
+: QObject(*new QmlExpressionPrivate, 0)
+{
+ Q_D(QmlExpression);
+ d->init(ctxt, expression, scope);
+}
+
+/*! \internal */
+QmlExpression::QmlExpression(QmlContext *ctxt, const QString &expression,
+ QObject *scope, QmlExpressionPrivate &dd)
+: QObject(dd, 0)
+{
+ Q_D(QmlExpression);
+ d->init(ctxt, expression, scope);
+}
+
+/*!
+ Destroy the QmlExpression instance.
+*/
+QmlExpression::~QmlExpression()
+{
+}
+
+/*!
+ Returns the QmlEngine this expression is associated with, or 0 if there
+ is no association or the QmlEngine has been destroyed.
+*/
+QmlEngine *QmlExpression::engine() const
+{
+ Q_D(const QmlExpression);
+ return d->data->context()?d->data->context()->engine():0;
+}
+
+/*!
+ Returns the QmlContext this expression is associated with, or 0 if there
+ is no association or the QmlContext has been destroyed.
+*/
+QmlContext *QmlExpression::context() const
+{
+ Q_D(const QmlExpression);
+ return d->data->context();
+}
+
+/*!
+ Returns the expression string.
+*/
+QString QmlExpression::expression() const
+{
+ Q_D(const QmlExpression);
+ if (d->data->sse.isValid())
+ return QString::fromUtf8(d->data->sse.expression());
+ else
+ return d->data->expression;
+}
+
+/*!
+ Clear the expression.
+*/
+void QmlExpression::clearExpression()
+{
+ setExpression(QString());
+}
+
+/*!
+ Set the expression to \a expression.
+*/
+void QmlExpression::setExpression(const QString &expression)
+{
+ Q_D(QmlExpression);
+
+ d->clearGuards();
+
+ d->data->expression = expression;
+ d->data->expressionFunctionValid = false;
+ d->data->expressionRewritten = false;
+ d->data->expressionFunction = QScriptValue();
+
+ d->data->sse.clear();
+}
+
+QVariant QmlExpressionPrivate::evalSSE()
+{
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::BindValueSSE> perfsse;
+#endif
+
+ QVariant rv = data->sse.run(data->context(), data->me);
+
+ return rv;
+}
+
+void QmlExpressionPrivate::printException(QScriptEngine *scriptEngine)
+{
+ if (scriptEngine->hasUncaughtException() &&
+ scriptEngine->uncaughtException().isError()) {
+
+ QString fileName;
+ int lineNumber = scriptEngine->uncaughtExceptionLineNumber();
+
+ QScriptValue exception = scriptEngine->uncaughtException();
+ QLatin1String fileNameProp("fileName");
+
+ if (!exception.property(fileNameProp).toString().isEmpty()){
+ fileName = exception.property(fileNameProp).toString();
+ } else {
+ fileName = QLatin1String("<Unknown File>");
+ }
+
+ qWarning().nospace() << qPrintable(fileName) << ":" << lineNumber << ": "
+ << qPrintable(exception.toString());
+ }
+}
+
+QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope, bool *isUndefined)
+{
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::BindValueQt> perfqt;
+#endif
+
+ QmlContextPrivate *ctxtPriv = data->context()->d_func();
+ QmlEngine *engine = data->context()->engine();
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
+
+ if (secondaryScope)
+ ctxtPriv->defaultObjects.insert(ctxtPriv->highPriorityCount,
+ secondaryScope);
+
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+
+ if (!data->expressionFunctionValid) {
+
+ QScriptContext *scriptContext = scriptEngine->pushCleanContext();
+ scriptContext->pushScope(ep->contextClass->newContext(data->context(), data->me));
+
+ if (data->expressionRewritten) {
+ data->expressionFunction = scriptEngine->evaluate(data->expression,
+ data->fileName, data->line);
+ } else {
+ QmlRewrite::RewriteBinding rewriteBinding;
+
+ const QString code = rewriteBinding(data->expression);
+ data->expressionFunction = scriptEngine->evaluate(code, data->fileName, data->line);
+ }
+
+ scriptEngine->popContext();
+ data->expressionFunctionValid = true;
+ }
+
+ QScriptValue svalue = data->expressionFunction.call();
+
+ if (isUndefined)
+ *isUndefined = svalue.isUndefined() || scriptEngine->hasUncaughtException();
+
+ if (scriptEngine->hasUncaughtException()) {
+ printException(scriptEngine);
+ scriptEngine->clearExceptions();
+ return QVariant();
+ }
+
+ if (secondaryScope)
+ ctxtPriv->defaultObjects.removeAt(ctxtPriv->highPriorityCount);
+
+ QVariant rv;
+
+ if (svalue.isArray()) {
+ int length = svalue.property(QLatin1String("length")).toInt32();
+ if (length && svalue.property(0).isObject()) {
+ QList<QObject *> list;
+ for (int ii = 0; ii < length; ++ii) {
+ QScriptValue arrayItem = svalue.property(ii);
+ QObject *d = arrayItem.toQObject();
+ list << d;
+ }
+ rv = QVariant::fromValue(list);
+ }
+ } else if (svalue.isObject() &&
+ ep->objectClass->scriptClass(svalue) == ep->objectClass) {
+ QObject *o = svalue.toQObject();
+ int type = QMetaType::QObjectStar;
+ // If the object is null, we extract the predicted type. While this isn't
+ // 100% reliable, in many cases it gives us better error messages if we
+ // assign this null-object to an incompatible property
+ if (!o) type = ep->objectClass->objectType(svalue);
+
+ return QVariant(type, &o);
+ }
+
+ if (rv.isNull())
+ rv = svalue.toVariant();
+
+ return rv;
+}
+
+QVariant QmlExpressionPrivate::value(QObject *secondaryScope, bool *isUndefined)
+{
+ Q_Q(QmlExpression);
+
+ QVariant rv;
+ if (!q->engine() || (!data->sse.isValid() && data->expression.isEmpty()))
+ return rv;
+
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::BindValue> perf;
+#endif
+
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(q->engine());
+
+ QmlExpression *lastCurrentExpression = ep->currentExpression;
+ QPODVector<QmlEnginePrivate::CapturedProperty> lastCapturedProperties;
+ ep->capturedProperties.copyAndClear(lastCapturedProperties);
+
+ ep->currentExpression = q;
+
+ // This object might be deleted during the eval
+ QmlExpressionData *localData = data;
+ localData->addref();
+
+ if (data->sse.isValid()) {
+ rv = evalSSE();
+ } else {
+ rv = evalQtScript(secondaryScope, isUndefined);
+ }
+
+ ep->currentExpression = lastCurrentExpression;
+
+ // 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;
+}
+
+/*!
+ Returns the value of the expression, or an invalid QVariant if the
+ expression is invalid or has an error.
+
+ \a isUndefined is set to true if the expression resulted in an
+ undefined value.
+*/
+QVariant QmlExpression::value(bool *isUndefined)
+{
+ Q_D(QmlExpression);
+ return d->value(0, isUndefined);
+}
+
+/*!
+ Returns true if the expression results in a constant value.
+ QmlExpression::value() must have been invoked at least once before the
+ return from this method is valid.
+ */
+bool QmlExpression::isConstant() const
+{
+ Q_D(const QmlExpression);
+ return !d->data->guardList;
+}
+
+/*!
+ Returns true if the changes are tracked in the expression's value.
+*/
+bool QmlExpression::trackChange() const
+{
+ Q_D(const QmlExpression);
+ return d->data->trackChange;
+}
+
+/*!
+ Set whether changes are tracked in the expression's value to \a trackChange.
+
+ If true, the QmlExpression will monitor properties involved in the
+ expression's evaluation, and call QmlExpression::valueChanged() if they have
+ changed. This allows an application to ensure that any value associated
+ with the result of the expression remains up to date.
+
+ If false, the QmlExpression will not montitor properties involved in the
+ expression's evaluation, and QmlExpression::valueChanged() will never be
+ called. This is more efficient if an application wants a "one off"
+ evaluation of the expression.
+
+ By default, trackChange is true.
+*/
+void QmlExpression::setTrackChange(bool trackChange)
+{
+ Q_D(QmlExpression);
+ d->data->trackChange = trackChange;
+}
+
+/*!
+ Returns the source file URL for this expression. The source location must
+ have been previously set by calling setSourceLocation().
+*/
+QUrl QmlExpression::sourceFile() const
+{
+ Q_D(const QmlExpression);
+ return QUrl(d->data->fileName);
+}
+
+/*!
+ Returns the source file line number for this expression. The source location
+ must have been previously set by calling setSourceLocation().
+*/
+int QmlExpression::lineNumber() const
+{
+ Q_D(const QmlExpression);
+ return d->data->line;
+}
+
+/*!
+ Set the location of this expression to \a line of \a fileName. This information
+ is used by the script engine.
+*/
+void QmlExpression::setSourceLocation(const QUrl &fileName, int line)
+{
+ Q_D(QmlExpression);
+ d->data->fileName = fileName.toString();
+ d->data->line = line;
+}
+
+/*!
+ Returns the expression's scope object, if provided, otherwise 0.
+
+ In addition to data provided by the expression's QmlContext, the scope
+ object's properties are also in scope during the expression's evaluation.
+*/
+QObject *QmlExpression::scopeObject() const
+{
+ Q_D(const QmlExpression);
+ return d->data->me;
+}
+
+/*! \internal */
+void QmlExpression::__q_notify()
+{
+ valueChanged();
+}
+
+void QmlExpressionPrivate::clearGuards()
+{
+ Q_Q(QmlExpression);
+
+ static int notifyIdx = -1;
+ if (notifyIdx == -1)
+ notifyIdx =
+ QmlExpression::staticMetaObject.indexOfMethod("__q_notify()");
+
+ 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 [] data->guardList; data->guardList = 0;
+ data->guardListLength = 0;
+}
+
+void QmlExpressionPrivate::updateGuards(const QPODVector<QmlEnginePrivate::CapturedProperty> &properties)
+{
+ //clearGuards();
+ Q_Q(QmlExpression);
+
+ static int notifyIdx = -1;
+ if (notifyIdx == -1)
+ notifyIdx =
+ QmlExpression::staticMetaObject.indexOfMethod("__q_notify()");
+
+ QmlExpressionData::SignalGuard *newGuardList = 0;
+
+ if (properties.count() != data->guardListLength)
+ newGuardList = new QmlExpressionData::SignalGuard[properties.count()];
+
+ bool outputWarningHeader = false;
+ int hit = 0;
+ for (int ii = 0; ii < properties.count(); ++ii) {
+ const QmlEnginePrivate::CapturedProperty &property = properties.at(ii);
+
+ bool needGuard = true;
+ if (ii >= data->guardListLength) {
+ // New guard
+ } else if(data->guardList[ii].data() == property.object &&
+ data->guardList[ii].notifyIndex == property.notifyIndex) {
+ // Cache hit
+ if (!data->guardList[ii].isDuplicate ||
+ (data->guardList[ii].isDuplicate && hit == ii)) {
+ needGuard = false;
+ ++hit;
+ }
+ } else if(data->guardList[ii].data() && !data->guardList[ii].isDuplicate) {
+ // Cache miss
+ QMetaObject::disconnect(data->guardList[ii].data(),
+ data->guardList[ii].notifyIndex,
+ q, notifyIdx);
+ }
+ /* else {
+ // Cache miss, but nothing to do
+ } */
+
+ if (needGuard) {
+ if (!newGuardList) {
+ newGuardList = new QmlExpressionData::SignalGuard[properties.count()];
+ for (int jj = 0; jj < ii; ++jj)
+ newGuardList[jj] = data->guardList[jj];
+ }
+
+ if (property.notifyIndex != -1) {
+ bool existing = false;
+ for (int jj = 0; !existing && jj < ii; ++jj)
+ existing = newGuardList[jj].data() == property.object &&
+ newGuardList[jj].notifyIndex == property.notifyIndex;
+
+ newGuardList[ii] = property.object;
+ newGuardList[ii].notifyIndex = property.notifyIndex;
+ if (existing)
+ newGuardList[ii].isDuplicate = true;
+ else
+ QMetaObject::connect(property.object, property.notifyIndex,
+ q, notifyIdx);
+ } else {
+ if (!outputWarningHeader) {
+ outputWarningHeader = true;
+ qWarning() << "QmlExpression: Expression" << q->expression()
+ << "depends on non-NOTIFYable properties:";
+ }
+
+ const QMetaObject *metaObj = property.object->metaObject();
+ QMetaProperty metaProp = metaObj->property(property.coreIndex);
+
+ qWarning().nospace() << " " << metaObj->className()
+ << "::" << metaProp.name();
+ }
+ } else if (newGuardList) {
+ newGuardList[ii] = data->guardList[ii];
+ }
+ }
+
+ 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 (data->guardList) delete [] data->guardList;
+ data->guardList = newGuardList;
+ data->guardListLength = properties.count();
+ }
+}
+
+/*!
+ \fn void QmlExpression::valueChanged()
+
+ Emitted each time the expression value changes from the last time it was
+ evaluated. The expression must have been evaluated at least once (by
+ calling QmlExpression::value()) before this signal will be emitted.
+*/
+
+QmlAbstractExpression::QmlAbstractExpression()
+: m_context(0), m_prevExpression(0), m_nextExpression(0)
+{
+}
+
+QmlAbstractExpression::~QmlAbstractExpression()
+{
+ if (m_prevExpression) {
+ *m_prevExpression = m_nextExpression;
+ if (m_nextExpression)
+ m_nextExpression->m_prevExpression = m_prevExpression;
+ }
+}
+
+QmlContext *QmlAbstractExpression::context() const
+{
+ return m_context;
+}
+
+void QmlAbstractExpression::setContext(QmlContext *context)
+{
+ if (m_prevExpression) {
+ *m_prevExpression = m_nextExpression;
+ if (m_nextExpression)
+ m_nextExpression->m_prevExpression = m_prevExpression;
+ m_prevExpression = 0;
+ m_nextExpression = 0;
+ }
+
+ m_context = context;
+
+ if (m_context) {
+ QmlContextPrivate *cp =
+ static_cast<QmlContextPrivate *>(QObjectPrivate::get(m_context));
+ m_nextExpression = cp->expressions;
+ if (m_nextExpression)
+ m_nextExpression->m_prevExpression = &m_nextExpression;
+ m_prevExpression = &cp->expressions;
+ cp->expressions = this;
+ }
+}
+
+bool QmlAbstractExpression::isValid() const
+{
+ return m_context != 0;
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/declarative/qml/qmlexpression.h b/src/declarative/qml/qmlexpression.h
new file mode 100644
index 0000000..96694d6
--- /dev/null
+++ b/src/declarative/qml/qmlexpression.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 QMLEXPRESSION_H
+#define QMLEXPRESSION_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QString;
+class QmlRefCount;
+class QmlEngine;
+class QmlContext;
+class QmlExpressionPrivate;
+class QmlBasicScript;
+class Q_DECLARATIVE_EXPORT QmlExpression : public QObject
+{
+ Q_OBJECT
+public:
+ QmlExpression();
+ QmlExpression(QmlContext *, const QString &, QObject *);
+ virtual ~QmlExpression();
+
+ QmlEngine *engine() const;
+ QmlContext *context() const;
+
+ QString expression() const;
+ void clearExpression();
+ virtual void setExpression(const QString &);
+ bool isConstant() const;
+
+ bool trackChange() const;
+ void setTrackChange(bool);
+
+ QUrl sourceFile() const;
+ int lineNumber() const;
+ void setSourceLocation(const QUrl &fileName, int line);
+
+ QObject *scopeObject() const;
+
+public Q_SLOTS:
+ QVariant value(bool *isUndefined = 0);
+
+Q_SIGNALS:
+ virtual void valueChanged();
+
+protected:
+ QmlExpression(QmlContext *, const QString &, QObject *,
+ QmlExpressionPrivate &dd);
+ QmlExpression(QmlContext *, void *, QmlRefCount *rc, QObject *me, const QUrl &,
+ int, QmlExpressionPrivate &dd);
+
+private Q_SLOTS:
+ void __q_notify();
+
+private:
+ Q_DECLARE_PRIVATE(QmlExpression)
+ friend class QmlDebugger;
+ friend class QmlContext;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLEXPRESSION_H
+
diff --git a/src/declarative/qml/qmlexpression_p.h b/src/declarative/qml/qmlexpression_p.h
new file mode 100644
index 0000000..3ec8d1c
--- /dev/null
+++ b/src/declarative/qml/qmlexpression_p.h
@@ -0,0 +1,159 @@
+/****************************************************************************
+**
+** 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 QMLEXPRESSION_P_H
+#define QMLEXPRESSION_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 "qmlbasicscript_p.h"
+#include "qmlexpression.h"
+#include "qmlengine_p.h"
+#include <private/qguard_p.h>
+#include <QtScript/qscriptvalue.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlAbstractExpression
+{
+public:
+ QmlAbstractExpression();
+ virtual ~QmlAbstractExpression();
+
+ bool isValid() const;
+
+ QmlContext *context() const;
+ void setContext(QmlContext *);
+
+private:
+ friend class QmlContext;
+ QmlContext *m_context;
+ QmlAbstractExpression **m_prevExpression;
+ QmlAbstractExpression *m_nextExpression;
+};
+
+class QmlExpressionData : public QmlAbstractExpression, public QmlRefCount
+{
+public:
+ QmlExpressionData();
+ ~QmlExpressionData();
+
+ QmlExpressionPrivate *q;
+
+ QString expression;
+ bool expressionFunctionValid:1;
+ bool expressionRewritten:1;
+ QScriptValue expressionFunction;
+
+ QmlBasicScript sse;
+ QObject *me;
+ bool trackChange;
+
+ QString fileName;
+ int line;
+
+ struct SignalGuard : public QGuard<QObject> {
+ SignalGuard() : isDuplicate(false), notifyIndex(-1) {}
+
+ SignalGuard &operator=(QObject *obj) {
+ QGuard<QObject>::operator=(obj);
+ return *this;
+ }
+ SignalGuard &operator=(const SignalGuard &o) {
+ QGuard<QObject>::operator=(o);
+ isDuplicate = o.isDuplicate;
+ notifyIndex = o.notifyIndex;
+ return *this;
+ }
+
+ bool isDuplicate:1;
+ int notifyIndex:31;
+ };
+ 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 *, const QUrl &, int);
+
+ QmlExpressionData *data;
+
+ QVariant value(QObject *secondaryScope = 0, bool *isUndefined = 0);
+ QVariant evalSSE();
+ QVariant evalQtScript(QObject *secondaryScope, bool *isUndefined = 0);
+
+ void updateGuards(const QPODVector<QmlEnginePrivate::CapturedProperty> &properties);
+ void clearGuards();
+
+ static QmlExpressionPrivate *get(QmlExpression *expr) {
+ return static_cast<QmlExpressionPrivate *>(QObjectPrivate::get(expr));
+ }
+
+ static void printException(QScriptEngine *);
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLEXPRESSION_P_H
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/qml/qmlglobalscriptclass_p.h b/src/declarative/qml/qmlglobalscriptclass_p.h
new file mode 100644
index 0000000..1b58f1e
--- /dev/null
+++ b/src/declarative/qml/qmlglobalscriptclass_p.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** 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 QMLGLOBALSCRIPTCLASS_P_H
+#define QMLGLOBALSCRIPTCLASS_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>
+
+QT_BEGIN_NAMESPACE
+
+class QmlGlobalScriptClass : public QScriptClass
+{
+public:
+ QmlGlobalScriptClass(QScriptEngine *);
+
+ 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);
+
+private:
+ QScriptValue globalObject;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLGLOBALSCRIPTCLASS_P_H
diff --git a/src/declarative/qml/qmlinfo.cpp b/src/declarative/qml/qmlinfo.cpp
new file mode 100644
index 0000000..119641f
--- /dev/null
+++ b/src/declarative/qml/qmlinfo.cpp
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** 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 "qmlinfo.h"
+#include <private/qmldeclarativedata_p.h>
+#include <QtDeclarative/qmlcontext.h>
+#include <QtGui/qapplication.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \fn void qmlInfo(const QString& message, QObject *object)
+
+ \brief Prints warnings messages that include the file and line number for QML types.
+
+ When QML types display warning messages, it improves tracibility
+ if they include the QML file and line number on which the
+ particular instance was instantiated.
+
+ To include the file and line number, an object must be passed. If
+ the file and line number is not available for that instance
+ (either it was not instantiated by the QML engine or location
+ information is disabled), "unknown location" will be used instead.
+
+ For example,
+
+ \code
+ qmlInfo(tr("component property is a write-once property"), object);
+ \endcode
+
+ prints
+
+ \code
+ QML ComponentInstance (unknown location): component property is a write-once property
+ \endcode
+*/
+
+void qmlInfo(const QString& msg, QObject* object)
+{
+ QString pos = QLatin1String("QML");
+ if (object) {
+ pos += QLatin1Char(' ');
+ pos += QLatin1String(object->metaObject()->className());
+ }
+ QmlDeclarativeData *ddata = QmlDeclarativeData::get(object);
+ pos += QLatin1String(" (");
+ if (ddata) {
+ if (ddata->outerContext) {
+ pos += ddata->outerContext->baseUrl().toString();
+ } else {
+ pos += qApp->translate("QmlInfo","unknown");
+ }
+ pos += QLatin1String(":");
+ pos += QString::number(ddata->lineNumber);
+ pos += QLatin1String(":");
+ pos += QString::number(ddata->columnNumber);
+ } else {
+ pos += qApp->translate("QmlInfo","unknown location");
+ }
+ pos += QLatin1String(") ");
+ qWarning((pos + msg).toLocal8Bit()); // XXX allow other processing?
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlinfo.h b/src/declarative/qml/qmlinfo.h
new file mode 100644
index 0000000..f2d17fe
--- /dev/null
+++ b/src/declarative/qml/qmlinfo.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** 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 QMLINFO_H
+#define QMLINFO_H
+
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+Q_DECLARATIVE_EXPORT void qmlInfo(const QString& msg, QObject *me=0);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLINFO_H
diff --git a/src/declarative/qml/qmlinstruction.cpp b/src/declarative/qml/qmlinstruction.cpp
new file mode 100644
index 0000000..a465445
--- /dev/null
+++ b/src/declarative/qml/qmlinstruction.cpp
@@ -0,0 +1,200 @@
+/****************************************************************************
+**
+** 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 "qmlinstruction_p.h"
+#include "qmlcompiler_p.h"
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+void QmlCompiledData::dump(QmlInstruction *instr, int idx)
+{
+ QByteArray lineNumber = QByteArray::number(instr->line);
+ if (instr->line == (unsigned short)-1)
+ lineNumber = "NA";
+ const char *line = lineNumber.constData();
+
+ switch(instr->type) {
+ case QmlInstruction::Init:
+ qWarning() << idx << "\t" << line << "\t" << "INIT";
+ break;
+ case QmlInstruction::CreateObject:
+ qWarning() << idx << "\t" << line << "\t" << "CREATE\t\t\t" << instr->create.type << "\t\t\t" << types.at(instr->create.type).className;
+ break;
+ case QmlInstruction::SetId:
+ qWarning() << idx << "\t" << line << "\t" << "SETID\t\t\t" << instr->setId.value << "\t\t\t\t" << primitives.at(instr->setId.value);
+ break;
+ case QmlInstruction::SetDefault:
+ qWarning() << idx << "\t" << line << "\t" << "SET_DEFAULT";
+ break;
+ case QmlInstruction::CreateComponent:
+ 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";
+ break;
+ case QmlInstruction::StoreFloat:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_FLOAT\t\t" << instr->storeFloat.propertyIndex << "\t" << instr->storeFloat.value;
+ break;
+ case QmlInstruction::StoreDouble:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_DOUBLE\t\t" << instr->storeDouble.propertyIndex << "\t" << instr->storeDouble.value;
+ break;
+ case QmlInstruction::StoreInteger:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_INTEGER\t\t" << instr->storeInteger.propertyIndex << "\t" << instr->storeInteger.value;
+ break;
+ case QmlInstruction::StoreBool:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_BOOL\t\t" << instr->storeBool.propertyIndex << "\t" << instr->storeBool.value;
+ break;
+ case QmlInstruction::StoreString:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_STRING\t\t" << instr->storeString.propertyIndex << "\t" << instr->storeString.value << "\t\t" << primitives.at(instr->storeString.value);
+ break;
+ case QmlInstruction::StoreUrl:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_URL\t\t" << instr->storeUrl.propertyIndex << "\t" << instr->storeUrl.value << "\t\t" << primitives.at(instr->storeUrl.value);
+ break;
+ case QmlInstruction::StoreColor:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_COLOR\t\t" << instr->storeColor.propertyIndex << "\t" << QString::number(instr->storeColor.value, 16);
+ break;
+ case QmlInstruction::StoreDate:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_DATE\t\t" << instr->storeDate.propertyIndex << "\t" << instr->storeDate.value;
+ break;
+ case QmlInstruction::StoreTime:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_TIME\t\t" << instr->storeTime.propertyIndex << "\t" << instr->storeTime.valueIndex;
+ break;
+ case QmlInstruction::StoreDateTime:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_DATETIME\t\t" << instr->storeDateTime.propertyIndex << "\t" << instr->storeDateTime.valueIndex;
+ break;
+ case QmlInstruction::StorePoint:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_POINT\t\t" << instr->storeRealPair.propertyIndex << "\t" << instr->storeRealPair.valueIndex;
+ break;
+ case QmlInstruction::StorePointF:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_POINTF\t\t" << instr->storeRealPair.propertyIndex << "\t" << instr->storeRealPair.valueIndex;
+ break;
+ case QmlInstruction::StoreSize:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_SIZE\t\t" << instr->storeRealPair.propertyIndex << "\t" << instr->storeRealPair.valueIndex;
+ break;
+ case QmlInstruction::StoreSizeF:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_SIZEF\t\t" << instr->storeRealPair.propertyIndex << "\t" << instr->storeRealPair.valueIndex;
+ break;
+ case QmlInstruction::StoreRect:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_RECT\t\t" << instr->storeRect.propertyIndex << "\t" << instr->storeRect.valueIndex;
+ break;
+ case QmlInstruction::StoreRectF:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_RECTF\t\t" << instr->storeRect.propertyIndex << "\t" << instr->storeRect.valueIndex;
+ break;
+ case QmlInstruction::StoreVector3D:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_VECTOR3D\t\t" << instr->storeVector3D.propertyIndex << "\t" << instr->storeVector3D.valueIndex;
+ break;
+ case QmlInstruction::StoreVariant:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_VARIANT\t\t" << instr->storeString.propertyIndex << "\t" << instr->storeString.value << "\t\t" << primitives.at(instr->storeString.value);
+ break;
+ case QmlInstruction::StoreObject:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_OBJECT\t\t" << instr->storeObject.propertyIndex;
+ break;
+ case QmlInstruction::StoreVariantObject:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_VARIANT_OBJECT\t" << instr->storeObject.propertyIndex;
+ break;
+ case QmlInstruction::StoreInterface:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_INTERFACE\t\t" << instr->storeObject.propertyIndex;
+ break;
+ case QmlInstruction::StoreSignal:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_SIGNAL\t\t" << instr->storeSignal.signalIndex << "\t" << instr->storeSignal.value << "\t\t" << primitives.at(instr->storeSignal.value);
+ break;
+ case QmlInstruction::AssignSignalObject:
+ qWarning() << idx << "\t" << line << "\t" << "ASSIGN_SIGNAL_OBJECT\t" << instr->assignSignalObject.signal << "\t\t\t" << datas.at(instr->assignSignalObject.signal);
+ break;
+ case QmlInstruction::AssignCustomType:
+ qWarning() << idx << "\t" << line << "\t" << "ASSIGN_CUSTOMTYPE\t\t" << instr->assignCustomType.propertyIndex << "\t" << instr->assignCustomType.valueIndex;
+ break;
+ case QmlInstruction::StoreBinding:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_COMPILED_BINDING\t" << instr->assignBinding.property << "\t" << instr->assignBinding.value << "\t\t" << instr->assignBinding.context;
+ break;
+ case QmlInstruction::StoreValueSource:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_VALUE_SOURCE\t" << instr->assignValueSource.property << "\t" << instr->assignValueSource.castValue;
+ break;
+ case QmlInstruction::StoreValueInterceptor:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_VALUE_INTERCEPTOR\t" << instr->assignValueInterceptor.property << "\t" << instr->assignValueInterceptor.castValue;
+ break;
+ case QmlInstruction::BeginObject:
+ qWarning() << idx << "\t" << line << "\t" << "BEGIN\t\t\t" << instr->begin.castValue;
+ break;
+ case QmlInstruction::StoreObjectQmlList:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_OBJECT_QMLLIST";
+ break;
+ case QmlInstruction::StoreObjectQList:
+ qWarning() << idx << "\t" << line << "\t" << "STORE_OBJECT_QLIST";
+ break;
+ case QmlInstruction::AssignObjectList:
+ qWarning() << idx << "\t" << line << "\t" << "ASSIGN_OBJECT_LIST\t";
+ break;
+ case QmlInstruction::FetchAttached:
+ qWarning() << idx << "\t" << line << "\t" << "FETCH_ATTACHED\t\t" << instr->fetchAttached.id;
+ break;
+ case QmlInstruction::FetchQmlList:
+ qWarning() << idx << "\t" << line << "\t" << "FETCH_QMLLIST\t\t" << instr->fetchQmlList.property << "\t" << instr->fetchQmlList.type;
+ break;
+ case QmlInstruction::FetchQList:
+ qWarning() << idx << "\t" << line << "\t" << "FETCH_QLIST\t\t" << instr->fetch.property;
+ break;
+ case QmlInstruction::FetchObject:
+ qWarning() << idx << "\t" << line << "\t" << "FETCH\t\t\t" << instr->fetch.property;
+ break;
+ case QmlInstruction::FetchValueType:
+ qWarning() << idx << "\t" << line << "\t" << "FETCH_VALUE\t\t" << instr->fetchValue.property << "\t" << instr->fetchValue.type;
+ break;
+ case QmlInstruction::PopFetchedObject:
+ qWarning() << idx << "\t" << line << "\t" << "POP";
+ break;
+ case QmlInstruction::PopQList:
+ qWarning() << idx << "\t" << line << "\t" << "POP_QLIST";
+ break;
+ case QmlInstruction::PopValueType:
+ qWarning() << idx << "\t" << line << "\t" << "POP_VALUE\t\t" << instr->fetchValue.property << "\t" << instr->fetchValue.type;
+ break;
+ case QmlInstruction::Defer:
+ qWarning() << idx << "\t" << line << "\t" << "DEFER" << "\t\t" << instr->defer.deferCount;
+ break;
+ default:
+ qWarning() << idx << "\t" << line << "\t" << "XXX UNKOWN INSTRUCTION" << "\t" << instr->type;
+ break;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h
new file mode 100644
index 0000000..dc18b05
--- /dev/null
+++ b/src/declarative/qml/qmlinstruction_p.h
@@ -0,0 +1,323 @@
+/****************************************************************************
+**
+** 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 QMLINSTRUCTION_P_H
+#define QMLINSTRUCTION_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 <QtDeclarative/qfxglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlCompiledData;
+class Q_DECLARATIVE_EXPORT QmlInstruction
+{
+public:
+ enum Type {
+ //
+ // Object Creation
+ //
+ // CreateObject - Create a new object instance and push it on the
+ // object stack
+ // SetId - Set the id of the object on the top of the object stack
+ // SetDefault - Sets the instance on the top of the object stack to
+ // be the context's default object.
+ // StoreMetaObject - Assign the dynamic metaobject to object on the
+ // top of the stack.
+ Init, /* init */
+ CreateObject, /* create */
+ SetId, /* setId */
+ SetDefault,
+ CreateComponent, /* createComponent */
+ StoreMetaObject, /* storeMeta */
+
+ //
+ // Precomputed single assignment
+ //
+ // StoreFloat - Store a float in a core property
+ // StoreDouble - Store a double in a core property
+ // StoreInteger - Store a int or uint in a core property
+ // StoreBool - Store a bool in a core property
+ // StoreString - Store a QString in a core property
+ // StoreUrl - Store a QUrl in a core property
+ // StoreColor - Store a QColor in a core property
+ // StoreDate - Store a QDate in a core property
+ // StoreTime - Store a QTime in a core property
+ // StoreDateTime - Store a QDateTime in a core property
+ // StoreVariant - Store a QVariant in a core property
+ // StoreObject - Pop the object on the top of the object stack and
+ // store it in a core property
+ StoreFloat, /* storeFloat */
+ StoreDouble, /* storeDouble */
+ StoreInteger, /* storeInteger */
+ StoreBool, /* storeBool */
+ StoreString, /* storeString */
+ StoreUrl, /* storeUrl */
+ StoreColor, /* storeColor */
+ StoreDate, /* storeDate */
+ StoreTime, /* storeTime */
+ StoreDateTime, /* storeDateTime */
+ StorePoint, /* storeRealPair */
+ StorePointF, /* storeRealPair */
+ StoreSize, /* storeRealPair */
+ StoreSizeF, /* storeRealPair */
+ StoreRect, /* storeRect */
+ StoreRectF, /* storeRect */
+ StoreVector3D, /* storeVector3D */
+ StoreVariant, /* storeString */
+ StoreObject, /* storeObject */
+ StoreVariantObject, /* storeObject */
+ StoreInterface, /* storeObject */
+
+ StoreSignal, /* storeSignal */
+ StoreScript, /* storeScript */
+ StoreScriptString, /* storeScriptString */
+
+ //
+ // Unresolved single assignment
+ //
+ AssignSignalObject, /* assignSignalObject */
+ AssignCustomType, /* assignCustomType */
+
+ StoreBinding, /* assignBinding */
+ StoreIdOptBinding, /* assignIdOptBinding */
+ StoreObjPropBinding, /* assignObjPropBinding */
+ StoreValueSource, /* assignValueSource */
+ StoreValueInterceptor, /* assignValueInterceptor */
+
+ BeginObject, /* begin */
+
+ StoreObjectQmlList, /* NA */
+ StoreObjectQList, /* NA */
+ AssignObjectList, /* NA */
+
+ FetchAttached, /* fetchAttached */
+ FetchQmlList, /* fetchQmlList */
+ FetchQList, /* fetch */
+ FetchObject, /* fetch */
+ FetchValueType, /* fetchValue */
+
+ //
+ // Stack manipulation
+ //
+ // PopFetchedObject - Remove an object from the object stack
+ // PopQList - Remove a list from the list stack
+ PopFetchedObject,
+ PopQList,
+ PopValueType, /* fetchValue */
+
+ //
+ // Deferred creation
+ //
+ Defer, /* defer */
+ };
+ QmlInstruction()
+ : line(0) {}
+
+ Type type;
+ unsigned short line;
+ union {
+ struct {
+ int bindingsSize;
+ int parserStatusSize;
+ int contextCache;
+ } init;
+ struct {
+ int type;
+ int data;
+ int bindingBits;
+ ushort column;
+ } create;
+ struct {
+ int data;
+ int aliasData;
+ int propertyCache;
+ } storeMeta;
+ struct {
+ int value;
+ int index;
+ } setId;
+ struct {
+ int property;
+ int owner;
+ int castValue;
+ } assignValueSource;
+ struct {
+ int property;
+ int owner;
+ int castValue;
+ } assignValueInterceptor; //### merge with above
+ struct {
+ int property;
+ int value;
+ short context;
+ short owner;
+ } assignBinding;
+ struct {
+ int property;
+ int id;
+ } assignIdOptBinding;
+ struct {
+ int property;
+ int contextIdx;
+ short context;
+ short notifyIdx;
+ } assignObjPropBinding;
+ struct {
+ int property;
+ } fetch;
+ struct {
+ int property;
+ int type;
+ } fetchValue;
+ struct {
+ int property;
+ int type;
+ } fetchQmlList;
+ struct {
+ int castValue;
+ } begin;
+ struct {
+ int propertyIndex;
+ float value;
+ } storeFloat;
+ struct {
+ int propertyIndex;
+ double value;
+ } storeDouble;
+ struct {
+ int propertyIndex;
+ int value;
+ } storeInteger;
+ struct {
+ int propertyIndex;
+ bool value;
+ } storeBool;
+ struct {
+ int propertyIndex;
+ int value;
+ } storeString;
+ struct {
+ int propertyIndex;
+ int value;
+ int scope;
+ } storeScriptString;
+ struct {
+ int value;
+ int fileName;
+ int lineNumber;
+ } storeScript;
+ struct {
+ int propertyIndex;
+ int value;
+ } storeUrl;
+ struct {
+ int propertyIndex;
+ unsigned int value;
+ } storeColor;
+ struct {
+ int propertyIndex;
+ int value;
+ } storeDate;
+ struct {
+ int propertyIndex;
+ int valueIndex;
+ } storeTime;
+ struct {
+ int propertyIndex;
+ int valueIndex;
+ } storeDateTime;
+ struct {
+ int propertyIndex;
+ int valueIndex;
+ } storeRealPair;
+ struct {
+ int propertyIndex;
+ int valueIndex;
+ } storeRect;
+ struct {
+ int propertyIndex;
+ int valueIndex;
+ } storeVector3D;
+ struct {
+ int propertyIndex;
+ } storeObject;
+ struct {
+ int propertyIndex;
+ int valueIndex;
+ } assignCustomType;
+ struct {
+ int signalIndex;
+ int value;
+ } storeSignal;
+ struct {
+ int signal;
+ } assignSignalObject;
+ struct {
+ int count;
+ ushort column;
+ int endLine;
+ int metaObject;
+ } createComponent;
+ struct {
+ int id;
+ } fetchAttached;
+ struct {
+ int deferCount;
+ } defer;
+ };
+
+ void dump(QmlCompiledData *);
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLINSTRUCTION_P_H
diff --git a/src/declarative/qml/qmlintegercache.cpp b/src/declarative/qml/qmlintegercache.cpp
new file mode 100644
index 0000000..06955c7
--- /dev/null
+++ b/src/declarative/qml/qmlintegercache.cpp
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** 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)
+: QmlCleanup(e), engine(e)
+{
+}
+
+QmlIntegerCache::~QmlIntegerCache()
+{
+ clear();
+}
+
+void QmlIntegerCache::clear()
+{
+ qDeleteAll(stringCache);
+ stringCache.clear();
+ identifierCache.clear();
+ engine = 0;
+}
+
+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 = QString::fromUtf8(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..6e9fadd
--- /dev/null
+++ b/src/declarative/qml/qmlintegercache_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 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 <private/qmlcleanup_p.h>
+#include <QtCore/qhash.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlType;
+class QmlEngine;
+class QmlIntegerCache : public QmlRefCount, public QmlCleanup
+{
+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 *);
+
+protected:
+ virtual void clear();
+
+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/qmllist.h b/src/declarative/qml/qmllist.h
new file mode 100644
index 0000000..80c3138
--- /dev/null
+++ b/src/declarative/qml/qmllist.h
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** 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 QMLLIST_H
+#define QMLLIST_H
+
+#include <QtDeclarative/qmlprivate.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+template<typename T>
+class QmlList : private QmlPrivate::ListInterface
+{
+public:
+ virtual void append(T) = 0;
+ virtual void insert(int, T) = 0;
+ virtual void removeAt(int) = 0;
+ virtual T at(int) const = 0;
+ virtual int count() const = 0;
+ virtual void clear() = 0;
+ QmlList<T> &operator<<(T t) { append(t); return *this; }
+
+protected:
+ virtual int type() const { return qMetaTypeId<T>(); }
+ virtual void append(void *d) { const T &v = *(T *)d; append(v); }
+ virtual void insert(int i, void *d) { const T &v = *(T *)d; insert(i, v); }
+ virtual void at(int i, void *p) const { const T &v = at(i); *((T*)p) = v; }
+};
+
+template<typename T>
+class QmlConcreteList : public QList<T>, public QmlList<T>
+{
+public:
+ virtual void append(T v) { QList<T>::append(v); }
+ virtual void insert(int i, T v) { QList<T>::insert(i, v); }
+ virtual void clear() { QList<T>::clear(); }
+ virtual T at(int i) const { return QList<T>::at(i); }
+ virtual void removeAt(int i) { QList<T>::removeAt(i); }
+ virtual int count() const { return QList<T>::count(); }
+};
+
+#define QML_DECLARE_LIST_PROXY(ClassName, ListType, ListName) \
+class Qml_ProxyList_ ##ListName : public QmlList<ListType> \
+{ \
+ public: \
+ virtual void removeAt(int idx) \
+ { \
+ ClassName *p = (ClassName *)((char *)this + ((char *)(ClassName *)(0x10000000) - (char *)&((ClassName *)(0x10000000))->ListName)); \
+ p->ListName ## _removeAt(idx); \
+ } \
+ virtual int count() const \
+ { \
+ ClassName *p = (ClassName *)((char *)this + ((char *)(ClassName *)(0x10000000) - (char *)&((ClassName *)(0x10000000))->ListName)); \
+ return p->ListName ## _count(); \
+ } \
+ virtual void append(ListType v) \
+ { \
+ ClassName *p = (ClassName *)((char *)this + ((char *)(ClassName *)(0x10000000) - (char *)&((ClassName *)(0x10000000))->ListName)); \
+ p->ListName ## _append(v); \
+ } \
+ virtual void insert(int idx, ListType v) \
+ { \
+ ClassName *p = (ClassName *)((char *)this + ((char *)(ClassName *)(0x10000000) - (char *)&((ClassName *)(0x10000000))->ListName)); \
+ p->ListName ## _insert(idx, v); \
+ } \
+ virtual ListType at(int idx) const \
+ { \
+ ClassName *p = (ClassName *)((char *)this + ((char *)(ClassName *)(0x10000000) - (char *)&((ClassName *)(0x10000000))->ListName)); \
+ return p->ListName ## _at(idx); \
+ } \
+ virtual void clear() \
+ { \
+ ClassName *p = (ClassName *)((char *)this + ((char *)(ClassName *)(0x10000000) - (char *)&((ClassName *)(0x10000000))->ListName)); \
+ p->ListName ## _clear(); \
+ } \
+}; \
+friend class Qml_ProxyList_ ##ListName ; \
+Qml_ProxyList_##ListName ListName;
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLLIST_H
diff --git a/src/declarative/qml/qmllistscriptclass.cpp b/src/declarative/qml/qmllistscriptclass.cpp
new file mode 100644
index 0000000..09bde8c
--- /dev/null
+++ b/src/declarative/qml/qmllistscriptclass.cpp
@@ -0,0 +1,141 @@
+/****************************************************************************
+**
+** 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 "qmllistscriptclass_p.h"
+#include <private/qmlengine_p.h>
+
+QT_BEGIN_NAMESPACE
+
+struct ListData : public QScriptDeclarativeClass::Object {
+ QGuard<QObject> object;
+ int propertyIdx;
+ QmlListScriptClass::ListType type;
+};
+
+QmlListScriptClass::QmlListScriptClass(QmlEngine *e)
+: QScriptDeclarativeClass(QmlEnginePrivate::getScriptEngine(e)), engine(e)
+{
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+
+ m_lengthId = createPersistentIdentifier(QLatin1String("length"));
+}
+
+QmlListScriptClass::~QmlListScriptClass()
+{
+}
+
+QScriptValue QmlListScriptClass::newList(QObject *object, int propId, ListType type)
+{
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+
+ if (!object || propId == -1)
+ return scriptEngine->nullValue();
+
+ ListData *data = new ListData;
+ data->object = object;
+ data->propertyIdx = propId;
+ data->type = type;
+
+ return newObject(scriptEngine, this, data);
+}
+
+QScriptClass::QueryFlags
+QmlListScriptClass::queryProperty(Object *object, const Identifier &name,
+ QScriptClass::QueryFlags flags)
+{
+ if (name == m_lengthId.identifier)
+ return QScriptClass::HandlesReadAccess;
+
+ bool ok = false;
+ quint32 idx = toArrayIndex(name, &ok);
+
+ if (ok) {
+ lastIndex = idx;
+ return QScriptClass::HandlesReadAccess;
+ } else {
+ return 0;
+ }
+}
+
+QScriptValue QmlListScriptClass::property(Object *obj, const Identifier &name)
+{
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+ QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine);
+
+ ListData *data = (ListData *)obj;
+ if (!data->object)
+ return scriptEngine->undefinedValue();
+
+ void *list = 0;
+ void *args[] = { &list, 0 };
+ QMetaObject::metacall(data->object, QMetaObject::ReadProperty,
+ data->propertyIdx, args);
+
+ if (!list)
+ return scriptEngine->undefinedValue();
+
+ if (data->type == QListPtr) {
+ const QList<QObject *> &qlist = *((QList<QObject *>*)list);
+
+ if (name == m_lengthId.identifier)
+ return qlist.count();
+ else if (lastIndex < qlist.count())
+ return enginePriv->objectClass->newQObject(qlist.at(lastIndex));
+ else
+ return scriptEngine->undefinedValue();
+
+ } else {
+ Q_ASSERT(data->type == QmlListPtr);
+ const QmlList<QObject *> &qmllist = *((QmlList<QObject *>*)list);
+
+ int count = qmllist.count();
+
+ if (name == m_lengthId.identifier)
+ return count;
+ else if (lastIndex < count)
+ return enginePriv->objectClass->newQObject(qmllist.at(lastIndex));
+ else
+ return scriptEngine->undefinedValue();
+ }
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/declarative/qml/qmllistscriptclass_p.h b/src/declarative/qml/qmllistscriptclass_p.h
new file mode 100644
index 0000000..7592098
--- /dev/null
+++ b/src/declarative/qml/qmllistscriptclass_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** 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 QMLLISTSCRIPTCLASS_P_H
+#define QMLLISTSCRIPTCLASS_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/qscriptdeclarativeclass_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlEngine;
+class QmlListScriptClass : public QScriptDeclarativeClass
+{
+public:
+ QmlListScriptClass(QmlEngine *);
+ ~QmlListScriptClass();
+
+ enum ListType { QListPtr, QmlListPtr };
+ QScriptValue newList(QObject *, int, ListType);
+
+protected:
+ virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &,
+ QScriptClass::QueryFlags flags);
+ virtual QScriptValue property(Object *, const Identifier &);
+
+private:
+ PersistentIdentifier m_lengthId;
+ QmlEngine *engine;
+
+ quint32 lastIndex;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLLISTSCRIPTCLASS_P_H
+
diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp
new file mode 100644
index 0000000..edec988
--- /dev/null
+++ b/src/declarative/qml/qmlmetaproperty.cpp
@@ -0,0 +1,1254 @@
+/****************************************************************************
+**
+** 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 "qmlmetaproperty.h"
+#include "qmlmetaproperty_p.h"
+#include "qmlcompositetypedata_p.h"
+#include <qml.h>
+#include <private/qfxperf_p.h>
+#include <QStringList>
+#include "qmlbinding.h"
+#include <qmlcontext.h>
+#include "qmlboundsignal_p.h"
+#include <math.h>
+#include <QtCore/qdebug.h>
+#include <QtDeclarative/qmlengine.h>
+#include <private/qmlengine_p.h>
+#include <private/qmldeclarativedata_p.h>
+
+Q_DECLARE_METATYPE(QList<QObject *>);
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QmlMetaProperty
+ \brief The QmlMetaProperty class abstracts accessing QML properties.
+ \internal
+ */
+
+/*!
+ Create an invalid QmlMetaProperty.
+*/
+QmlMetaProperty::QmlMetaProperty()
+: d(new QmlMetaPropertyPrivate)
+{
+ d->q = this;
+}
+
+/*! \internal */
+QmlMetaProperty::~QmlMetaProperty()
+{
+ delete d; d = 0;
+}
+
+/*!
+ Creates a QmlMetaProperty for the default property of \a obj. If there is no
+ default property, an invalid QmlMetaProperty will be created.
+ */
+QmlMetaProperty::QmlMetaProperty(QObject *obj)
+: d(new QmlMetaPropertyPrivate)
+{
+ d->q = this;
+ d->initDefault(obj);
+}
+
+/*!
+ \internal
+ Creates a QmlMetaProperty for the default property of \a obj. If there is no
+ default property, an invalid QmlMetaProperty will be created.
+ */
+QmlMetaProperty::QmlMetaProperty(QObject *obj, QmlContext *ctxt)
+: d(new QmlMetaPropertyPrivate)
+{
+ d->q = this;
+ d->context = ctxt;
+ d->initDefault(obj);
+}
+
+/*!
+ Initialize from the default property of \a obj
+*/
+void QmlMetaPropertyPrivate::initDefault(QObject *obj)
+{
+ if (!obj)
+ return;
+
+ object = obj;
+ QMetaProperty p = QmlMetaType::defaultProperty(obj);
+ core.load(p);
+ if (core.isValid())
+ isDefaultProperty = true;
+}
+
+/*!
+ \internal
+
+ Creates a QmlMetaProperty for the property at index \a idx of \a 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->core.load(obj->metaObject()->property(idx));
+}
+
+/*!
+ Creates a QmlMetaProperty for the property \a name of \a obj.
+ */
+QmlMetaProperty::QmlMetaProperty(QObject *obj, const QString &name)
+: d(new QmlMetaPropertyPrivate)
+{
+ d->q = this;
+ d->initProperty(obj, name);
+}
+
+/*!
+ \internal
+ Creates a QmlMetaProperty for the property \a name of \a obj.
+ */
+QmlMetaProperty::QmlMetaProperty(QObject *obj, const QString &name, QmlContext *ctxt)
+: d(new QmlMetaPropertyPrivate)
+{
+ d->q = this;
+ d->context = ctxt;
+ d->initProperty(obj, name);
+}
+
+void QmlMetaPropertyPrivate::initProperty(QObject *obj, const QString &name)
+{
+ QmlEnginePrivate *enginePrivate = 0;
+ if (context && context->engine())
+ enginePrivate = QmlEnginePrivate::get(context->engine());
+
+ object = obj;
+
+ if (name.isEmpty() || !obj)
+ return;
+
+ if (enginePrivate && name.at(0).isUpper()) {
+ // Attached property
+ //### needs to be done in a better way
+ QmlCompositeTypeData *typeData =
+ enginePrivate->typeManager.get(context->baseUrl());
+
+ if (typeData) {
+ QmlType *t = 0;
+ enginePrivate->resolveType(typeData->imports, name.toUtf8(), &t, 0, 0, 0, 0);
+ if (t && t->attachedPropertiesFunction()) {
+ attachedFunc = t->index();
+ }
+ typeData->release();
+ }
+ return;
+
+ } else if (name.count() >= 3 &&
+ name.at(0) == QChar(QLatin1Char('o')) &&
+ name.at(1) == QChar(QLatin1Char('n')) &&
+ name.at(2).isUpper()) {
+ // Signal
+ QString signalName = name.mid(2);
+ signalName[0] = signalName.at(0).toLower();
+
+ QMetaMethod method = findSignal(obj, signalName);
+ if (method.signature()) {
+ core.load(method);
+ return;
+ }
+ }
+
+ // Property
+ QmlPropertyCache *cache = 0;
+ QmlDeclarativeData *ddata = QmlDeclarativeData::get(obj);
+ if (ddata)
+ cache = ddata->propertyCache;
+ if (!cache)
+ cache = enginePrivate?enginePrivate->cache(obj):0;
+
+ if (cache) {
+ QmlPropertyCache::Data *data = cache->property(name);
+
+ if (data && !(data->flags & QmlPropertyCache::Data::IsFunction))
+ core = *data;
+
+ } else {
+ // No cache available
+ QMetaProperty p = QmlMetaType::property(obj, name.toUtf8().constData());
+ core.load(p);
+ }
+}
+
+/*!
+ Create a copy of \a other.
+*/
+QmlMetaProperty::QmlMetaProperty(const QmlMetaProperty &other)
+: d(new QmlMetaPropertyPrivate(*other.d))
+{
+ d->q = this;
+}
+
+/*!
+ \enum QmlMetaProperty::PropertyCategory
+
+ This enum specifies a category of QML property.
+
+ \value Unknown The category is unknown. This will never be returned from propertyCategory()
+ \value InvalidProperty The property is invalid.
+ \value Bindable The property is a QmlBinding.
+ \value List The property is a QList pointer
+ \value QmlList The property is a QmlList pointer
+ \value Object The property is a QObject derived type pointer
+ \value Normal The property is none of the above.
+ */
+
+/*!
+ \enum QmlMetaProperty::Type
+
+ This enum specifies a type of QML property.
+
+ \value Invalid The property is invalid.
+ \value Property The property is a regular Qt property.
+ \value SignalProperty The property is a signal property.
+ \value Default The property is the default property.
+ \value Attached The property is an attached property.
+*/
+
+/*!
+ Returns the property category.
+*/
+QmlMetaProperty::PropertyCategory QmlMetaProperty::propertyCategory() const
+{
+ return d->propertyCategory();
+}
+
+QmlMetaProperty::PropertyCategory
+QmlMetaPropertyPrivate::propertyCategory() const
+{
+ 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 == QVariant::Invalid)
+ return QmlMetaProperty::InvalidProperty;
+ else if ((uint)type < QVariant::UserType)
+ return QmlMetaProperty::Normal;
+ else if (type == qMetaTypeId<QmlBinding *>())
+ 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;
+ }
+}
+
+/*!
+ Returns the type name of the property, or 0 if the property has no type
+ name.
+*/
+const char *QmlMetaProperty::propertyTypeName() const
+{
+ 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;
+ }
+}
+
+/*!
+ Returns true if \a other and this QmlMetaProperty represent the same
+ property.
+*/
+bool QmlMetaProperty::operator==(const QmlMetaProperty &other) const
+{
+ // 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;
+}
+
+/*!
+ Returns the QVariant type of the property, or QVariant::Invalid if the
+ property has no QVariant type.
+*/
+int QmlMetaProperty::propertyType() const
+{
+ return d->propertyType();
+}
+
+int QmlMetaPropertyPrivate::propertyType() const
+{
+ 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
+ return core.propType;
+ } else {
+ return QVariant::Invalid;
+ }
+}
+
+/*!
+ Returns the type of the property.
+*/
+QmlMetaProperty::Type QmlMetaProperty::type() const
+{
+ 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;
+}
+
+/*!
+ Returns true if this QmlMetaProperty represents a regular Qt property.
+*/
+bool QmlMetaProperty::isProperty() const
+{
+ return type() & Property;
+}
+
+/*!
+ Returns true if this QmlMetaProperty represents a default property.
+*/
+bool QmlMetaProperty::isDefault() const
+{
+ return type() & Default;
+}
+
+/*!
+ Returns the QmlMetaProperty's QObject.
+*/
+QObject *QmlMetaProperty::object() const
+{
+ return d->object;
+}
+
+/*!
+ Assign \a other to this QmlMetaProperty.
+*/
+QmlMetaProperty &QmlMetaProperty::operator=(const QmlMetaProperty &other)
+{
+ d->context = other.d->context;
+ d->object = other.d->object;
+
+ 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;
+}
+
+/*!
+ Returns true if the property is writable, otherwise false.
+*/
+bool QmlMetaProperty::isWritable() const
+{
+ QmlMetaProperty::PropertyCategory category = propertyCategory();
+
+ if (category == List || category == QmlList)
+ return true;
+ else if (type() & SignalProperty)
+ return true;
+ else if (d->core.isValid() && d->object)
+ return d->object->metaObject()->property(d->core.coreIndex).isWritable();
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property is designable, otherwise false.
+*/
+bool QmlMetaProperty::isDesignable() const
+{
+ if (type() & Property && d->core.isValid() && d->object)
+ return d->object->metaObject()->property(d->core.coreIndex).isDesignable();
+ else
+ return false;
+}
+
+/*!
+ Returns true if the QmlMetaProperty refers to a valid property, otherwise
+ false.
+*/
+bool QmlMetaProperty::isValid() const
+{
+ return type() != Invalid;
+}
+
+/*!
+ Returns all of \a obj's Qt properties.
+*/
+QStringList QmlMetaProperty::properties(QObject *obj)
+{
+ // ### What is this used for?
+ if (!obj)
+ return QStringList();
+
+ QStringList rv;
+ const QMetaObject *mo = obj->metaObject();
+ for (int ii = 0; ii < mo->propertyCount(); ++ii) {
+ QMetaProperty prop = mo->property(ii);
+ rv << QString::fromUtf8(prop.name());
+ }
+
+ return rv;
+}
+
+/*!
+ Return the name of this QML property.
+*/
+QString QmlMetaProperty::name() const
+{
+ 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 += QString::fromUtf8(valueType->metaObject()->property(d->valueTypeCoreIdx).name());
+
+ if (!ep) delete valueType;
+
+ return rv;
+ } else {
+ return d->core.name;
+ }
+}
+
+/*!
+ Returns the \l{QMetaProperty} {Qt property} associated with
+ this QML property.
+ */
+QMetaProperty QmlMetaProperty::property() const
+{
+ 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.
+*/
+QmlAbstractBinding *QmlMetaProperty::binding() const
+{
+ if (!isProperty() || (type() & Attached) || !d->object)
+ return 0;
+
+ QmlDeclarativeData *data = QmlDeclarativeData::get(d->object);
+ if (!data)
+ return 0;
+
+ if (!data->hasBindingBit(d->core.coreIndex))
+ return 0;
+
+ QmlAbstractBinding *binding = data->bindings;
+ while (binding) {
+ // ### This wont work for value types
+ if (binding->propertyIndex() == d->core.coreIndex)
+ return binding;
+ binding = binding->m_nextBinding;
+ }
+ return 0;
+}
+
+/*!
+ Set the binding associated with this property to \a newBinding. Returns
+ the existing binding (if any), otherwise 0.
+
+ \a newBinding will be enabled, and the returned binding (if any) will be
+ disabled.
+
+ Ownership of \a newBinding transfers to QML. Ownership of the return value
+ is assumed by the caller.
+*/
+QmlAbstractBinding *
+QmlMetaProperty::setBinding(QmlAbstractBinding *newBinding, QmlMetaProperty::WriteFlags flags) const
+{
+ if (!isProperty() || (type() & Attached) || !d->object)
+ return 0;
+
+ return d->setBinding(d->object, d->core, newBinding, flags);
+}
+
+QmlAbstractBinding *
+QmlMetaPropertyPrivate::setBinding(QObject *object, const QmlPropertyCache::Data &core,
+ QmlAbstractBinding *newBinding, QmlMetaProperty::WriteFlags flags)
+{
+ QmlDeclarativeData *data = QmlDeclarativeData::get(object, 0 != newBinding);
+
+ if (data && data->hasBindingBit(core.coreIndex)) {
+ QmlAbstractBinding *binding = data->bindings;
+ while (binding) {
+ // ### This wont work for value types
+ if (binding->propertyIndex() == core.coreIndex) {
+ binding->setEnabled(false);
+
+ if (newBinding)
+ newBinding->setEnabled(true, flags);
+
+ return binding; // ### QmlAbstractBinding;
+ }
+
+ binding = binding->m_nextBinding;
+ }
+ }
+
+ if (newBinding)
+ newBinding->setEnabled(true, flags);
+
+ return 0;
+}
+/*!
+ Returns the expression associated with this signal property, or 0 if no
+ signal expression exists.
+*/
+QmlExpression *QmlMetaProperty::signalExpression() const
+{
+ if (!(type() & SignalProperty))
+ return 0;
+
+ const QObjectList &children = d->object->children();
+
+ for (int ii = 0; ii < children.count(); ++ii) {
+ QObject *child = children.at(ii);
+
+ QmlBoundSignal *signal = QmlBoundSignal::cast(child);
+ if (signal && signal->index() == coreIndex())
+ return signal->expression();
+ }
+
+ return 0;
+}
+
+/*!
+ Set the signal expression associated with this signal property to \a expr.
+ Returns the existing signal expression (if any), otherwise 0.
+
+ Ownership of \a expr transfers to QML. Ownership of the return value is
+ assumed by the caller.
+*/
+QmlExpression *QmlMetaProperty::setSignalExpression(QmlExpression *expr) const
+{
+ if (!(type() & SignalProperty))
+ return 0;
+
+ const QObjectList &children = d->object->children();
+
+ for (int ii = 0; ii < children.count(); ++ii) {
+ QObject *child = children.at(ii);
+
+ QmlBoundSignal *signal = QmlBoundSignal::cast(child);
+ if (signal && signal->index() == coreIndex())
+ return signal->setExpression(expr);
+ }
+
+ if (expr) {
+ QmlBoundSignal *signal = new QmlBoundSignal(d->object, method(), d->object);
+ return signal->setExpression(expr);
+ } else {
+ return 0;
+ }
+}
+
+QMetaMethod QmlMetaPropertyPrivate::findSignal(QObject *obj, const QString &name)
+{
+ const QMetaObject *mo = obj->metaObject();
+
+ int methods = mo->methodCount();
+ for (int ii = methods - 1; ii >= 0; --ii) {
+ QMetaMethod method = mo->method(ii);
+ QString methodName = QString::fromUtf8(method.signature());
+ int idx = methodName.indexOf(QLatin1Char('('));
+ methodName = methodName.left(idx);
+
+ if (methodName == name)
+ return method;
+ }
+ return QMetaMethod();
+}
+
+QObject *QmlMetaPropertyPrivate::attachedObject() const
+{
+ if (attachedFunc == -1)
+ return 0;
+ else
+ return qmlAttachedPropertiesObjectById(attachedFunc, object);
+}
+
+/*!
+ Returns the property value.
+*/
+QVariant QmlMetaProperty::read() const
+{
+ if (!d->object)
+ return QVariant();
+
+ if (type() & SignalProperty) {
+
+ const QObjectList &children = object()->children();
+
+ for (int ii = 0; ii < children.count(); ++ii) {
+ QmlBoundSignal *sig = QmlBoundSignal::cast(children.at(ii));
+ if (sig && sig->index() == d->core.coreIndex)
+ return sig->expression()->expression();
+ }
+
+ } else if (type() & Property) {
+
+ return d->readValueProperty();
+
+ }
+ return QVariant();
+}
+
+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());
+
+ }
+}
+
+//###
+//writeEnumProperty MIRRORS the relelvant bit of QMetaProperty::write AND MUST BE KEPT IN SYNC!
+//###
+bool QmlMetaPropertyPrivate::writeEnumProperty(const QMetaProperty &prop, int idx, QObject *object, const QVariant &value, int flags)
+{
+ if (!object || !prop.isWritable())
+ return false;
+
+ QVariant v = value;
+ if (prop.isEnumType()) {
+ QMetaEnum menum = prop.enumerator();
+ if (v.type() == QVariant::String
+#ifdef QT3_SUPPORT
+ || v.type() == QVariant::CString
+#endif
+ ) {
+ if (prop.isFlagType())
+ v = QVariant(menum.keysToValue(value.toByteArray()));
+ else
+ v = QVariant(menum.keyToValue(value.toByteArray()));
+ } else if (v.type() != QVariant::Int && v.type() != QVariant::UInt) {
+ int enumMetaTypeId = QMetaType::type(QByteArray(menum.scope()) + "::" + menum.name());
+ if ((enumMetaTypeId == 0) || (v.userType() != enumMetaTypeId) || !v.constData())
+ return false;
+ v = QVariant(*reinterpret_cast<const int *>(v.constData()));
+ }
+ v.convert(QVariant::Int);
+ }
+
+ // the status variable is changed by qt_metacall to indicate what it did
+ // this feature is currently only used by QtDBus and should not be depended
+ // upon. Don't change it without looking into QDBusAbstractInterface first
+ // -1 (unchanged): normal qt_metacall, result stored in argv[0]
+ // changed: result stored directly in value, return the value of status
+ int status = -1;
+ void *argv[] = { v.data(), &v, &status, &flags };
+ QMetaObject::metacall(object, QMetaObject::WriteProperty, idx, argv);
+ return status;
+}
+
+bool QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value,
+ QmlMetaProperty::WriteFlags flags)
+{
+ // Remove any existing bindings on this property
+ if (!(flags & QmlMetaProperty::DontRemoveBinding))
+ delete q->setBinding(0);
+
+ bool rv = false;
+ uint type = q->type();
+ if (type & QmlMetaProperty::ValueTypeProperty) {
+ QmlEnginePrivate *ep =
+ context?static_cast<QmlEnginePrivate *>(QObjectPrivate::get(context->engine())):0;
+
+ QmlValueType *writeBack = 0;
+ if (ep) {
+ writeBack = ep->valueTypes[core.propType];
+ } else {
+ writeBack = QmlValueTypeFactory::valueType(core.propType);
+ }
+
+ writeBack->read(object, core.coreIndex);
+
+ QmlPropertyCache::Data data = core;
+ data.coreIndex = valueTypeCoreIdx;
+ data.propType = valueTypePropType;
+ rv = write(writeBack, data, value, context, flags);
+
+ writeBack->write(object, core.coreIndex, flags);
+ if (!ep) delete writeBack;
+
+ } else {
+
+ rv = write(object, core, value, context, flags);
+
+ }
+
+ return rv;
+}
+
+bool QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data &property,
+ const QVariant &value, QmlContext *context,
+ QmlMetaProperty::WriteFlags flags)
+{
+ int coreIdx = property.coreIndex;
+ int status = -1; //for dbus
+
+ if (property.flags & QmlPropertyCache::Data::IsEnumType) {
+ QMetaProperty prop = object->metaObject()->property(property.coreIndex);
+ QVariant v = value;
+ // 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))
+ v.convert(QVariant::Int);
+ }
+ return writeEnumProperty(prop, coreIdx, object, v, flags);
+ }
+
+ int t = property.propType;
+ int vt = value.userType();
+
+ QmlEnginePrivate *enginePriv = 0;
+ if (context && context->engine())
+ enginePriv = QmlEnginePrivate::get(context->engine());
+
+ 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(QString::fromUtf8(value.toByteArray()));
+ found = true;
+ } else if (vt == QVariant::String) {
+ u = QUrl(value.toString());
+ found = true;
+ }
+
+ if (!found)
+ return false;
+
+ if (context && u.isRelative() && !u.isEmpty())
+ u = context->baseUrl().resolved(u);
+ int status = -1;
+ void *argv[] = { &u, 0, &status, &flags };
+ QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, argv);
+
+ } else if (vt == t) {
+
+ void *a[] = { (void *)value.constData(), 0, &status, &flags };
+ QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a);
+
+ } else if (qMetaTypeId<QVariant>() == t) {
+
+ void *a[] = { (void *)&value, 0, &status, &flags };
+ QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a);
+
+ } else if (property.flags & QmlPropertyCache::Data::IsQObjectDerived) {
+
+ const QMetaObject *valMo = 0;
+ if (enginePriv) valMo = enginePriv->rawMetaObjectForType(value.userType());
+ else valMo = QmlMetaType::rawMetaObjectForType(value.userType());
+
+ if (!valMo)
+ return false;
+
+ QObject *o = *(QObject **)value.constData();
+ const QMetaObject *propMo = 0;
+ if (enginePriv) propMo = enginePriv->rawMetaObjectForType(t);
+ else propMo = QmlMetaType::rawMetaObjectForType(t);
+
+ if (o) valMo = o->metaObject();
+
+ if (canConvert(valMo, propMo)) {
+ void *args[] = { &o, 0, &status, &flags };
+ QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx,
+ args);
+ } else if (!o && canConvert(propMo, valMo)) {
+ // In the case of a null QObject, we assign the null if there is
+ // any change that the null variant type could be up or down cast to
+ // the property type.
+ void *args[] = { &o, 0, &status, &flags };
+ QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx,
+ args);
+ } else {
+ return false;
+ }
+
+ } 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 =
+ qvariant_cast<QList<QObject *> >(value);
+ QVariant listVar = prop.read(object);
+ QmlMetaType::clear(listVar);
+ for (int ii = 0; ii < list.count(); ++ii) {
+ QVariant v = QmlMetaType::fromObject(list.at(ii), listType);
+ QmlMetaType::append(listVar, v);
+ }
+
+ } else if (vt == listType ||
+ value.userType() == listType) {
+ QVariant listVar = prop.read(object);
+ QmlMetaType::append(listVar, value);
+ }
+
+ } 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();
+
+ int type = li->type();
+
+ if (QObject *obj = QmlMetaType::toQObject(value)) {
+ const QMetaObject *mo =
+ QmlMetaType::rawMetaObjectForType(type);
+
+ const QMetaObject *objMo = obj->metaObject();
+ bool found = false;
+ while(!found && objMo) {
+ if (equal(objMo, mo))
+ found = true;
+ else
+ objMo = objMo->superClass();
+ }
+
+ if (!found)
+ return false;
+
+ // NOTE: This assumes a cast to QObject does not alter
+ // the object pointer
+ void *d = (void *)&obj;
+ li->append(d);
+ }
+ } else {
+ Q_ASSERT(vt != t);
+
+ QVariant v = value;
+ if (v.convert((QVariant::Type)t)) {
+ void *a[] = { (void *)v.constData(), 0, &status, &flags};
+ QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a);
+ } else if ((uint)t >= QVariant::UserType && vt == QVariant::String) {
+ QmlMetaType::StringConverter con = QmlMetaType::customStringConverter(t);
+ if (!con)
+ return false;
+
+ QVariant v = con(value.toString());
+ if (v.userType() == t) {
+ void *a[] = { (void *)v.constData(), 0, &status, &flags};
+ QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a);
+ }
+ } else {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/*!
+ Set the property value to \a value.
+*/
+bool QmlMetaProperty::write(const QVariant &value) const
+{
+ return write(value, 0);
+}
+
+bool QmlMetaProperty::write(const QVariant &value, QmlMetaProperty::WriteFlags flags) const
+{
+ if (d->object && type() & Property && d->core.isValid())
+ return d->writeValueProperty(value, flags);
+ else
+ return false;
+}
+
+/*!
+ Returns true if the property has a change notifier signal, otherwise false.
+*/
+bool QmlMetaProperty::hasChangedNotifier() const
+{
+ if (type() & Property && !(type() & Attached) && d->object) {
+ return d->object->metaObject()->property(d->core.coreIndex).hasNotifySignal();
+ }
+ return false;
+}
+
+/*!
+ Returns true if the property needs a change notifier signal for bindings
+ to remain upto date, false otherwise.
+
+ Some properties, such as attached properties or those whose value never
+ changes, do not require a change notifier.
+*/
+bool QmlMetaProperty::needsChangedNotifier() const
+{
+ return type() & Property && !(type() & Attached) &&
+ !property().isConstant();
+}
+
+/*!
+ Connects the property's change notifier signal to the
+ specified \a method of the \a dest object and returns
+ true. Returns false if this metaproperty does not
+ represent a regular Qt property or if it has no
+ change notifier signal, or if the \a dest object does
+ not have the specified \a method.
+*/
+bool QmlMetaProperty::connectNotifier(QObject *dest, int method) const
+{
+ if (!(type() & Property) || (type() & Attached) || !d->object)
+ return false;
+
+ QMetaProperty prop = d->object->metaObject()->property(d->core.coreIndex);
+ if (prop.hasNotifySignal()) {
+ return QMetaObject::connect(d->object, prop.notifySignalIndex(), dest, method, Qt::DirectConnection);
+ } else {
+ return false;
+ }
+}
+
+/*!
+ Connects the property's change notifier signal to the
+ specified \a slot of the \a dest object and returns
+ true. Returns false if this metaproperty does not
+ represent a regular Qt property or if it has no
+ change notifier signal, or if the \a dest object does
+ not have the specified \a slot.
+*/
+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->core.coreIndex);
+ if (prop.hasNotifySignal()) {
+ QByteArray signal(QByteArray("2") + prop.notifySignal().signature());
+ return QObject::connect(d->object, signal.constData(), dest, slot);
+ } else {
+ return false;
+ }
+}
+
+/*!
+ Return the Qt metaobject index of the property.
+*/
+int QmlMetaProperty::coreIndex() const
+{
+ return d->core.coreIndex;
+}
+
+/*! \internal */
+int QmlMetaProperty::valueTypeCoreIndex() const
+{
+ return d->valueTypeCoreIdx;
+}
+
+Q_GLOBAL_STATIC(QmlValueTypeFactory, qmlValueTypes);
+
+/*!
+ Returns the property information serialized into a single integer.
+ QmlMetaProperty uses the bottom 24 bits only.
+*/
+quint32 QmlMetaProperty::save() const
+{
+ quint32 rv = 0;
+ if (type() & Attached) {
+ rv = d->attachedFunc;
+ } else if (type() != Invalid) {
+ rv = d->core.coreIndex;
+ }
+
+ Q_ASSERT(rv <= 0x7FF);
+ Q_ASSERT(type() <= 0x3F);
+ Q_ASSERT(d->valueTypeCoreIdx <= 0x7F);
+
+ rv |= (type() << 18);
+
+ if (type() & ValueTypeProperty)
+ rv |= (d->valueTypeCoreIdx << 11);
+
+ return rv;
+}
+
+quint32 QmlMetaPropertyPrivate::saveValueType(int core, int valueType)
+{
+ Q_ASSERT(core <= 0x7FF);
+ Q_ASSERT(valueType <= 0x7F);
+ quint32 rv = 0;
+ rv = (QmlMetaProperty::ValueTypeProperty | QmlMetaProperty::Property) << 18;
+ rv |= core;
+ rv |= valueType << 11;
+ return rv;
+}
+
+quint32 QmlMetaPropertyPrivate::saveProperty(int core)
+{
+ Q_ASSERT(core <= 0x7FF);
+ quint32 rv = 0;
+ rv = (QmlMetaProperty::Property) << 18;
+ rv |= core;
+ return rv;
+}
+
+/*!
+ Restore a QmlMetaProperty from a previously saved \a id.
+ \a obj must be the same object as used in the previous call
+ to QmlMetaProperty::save(). Only the bottom 24-bits are
+ used, the high bits can be set to any value.
+*/
+void QmlMetaProperty::restore(quint32 id, QObject *obj, QmlContext *ctxt)
+{
+ QmlEnginePrivate *enginePrivate = 0;
+ if (ctxt && ctxt->engine())
+ enginePrivate = QmlEnginePrivate::get(ctxt->engine());
+
+ d->object = obj;
+ d->context = ctxt;
+
+ id &= 0xFFFFFF;
+ uint type = id >> 18;
+ id &= 0xFFFF;
+
+ if (type & Attached) {
+ d->attachedFunc = id;
+ } else if (type & ValueTypeProperty) {
+ int coreIdx = id & 0x7FF;
+ int valueTypeIdx = id >> 11;
+
+ QMetaProperty p(obj->metaObject()->property(coreIdx));
+ Q_ASSERT(p.type() < QVariant::UserType);
+
+ QmlValueType *valueType = qmlValueTypes()->valueTypes[p.type()];
+
+ QMetaProperty p2(valueType->metaObject()->property(valueTypeIdx));
+
+ d->core.load(p);
+ d->valueTypeCoreIdx = valueTypeIdx;
+ d->valueTypePropType = p2.userType();
+ } else if (type & Property) {
+
+ QmlPropertyCache *cache = enginePrivate?enginePrivate->cache(obj):0;
+
+ if (cache) {
+ QmlPropertyCache::Data *data = cache->property(id);
+ if (data) d->core = *data;
+ } else {
+ QMetaProperty p(obj->metaObject()->property(id));
+ d->core.load(p);
+ }
+
+ } else if (type & SignalProperty) {
+
+ QMetaMethod method = obj->metaObject()->method(id);
+ d->core.load(method);
+ } else {
+ *this = QmlMetaProperty();
+ }
+}
+
+/*!
+ \internal
+
+ Creates a QmlMetaProperty for the property \a name of \a obj. Unlike
+ the QmlMetaProperty(QObject*, QString) constructor, this static function
+ will correctly handle dot properties.
+*/
+QmlMetaProperty QmlMetaProperty::createProperty(QObject *obj,
+ const QString &name)
+{
+ QStringList path = name.split(QLatin1Char('.'));
+
+ QObject *object = obj;
+
+ for (int jj = 0; jj < path.count() - 1; ++jj) {
+ const QString &pathName = path.at(jj);
+ QmlMetaProperty prop(object, pathName);
+
+ if (jj == path.count() - 2 &&
+ prop.propertyType() < (int)QVariant::UserType &&
+ qmlValueTypes()->valueTypes[prop.propertyType()]) {
+ // We're now at a value type property
+ QObject *typeObject =
+ qmlValueTypes()->valueTypes[prop.propertyType()];
+ int idx = typeObject->metaObject()->indexOfProperty(path.last().toUtf8().constData());
+ if (idx == -1)
+ return QmlMetaProperty();
+ QMetaProperty vtProp = typeObject->metaObject()->property(idx);
+
+ QmlMetaProperty p = prop;
+ p.d->valueTypeCoreIdx = idx;
+ p.d->valueTypePropType = vtProp.userType();
+ return p;
+ }
+
+ QObject *objVal = QmlMetaType::toQObject(prop.read());
+ if (!objVal)
+ return QmlMetaProperty();
+ object = objVal;
+ }
+
+ const QString &propName = path.last();
+ QmlMetaProperty prop(object, propName);
+ if (!prop.isValid())
+ return QmlMetaProperty();
+ else
+ return prop;
+}
+
+/*!
+ Returns true if lhs and rhs refer to the same metaobject data
+*/
+bool QmlMetaPropertyPrivate::equal(const QMetaObject *lhs, const QMetaObject *rhs)
+{
+ return lhs == rhs || (1 && lhs && rhs && lhs->d.stringdata == rhs->d.stringdata);
+}
+
+/*!
+ Returns true if from inherits to.
+*/
+bool QmlMetaPropertyPrivate::canConvert(const QMetaObject *from, const QMetaObject *to)
+{
+ if (from && to == &QObject::staticMetaObject)
+ return true;
+
+ while (from) {
+ if (equal(from, to))
+ return true;
+ from = from->superClass();
+ }
+
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlmetaproperty.h b/src/declarative/qml/qmlmetaproperty.h
new file mode 100644
index 0000000..4a2b864
--- /dev/null
+++ b/src/declarative/qml/qmlmetaproperty.h
@@ -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$
+**
+****************************************************************************/
+
+#ifndef QMLMETAPROPERTY_H
+#define QMLMETAPROPERTY_H
+
+#include <QtDeclarative/qfxglobal.h>
+#include <QtCore/QMetaProperty>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QObject;
+class QmlAbstractBinding;
+class QmlExpression;
+class QStringList;
+class QVariant;
+struct QMetaObject;
+class QmlContext;
+class QmlEngine;
+
+class QmlMetaPropertyPrivate;
+class Q_DECLARATIVE_EXPORT QmlMetaProperty
+{
+public:
+ enum PropertyCategory {
+ Unknown,
+ InvalidProperty,
+ Bindable,
+ List,
+ QmlList, //XXX
+ Object,
+ Normal
+ };
+ QmlMetaProperty();
+ QmlMetaProperty(QObject *);
+ QmlMetaProperty(QObject *, const QString &);
+ QmlMetaProperty(QObject *, QmlContext *);
+ QmlMetaProperty(QObject *, const QString &, QmlContext *);
+ QmlMetaProperty(const QmlMetaProperty &);
+ QmlMetaProperty &operator=(const QmlMetaProperty &);
+ QmlMetaProperty(QObject *, int, QmlContext * = 0);
+ ~QmlMetaProperty();
+
+ static QStringList properties(QObject *);
+ QString name() const;
+
+ QVariant read() const;
+ bool write(const QVariant &) const;
+ enum WriteFlag { BypassInterceptor = 0x01, DontRemoveBinding = 0x02 };
+ Q_DECLARE_FLAGS(WriteFlags, WriteFlag)
+ bool write(const QVariant &, QmlMetaProperty::WriteFlags) const;
+
+ bool hasChangedNotifier() const;
+ bool needsChangedNotifier() const;
+ bool connectNotifier(QObject *dest, const char *slot) const;
+ bool connectNotifier(QObject *dest, int method) const;
+
+ quint32 save() const;
+ void restore(quint32, QObject *, QmlContext * = 0);
+
+ QMetaMethod method() const;
+
+ enum Type { Invalid = 0x00,
+ Property = 0x01,
+ SignalProperty = 0x02,
+ Default = 0x08,
+ Attached = 0x10,
+ ValueTypeProperty = 0x20 };
+
+ Type type() const;
+ bool isProperty() const;
+ bool isDefault() const;
+ bool isWritable() const;
+ bool isDesignable() const;
+ bool isValid() const;
+ QObject *object() const;
+
+ PropertyCategory propertyCategory() const;
+
+ int propertyType() const;
+ const char *propertyTypeName() const;
+
+ bool operator==(const QmlMetaProperty &) const;
+
+ QMetaProperty property() const;
+
+ QmlAbstractBinding *binding() const;
+ QmlAbstractBinding *setBinding(QmlAbstractBinding *,
+ QmlMetaProperty::WriteFlags flags = QmlMetaProperty::DontRemoveBinding) const;
+
+ QmlExpression *signalExpression() const;
+ QmlExpression *setSignalExpression(QmlExpression *) const;
+
+ static QmlMetaProperty createProperty(QObject *, const QString &);
+
+ int coreIndex() const;
+ int valueTypeCoreIndex() const;
+private:
+ friend class QmlEnginePrivate;
+ QmlMetaPropertyPrivate *d;
+};
+typedef QList<QmlMetaProperty> QmlMetaProperties;
+ Q_DECLARE_OPERATORS_FOR_FLAGS(QmlMetaProperty::WriteFlags)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLMETAPROPERTY_H
diff --git a/src/declarative/qml/qmlmetaproperty_p.h b/src/declarative/qml/qmlmetaproperty_p.h
new file mode 100644
index 0000000..368ca30
--- /dev/null
+++ b/src/declarative/qml/qmlmetaproperty_p.h
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** 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 QMLMETAPROPERTY_P_H
+#define QMLMETAPROPERTY_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 "qmlmetaproperty.h"
+#include <private/qobject_p.h>
+#include <private/qmlpropertycache_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlContext;
+class QmlMetaPropertyPrivate
+{
+public:
+ QmlMetaPropertyPrivate()
+ : q(0), context(0), object(0), isDefaultProperty(false), valueTypeCoreIdx(-1),
+ valueTypePropType(0), attachedFunc(-1) {}
+
+ QmlMetaPropertyPrivate(const QmlMetaPropertyPrivate &other)
+ : 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;
+ QmlContext *context;
+ QGuard<QObject> object;
+
+ 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;
+ QMetaMethod findSignal(QObject *, const QString &);
+
+ int propertyType() const;
+ QmlMetaProperty::PropertyCategory propertyCategory() const;
+
+ QVariant readValueProperty();
+ bool writeValueProperty(const QVariant &, QmlMetaProperty::WriteFlags);
+ static bool writeEnumProperty(const QMetaProperty &prop, int idx, QObject *object, const QVariant &value, int flags);
+ static bool write(QObject *, const QmlPropertyCache::Data &, const QVariant &, QmlContext *,
+ QmlMetaProperty::WriteFlags flags = 0);
+ static QmlAbstractBinding *setBinding(QObject *, const QmlPropertyCache::Data &, QmlAbstractBinding *,
+ QmlMetaProperty::WriteFlags flags = QmlMetaProperty::DontRemoveBinding);
+
+ static quint32 saveValueType(int, int);
+ static quint32 saveProperty(int);
+
+ static bool equal(const QMetaObject *, const QMetaObject *);
+ static bool canConvert(const QMetaObject *from, const QMetaObject *to);
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLMETAPROPERTY_P_H
diff --git a/src/declarative/qml/qmlmetatype.cpp b/src/declarative/qml/qmlmetatype.cpp
new file mode 100644
index 0000000..1ab7aff
--- /dev/null
+++ b/src/declarative/qml/qmlmetatype.cpp
@@ -0,0 +1,1399 @@
+/****************************************************************************
+**
+** 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 "qmlmetatype.h"
+#include <QtCore/qdebug.h>
+#include <QtCore/qstringlist.h>
+#include <QtCore/qmetaobject.h>
+#include <QtCore/qbitarray.h>
+#include <QtCore/qreadwritelock.h>
+#include <private/qmlproxymetaobject_p.h>
+
+#include <qmetatype.h>
+#include <qobjectdefs.h>
+#include <qdatetime.h>
+#include <qbytearray.h>
+#include <qreadwritelock.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qvector.h>
+#include <qlocale.h>
+#include <ctype.h>
+#include <QtCore/qcryptographichash.h>
+#include <private/qmlcustomparser_p.h>
+
+#ifdef QT_BOOTSTRAPPED
+# ifndef QT_NO_GEOM_VARIANT
+# define QT_NO_GEOM_VARIANT
+# endif
+#else
+# include <qbitarray.h>
+# include <qurl.h>
+# include <qvariant.h>
+#endif
+
+#ifndef QT_NO_GEOM_VARIANT
+# include <qsize.h>
+# include <qpoint.h>
+# include <qrect.h>
+# include <qline.h>
+# include <qvector3d.h>
+#endif
+#define NS(x) QT_PREPEND_NAMESPACE(x)
+
+QT_BEGIN_NAMESPACE
+
+struct QmlMetaTypeData
+{
+ ~QmlMetaTypeData();
+ QList<QmlType *> types;
+ typedef QHash<int, QmlType *> Ids;
+ Ids idToType;
+ typedef QHash<QByteArray, QmlType *> Names;
+ Names nameToType;
+ typedef QHash<const QMetaObject *, QmlType *> MetaObjects;
+ MetaObjects metaObjectToType;
+ typedef QHash<int, QmlMetaType::StringConverter> StringConverters;
+ StringConverters stringConverters;
+
+ QBitArray objects;
+ QBitArray interfaces;
+ QBitArray qmllists;
+ QBitArray lists;
+};
+Q_GLOBAL_STATIC(QmlMetaTypeData, metaTypeData)
+Q_GLOBAL_STATIC(QReadWriteLock, metaTypeDataLock)
+
+QmlMetaTypeData::~QmlMetaTypeData()
+{
+ for (int i = 0; i < types.count(); ++i)
+ delete types.at(i);
+}
+
+class QmlTypePrivate
+{
+public:
+ QmlTypePrivate();
+
+ void init() const;
+
+ bool m_isInterface : 1;
+ const char *m_iid;
+ QByteArray m_name;
+ int m_version_maj;
+ int m_version_min_from;
+ int m_version_min_to;
+ int m_typeId; int m_listId; int m_qmlListId;
+ QmlPrivate::Func m_opFunc;
+ const QMetaObject *m_baseMetaObject;
+ QmlAttachedPropertiesFunc m_attachedPropertiesFunc;
+ const QMetaObject *m_attachedPropertiesType;
+ int m_parserStatusCast;
+ int m_propertyValueSourceCast;
+ int m_propertyValueInterceptorCast;
+ QmlPrivate::CreateFunc m_extFunc;
+ const QMetaObject *m_extMetaObject;
+ int m_index;
+ QmlCustomParser *m_customParser;
+ mutable volatile bool m_isSetup:1;
+ mutable QList<QmlProxyMetaObject::ProxyData> m_metaObjects;
+ mutable QByteArray m_hash;
+};
+
+QmlTypePrivate::QmlTypePrivate()
+: m_isInterface(false), m_iid(0), m_typeId(0), m_listId(0), m_qmlListId(0),
+ m_opFunc(0), m_baseMetaObject(0), m_attachedPropertiesFunc(0), m_attachedPropertiesType(0),
+ m_parserStatusCast(-1), m_propertyValueSourceCast(-1), m_propertyValueInterceptorCast(-1),
+ m_extFunc(0), m_extMetaObject(0), m_index(-1), m_customParser(0), m_isSetup(false)
+{
+}
+
+
+QmlType::QmlType(int type, int listType, int qmlListType,
+ QmlPrivate::Func opFunc, const char *iid, int index)
+: d(new QmlTypePrivate)
+{
+ d->m_isInterface = true;
+ d->m_iid = iid;
+ d->m_typeId = type;
+ d->m_listId = listType;
+ d->m_qmlListId = qmlListType;
+ d->m_opFunc = opFunc;
+ d->m_index = index;
+ d->m_isSetup = true;
+ d->m_version_maj = 0;
+ d->m_version_min_from = 0;
+ d->m_version_min_to = 0;
+}
+
+QmlType::QmlType(int type, int listType, int qmlListType,
+ QmlPrivate::Func opFunc, const char *qmlName,
+ int version_maj, int version_min_from, int version_min_to,
+ const QMetaObject *metaObject,
+ QmlAttachedPropertiesFunc attachedPropertiesFunc,
+ const QMetaObject *attachedType,
+ int parserStatusCast, int propertyValueSourceCast, int propertyValueInterceptorCast,
+ QmlPrivate::CreateFunc extFunc,
+ const QMetaObject *extMetaObject, int index,
+ QmlCustomParser *customParser)
+: d(new QmlTypePrivate)
+{
+ d->m_name = qmlName;
+ d->m_version_maj = version_maj;
+ d->m_version_min_from = version_min_from;
+ d->m_version_min_to = version_min_to;
+ d->m_typeId = type;
+ d->m_listId = listType;
+ d->m_qmlListId = qmlListType;
+ d->m_opFunc = opFunc;
+ d->m_baseMetaObject = metaObject;
+ d->m_attachedPropertiesFunc = attachedPropertiesFunc;
+ d->m_attachedPropertiesType = attachedType;
+ d->m_parserStatusCast = parserStatusCast;
+ d->m_propertyValueSourceCast = propertyValueSourceCast;
+ d->m_propertyValueInterceptorCast = propertyValueInterceptorCast;
+ d->m_extFunc = extFunc;
+ d->m_index = index;
+ d->m_customParser = customParser;
+
+ if (extMetaObject)
+ d->m_extMetaObject = extMetaObject;
+}
+
+QmlType::~QmlType()
+{
+ delete d->m_customParser;
+ delete d;
+}
+
+int QmlType::majorVersion() const
+{
+ return d->m_version_maj;
+}
+
+int QmlType::minMinorVersion() const
+{
+ return d->m_version_min_from;
+}
+
+int QmlType::maxMinorVersion() const
+{
+ return d->m_version_min_to;
+}
+
+bool QmlType::availableInVersion(int vmajor, int vminor) const
+{
+ return vmajor == d->m_version_maj && vminor >= d->m_version_min_from && vminor <= d->m_version_min_to;
+}
+
+void QmlTypePrivate::init() const
+{
+ if (m_isSetup) return;
+
+ QWriteLocker lock(metaTypeDataLock());
+ if (m_isSetup)
+ return;
+
+ // Setup extended meta object
+ // XXX - very inefficient
+ const QMetaObject *mo = m_baseMetaObject;
+ if (m_extFunc) {
+ QMetaObject *mmo = new QMetaObject;
+ *mmo = *m_extMetaObject;
+ mmo->d.superdata = mo;
+ QmlProxyMetaObject::ProxyData data = { mmo, m_extFunc, 0, 0 };
+ m_metaObjects << data;
+ }
+
+ mo = mo->d.superdata;
+ while(mo) {
+ QmlType *t = metaTypeData()->metaObjectToType.value(mo);
+ if (t) {
+ if (t->d->m_extFunc) {
+ QMetaObject *mmo = new QMetaObject;
+ *mmo = *t->d->m_extMetaObject;
+ mmo->d.superdata = m_baseMetaObject;
+ if (!m_metaObjects.isEmpty())
+ m_metaObjects.last().metaObject->d.superdata = mmo;
+ QmlProxyMetaObject::ProxyData data = { mmo, t->d->m_extFunc, 0, 0 };
+ m_metaObjects << data;
+ }
+ }
+ mo = mo->d.superdata;
+ }
+
+ for (int ii = 0; ii < m_metaObjects.count(); ++ii) {
+ m_metaObjects[ii].propertyOffset =
+ m_metaObjects.at(ii).metaObject->propertyOffset();
+ m_metaObjects[ii].methodOffset =
+ m_metaObjects.at(ii).metaObject->methodOffset();
+ }
+
+ // Calculate hash
+ QByteArray hashData;
+
+ const QMetaObject *myMetaObject = m_metaObjects.isEmpty()?m_baseMetaObject:m_metaObjects.first().metaObject;
+
+ for (int ii = 0; ii < myMetaObject->propertyCount(); ++ii) {
+ QMetaProperty prop = myMetaObject->property(ii);
+ hashData.append(prop.type());
+ hashData.append("|");
+ hashData.append(prop.name());
+ hashData.append("|");
+ }
+
+ for (int ii = 0; ii < myMetaObject->methodCount(); ++ii) {
+ QMetaMethod method = myMetaObject->method(ii);
+ hashData.append(method.signature());
+ hashData.append("|");
+ }
+
+ m_hash = QCryptographicHash::hash(hashData, QCryptographicHash::Md5);
+
+ m_isSetup = true;
+ lock.unlock();
+}
+
+QByteArray QmlType::typeName() const
+{
+ if (d->m_baseMetaObject)
+ return d->m_baseMetaObject->className();
+ else
+ return QByteArray();
+}
+
+QByteArray QmlType::qmlTypeName() const
+{
+ return d->m_name;
+}
+
+QByteArray QmlType::hash() const
+{
+ d->init();
+
+ return d->m_hash;
+}
+
+QObject *QmlType::create() const
+{
+ d->init();
+
+ QVariant v;
+ QObject *rv = 0;
+ d->m_opFunc(QmlPrivate::Create, 0, v, v, (void **)&rv);
+
+ if (rv && !d->m_metaObjects.isEmpty())
+ (void *)new QmlProxyMetaObject(rv, &d->m_metaObjects);
+
+ return rv;
+}
+
+QmlCustomParser *QmlType::customParser() const
+{
+ return d->m_customParser;
+}
+
+bool QmlType::isInterface() const
+{
+ return d->m_isInterface;
+}
+
+int QmlType::typeId() const
+{
+ return d->m_typeId;
+}
+
+int QmlType::qListTypeId() const
+{
+ return d->m_listId;
+}
+
+int QmlType::qmlListTypeId() const
+{
+ return d->m_qmlListId;
+}
+
+void QmlType::listClear(const QVariant &list)
+{
+ Q_ASSERT(list.userType() == qListTypeId());
+ QVariant arg;
+ d->m_opFunc(QmlPrivate::Clear, 0, list, arg, 0);
+}
+
+void QmlType::listAppend(const QVariant &list, const QVariant &item)
+{
+ Q_ASSERT(list.userType() == qListTypeId());
+ d->m_opFunc(QmlPrivate::Append, 0, list, item, 0);
+}
+
+QVariant QmlType::listAt(const QVariant &list, int idx)
+{
+ Q_ASSERT(list.userType() == qListTypeId());
+ QVariant rv;
+ void *ptr = (void *)&rv;
+ d->m_opFunc(QmlPrivate::Value, idx, list, QVariant(), &ptr);
+ return rv;
+}
+
+int QmlType::listCount(const QVariant &list)
+{
+ Q_ASSERT(list.userType() == qListTypeId());
+ return d->m_opFunc(QmlPrivate::Length, 0, list, QVariant(), 0);
+}
+
+const QMetaObject *QmlType::metaObject() const
+{
+ d->init();
+
+ if (d->m_metaObjects.isEmpty())
+ return d->m_baseMetaObject;
+ else
+ return d->m_metaObjects.first().metaObject;
+
+}
+
+const QMetaObject *QmlType::baseMetaObject() const
+{
+ return d->m_baseMetaObject;
+}
+
+QmlAttachedPropertiesFunc QmlType::attachedPropertiesFunction() const
+{
+ return d->m_attachedPropertiesFunc;
+}
+
+const QMetaObject *QmlType::attachedPropertiesType() const
+{
+ return d->m_attachedPropertiesType;
+}
+
+int QmlType::parserStatusCast() const
+{
+ return d->m_parserStatusCast;
+}
+
+int QmlType::propertyValueSourceCast() const
+{
+ return d->m_propertyValueSourceCast;
+}
+
+int QmlType::propertyValueInterceptorCast() const
+{
+ return d->m_propertyValueInterceptorCast;
+}
+
+QVariant QmlType::fromObject(QObject *obj) const
+{
+ QVariant rv;
+ QVariant *v_ptr = &rv;
+ QVariant vobj = QVariant::fromValue(obj);
+ d->m_opFunc(QmlPrivate::FromObject, 0, QVariant(), vobj, (void **)&v_ptr);
+ return rv;
+}
+
+const char *QmlType::interfaceIId() const
+{
+ return d->m_iid;
+}
+
+int QmlType::index() const
+{
+ return d->m_index;
+}
+
+int QmlMetaType::registerInterface(const QmlPrivate::MetaTypeIds &id,
+ QmlPrivate::Func listFunction,
+ const char *iid)
+{
+ QWriteLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ int index = data->types.count();
+
+ QmlType *type = new QmlType(id.typeId, id.listId, id.qmlListId,
+ listFunction, iid, index);
+
+ data->types.append(type);
+ data->idToType.insert(type->typeId(), type);
+ data->idToType.insert(type->qListTypeId(), type);
+ data->idToType.insert(type->qmlListTypeId(), type);
+ // XXX No insertMulti, so no multi-version interfaces?
+ if (!type->qmlTypeName().isEmpty())
+ data->nameToType.insert(type->qmlTypeName(), type);
+
+ if (data->interfaces.size() < id.typeId)
+ data->interfaces.resize(id.typeId + 16);
+ if (data->qmllists.size() < id.qmlListId)
+ data->qmllists.resize(id.qmlListId + 16);
+ if (data->lists.size() < id.listId)
+ data->lists.resize(id.listId + 16);
+ data->interfaces.setBit(id.typeId, true);
+ data->qmllists.setBit(id.qmlListId, true);
+ data->lists.setBit(id.listId, true);
+
+ return index;
+}
+
+int QmlMetaType::registerType(const QmlPrivate::MetaTypeIds &id, QmlPrivate::Func func,
+ const char *uri, int version_maj, int version_min_from, int version_min_to, const char *cname,
+ const QMetaObject *mo, QmlAttachedPropertiesFunc attach, const QMetaObject *attachMo,
+ int pStatus, int object, int valueSource, int valueInterceptor, QmlPrivate::CreateFunc extFunc, const QMetaObject *extmo, QmlCustomParser *parser)
+{
+ Q_UNUSED(object);
+
+ if (cname) {
+ for (int ii = 0; cname[ii]; ++ii) {
+ if (!isalnum(cname[ii])) {
+ qWarning("QmlMetaType: Invalid QML name %s", cname);
+ return -1;
+ }
+ }
+ }
+
+ QWriteLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ int index = data->types.count();
+
+ QByteArray name = uri;
+ if (uri)
+ name += "/";
+ name += cname;
+ name.replace('.','/');
+
+ QmlType *type = new QmlType(id.typeId, id.listId, id.qmlListId,
+ func, name, version_maj, version_min_from, version_min_to, mo, attach, attachMo, pStatus,
+ valueSource, valueInterceptor, extFunc, extmo, index, parser);
+
+ data->types.append(type);
+ data->idToType.insert(type->typeId(), type);
+ data->idToType.insert(type->qListTypeId(), type);
+ data->idToType.insert(type->qmlListTypeId(), type);
+
+ if (!type->qmlTypeName().isEmpty())
+ data->nameToType.insertMulti(type->qmlTypeName(), type);
+
+ data->metaObjectToType.insert(type->baseMetaObject(), type);
+
+ if (data->objects.size() <= id.typeId)
+ data->objects.resize(id.typeId + 16);
+ if (data->qmllists.size() <= id.qmlListId)
+ data->qmllists.resize(id.qmlListId + 16);
+ if (data->lists.size() <= id.listId)
+ data->lists.resize(id.listId + 16);
+ data->objects.setBit(id.typeId, true);
+ data->qmllists.setBit(id.qmlListId, true);
+ data->lists.setBit(id.listId, true);
+
+ return index;
+}
+
+int QmlMetaType::qmlParserStatusCast(int userType)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(userType);
+ if (type && type->typeId() == userType)
+ return type->parserStatusCast();
+ else
+ return -1;
+}
+
+int QmlMetaType::qmlPropertyValueSourceCast(int userType)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(userType);
+ if (type && type->typeId() == userType)
+ return type->propertyValueSourceCast();
+ else
+ return -1;
+}
+
+int QmlMetaType::qmlPropertyValueInterceptorCast(int userType)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(userType);
+ if (type && type->typeId() == userType)
+ return type->propertyValueInterceptorCast();
+ else
+ return -1;
+}
+
+QObject *QmlMetaType::toQObject(const QVariant &v)
+{
+ if (!isObject(v.userType()))
+ return 0;
+
+ // NOTE: This assumes a cast to QObject does not alter the
+ // object pointer
+ QObject *rv = *(QObject **)v.constData();
+ return rv;
+}
+
+/*
+ Returns the item type for a list of type \a id.
+ */
+int QmlMetaType::listType(int id)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(id);
+ if (type && type->qListTypeId() == id)
+ return type->typeId();
+ else
+ return 0;
+}
+
+/*
+ Returns the item type for a qml list of type \a id.
+ */
+int QmlMetaType::qmlListType(int id)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(id);
+ if (type && type->qmlListTypeId() == id)
+ return type->typeId();
+ else
+ return 0;
+}
+
+bool QmlMetaType::clear(const QVariant &list)
+{
+ int userType = list.userType();
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(userType);
+ lock.unlock();
+ if (type && type->qListTypeId() == userType) {
+ type->listClear(list);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool QmlMetaType::append(const QVariant &list, const QVariant &item)
+{
+ int userType = list.userType();
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(userType);
+ lock.unlock();
+ if (type && type->qListTypeId() == userType &&
+ item.userType() == type->typeId()) {
+ type->listAppend(list, item);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+QVariant QmlMetaType::fromObject(QObject *obj, int typeId)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ QmlType *type = data->idToType.value(typeId);
+ if (type && type->typeId() == typeId)
+ return type->fromObject(obj);
+ else
+ return QVariant();
+}
+
+const QMetaObject *QmlMetaType::rawMetaObjectForType(int id)
+{
+ if (id == QMetaType::QObjectStar)
+ return &QObject::staticMetaObject;
+
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ QmlType *type = data->idToType.value(id);
+ if (type && type->typeId() == id)
+ return type->baseMetaObject();
+ else
+ return 0;
+}
+
+const QMetaObject *QmlMetaType::metaObjectForType(int id)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(id);
+ lock.unlock();
+
+ if (type && type->typeId() == id)
+ return type->metaObject();
+ else
+ return 0;
+}
+
+int QmlMetaType::attachedPropertiesFuncId(const QMetaObject *mo)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ QmlType *type = data->metaObjectToType.value(mo);
+ if (type && type->attachedPropertiesFunction())
+ return type->index();
+ else
+ return -1;
+}
+
+QmlAttachedPropertiesFunc QmlMetaType::attachedPropertiesFuncById(int id)
+{
+ if (id < 0)
+ return 0;
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ return data->types.at(id)->attachedPropertiesFunction();
+}
+
+QMetaProperty QmlMetaType::defaultProperty(const QMetaObject *metaObject)
+{
+ int idx = metaObject->indexOfClassInfo("DefaultProperty");
+ if (-1 == idx)
+ return QMetaProperty();
+
+ QMetaClassInfo info = metaObject->classInfo(idx);
+ if (!info.value())
+ return QMetaProperty();
+
+ idx = metaObject->indexOfProperty(info.value());
+ if (-1 == idx)
+ return QMetaProperty();
+
+ return metaObject->property(idx);
+}
+
+QMetaProperty QmlMetaType::defaultProperty(QObject *obj)
+{
+ if (!obj)
+ return QMetaProperty();
+
+ const QMetaObject *metaObject = obj->metaObject();
+ return defaultProperty(metaObject);
+}
+
+QMetaMethod QmlMetaType::defaultMethod(const QMetaObject *metaObject)
+{
+ int idx = metaObject->indexOfClassInfo("DefaultMethod");
+ if (-1 == idx)
+ return QMetaMethod();
+
+ QMetaClassInfo info = metaObject->classInfo(idx);
+ if (!info.value())
+ return QMetaMethod();
+
+ idx = metaObject->indexOfMethod(info.value());
+ if (-1 == idx)
+ return QMetaMethod();
+
+ return metaObject->method(idx);
+}
+
+QMetaMethod QmlMetaType::defaultMethod(QObject *obj)
+{
+ if (!obj)
+ return QMetaMethod();
+
+ const QMetaObject *metaObject = obj->metaObject();
+ return defaultMethod(metaObject);
+}
+
+/*!
+ */
+QMetaProperty QmlMetaType::property(QObject *obj, const QByteArray &bname)
+{
+ return property(obj, bname.constData());
+}
+
+/*!
+ */
+QMetaProperty QmlMetaType::property(QObject *obj, const char *name)
+{
+ if (!obj)
+ return QMetaProperty();
+
+ const QMetaObject *metaObject = obj->metaObject();
+
+ int idx = metaObject->indexOfProperty(name);
+ if (-1 == idx)
+ return QMetaProperty();
+
+ return metaObject->property(idx);
+}
+
+QmlMetaType::TypeCategory QmlMetaType::typeCategory(int userType)
+{
+ if (userType < 0)
+ return Unknown;
+ if (userType == QMetaType::QObjectStar)
+ return Object;
+
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ if (userType < data->objects.size() && data->objects.testBit(userType))
+ return Object;
+ else if (userType < data->qmllists.size() && data->qmllists.testBit(userType))
+ return QmlList;
+ else if (userType < data->lists.size() && data->lists.testBit(userType))
+ return List;
+ else
+ return Unknown;
+}
+
+bool QmlMetaType::isObject(int userType)
+{
+ if (userType == QMetaType::QObjectStar)
+ return true;
+
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ return userType >= 0 && userType < data->objects.size() && data->objects.testBit(userType);
+}
+
+bool QmlMetaType::isInterface(int userType)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ return userType >= 0 && userType < data->interfaces.size() && data->interfaces.testBit(userType);
+}
+
+const char *QmlMetaType::interfaceIId(int userType)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(userType);
+ lock.unlock();
+ if (type && type->isInterface() && type->typeId() == userType)
+ return type->interfaceIId();
+ else
+ return 0;
+}
+
+bool QmlMetaType::isObject(const QMetaObject *mo)
+{
+ // ### Huh?
+ while(mo) {
+ if (mo == &QObject::staticMetaObject)
+ return true;
+ mo = mo->superClass();
+ }
+ return false;
+}
+
+bool QmlMetaType::isQmlList(int userType)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ return userType >= 0 && userType < data->qmllists.size() && data->qmllists.testBit(userType);
+}
+
+bool QmlMetaType::isList(int userType)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ return userType >= 0 && userType < data->lists.size() && data->lists.testBit(userType);
+}
+
+bool QmlMetaType::isList(const QVariant &v)
+{
+ return (v.type() == QVariant::UserType && isList(v.userType()));
+}
+
+int QmlMetaType::listCount(const QVariant &v)
+{
+ int userType = v.userType();
+
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(userType);
+ lock.unlock();
+
+ if (type && type->qListTypeId() == userType)
+ return type->listCount(v);
+ else
+ return 0;
+}
+
+QVariant QmlMetaType::listAt(const QVariant &v, int idx)
+{
+ int userType = v.userType();
+
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+ QmlType *type = data->idToType.value(userType);
+ lock.unlock();
+
+ if (type && type->qListTypeId() == userType)
+ return type->listAt(v, idx);
+ else
+ return 0;
+}
+
+/*!
+ A custom string convertor allows you to specify a function pointer that
+ returns a variant of \a type. For example, if you have written your own icon
+ class that you want to support as an object property assignable in QML:
+
+ \code
+ int type = qRegisterMetaType<SuperIcon>("SuperIcon");
+ QML::addCustomStringConvertor(type, &SuperIcon::pixmapFromString);
+ \endcode
+
+ The function pointer must be of the form:
+ \code
+ QVariant (*StringConverter)(const QString &);
+ \endcode
+ */
+void QmlMetaType::registerCustomStringConverter(int type, StringConverter converter)
+{
+ QWriteLocker lock(metaTypeDataLock());
+
+ QmlMetaTypeData *data = metaTypeData();
+ if (data->stringConverters.contains(type))
+ return;
+ data->stringConverters.insert(type, converter);
+}
+
+/*!
+ Return the custom string converter for \a type, previously installed through
+ registerCustomStringConverter()
+ */
+QmlMetaType::StringConverter QmlMetaType::customStringConverter(int type)
+{
+ QReadLocker lock(metaTypeDataLock());
+
+ QmlMetaTypeData *data = metaTypeData();
+ return data->stringConverters.value(type);
+}
+
+/*!
+ Returns the type (if any) of URI-qualified named \a name in version specified
+ by \a version_major and \a version_minor.
+*/
+QmlType *QmlMetaType::qmlType(const QByteArray &name, int version_major, int version_minor)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ QList<QmlType*> types = data->nameToType.values(name);
+ foreach (QmlType *t, types) {
+ // XXX version_major<0 just a kludge for QmlMetaPropertyPrivate::initProperty
+ if (version_major<0 || t->availableInVersion(version_major,version_minor))
+ return t;
+ }
+ return 0;
+}
+
+QmlType *QmlMetaType::qmlType(const QMetaObject *metaObject)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ return data->metaObjectToType.value(metaObject);
+}
+
+QList<QByteArray> QmlMetaType::qmlTypeNames()
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ return data->nameToType.keys();
+}
+
+QList<QmlType*> QmlMetaType::qmlTypes()
+{
+ QReadLocker lock(metaTypeDataLock());
+ QmlMetaTypeData *data = metaTypeData();
+
+ 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
+ successful and false if not.
+
+ \note This should move into QMetaType once complete
+
+*/
+bool QmlMetaType::copy(int type, void *data, const void *copy)
+{
+ if (copy) {
+ switch(type) {
+ case QMetaType::VoidStar:
+ case QMetaType::QObjectStar:
+ case QMetaType::QWidgetStar:
+ *static_cast<void **>(data) = *static_cast<void* const *>(copy);
+ return true;
+ case QMetaType::Long:
+ *static_cast<long *>(data) = *static_cast<const long*>(copy);
+ return true;
+ case QMetaType::Int:
+ *static_cast<int *>(data) = *static_cast<const int*>(copy);
+ return true;
+ case QMetaType::Short:
+ *static_cast<short *>(data) = *static_cast<const short*>(copy);
+ return true;
+ case QMetaType::Char:
+ *static_cast<char *>(data) = *static_cast<const char*>(copy);
+ return true;
+ case QMetaType::ULong:
+ *static_cast<ulong *>(data) = *static_cast<const ulong*>(copy);
+ return true;
+ case QMetaType::UInt:
+ *static_cast<uint *>(data) = *static_cast<const uint*>(copy);
+ return true;
+ case QMetaType::LongLong:
+ *static_cast<qlonglong *>(data) = *static_cast<const qlonglong*>(copy);
+ return true;
+ case QMetaType::ULongLong:
+ *static_cast<qulonglong *>(data) = *static_cast<const qulonglong*>(copy);
+ return true;
+ case QMetaType::UShort:
+ *static_cast<ushort *>(data) = *static_cast<const ushort*>(copy);
+ return true;
+ case QMetaType::UChar:
+ *static_cast<uchar *>(data) = *static_cast<const uchar*>(copy);
+ return true;
+ case QMetaType::Bool:
+ *static_cast<bool *>(data) = *static_cast<const bool*>(copy);
+ return true;
+ case QMetaType::Float:
+ *static_cast<float *>(data) = *static_cast<const float*>(copy);
+ return true;
+ case QMetaType::Double:
+ *static_cast<double *>(data) = *static_cast<const double*>(copy);
+ return true;
+ case QMetaType::QChar:
+ *static_cast<NS(QChar) *>(data) = *static_cast<const NS(QChar)*>(copy);
+ return true;
+ case QMetaType::QVariantMap:
+ *static_cast<NS(QVariantMap) *>(data) = *static_cast<const NS(QVariantMap)*>(copy);
+ return true;
+ case QMetaType::QVariantHash:
+ *static_cast<NS(QVariantHash) *>(data) = *static_cast<const NS(QVariantHash)*>(copy);
+ return true;
+ case QMetaType::QVariantList:
+ *static_cast<NS(QVariantList) *>(data) = *static_cast<const NS(QVariantList)*>(copy);
+ return true;
+ case QMetaType::QByteArray:
+ *static_cast<NS(QByteArray) *>(data) = *static_cast<const NS(QByteArray)*>(copy);
+ return true;
+ case QMetaType::QString:
+ *static_cast<NS(QString) *>(data) = *static_cast<const NS(QString)*>(copy);
+ return true;
+ case QMetaType::QStringList:
+ *static_cast<NS(QStringList) *>(data) = *static_cast<const NS(QStringList)*>(copy);
+ return true;
+ case QMetaType::QBitArray:
+ *static_cast<NS(QBitArray) *>(data) = *static_cast<const NS(QBitArray)*>(copy);
+ return true;
+ case QMetaType::QDate:
+ *static_cast<NS(QDate) *>(data) = *static_cast<const NS(QDate)*>(copy);
+ return true;
+ case QMetaType::QTime:
+ *static_cast<NS(QTime) *>(data) = *static_cast<const NS(QTime)*>(copy);
+ return true;
+ case QMetaType::QDateTime:
+ *static_cast<NS(QDateTime) *>(data) = *static_cast<const NS(QDateTime)*>(copy);
+ return true;
+ case QMetaType::QUrl:
+ *static_cast<NS(QUrl) *>(data) = *static_cast<const NS(QUrl)*>(copy);
+ return true;
+ case QMetaType::QLocale:
+ *static_cast<NS(QLocale) *>(data) = *static_cast<const NS(QLocale)*>(copy);
+ return true;
+ case QMetaType::QRect:
+ *static_cast<NS(QRect) *>(data) = *static_cast<const NS(QRect)*>(copy);
+ return true;
+ case QMetaType::QRectF:
+ *static_cast<NS(QRectF) *>(data) = *static_cast<const NS(QRectF)*>(copy);
+ return true;
+ case QMetaType::QSize:
+ *static_cast<NS(QSize) *>(data) = *static_cast<const NS(QSize)*>(copy);
+ return true;
+ case QMetaType::QSizeF:
+ *static_cast<NS(QSizeF) *>(data) = *static_cast<const NS(QSizeF)*>(copy);
+ return true;
+ case QMetaType::QLine:
+ *static_cast<NS(QLine) *>(data) = *static_cast<const NS(QLine)*>(copy);
+ return true;
+ case QMetaType::QLineF:
+ *static_cast<NS(QLineF) *>(data) = *static_cast<const NS(QLineF)*>(copy);
+ return true;
+ case QMetaType::QPoint:
+ *static_cast<NS(QPoint) *>(data) = *static_cast<const NS(QPoint)*>(copy);
+ return true;
+ case QMetaType::QPointF:
+ *static_cast<NS(QPointF) *>(data) = *static_cast<const NS(QPointF)*>(copy);
+ return true;
+ case QMetaType::QVector3D:
+ *static_cast<NS(QVector3D) *>(data) = *static_cast<const NS(QVector3D)*>(copy);
+ return true;
+#ifndef QT_NO_REGEXP
+ case QMetaType::QRegExp:
+ *static_cast<NS(QRegExp) *>(data) = *static_cast<const NS(QRegExp)*>(copy);
+ return true;
+#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) {
+ case QMetaType::VoidStar:
+ case QMetaType::QObjectStar:
+ case QMetaType::QWidgetStar:
+ *static_cast<void **>(data) = 0;
+ return true;
+ case QMetaType::Long:
+ *static_cast<long *>(data) = long(0);
+ return true;
+ case QMetaType::Int:
+ *static_cast<int *>(data) = int(0);
+ return true;
+ case QMetaType::Short:
+ *static_cast<short *>(data) = short(0);
+ return true;
+ case QMetaType::Char:
+ *static_cast<char *>(data) = char(0);
+ return true;
+ case QMetaType::ULong:
+ *static_cast<ulong *>(data) = ulong(0);
+ return true;
+ case QMetaType::UInt:
+ *static_cast<uint *>(data) = uint(0);
+ return true;
+ case QMetaType::LongLong:
+ *static_cast<qlonglong *>(data) = qlonglong(0);
+ return true;
+ case QMetaType::ULongLong:
+ *static_cast<qulonglong *>(data) = qulonglong(0);
+ return true;
+ case QMetaType::UShort:
+ *static_cast<ushort *>(data) = ushort(0);
+ return true;
+ case QMetaType::UChar:
+ *static_cast<uchar *>(data) = uchar(0);
+ return true;
+ case QMetaType::Bool:
+ *static_cast<bool *>(data) = bool(false);
+ return true;
+ case QMetaType::Float:
+ *static_cast<float *>(data) = float(0);
+ return true;
+ case QMetaType::Double:
+ *static_cast<double *>(data) = double();
+ return true;
+ case QMetaType::QChar:
+ *static_cast<NS(QChar) *>(data) = NS(QChar)();
+ return true;
+ case QMetaType::QVariantMap:
+ *static_cast<NS(QVariantMap) *>(data) = NS(QVariantMap)();
+ return true;
+ case QMetaType::QVariantHash:
+ *static_cast<NS(QVariantHash) *>(data) = NS(QVariantHash)();
+ return true;
+ case QMetaType::QVariantList:
+ *static_cast<NS(QVariantList) *>(data) = NS(QVariantList)();
+ return true;
+ case QMetaType::QByteArray:
+ *static_cast<NS(QByteArray) *>(data) = NS(QByteArray)();
+ return true;
+ case QMetaType::QString:
+ *static_cast<NS(QString) *>(data) = NS(QString)();
+ return true;
+ case QMetaType::QStringList:
+ *static_cast<NS(QStringList) *>(data) = NS(QStringList)();
+ return true;
+ case QMetaType::QBitArray:
+ *static_cast<NS(QBitArray) *>(data) = NS(QBitArray)();
+ return true;
+ case QMetaType::QDate:
+ *static_cast<NS(QDate) *>(data) = NS(QDate)();
+ return true;
+ case QMetaType::QTime:
+ *static_cast<NS(QTime) *>(data) = NS(QTime)();
+ return true;
+ case QMetaType::QDateTime:
+ *static_cast<NS(QDateTime) *>(data) = NS(QDateTime)();
+ return true;
+ case QMetaType::QUrl:
+ *static_cast<NS(QUrl) *>(data) = NS(QUrl)();
+ return true;
+ case QMetaType::QLocale:
+ *static_cast<NS(QLocale) *>(data) = NS(QLocale)();
+ return true;
+ case QMetaType::QRect:
+ *static_cast<NS(QRect) *>(data) = NS(QRect)();
+ return true;
+ case QMetaType::QRectF:
+ *static_cast<NS(QRectF) *>(data) = NS(QRectF)();
+ return true;
+ case QMetaType::QSize:
+ *static_cast<NS(QSize) *>(data) = NS(QSize)();
+ return true;
+ case QMetaType::QSizeF:
+ *static_cast<NS(QSizeF) *>(data) = NS(QSizeF)();
+ return true;
+ case QMetaType::QLine:
+ *static_cast<NS(QLine) *>(data) = NS(QLine)();
+ return true;
+ case QMetaType::QLineF:
+ *static_cast<NS(QLineF) *>(data) = NS(QLineF)();
+ return true;
+ case QMetaType::QPoint:
+ *static_cast<NS(QPoint) *>(data) = NS(QPoint)();
+ return true;
+ case QMetaType::QPointF:
+ *static_cast<NS(QPointF) *>(data) = NS(QPointF)();
+ return true;
+ case QMetaType::QVector3D:
+ *static_cast<NS(QVector3D) *>(data) = NS(QVector3D)();
+ return true;
+#ifndef QT_NO_REGEXP
+ case QMetaType::QRegExp:
+ *static_cast<NS(QRegExp) *>(data) = NS(QRegExp)();
+ return true;
+#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;
+ }
+ }
+
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlmetatype.h b/src/declarative/qml/qmlmetatype.h
new file mode 100644
index 0000000..42c278c
--- /dev/null
+++ b/src/declarative/qml/qmlmetatype.h
@@ -0,0 +1,309 @@
+/****************************************************************************
+**
+** 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 QMLMETATYPE_H
+#define QMLMETATYPE_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qvariant.h>
+#include <QtCore/qbitarray.h>
+#include <QtDeclarative/qmlprivate.h>
+#include <QtDeclarative/qmlparserstatus.h>
+#include <QtDeclarative/qmlpropertyvaluesource.h>
+#include <QtDeclarative/qmlpropertyvalueinterceptor.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlType;
+class QmlCustomParser;
+class Q_DECLARATIVE_EXPORT QmlMetaType
+{
+public:
+ static int registerType(const QmlPrivate::MetaTypeIds &, QmlPrivate::Func, const char *, int vmaj, int vmin_from, int vmin_to, const char *qmlName, const QMetaObject *, QmlAttachedPropertiesFunc, const QMetaObject *, int pStatus, int object, int valueSource, int valueInterceptor, QmlPrivate::CreateFunc extFunc, const QMetaObject *extmo, QmlCustomParser *);
+ static int registerInterface(const QmlPrivate::MetaTypeIds &, QmlPrivate::Func, const char *);
+
+ static bool copy(int type, void *data, const void *copy = 0);
+
+ static QList<QByteArray> qmlTypeNames();
+ static QList<QmlType*> qmlTypes();
+
+ static QmlType *qmlType(const QByteArray &, int, int);
+ static QmlType *qmlType(const QMetaObject *);
+
+ static QMetaProperty defaultProperty(const QMetaObject *);
+ static QMetaProperty defaultProperty(QObject *);
+ static QMetaMethod defaultMethod(const QMetaObject *);
+ static QMetaMethod defaultMethod(QObject *);
+ static QMetaProperty property(QObject *, const QByteArray &);
+ static QMetaProperty property(QObject *, const char *);
+ static QObject *toQObject(const QVariant &);
+ static int qmlParserStatusCast(int);
+ static int qmlPropertyValueSourceCast(int);
+ static int qmlPropertyValueInterceptorCast(int);
+ static int listType(int);
+ static bool clear(const QVariant &);
+ static bool append(const QVariant &, const QVariant &);
+ static QVariant fromObject(QObject *, int type);
+ static const QMetaObject *rawMetaObjectForType(int);
+ static const QMetaObject *metaObjectForType(int);
+ static int attachedPropertiesFuncId(const QMetaObject *);
+ static QmlAttachedPropertiesFunc attachedPropertiesFuncById(int);
+
+ enum TypeCategory { Unknown, Object, List, QmlList };
+ static TypeCategory typeCategory(int);
+
+ static bool isInterface(int);
+ static const char *interfaceIId(int);
+ static bool isObject(int);
+ static bool isObject(const QMetaObject *);
+ static bool isList(int);
+ static bool isList(const QVariant &);
+ static bool isQmlList(int);
+ static int qmlListType(int);
+ static int listCount(const QVariant &);
+ static QVariant listAt(const QVariant &, int);
+
+ typedef QVariant (*StringConverter)(const QString &);
+ static void registerCustomStringConverter(int, StringConverter);
+ static StringConverter customStringConverter(int);
+};
+
+class QmlTypePrivate;
+class Q_DECLARATIVE_EXPORT QmlType
+{
+public:
+ QByteArray typeName() const;
+ QByteArray qmlTypeName() const;
+
+ int majorVersion() const;
+ int minMinorVersion() const;
+ int maxMinorVersion() const;
+ bool availableInVersion(int vmajor, int vminor) const;
+
+ QByteArray hash() const;
+
+ QObject *create() const;
+
+ QmlCustomParser *customParser() const;
+
+ bool isInterface() const;
+ int typeId() const;
+ int qListTypeId() const;
+ int qmlListTypeId() const;
+
+ void listClear(const QVariant &);
+ void listAppend(const QVariant &, const QVariant &);
+ QVariant listAt(const QVariant &, int);
+ int listCount(const QVariant &);
+
+ const QMetaObject *metaObject() const;
+ const QMetaObject *baseMetaObject() const;
+
+ QmlAttachedPropertiesFunc attachedPropertiesFunction() const;
+ const QMetaObject *attachedPropertiesType() const;
+
+ int parserStatusCast() const;
+ QVariant fromObject(QObject *) const;
+ const char *interfaceIId() const;
+ int propertyValueSourceCast() const;
+ int propertyValueInterceptorCast() const;
+
+ int index() const;
+private:
+ friend class QmlMetaType;
+ friend class QmlTypePrivate;
+ friend class QmlMetaTypeData;
+ QmlType(int, int, int, QmlPrivate::Func, const char *, int);
+ QmlType(int, int, int, QmlPrivate::Func, const char *, int, int, int, const QMetaObject *, QmlAttachedPropertiesFunc, const QMetaObject *, int, int, int, QmlPrivate::CreateFunc, const QMetaObject *, int, QmlCustomParser *);
+ ~QmlType();
+
+ QmlTypePrivate *d;
+};
+
+template<typename T>
+int qmlRegisterType(const char *typeName)
+{
+ QByteArray name(typeName);
+ QmlPrivate::MetaTypeIds ids = {
+ qRegisterMetaType<T *>(QByteArray(name + "*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QList<" + name + "*>*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QmlList<" + name + "*>*").constData())
+ };
+
+ return QmlMetaType::registerType(ids, QmlPrivate::list_nocreate_op<T>, 0, 0, 0, 0, 0,
+ &T::staticMetaObject,
+ QmlPrivate::attachedPropertiesFunc<T>(),
+ QmlPrivate::attachedPropertiesMetaObject<T>(),
+ QmlPrivate::StaticCastSelector<T,QmlParserStatus>::cast(),
+ QmlPrivate::StaticCastSelector<T,QObject>::cast(),
+ QmlPrivate::StaticCastSelector<T,QmlPropertyValueSource>::cast(),
+ QmlPrivate::StaticCastSelector<T,QmlPropertyValueInterceptor>::cast(),
+ 0, 0, 0);
+}
+
+template<typename T>
+int qmlRegisterType(const char *uri, int version_maj, int version_min_from, int version_min_to, const char *qmlName, const char *typeName)
+{
+ QByteArray name(typeName);
+ QmlPrivate::MetaTypeIds ids = {
+ qRegisterMetaType<T *>(QByteArray(name + "*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QList<" + name + "*>*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QmlList<" + name + "*>*").constData())
+ };
+
+ return QmlMetaType::registerType(ids, QmlPrivate::list_op<T>,
+ uri, version_maj, version_min_from, version_min_to, qmlName,
+ &T::staticMetaObject,
+ QmlPrivate::attachedPropertiesFunc<T>(),
+ QmlPrivate::attachedPropertiesMetaObject<T>(),
+ QmlPrivate::StaticCastSelector<T,QmlParserStatus>::cast(),
+ QmlPrivate::StaticCastSelector<T,QObject>::cast(),
+ QmlPrivate::StaticCastSelector<T,QmlPropertyValueSource>::cast(),
+ QmlPrivate::StaticCastSelector<T,QmlPropertyValueInterceptor>::cast(),
+ 0, 0, 0);
+}
+
+template<typename T, typename E>
+int qmlRegisterExtendedType(const char *typeName)
+{
+ QByteArray name(typeName);
+ QmlPrivate::MetaTypeIds ids = {
+ qRegisterMetaType<T *>(QByteArray(name + "*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QList<" + name + "*>*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QmlList<" + name + "*>*").constData())
+ };
+
+ QmlAttachedPropertiesFunc attached =
+ QmlPrivate::attachedPropertiesFunc<E>();
+ const QMetaObject * attachedMo =
+ QmlPrivate::attachedPropertiesMetaObject<E>();
+ if (!attached) {
+ attached = QmlPrivate::attachedPropertiesFunc<T>();
+ attachedMo = QmlPrivate::attachedPropertiesMetaObject<T>();
+ }
+
+ return QmlMetaType::registerType(ids, QmlPrivate::list_nocreate_op<T>, 0, 0, 0, 0, 0,
+ &T::staticMetaObject, attached, attachedMo,
+ QmlPrivate::StaticCastSelector<T,QmlParserStatus>::cast(),
+ QmlPrivate::StaticCastSelector<T,QObject>::cast(),
+ QmlPrivate::StaticCastSelector<T,QmlPropertyValueSource>::cast(),
+ QmlPrivate::StaticCastSelector<T,QmlPropertyValueInterceptor>::cast(),
+ &QmlPrivate::CreateParent<E>::create, &E::staticMetaObject, 0);
+}
+
+template<typename T, typename E>
+int qmlRegisterExtendedType(const char *uri, int version_maj, int version_min_from, int version_min_to, const char *qmlName, const char *typeName)
+{
+ QByteArray name(typeName);
+ QmlPrivate::MetaTypeIds ids = {
+ qRegisterMetaType<T *>(QByteArray(name + "*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QList<" + name + "*>*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QmlList<" + name + "*>*").constData())
+ };
+
+ QmlAttachedPropertiesFunc attached =
+ QmlPrivate::attachedPropertiesFunc<E>();
+ const QMetaObject * attachedMo =
+ QmlPrivate::attachedPropertiesMetaObject<E>();
+ if (!attached) {
+ attached = QmlPrivate::attachedPropertiesFunc<T>();
+ attachedMo = QmlPrivate::attachedPropertiesMetaObject<T>();
+ }
+
+ return QmlMetaType::registerType(ids, QmlPrivate::list_op<T>,
+ uri, version_maj, version_min_from, version_min_to, qmlName,
+ &T::staticMetaObject,
+ attached, attachedMo,
+ QmlPrivate::StaticCastSelector<T,QmlParserStatus>::cast(),
+ QmlPrivate::StaticCastSelector<T,QObject>::cast(),
+ QmlPrivate::StaticCastSelector<T,QmlPropertyValueSource>::cast(),
+ QmlPrivate::StaticCastSelector<T,QmlPropertyValueInterceptor>::cast(),
+ &QmlPrivate::CreateParent<E>::create,
+ &E::staticMetaObject, 0);
+}
+
+template<typename T>
+int qmlRegisterInterface(const char *typeName)
+{
+ QByteArray name(typeName);
+ QmlPrivate::MetaTypeIds ids = {
+ qRegisterMetaType<T *>(QByteArray(name + "*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QList<" + name + "*>*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QmlList<" + name + "*>*").constData())
+ };
+
+ return QmlMetaType::registerInterface(ids,
+ QmlPrivate::list_interface_op<T>,
+ qobject_interface_iid<T *>());
+}
+
+template<typename T>
+int qmlRegisterCustomType(const char *uri, int version_maj, int version_min_from, int version_min_to, const char *qmlName, const char *typeName, QmlCustomParser *parser)
+{
+ QByteArray name(typeName);
+ QmlPrivate::MetaTypeIds ids = {
+ qRegisterMetaType<T *>(QByteArray(name + "*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QList<" + name + "*>*").constData()),
+ qRegisterMetaType<T *>(QByteArray("QmlList<" + name + "*>*").constData())
+ };
+
+ return QmlMetaType::registerType(ids, QmlPrivate::list_op<T>,
+ uri, version_maj, version_min_from, version_min_to, qmlName,
+ &T::staticMetaObject,
+ QmlPrivate::attachedPropertiesFunc<T>(),
+ QmlPrivate::attachedPropertiesMetaObject<T>(),
+ QmlPrivate::StaticCastSelector<T,QmlParserStatus>::cast(),
+ QmlPrivate::StaticCastSelector<T,QObject>::cast(),
+ QmlPrivate::StaticCastSelector<T,QmlPropertyValueSource>::cast(),
+ QmlPrivate::StaticCastSelector<T,QmlPropertyValueInterceptor>::cast(),
+ 0, 0, parser);
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLMETATYPE_H
+
diff --git a/src/declarative/qml/qmlobjectscriptclass.cpp b/src/declarative/qml/qmlobjectscriptclass.cpp
new file mode 100644
index 0000000..a6edd3b
--- /dev/null
+++ b/src/declarative/qml/qmlobjectscriptclass.cpp
@@ -0,0 +1,330 @@
+/****************************************************************************
+**
+** 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 <private/qmllistscriptclass_p.h>
+#include <QtDeclarative/qmlbinding.h>
+#include <QtCore/qtimer.h>
+
+QT_BEGIN_NAMESPACE
+
+struct ObjectData : public QScriptDeclarativeClass::Object {
+ ObjectData(QObject *o, int t) : object(o), type(t) {}
+ QGuard<QObject> object;
+ int type;
+};
+
+/*
+ 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)
+{
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+
+ 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, int type)
+{
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+
+ if (!object)
+ return newObject(scriptEngine, this, new ObjectData(object, type));
+
+ QmlDeclarativeData *ddata = QmlDeclarativeData::get(object, true);
+
+ if (!ddata->scriptValue.isValid()) {
+ ddata->scriptValue = newObject(scriptEngine, this, new ObjectData(object, type));
+ return ddata->scriptValue;
+ } else if (ddata->scriptValue.engine() == QmlEnginePrivate::getScriptEngine(engine)) {
+ return ddata->scriptValue;
+ } else {
+ return newObject(scriptEngine, this, new ObjectData(object, type));
+ }
+}
+
+QObject *QmlObjectScriptClass::toQObject(const QScriptValue &value) const
+{
+ return value.toQObject();
+}
+
+int QmlObjectScriptClass::objectType(const QScriptValue &value) const
+{
+ if (scriptClass(value) != this)
+ return QVariant::Invalid;
+
+ Object *o = object(value);
+ return ((ObjectData*)(o))->type;
+}
+
+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::IsQList) {
+ return enginePriv->listClass->newList(obj, lastData->coreIndex,
+ QmlListScriptClass::QListPtr);
+ } else if (lastData->flags & QmlPropertyCache::Data::IsQmlList) {
+ return enginePriv->listClass->newList(obj, lastData->coreIndex,
+ QmlListScriptClass::QmlListPtr);
+ } if (lastData->flags & QmlPropertyCache::Data::IsQObjectDerived) {
+ QObject *rv = 0;
+ void *args[] = { &rv, 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
+
+ return newQObject(rv, lastData->propType);
+ } 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,
+ QmlContext *evalContext)
+{
+ Q_UNUSED(name);
+
+ Q_ASSERT(obj);
+ Q_ASSERT(lastData);
+
+ QmlEnginePrivate *enginePriv = QmlEnginePrivate::get(engine);
+
+ if (!evalContext && context()) {
+ // Global object, QScriptContext activation object, QmlContext object
+ QScriptValue scopeNode = scopeChainValue(context(), -3);
+ Q_ASSERT(scopeNode.isValid());
+ Q_ASSERT(scriptClass(scopeNode) == enginePriv->contextClass);
+
+ evalContext = enginePriv->contextClass->contextFromValue(scopeNode);
+ }
+
+ // ### Can well known types be optimized?
+ QVariant v = QmlScriptClass::toVariant(engine, value);
+ delete QmlMetaPropertyPrivate::setBinding(obj, *lastData, 0);
+ QmlMetaPropertyPrivate::write(obj, *lastData, v, evalContext);
+}
+
+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 += QString::fromUtf8(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..7fb727e
--- /dev/null
+++ b/src/declarative/qml/qmlobjectscriptclass_p.h
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** 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 *, int type = QMetaType::QObjectStar);
+ QObject *toQObject(const QScriptValue &) const;
+ int objectType(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 &,
+ QmlContext *evalContext = 0);
+
+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
new file mode 100644
index 0000000..f9e3c50
--- /dev/null
+++ b/src/declarative/qml/qmlparser.cpp
@@ -0,0 +1,424 @@
+/****************************************************************************
+**
+** 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 "qmlparser_p.h"
+#include <QStack>
+#include <qmlpropertyvaluesource.h>
+#include <QColor>
+#include <QPointF>
+#include <QSizeF>
+#include <QRectF>
+#include <private/qmlvme_p.h>
+#include <private/qfxperf_p.h>
+#include <qml.h>
+#include "private/qmlcomponent_p.h"
+#include <qmlcomponent.h>
+#include "private/qmetaobjectbuilder_p.h"
+#include <private/qmlvmemetaobject_p.h>
+#include <private/qmlcompiler_p.h>
+#include <QtDebug>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QmlParser;
+
+QmlParser::Object::Object()
+: type(-1), majorVersion(-1), minorVersion(-1), idIndex(-1), metatype(0), defaultProperty(0), parserStatusCast(-1)
+{
+}
+
+QmlParser::Object::~Object()
+{
+ if (defaultProperty) defaultProperty->release();
+ foreach(Property *prop, properties)
+ prop->release();
+ foreach(Property *prop, valueProperties)
+ prop->release();
+ foreach(Property *prop, signalProperties)
+ prop->release();
+ foreach(Property *prop, attachedProperties)
+ prop->release();
+ foreach(Property *prop, groupedProperties)
+ prop->release();
+ foreach(Property *prop, valueTypeProperties)
+ prop->release();
+ typedef QPair<Property *, int> PropPair;
+ foreach(const PropPair &prop, scriptStringProperties)
+ prop.first->release();
+ foreach(const DynamicProperty &prop, dynamicProperties)
+ if (prop.defaultValue) prop.defaultValue->release();
+ foreach(Object *obj, scriptBlockObjects)
+ obj->release();
+}
+
+void Object::setBindingBit(int b)
+{
+ while (bindingBitmask.size() < 4 * (1 + b / 32))
+ bindingBitmask.append(char(0));
+
+ quint32 *bits = (quint32 *)bindingBitmask.data();
+ bits[b / 32] |= (1 << (b % 32));
+}
+
+const QMetaObject *Object::metaObject() const
+{
+ if (!metadata.isEmpty() && metatype)
+ return &extObject;
+ else
+ return metatype;
+}
+
+QmlParser::Property *Object::getDefaultProperty()
+{
+ if (!defaultProperty) {
+ defaultProperty = new Property;
+ defaultProperty->parent = this;
+ }
+ return defaultProperty;
+}
+
+void QmlParser::Object::addValueProperty(Property *p)
+{
+ p->addref();
+ valueProperties << p;
+}
+
+void QmlParser::Object::addSignalProperty(Property *p)
+{
+ p->addref();
+ signalProperties << p;
+}
+
+void QmlParser::Object::addAttachedProperty(Property *p)
+{
+ p->addref();
+ attachedProperties << p;
+}
+
+void QmlParser::Object::addGroupedProperty(Property *p)
+{
+ p->addref();
+ groupedProperties << p;
+}
+
+void QmlParser::Object::addValueTypeProperty(Property *p)
+{
+ p->addref();
+ valueTypeProperties << p;
+}
+
+void QmlParser::Object::addScriptStringProperty(Property *p, int stack)
+{
+ p->addref();
+ scriptStringProperties << qMakePair(p, stack);
+}
+
+
+Property *QmlParser::Object::getProperty(const QByteArray &name, bool create)
+{
+ if (!properties.contains(name)) {
+ if (create) {
+ Property *property = new Property(name);
+ property->parent = this;
+ properties.insert(name, property);
+ } else {
+ return 0;
+ }
+ }
+ return properties[name];
+}
+
+QmlParser::Object::DynamicProperty::DynamicProperty()
+: isDefaultProperty(false), type(Variant), defaultValue(0)
+{
+}
+
+QmlParser::Object::DynamicProperty::DynamicProperty(const DynamicProperty &o)
+: isDefaultProperty(o.isDefaultProperty),
+ type(o.type),
+ customType(o.customType),
+ name(o.name),
+ defaultValue(o.defaultValue),
+ location(o.location)
+{
+}
+
+QmlParser::Object::DynamicSignal::DynamicSignal()
+{
+}
+
+QmlParser::Object::DynamicSignal::DynamicSignal(const DynamicSignal &o)
+: name(o.name), parameterTypes(o.parameterTypes),
+ parameterNames(o.parameterNames)
+{
+}
+
+QmlParser::Object::DynamicSlot::DynamicSlot()
+{
+}
+
+QmlParser::Object::DynamicSlot::DynamicSlot(const DynamicSlot &o)
+: name(o.name), body(o.body), parameterNames(o.parameterNames)
+{
+}
+
+void QmlParser::Object::dump(int indent) const
+{
+ QByteArray ba(indent * 4, ' ');
+ if (type != -1) {
+ qWarning() << ba.constData() << "Object:" << typeName;
+ } else {
+ qWarning() << ba.constData() << "Object: fetched";
+ }
+
+ for (QHash<QByteArray, Property *>::ConstIterator iter = properties.begin();
+ iter != properties.end();
+ ++iter) {
+ qWarning() << ba.constData() << " Property" << iter.key();
+ (*iter)->dump(indent + 1);
+ }
+
+ if (defaultProperty) {
+ qWarning() << ba.constData() << " Default property";
+ defaultProperty->dump(indent + 1);
+ }
+}
+
+QmlParser::Property::Property()
+: parent(0), type(0), index(-1), value(0), isDefault(true), isDeferred(false)
+{
+}
+
+QmlParser::Property::Property(const QByteArray &n)
+: parent(0), type(0), index(-1), value(0), name(n), isDefault(false),
+ isDeferred(false)
+{
+}
+
+QmlParser::Property::~Property()
+{
+ foreach(Value *value, values)
+ value->release();
+ if (value) value->release();
+}
+
+Object *QmlParser::Property::getValue()
+{
+ if (!value) value = new Object;
+ return value;
+}
+
+void QmlParser::Property::addValue(Value *v)
+{
+ values << v;
+}
+
+bool QmlParser::Property::isEmpty() const
+{
+ return !value && values.isEmpty();
+}
+
+void QmlParser::Property::dump(int indent) const
+{
+ QByteArray ba(indent * 4, ' ');
+ for (int ii = 0; ii < values.count(); ++ii)
+ values.at(ii)->dump(indent);
+ if (value)
+ value->dump(indent);
+}
+
+QmlParser::Value::Value()
+: type(Unknown), object(0)
+{
+}
+
+QmlParser::Value::~Value()
+{
+ if (object) object->release();
+}
+
+void QmlParser::Value::dump(int indent) const
+{
+ QByteArray type;
+ switch(this->type) {
+ default:
+ case Value::Unknown:
+ type = "Unknown";
+ break;
+ case Value::Literal:
+ type = "Literal";
+ break;
+ case Value::PropertyBinding:
+ type = "PropertyBinding";
+ break;
+ case Value::ValueSource:
+ type = "ValueSource";
+ break;
+ case Value::ValueInterceptor:
+ type = "ValueInterceptor";
+ break;
+ case Value::CreatedObject:
+ type = "CreatedObject";
+ break;
+ case Value::SignalObject:
+ type = "SignalObject";
+ break;
+ case Value::SignalExpression:
+ type = "SignalExpression";
+ break;
+ case Value::Id:
+ type = "Id";
+ break;
+ }
+
+ QByteArray primType;
+ switch(this->value.type()) {
+ default:
+ case Variant::Invalid:
+ primType = "Invalid";
+ break;
+ case Variant::Boolean:
+ primType = "Boolean";
+ break;
+ case Variant::Number:
+ primType = "Number";
+ break;
+ case Variant::String:
+ primType = "String";
+ break;
+ case Variant::Script:
+ primType = "Script";
+ break;
+ }
+
+ QByteArray ba(indent * 4, ' ');
+ if (object) {
+ qWarning() << ba.constData() << "Value (" << type << "):";
+ object->dump(indent + 1);
+ } else {
+ qWarning() << ba.constData() << "Value (" << type << "):" << primType.constData() << primitive();
+ }
+}
+
+QmlParser::Variant::Variant()
+: t(Invalid) {}
+
+QmlParser::Variant::Variant(const Variant &o)
+: t(o.t), d(o.d), s(o.s)
+{
+}
+
+QmlParser::Variant::Variant(bool v)
+: t(Boolean), b(v)
+{
+}
+
+QmlParser::Variant::Variant(double v, const QString &asWritten)
+: t(Number), d(v), s(asWritten)
+{
+}
+
+QmlParser::Variant::Variant(const QString &v)
+: t(String), s(v)
+{
+}
+
+QmlParser::Variant::Variant(const QString &v, QmlJS::AST::Node *n)
+: t(Script), n(n), s(v)
+{
+}
+
+QmlParser::Variant &QmlParser::Variant::operator=(const Variant &o)
+{
+ t = o.t;
+ d = o.d;
+ s = o.s;
+ return *this;
+}
+
+QmlParser::Variant::Type QmlParser::Variant::type() const
+{
+ return t;
+}
+
+bool QmlParser::Variant::asBoolean() const
+{
+ return b;
+}
+
+QString QmlParser::Variant::asString() const
+{
+ return s;
+}
+
+double QmlParser::Variant::asNumber() const
+{
+ return d;
+}
+
+QString QmlParser::Variant::asScript() const
+{
+ switch(type()) {
+ default:
+ case Invalid:
+ return QString();
+ case Boolean:
+ return b?QLatin1String("true"):QLatin1String("false");
+ case Number:
+ if (s.isEmpty())
+ return QString::number(d);
+ else
+ return s;
+ case String:
+ case Script:
+ return s;
+ }
+}
+
+QmlJS::AST::Node *QmlParser::Variant::asAST() const
+{
+ if (type() == Script)
+ return n;
+ else
+ return 0;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlparser_p.h b/src/declarative/qml/qmlparser_p.h
new file mode 100644
index 0000000..f0867ea
--- /dev/null
+++ b/src/declarative/qml/qmlparser_p.h
@@ -0,0 +1,356 @@
+/****************************************************************************
+**
+** 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 QMLPARSER_P_H
+#define QMLPARSER_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/QByteArray>
+#include <QtCore/QList>
+#include <QtCore/qstring.h>
+#include <QtDeclarative/qml.h>
+#include <private/qmlrefcount_p.h>
+#include <private/qobject_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+namespace QmlJS { namespace AST { class Node; } }
+
+/*
+ XXX
+
+ These types are created (and owned) by the QmlXmlParser and consumed by the
+ QmlCompiler. During the compilation phase the compiler will update some of
+ the fields for both its own use and for the use of the upcoming QmlDom API.
+
+ The types are part of the generic sounding "QmlParser" namespace for legacy
+ reasons (there used to be more in this namespace) and will be cleaned up and
+ migrated into a more appropriate location shortly.
+*/
+namespace QmlParser
+{
+ struct Location
+ {
+ Location() : line(-1), column(-1) {}
+ int line;
+ int column;
+ };
+
+ struct LocationRange
+ {
+ LocationRange() : offset(0), length(0) {}
+ quint32 offset;
+ quint32 length;
+ };
+
+ struct LocationSpan
+ {
+ Location start;
+ Location end;
+ LocationRange range;
+ };
+
+ class Property;
+ class Object : public QmlRefCount
+ {
+ public:
+ Object();
+ virtual ~Object();
+
+ // Type of the object. The integer is an index into the
+ // QmlCompiledData::types array, or -1 if the object is a property
+ // group.
+ int type;
+ // The url of this object if it is an external type. Used by the DOM
+ QUrl url;
+
+ // version information if type is defined in library or C++
+ int majorVersion;
+ int minorVersion;
+
+ // The fully-qualified name of this type
+ QByteArray typeName;
+ // The class name
+ QByteArray className;
+ // The id assigned to the object (if any). Set by the QmlCompiler
+ QString id;
+ // The id index assigned to the object (if any). Set by the QmlCompiler
+ int idIndex;
+ // Custom parsed data
+ QByteArray custom;
+ // Bit mask of the properties assigned bindings
+ QByteArray bindingBitmask;
+ void setBindingBit(int);
+ // Returns the metaobject for this type, or 0 if not available.
+ // Internally selectd between the metatype and extObject variables
+ const QMetaObject *metaObject() const;
+
+ // The compile time metaobject for this type
+ const QMetaObject *metatype;
+ // The synthesized metaobject, if QML added signals or properties to
+ // this type. Otherwise null
+ QAbstractDynamicMetaObject extObject;
+ QByteArray metadata; // Generated by compiler
+ QByteArray synthdata; // Generated by compiler
+
+ Property *getDefaultProperty();
+ Property *getProperty(const QByteArray &name, bool create=true);
+
+ 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 *);
+ void addSignalProperty(Property *);
+ void addAttachedProperty(Property *);
+ void addGroupedProperty(Property *);
+ void addValueTypeProperty(Property *);
+ void addScriptStringProperty(Property *, int = 0);
+ QList<Property *> valueProperties;
+ QList<Property *> signalProperties;
+ QList<Property *> attachedProperties;
+ QList<Property *> groupedProperties;
+ QList<Property *> valueTypeProperties;
+ QList<QPair<Property *, int> > scriptStringProperties;
+
+ // Script blocks that were nested under this object
+ QStringList scriptBlocks;
+ QStringList scriptBlocksFile;
+ QList<int> scriptBlocksLineNumber;
+
+ // 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.
+ int parserStatusCast;
+
+ LocationSpan location;
+
+ struct DynamicProperty {
+ DynamicProperty();
+ DynamicProperty(const DynamicProperty &);
+
+ enum Type { Variant, Int, Bool, Real, String, Url, Color, Date, Alias, Custom, CustomList };
+
+ bool isDefaultProperty;
+ Type type;
+ QByteArray customType;
+ QByteArray name;
+ QmlParser::Property *defaultValue;
+ LocationSpan location;
+ };
+ struct DynamicSignal {
+ DynamicSignal();
+ DynamicSignal(const DynamicSignal &);
+
+ QByteArray name;
+ QList<QByteArray> parameterTypes;
+ QList<QByteArray> parameterNames;
+ };
+ struct DynamicSlot {
+ DynamicSlot();
+ DynamicSlot(const DynamicSlot &);
+
+ QByteArray name;
+ QString body;
+ QList<QByteArray> parameterNames;
+ };
+
+ // The list of dynamic properties
+ QList<DynamicProperty> dynamicProperties;
+ // The list of dynamic signals
+ QList<DynamicSignal> dynamicSignals;
+ // The list of dynamic slots
+ QList<DynamicSlot> dynamicSlots;
+
+ void dump(int = 0) const;
+ };
+
+ class Variant
+ {
+ public:
+ enum Type {
+ Invalid,
+ Boolean,
+ Number,
+ String,
+ Script
+ };
+
+ Variant();
+ Variant(const Variant &);
+ Variant(bool);
+ Variant(double, const QString &asWritten=QString());
+ Variant(const QString &);
+ Variant(const QString &, QmlJS::AST::Node *);
+ Variant &operator=(const Variant &);
+
+ Type type() const;
+
+ bool isBoolean() const { return type() == Boolean; }
+ bool isNumber() const { return type() == Number; }
+ bool isString() const { return type() == String; }
+ bool isScript() const { return type() == Script; }
+
+ bool asBoolean() const;
+ QString asString() const;
+ double asNumber() const;
+ QString asScript() const;
+ QmlJS::AST::Node *asAST() const;
+
+ private:
+ Type t;
+ union {
+ bool b;
+ double d;
+ QmlJS::AST::Node *n;
+ };
+ QString s;
+ };
+
+ class Value : public QmlRefCount
+ {
+ public:
+ Value();
+ virtual ~Value();
+
+ enum Type {
+ // The type of this value assignment is not yet known
+ Unknown,
+ // This is used as a literal property assignment
+ Literal,
+ // This is used as a property binding assignment
+ PropertyBinding,
+ // This is used as a QmlPropertyValueSource assignment
+ ValueSource,
+ // This is used as a QmlPropertyValueInterceptor assignment
+ ValueInterceptor,
+ // This is used as a property QObject assignment
+ CreatedObject,
+ // This is used as a signal object assignment
+ SignalObject,
+ // This is used as a signal expression assignment
+ SignalExpression,
+ // This is used as an id assignment only
+ Id
+ };
+ Type type;
+
+ // ### Temporary
+ QString primitive() const { return value.asScript(); }
+
+ // Primitive value
+ Variant value;
+ // Object value
+ Object *object;
+
+ LocationSpan location;
+
+ void dump(int = 0) const;
+ };
+
+ class Property : public QmlRefCount
+ {
+ public:
+ Property();
+ Property(const QByteArray &n);
+ virtual ~Property();
+
+ // The Object to which this property is attached
+ Object *parent;
+
+ Object *getValue();
+ void addValue(Value *v);
+
+ // The QVariant::Type of the property, or 0 (QVariant::Invalid) if
+ // unknown.
+ int type;
+ // The metaobject index of this property, or -1 if unknown.
+ int index;
+
+ // Returns true if this is an empty property - both value and values
+ // are unset.
+ bool isEmpty() const;
+ // The list of values assigned to this property. Content in values
+ // and value are mutually exclusive
+ QList<Value *> values;
+ // The accessed property. This is used to represent dot properties.
+ // Content in value and values are mutually exclusive.
+ Object *value;
+ // The property name
+ QByteArray name;
+ // True if this property was accessed as the default property.
+ bool isDefault;
+ // True if the setting of this property will be deferred. Set by the
+ // QmlCompiler
+ bool isDeferred;
+
+ LocationSpan location;
+ LocationRange listValueRange;
+ QList<int> listCommaPositions;
+
+ void dump(int = 0) const;
+ };
+}
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QmlParser::Variant)
+
+QT_END_HEADER
+
+#endif // QMLPARSER_P_H
diff --git a/src/declarative/qml/qmlparserstatus.cpp b/src/declarative/qml/qmlparserstatus.cpp
new file mode 100644
index 0000000..0d262ca
--- /dev/null
+++ b/src/declarative/qml/qmlparserstatus.cpp
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** 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 "qmlparserstatus.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QmlParserStatus
+ \brief The QmlParserStatus class provides updates on the parser state.
+*/
+
+/*! \internal */
+QmlParserStatus::QmlParserStatus()
+: d(0)
+{
+}
+
+/*! \internal */
+QmlParserStatus::~QmlParserStatus()
+{
+ if(d)
+ (*d) = 0;
+}
+
+/*!
+ Invoked after class creation, but before any properties have been set.
+*/
+void QmlParserStatus::classBegin()
+{
+}
+
+/*!
+ Invoked after the root component that caused this instantiation has
+ completed construction. At this point all static values and binding values
+ have been assigned to the class.
+*/
+void QmlParserStatus::componentComplete()
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlparserstatus.h b/src/declarative/qml/qmlparserstatus.h
new file mode 100644
index 0000000..88ed865
--- /dev/null
+++ b/src/declarative/qml/qmlparserstatus.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** 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 QMLPARSERSTATUS_H
+#define QMLPARSERSTATUS_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class Q_DECLARATIVE_EXPORT QmlParserStatus
+{
+public:
+ QmlParserStatus();
+ virtual ~QmlParserStatus();
+
+ virtual void classBegin();
+ virtual void componentComplete();
+
+private:
+ friend class QmlVME;
+ friend class QmlComponent;
+ friend class QmlComponentPrivate;
+ friend class QmlEnginePrivate;
+ QmlParserStatus **d;
+};
+Q_DECLARE_INTERFACE(QmlParserStatus, "com.trolltech.qml.QmlParserStatus")
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLPARSERSTATUS_H
diff --git a/src/declarative/qml/qmlprivate.cpp b/src/declarative/qml/qmlprivate.cpp
new file mode 100644
index 0000000..21b19e8
--- /dev/null
+++ b/src/declarative/qml/qmlprivate.cpp
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** 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 "qmlprivate.h"
+
+QT_BEGIN_NAMESPACE
+
+QmlPrivate::InstanceType::InstanceType(int) {}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlprivate.h b/src/declarative/qml/qmlprivate.h
new file mode 100644
index 0000000..3e1a7e0
--- /dev/null
+++ b/src/declarative/qml/qmlprivate.h
@@ -0,0 +1,416 @@
+/****************************************************************************
+**
+** 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 QMLPRIVATE_H
+#define QMLPRIVATE_H
+
+#include <QtCore/qglobal.h>
+#ifndef Q_OS_WIN
+#include <stdint.h>
+#endif
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+typedef QObject *(*QmlAttachedPropertiesFunc)(QObject *);
+
+//template<typename T>
+//struct qml_hasAttached { static bool const value = false; };
+
+template <typename TYPE>
+class QmlTypeInfo
+{
+public:
+ enum {
+ hasAttachedProperties = 0
+ };
+};
+
+
+namespace QmlPrivate
+{
+ class ListInterface
+ {
+ public:
+ virtual ~ListInterface() {}
+ virtual int type() const = 0;
+ virtual void append(void *) = 0;
+ virtual void insert(int, void *) = 0;
+ virtual void removeAt(int) = 0;
+ virtual void at(int, void *) const = 0;
+ virtual int count() const = 0;
+ virtual void clear() = 0;
+ };
+
+ enum ListOp { Append, Set, Insert, Prepend, Length, FromObject,
+ Object, Create, Value, Clear };
+
+ template<typename T>
+ int list_op(ListOp op, int val,
+ const QVariant &vlist,
+ const QVariant &value,
+ void **out);
+
+ template<typename T>
+ int list_nocreate_op(ListOp op, int val,
+ const QVariant &vlist,
+ const QVariant &value,
+ void **out);
+
+ template<typename T>
+ int list_interface_op(ListOp op, int val,
+ const QVariant &vlist,
+ const QVariant &value,
+ void **out);
+
+ template<class From, class To, int N>
+ struct StaticCastSelectorClass
+ {
+ static inline int cast() { return -1; }
+ };
+
+ template<class From, class To>
+ struct StaticCastSelectorClass<From, To, sizeof(int)>
+ {
+ static inline int cast() { return (int)((intptr_t)static_cast<To *>((From *)0x10000000)) - 0x10000000; }
+ };
+
+ template<class From, class To>
+ struct StaticCastSelector
+ {
+ typedef int yes_type;
+ typedef char no_type;
+
+ static yes_type check(To *);
+ static no_type check(...);
+
+ static inline int cast()
+ {
+ return StaticCastSelectorClass<From, To, sizeof(check((From *)0))>::cast();
+ }
+ };
+
+#if defined(Q_CC_MSVC)
+ template <typename T>
+ class has_attachedPropertiesMember
+ {
+ public:
+ __if_exists(T::qmlAttachedProperties) {
+ static bool const value = true;
+ }
+ __if_not_exists(T::qmlAttachedProperties) {
+ static bool const value = false;
+ }
+ };
+#elif defined(Q_OS_SYMBIAN)
+ template <typename T>
+ struct has_attachedPropertiesMember
+ {
+ static bool const value = QmlTypeInfo<T>::hasAttachedProperties;
+ };
+#else
+ template <typename T>
+ class has_attachedPropertiesMember
+ {
+ typedef int yes_type;
+ typedef char no_type;
+ template <int>
+ struct Selector {};
+
+ template <typename S>
+ static yes_type test(Selector<sizeof(&S::qmlAttachedProperties)>*);
+
+ template <typename S>
+ static no_type test(...);
+
+ public:
+ static bool const value = sizeof(test<T>(0)) == sizeof(yes_type);
+ };
+#endif
+
+ template <typename T, bool hasMember>
+ class has_attachedPropertiesMethod
+ {
+ typedef int yes_type;
+ typedef char no_type;
+
+ template<typename ReturnType>
+ static yes_type check(ReturnType *(*)(QObject *));
+ static no_type check(...);
+
+ public:
+ static bool const value = sizeof(check(&T::qmlAttachedProperties)) == sizeof(yes_type);
+ };
+
+ template <typename T>
+ class has_attachedPropertiesMethod<T, false>
+ {
+ public:
+ static bool const value = false;
+ };
+
+ template<typename T, int N>
+ class AttachedPropertySelector
+ {
+ public:
+ static inline QmlAttachedPropertiesFunc func() { return 0; }
+ static inline const QMetaObject *metaObject() { return 0; }
+ };
+ template<typename T>
+ class AttachedPropertySelector<T, 1>
+ {
+ static inline QObject *attachedProperties(QObject *obj) {
+ return T::qmlAttachedProperties(obj);
+ }
+ template<typename ReturnType>
+ static inline const QMetaObject *attachedPropertiesMetaObject(ReturnType *(*)(QObject *)) {
+ return &ReturnType::staticMetaObject;
+ }
+ public:
+ static inline QmlAttachedPropertiesFunc func() {
+ return &attachedProperties;
+ }
+ static inline const QMetaObject *metaObject() {
+ return attachedPropertiesMetaObject(&T::qmlAttachedProperties);
+ }
+ };
+
+ template<typename T>
+ inline QmlAttachedPropertiesFunc attachedPropertiesFunc()
+ {
+ return AttachedPropertySelector<T, has_attachedPropertiesMethod<T, has_attachedPropertiesMember<T>::value>::value>::func();
+ }
+
+ template<typename T>
+ inline const QMetaObject *attachedPropertiesMetaObject()
+ {
+ return AttachedPropertySelector<T, has_attachedPropertiesMethod<T, has_attachedPropertiesMember<T>::value>::value>::metaObject();
+ }
+
+ struct MetaTypeIds {
+ int typeId;
+ int listId;
+ int qmlListId;
+ };
+ typedef int (*Func)(QmlPrivate::ListOp, int, const QVariant &, const QVariant &, void **);
+ typedef QObject *(*CreateFunc)(QObject *);
+
+ template<typename T>
+ struct CreateParent {
+ static QObject *create(QObject *other) {
+ return new T(other);
+ }
+ };
+
+ template<typename T>
+ struct CreateNoParent {
+ static QObject *create() {
+ return new T;
+ }
+ };
+
+ struct Q_DECLARATIVE_EXPORT InstanceType {
+ InstanceType(int);
+ };
+
+ template<typename T, int VMAJ, int VMIN1, int VMIN2>
+ struct Define {
+ static InstanceType instance;
+ };
+
+ template<typename T>
+ struct ExtCreate {
+ static QObject *create(QObject *other) {
+ return new T(other);
+ }
+ };
+}
+
+template<typename T>
+int QmlPrivate::list_op(QmlPrivate::ListOp op, int val,
+ const QVariant &vlist,
+ const QVariant &value,
+ void **out)
+{
+ if (op == QmlPrivate::Create) {
+ QObject *obj = static_cast<QObject *>(new T);
+ *((QObject **)out) = obj;
+ return 0;
+ }
+ QList<T *> *list = vlist.value<QList<T *> *>();
+ switch(op) {
+ case QmlPrivate::Append:
+ list->append(value.value<T *>());
+ break;
+ case QmlPrivate::Set:
+ (*list)[val] = value.value<T *>();
+ break;
+ case QmlPrivate::Insert:
+ list->insert(val, value.value<T *>());
+ break;
+ case QmlPrivate::Prepend:
+ list->prepend(value.value<T *>());
+ break;
+ case QmlPrivate::Length:
+ return list->count();
+ break;
+ case QmlPrivate::Clear:
+ list->clear();
+ return 0;
+ break;
+ case QmlPrivate::Create:
+ break;
+ case QmlPrivate::Object:
+ *out = static_cast<QObject *>(value.value<T *>());
+ break;
+ case QmlPrivate::FromObject:
+ {
+ QObject *fromObj = value.value<QObject *>();
+ T *me = qobject_cast<T *>(fromObj);
+ if (me) {
+ *((QVariant *)*out) = QVariant::fromValue(me);
+ }
+ }
+ break;
+ case QmlPrivate::Value:
+ *((QVariant *)*out) = QVariant::fromValue(list->at(val));
+ break;
+ }
+ return 0;
+}
+
+template<typename T>
+int QmlPrivate::list_nocreate_op(QmlPrivate::ListOp op, int val,
+ const QVariant &vlist,
+ const QVariant &value,
+ void **out)
+{
+ QList<T *> *list = vlist.value<QList<T *> *>();
+ switch(op) {
+ case QmlPrivate::Append:
+ list->append(value.value<T *>());
+ break;
+ case QmlPrivate::Set:
+ (*list)[val] = value.value<T *>();
+ break;
+ case QmlPrivate::Insert:
+ list->insert(val, value.value<T *>());
+ break;
+ case QmlPrivate::Prepend:
+ list->prepend(value.value<T *>());
+ break;
+ case QmlPrivate::Length:
+ return list->count();
+ break;
+ case QmlPrivate::Clear:
+ list->clear();
+ return 0;
+ break;
+ case QmlPrivate::Create:
+ break;
+ case QmlPrivate::Object:
+ *out = static_cast<QObject *>(value.value<T *>());
+ break;
+ case QmlPrivate::FromObject:
+ {
+ QObject *fromObj = value.value<QObject *>();
+ T *me = qobject_cast<T *>(fromObj);
+ if (me) {
+ *((QVariant *)*out) = QVariant::fromValue(me);
+ }
+ }
+ break;
+ case QmlPrivate::Value:
+ *((QVariant *)*out) = QVariant::fromValue(list->at(val));
+ break;
+ }
+ return 0;
+}
+
+template<typename T>
+int QmlPrivate::list_interface_op(QmlPrivate::ListOp op, int val,
+ const QVariant &vlist,
+ const QVariant &value,
+ void **out)
+{
+ QList<T *> *list = vlist.value<QList<T *> *>();
+ switch(op) {
+ case QmlPrivate::Append:
+ list->append(value.value<T *>());
+ break;
+ case QmlPrivate::Set:
+ (*list)[val] = value.value<T *>();
+ break;
+ case QmlPrivate::Insert:
+ list->insert(val, value.value<T *>());
+ break;
+ case QmlPrivate::Prepend:
+ list->prepend(value.value<T *>());
+ break;
+ case QmlPrivate::Length:
+ return list->count();
+ break;
+ case QmlPrivate::Clear:
+ list->clear();
+ return 0;
+ break;
+ case QmlPrivate::Create:
+ break;
+ case QmlPrivate::Object:
+ break;
+ case QmlPrivate::FromObject:
+ break;
+ case QmlPrivate::Value:
+ *((QVariant *)*out) = QVariant::fromValue(list->at(val));
+ break;
+ }
+ return 0;
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLPRIVATE_H
diff --git a/src/declarative/qml/qmlpropertycache.cpp b/src/declarative/qml/qmlpropertycache.cpp
new file mode 100644
index 0000000..3ede341
--- /dev/null
+++ b/src/declarative/qml/qmlpropertycache.cpp
@@ -0,0 +1,223 @@
+/****************************************************************************
+**
+** 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 = QString::fromUtf8(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 = QString::fromUtf8(m.signature());
+ int parenIdx = name.indexOf(QLatin1Char('('));
+ Q_ASSERT(parenIdx != -1);
+ name = name.left(parenIdx);
+
+ coreIndex = m.methodIndex();
+ flags |= Data::IsFunction;
+}
+
+
+QmlPropertyCache::QmlPropertyCache(QmlEngine *engine)
+: QmlCleanup(engine)
+{
+}
+
+QmlPropertyCache::~QmlPropertyCache()
+{
+ clear();
+}
+
+void QmlPropertyCache::clear()
+{
+ 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();
+
+ indexCache.clear();
+ stringCache.clear();
+ identifierCache.clear();
+}
+
+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 = QString::fromUtf8(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(engine);
+
+ 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 = QString::fromUtf8(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 = QString::fromUtf8(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..6c3142a
--- /dev/null
+++ b/src/declarative/qml/qmlpropertycache_p.h
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** 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 <private/qmlcleanup_p.h>
+#include <QtCore/qvector.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlEngine;
+class QMetaProperty;
+class QmlPropertyCache : public QmlRefCount, public QmlCleanup
+{
+public:
+ QmlPropertyCache(QmlEngine *);
+ 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;
+
+protected:
+ virtual void clear();
+
+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 &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/qmlpropertyvalueinterceptor.cpp b/src/declarative/qml/qmlpropertyvalueinterceptor.cpp
new file mode 100644
index 0000000..9a9aba8
--- /dev/null
+++ b/src/declarative/qml/qmlpropertyvalueinterceptor.cpp
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** 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 "qmlpropertyvalueinterceptor.h"
+#include "qml.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QmlPropertyValueInterceptor
+ \brief The QmlPropertyValueInterceptor class is inherited by property interceptors such as Behavior.
+ \internal
+
+ This class intercepts property writes, allowing for custom handling. For example, Behavior uses this
+ interception to provide a default animation for all changes to a property's value.
+ */
+
+/*!
+ Constructs a QmlPropertyValueInterceptor.
+*/
+QmlPropertyValueInterceptor::QmlPropertyValueInterceptor()
+{
+}
+
+QmlPropertyValueInterceptor::~QmlPropertyValueInterceptor()
+{
+}
+
+/*!
+ \fn void QmlPropertyValueInterceptor::setTarget(const QmlMetaProperty &property)
+ Set the target \a property for the value interceptor. This method will
+ be called by the QML engine when assigning a value interceptor.
+*/
+
+/*!
+ \fn void QmlPropertyValueInterceptor::write(const QVariant &value)
+ This method will be called when a new \a value is assigned to the property being intercepted.
+*/
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlpropertyvalueinterceptor.h b/src/declarative/qml/qmlpropertyvalueinterceptor.h
new file mode 100644
index 0000000..678c12c
--- /dev/null
+++ b/src/declarative/qml/qmlpropertyvalueinterceptor.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** 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 QMLPROPERTYVALUEINTERCEPTOR_H
+#define QMLPROPERTYVALUEINTERCEPTOR_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlMetaProperty;
+class Q_DECLARATIVE_EXPORT QmlPropertyValueInterceptor
+{
+public:
+ QmlPropertyValueInterceptor();
+ virtual ~QmlPropertyValueInterceptor();
+ virtual void setTarget(const QmlMetaProperty &property) = 0;
+ virtual void write(const QVariant &value) = 0;
+};
+Q_DECLARE_INTERFACE(QmlPropertyValueInterceptor, "com.trolltech.qml.QmlPropertyValueInterceptor")
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLPROPERTYVALUEINTERCEPTOR_H
diff --git a/src/declarative/qml/qmlpropertyvaluesource.cpp b/src/declarative/qml/qmlpropertyvaluesource.cpp
new file mode 100644
index 0000000..3317289
--- /dev/null
+++ b/src/declarative/qml/qmlpropertyvaluesource.cpp
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** 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 "qmlpropertyvaluesource.h"
+#include "qml.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QmlPropertyValueSource
+ \brief The QmlPropertyValueSource class is inherited by property value sources such as animations and bindings.
+ \internal
+ */
+
+/*!
+ Constructs a QmlPropertyValueSource.
+*/
+QmlPropertyValueSource::QmlPropertyValueSource()
+{
+}
+
+QmlPropertyValueSource::~QmlPropertyValueSource()
+{
+}
+
+/*!
+ \fn void QmlPropertyValueSource::setTarget(const QmlMetaProperty &property)
+ Set the target \a property for the value source. This method will
+ be called by the QML engine when assigning a value source.
+*/
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlpropertyvaluesource.h b/src/declarative/qml/qmlpropertyvaluesource.h
new file mode 100644
index 0000000..384d2f9
--- /dev/null
+++ b/src/declarative/qml/qmlpropertyvaluesource.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** 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 QMLPROPERTYVALUESOURCE_H
+#define QMLPROPERTYVALUESOURCE_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlMetaProperty;
+class Q_DECLARATIVE_EXPORT QmlPropertyValueSource
+{
+public:
+ QmlPropertyValueSource();
+ virtual ~QmlPropertyValueSource();
+ virtual void setTarget(const QmlMetaProperty &) = 0;
+};
+Q_DECLARE_INTERFACE(QmlPropertyValueSource, "com.trolltech.qml.QmlPropertyValueSource")
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLPROPERTYVALUESOURCE_H
diff --git a/src/declarative/qml/qmlproxymetaobject.cpp b/src/declarative/qml/qmlproxymetaobject.cpp
new file mode 100644
index 0000000..0baea31
--- /dev/null
+++ b/src/declarative/qml/qmlproxymetaobject.cpp
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** 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 "qmlproxymetaobject_p.h"
+
+#include <QDebug>
+
+QT_BEGIN_NAMESPACE
+
+QmlProxyMetaObject::QmlProxyMetaObject(QObject *obj, QList<ProxyData> *mList)
+: metaObjects(mList), proxies(0), parent(0), object(obj)
+{
+#ifdef QMLPROXYMETAOBJECT_DEBUG
+ qWarning() << "QmlProxyMetaObject" << obj->metaObject()->className();
+#endif
+
+ *static_cast<QMetaObject *>(this) = *metaObjects->first().metaObject;
+
+ QObjectPrivate *op = QObjectPrivate::get(obj);
+ if (op->metaObject)
+ parent = static_cast<QAbstractDynamicMetaObject*>(op->metaObject);
+
+ op->metaObject = this;
+
+#ifdef QMLPROXYMETAOBJECT_DEBUG
+ const QMetaObject *mo = obj->metaObject();
+ while(mo) {
+ qWarning() << " " << mo->className();
+ mo = mo->superClass();
+ }
+#endif
+}
+
+QmlProxyMetaObject::~QmlProxyMetaObject()
+{
+ if (parent)
+ delete parent;
+ parent = 0;
+
+ if (proxies)
+ delete [] proxies;
+ proxies = 0;
+}
+
+int QmlProxyMetaObject::metaCall(QMetaObject::Call c, int id, void **a)
+{
+ if ((c == QMetaObject::ReadProperty ||
+ c == QMetaObject::WriteProperty) &&
+ id >= metaObjects->last().propertyOffset) {
+
+ for (int ii = 0; ii < metaObjects->count(); ++ii) {
+ const ProxyData &data = metaObjects->at(ii);
+ if (id >= data.propertyOffset) {
+ if (!proxies) {
+ proxies = new QObject*[metaObjects->count()];
+ ::memset(proxies, 0,
+ sizeof(QObject *) * metaObjects->count());
+ }
+
+ if (!proxies[ii]) {
+ QObject *proxy = data.createFunc(object);
+ const QMetaObject *metaObject = proxy->metaObject();
+ proxies[ii] = proxy;
+
+ int localOffset = data.metaObject->methodOffset();
+ int methodOffset = metaObject->methodOffset();
+ int methods = metaObject->methodCount() - methodOffset;
+
+ // ### - Can this be done more optimally?
+ for (int jj = 0; jj < methods; ++jj) {
+ QMetaMethod method =
+ metaObject->method(jj + methodOffset);
+ if (method.methodType() == QMetaMethod::Signal)
+ QMetaObject::connect(proxy, methodOffset + jj,
+ object, localOffset + jj);
+ }
+ }
+
+ int proxyOffset = proxies[ii]->metaObject()->propertyOffset();
+ int proxyId = id - data.propertyOffset + proxyOffset;
+
+ return proxies[ii]->qt_metacall(c, proxyId, a);
+ }
+ }
+ } else if (c == QMetaObject::InvokeMetaMethod &&
+ id >= metaObjects->last().methodOffset) {
+ QMetaMethod m = object->metaObject()->method(id);
+ if (m.methodType() == QMetaMethod::Signal) {
+ QMetaObject::activate(object, id, a);
+ return -1;
+ }
+ }
+
+ if (parent)
+ return parent->metaCall(c, id, a);
+ else
+ return object->qt_metacall(c, id, a);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlproxymetaobject_p.h b/src/declarative/qml/qmlproxymetaobject_p.h
new file mode 100644
index 0000000..736bd91
--- /dev/null
+++ b/src/declarative/qml/qmlproxymetaobject_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 QMLPROXYMETAOBJECT_P_H
+#define QMLPROXYMETAOBJECT_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/QMetaObject>
+#include <QtCore/QObject>
+#include <private/qmetaobjectbuilder_p.h>
+#include <private/qobject_p.h>
+#include <QtDeclarative/qml.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlProxyMetaObject : public QAbstractDynamicMetaObject
+{
+public:
+ struct ProxyData {
+ typedef QObject *(*CreateFunc)(QObject *);
+ QMetaObject *metaObject;
+ CreateFunc createFunc;
+ int propertyOffset;
+ int methodOffset;
+ };
+
+ QmlProxyMetaObject(QObject *, QList<ProxyData> *);
+ virtual ~QmlProxyMetaObject();
+
+protected:
+ virtual int metaCall(QMetaObject::Call _c, int _id, void **_a);
+
+private:
+ QList<ProxyData> *metaObjects;
+ QObject **proxies;
+
+ QAbstractDynamicMetaObject *parent;
+ QObject *object;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLPROXYMETAOBJECT_P_H
+
diff --git a/src/declarative/qml/qmlrefcount.cpp b/src/declarative/qml/qmlrefcount.cpp
new file mode 100644
index 0000000..6c409e1
--- /dev/null
+++ b/src/declarative/qml/qmlrefcount.cpp
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** 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 "qmlrefcount_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QmlRefCount::QmlRefCount()
+: refCount(1)
+{
+}
+
+QmlRefCount::~QmlRefCount()
+{
+}
+
+void QmlRefCount::addref()
+{
+ Q_ASSERT(refCount > 0);
+ ++refCount;
+}
+
+void QmlRefCount::release()
+{
+ Q_ASSERT(refCount > 0);
+ --refCount;
+ if (refCount == 0)
+ delete this;
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/declarative/qml/qmlrefcount_p.h b/src/declarative/qml/qmlrefcount_p.h
new file mode 100644
index 0000000..a87d596
--- /dev/null
+++ b/src/declarative/qml/qmlrefcount_p.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** 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 QMLREFCOUNT_P_H
+#define QMLREFCOUNT_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/qglobal.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QmlRefCount
+{
+public:
+ QmlRefCount();
+ virtual ~QmlRefCount();
+ void addref();
+ void release();
+
+private:
+ int refCount;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLREFCOUNT_P_H
diff --git a/src/declarative/qml/qmlrewrite.cpp b/src/declarative/qml/qmlrewrite.cpp
new file mode 100644
index 0000000..43b2529
--- /dev/null
+++ b/src/declarative/qml/qmlrewrite.cpp
@@ -0,0 +1,191 @@
+/****************************************************************************
+**
+** 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 "qmlrewrite_p.h"
+#include <QtDeclarative/qfxglobal.h>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+DEFINE_BOOL_CONFIG_OPTION(rewriteDump, QML_REWRITE_DUMP);
+
+namespace QmlRewrite {
+
+QString RewriteBinding::operator()(const QString &code)
+{
+ Engine engine;
+ NodePool pool(QString(), &engine);
+ Lexer lexer(&engine);
+ Parser parser(&engine);
+ lexer.setCode(code, 0);
+ parser.parseStatement();
+ return rewrite(code, 0, parser.statement());
+}
+
+void RewriteBinding::accept(AST::Node *node)
+{
+ AST::Node::acceptChild(node, this);
+}
+
+QString RewriteBinding::rewrite(QString code, unsigned position,
+ AST::Statement *node)
+{
+ TextWriter w;
+ _writer = &w;
+ _position = position;
+ _inLoop = 0;
+
+ accept(node);
+
+ unsigned startOfStatement = node->firstSourceLocation().begin() - _position;
+ unsigned endOfStatement = node->lastSourceLocation().end() - _position;
+
+ _writer->replace(startOfStatement, 0, QLatin1String("(function() { "));
+ _writer->replace(endOfStatement, 0, QLatin1String(" })"));
+
+ if (rewriteDump()) {
+ qWarning() << "=============================================================";
+ qWarning() << "Rewrote:";
+ qWarning() << qPrintable(code);
+ }
+
+ w.write(&code);
+
+ if (rewriteDump()) {
+ qWarning() << "To:";
+ qWarning() << qPrintable(code);
+ qWarning() << "=============================================================";
+ }
+
+ return code;
+}
+
+bool RewriteBinding::visit(AST::Block *ast)
+{
+ for (AST::StatementList *it = ast->statements; it; it = it->next) {
+ if (! it->next) {
+ // we need to rewrite only the last statement of a block.
+ accept(it->statement);
+ }
+ }
+
+ return false;
+}
+
+bool RewriteBinding::visit(AST::ExpressionStatement *ast)
+{
+ if (! _inLoop) {
+ unsigned startOfExpressionStatement = ast->firstSourceLocation().begin() - _position;
+ _writer->replace(startOfExpressionStatement, 0, QLatin1String("return "));
+ }
+
+ return false;
+}
+
+bool RewriteBinding::visit(AST::DoWhileStatement *ast)
+{
+ ++_inLoop;
+ return true;
+}
+
+void RewriteBinding::endVisit(AST::DoWhileStatement *)
+{
+ --_inLoop;
+}
+
+bool RewriteBinding::visit(AST::WhileStatement *ast)
+{
+ ++_inLoop;
+ return true;
+}
+
+void RewriteBinding::endVisit(AST::WhileStatement *)
+{
+ --_inLoop;
+}
+
+bool RewriteBinding::visit(AST::ForStatement *ast)
+{
+ ++_inLoop;
+ return true;
+}
+
+void RewriteBinding::endVisit(AST::ForStatement *)
+{
+ --_inLoop;
+}
+
+bool RewriteBinding::visit(AST::LocalForStatement *ast)
+{
+ ++_inLoop;
+ return true;
+}
+
+void RewriteBinding::endVisit(AST::LocalForStatement *)
+{
+ --_inLoop;
+}
+
+bool RewriteBinding::visit(AST::ForEachStatement *ast)
+{
+ ++_inLoop;
+ return true;
+}
+
+void RewriteBinding::endVisit(AST::ForEachStatement *)
+{
+ --_inLoop;
+}
+
+bool RewriteBinding::visit(AST::LocalForEachStatement *ast)
+{
+ ++_inLoop;
+ return true;
+}
+
+void RewriteBinding::endVisit(AST::LocalForEachStatement *)
+{
+ --_inLoop;
+}
+
+} // namespace QmlRewrite
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlrewrite_p.h b/src/declarative/qml/qmlrewrite_p.h
new file mode 100644
index 0000000..59057d5
--- /dev/null
+++ b/src/declarative/qml/qmlrewrite_p.h
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** 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 QMLREWRITE_P_H
+#define QMLREWRITE_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 "rewriter/textwriter_p.h"
+#include "parser/qmljslexer_p.h"
+#include "parser/qmljsparser_p.h"
+#include "parser/qmljsnodepool_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QmlRewrite {
+using namespace QmlJS;
+
+class RewriteBinding: protected AST::Visitor
+{
+ unsigned _position;
+ TextWriter *_writer;
+
+public:
+ QString operator()(const QString &code);
+
+protected:
+ using AST::Visitor::visit;
+
+ void accept(AST::Node *node);
+ QString rewrite(QString code, unsigned position, AST::Statement *node);
+
+ virtual bool visit(AST::Block *ast);
+ virtual bool visit(AST::ExpressionStatement *ast);
+
+ virtual bool visit(AST::DoWhileStatement *ast);
+ virtual void endVisit(AST::DoWhileStatement *ast);
+
+ virtual bool visit(AST::WhileStatement *ast);
+ virtual void endVisit(AST::WhileStatement *ast);
+
+ virtual bool visit(AST::ForStatement *ast);
+ virtual void endVisit(AST::ForStatement *ast);
+
+ virtual bool visit(AST::LocalForStatement *ast);
+ virtual void endVisit(AST::LocalForStatement *ast);
+
+ virtual bool visit(AST::ForEachStatement *ast);
+ virtual void endVisit(AST::ForEachStatement *ast);
+
+ virtual bool visit(AST::LocalForEachStatement *ast);
+ virtual void endVisit(AST::LocalForEachStatement *ast);
+
+private:
+ int _inLoop;
+};
+
+} // namespace QmlRewrite
+
+QT_END_NAMESPACE
+
+#endif // QMLREWRITE_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
new file mode 100644
index 0000000..fb84651
--- /dev/null
+++ b/src/declarative/qml/qmlscriptparser.cpp
@@ -0,0 +1,941 @@
+/****************************************************************************
+**
+** 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 "qmlscriptparser_p.h"
+#include "qmlparser_p.h"
+
+#include "parser/qmljsengine_p.h"
+#include "parser/qmljsparser_p.h"
+#include "parser/qmljslexer_p.h"
+#include "parser/qmljsnodepool_p.h"
+#include "parser/qmljsastvisitor_p.h"
+#include "parser/qmljsast_p.h"
+
+#include "qmlrewrite_p.h"
+
+#include <QStack>
+#include <QCoreApplication>
+#include <QtDebug>
+
+#include <private/qfxperf_p.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QmlJS;
+using namespace QmlParser;
+
+namespace {
+
+class ProcessAST: protected AST::Visitor
+{
+ struct State {
+ State() : object(0), property(0) {}
+ State(Object *o) : object(o), property(0) {}
+ State(Object *o, Property *p) : object(o), property(p) {}
+
+ Object *object;
+ Property *property;
+ };
+
+ struct StateStack : public QStack<State>
+ {
+ void pushObject(Object *obj)
+ {
+ push(State(obj));
+ }
+
+ void pushProperty(const QString &name, const LocationSpan &location)
+ {
+ const State &state = top();
+ if (state.property) {
+ State s(state.property->getValue(),
+ state.property->getValue()->getProperty(name.toUtf8()));
+ s.property->location = location;
+ push(s);
+ } else {
+ State s(state.object,
+ state.object->getProperty(name.toUtf8()));
+
+ s.property->location = location;
+ push(s);
+ }
+ }
+ };
+
+public:
+ ProcessAST(QmlScriptParser *parser);
+ virtual ~ProcessAST();
+
+ void operator()(const QString &code, AST::Node *node);
+
+protected:
+ Object *defineObjectBinding(AST::UiQualifiedId *propertyName,
+ AST::UiQualifiedId *objectTypeName,
+ LocationSpan location,
+ AST::UiObjectInitializer *initializer = 0);
+
+ Object *defineObjectBinding_helper(AST::UiQualifiedId *propertyName,
+ const QString &objectType,
+ AST::SourceLocation typeLocation,
+ LocationSpan location,
+ AST::UiObjectInitializer *initializer = 0);
+
+ QmlParser::Variant getVariant(AST::ExpressionNode *expr);
+
+ LocationSpan location(AST::SourceLocation start, AST::SourceLocation end);
+ LocationSpan location(AST::UiQualifiedId *);
+
+ using AST::Visitor::visit;
+ using AST::Visitor::endVisit;
+
+ virtual bool visit(AST::UiProgram *node);
+ virtual bool visit(AST::UiImport *node);
+ virtual bool visit(AST::UiObjectDefinition *node);
+ virtual bool visit(AST::UiPublicMember *node);
+ virtual bool visit(AST::UiObjectBinding *node);
+
+ virtual bool visit(AST::UiScriptBinding *node);
+ virtual bool visit(AST::UiArrayBinding *node);
+ virtual bool visit(AST::UiSourceElement *node);
+
+ void accept(AST::Node *node);
+
+ QString asString(AST::UiQualifiedId *node) const;
+
+ const State state() const;
+ Object *currentObject() const;
+ Property *currentProperty() const;
+
+ QString qualifiedNameId() const;
+
+ QString textAt(const AST::SourceLocation &loc) const
+ { return _contents.mid(loc.offset, loc.length); }
+
+
+ QString textAt(const AST::SourceLocation &first,
+ const AST::SourceLocation &last) const
+ { return _contents.mid(first.offset, last.offset + last.length - first.offset); }
+
+ QString asString(AST::ExpressionNode *expr)
+ {
+ if (! expr)
+ return QString();
+
+ return textAt(expr->firstSourceLocation(), expr->lastSourceLocation());
+ }
+
+ QString asString(AST::Statement *stmt)
+ {
+ if (! stmt)
+ return QString();
+
+ QString s = textAt(stmt->firstSourceLocation(), stmt->lastSourceLocation());
+ s += QLatin1Char('\n');
+ return s;
+ }
+
+private:
+ QmlScriptParser *_parser;
+ StateStack _stateStack;
+ QStringList _scope;
+ QString _contents;
+
+ inline bool isSignalProperty(const QByteArray &propertyName) const {
+ return (propertyName.length() >= 3 && propertyName.startsWith("on") &&
+ ('A' <= propertyName.at(2) && 'Z' >= propertyName.at(2)));
+ }
+
+};
+
+ProcessAST::ProcessAST(QmlScriptParser *parser)
+ : _parser(parser)
+{
+}
+
+ProcessAST::~ProcessAST()
+{
+}
+
+void ProcessAST::operator()(const QString &code, AST::Node *node)
+{
+ _contents = code;
+ accept(node);
+}
+
+void ProcessAST::accept(AST::Node *node)
+{
+ AST::Node::acceptChild(node, this);
+}
+
+const ProcessAST::State ProcessAST::state() const
+{
+ if (_stateStack.isEmpty())
+ return State();
+
+ return _stateStack.back();
+}
+
+Object *ProcessAST::currentObject() const
+{
+ return state().object;
+}
+
+Property *ProcessAST::currentProperty() const
+{
+ return state().property;
+}
+
+QString ProcessAST::qualifiedNameId() const
+{
+ return _scope.join(QLatin1String("/"));
+}
+
+QString ProcessAST::asString(AST::UiQualifiedId *node) const
+{
+ QString s;
+
+ for (AST::UiQualifiedId *it = node; it; it = it->next) {
+ s.append(it->name->asString());
+
+ if (it->next)
+ s.append(QLatin1Char('.'));
+ }
+
+ return s;
+}
+
+Object *
+ProcessAST::defineObjectBinding_helper(AST::UiQualifiedId *propertyName,
+ const QString &objectType,
+ AST::SourceLocation typeLocation,
+ LocationSpan location,
+ AST::UiObjectInitializer *initializer)
+{
+ int lastTypeDot = objectType.lastIndexOf(QLatin1Char('.'));
+ bool isType = !objectType.isEmpty() &&
+ (objectType.at(0).isUpper() ||
+ (lastTypeDot >= 0 && objectType.at(lastTypeDot+1).isUpper()));
+
+ int propertyCount = 0;
+ for (; propertyName; propertyName = propertyName->next){
+ ++propertyCount;
+ _stateStack.pushProperty(propertyName->name->asString(),
+ this->location(propertyName));
+ }
+
+ if (!isType) {
+
+ if(propertyCount || !currentObject()) {
+ QmlError error;
+ error.setDescription(QCoreApplication::translate("QmlParser","Expected type name"));
+ error.setLine(typeLocation.startLine);
+ error.setColumn(typeLocation.startColumn);
+ _parser->_errors << error;
+ return 0;
+ }
+
+ LocationSpan loc = ProcessAST::location(typeLocation, typeLocation);
+ if (propertyName)
+ loc = ProcessAST::location(propertyName);
+
+ _stateStack.pushProperty(objectType, loc);
+ accept(initializer);
+ _stateStack.pop();
+
+ return 0;
+
+ } else {
+ // Class
+
+ QString resolvableObjectType = objectType;
+ if (lastTypeDot >= 0)
+ resolvableObjectType.replace(QLatin1Char('.'),QLatin1Char('/'));
+
+ bool isScript = resolvableObjectType == QLatin1String("Script");
+
+ if (isScript) {
+ if (_stateStack.isEmpty() || _stateStack.top().property) {
+ QmlError error;
+ error.setDescription(QCoreApplication::translate("QmlParser","Invalid use of Script block"));
+ error.setLine(typeLocation.startLine);
+ error.setColumn(typeLocation.startColumn);
+ _parser->_errors << error;
+ return 0;
+ }
+ }
+
+ Object *obj = new Object;
+
+ 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);
+ obj->typeName = qualifiedNameId().toUtf8();
+ _scope.removeLast();
+
+ obj->location = location;
+
+ if (isScript) {
+
+ _stateStack.top().object->scriptBlockObjects.append(obj);
+
+ } else if (propertyCount) {
+
+ Property *prop = currentProperty();
+ Value *v = new Value;
+ v->object = obj;
+ v->location = obj->location;
+ prop->addValue(v);
+
+ while (propertyCount--)
+ _stateStack.pop();
+
+ } else {
+
+ if (! _parser->tree()) {
+ _parser->setTree(obj);
+ } else {
+ const State state = _stateStack.top();
+ Value *v = new Value;
+ v->object = obj;
+ v->location = obj->location;
+ if (state.property)
+ state.property->addValue(v);
+ else
+ state.object->getDefaultProperty()->addValue(v);
+ }
+ }
+
+ _stateStack.pushObject(obj);
+ accept(initializer);
+ _stateStack.pop();
+
+ return obj;
+ }
+}
+
+Object *ProcessAST::defineObjectBinding(AST::UiQualifiedId *qualifiedId,
+ AST::UiQualifiedId *objectTypeName,
+ LocationSpan location,
+ AST::UiObjectInitializer *initializer)
+{
+ const QString objectType = asString(objectTypeName);
+ const AST::SourceLocation typeLocation = objectTypeName->identifierToken;
+
+ 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);
+}
+
+LocationSpan ProcessAST::location(AST::UiQualifiedId *id)
+{
+ return location(id->identifierToken, id->identifierToken);
+}
+
+LocationSpan ProcessAST::location(AST::SourceLocation start, AST::SourceLocation end)
+{
+ LocationSpan rv;
+ rv.start.line = start.startLine;
+ rv.start.column = start.startColumn;
+ rv.end.line = end.startLine;
+ rv.end.column = end.startColumn + end.length - 1;
+ rv.range.offset = start.offset;
+ rv.range.length = end.offset + end.length - start.offset;
+ return rv;
+}
+
+// UiProgram: UiImportListOpt UiObjectMemberList ;
+bool ProcessAST::visit(AST::UiProgram *node)
+{
+ accept(node->imports);
+ accept(node->members->member);
+ return false;
+}
+
+// UiImport: T_IMPORT T_STRING_LITERAL ;
+bool ProcessAST::visit(AST::UiImport *node)
+{
+ QString uri;
+ QmlScriptParser::Import import;
+
+ if (node->fileName) {
+ import.type = QmlScriptParser::Import::File;
+ uri = node->fileName->asString();
+ } else {
+ import.type = QmlScriptParser::Import::Library;
+ uri = asString(node->importUri);
+ }
+
+ AST::SourceLocation startLoc = node->importToken;
+ AST::SourceLocation endLoc = node->semicolonToken;
+
+ if (node->importId) {
+ import.qualifier = node->importId->asString();
+ if (!import.qualifier.at(0).isUpper()) {
+ QmlError error;
+ error.setDescription(QCoreApplication::translate("QmlParser","Invalid import qualifier ID"));
+ error.setLine(node->importIdToken.startLine);
+ error.setColumn(node->importIdToken.startColumn);
+ _parser->_errors << error;
+ return false;
+ }
+ }
+ if (node->versionToken.isValid())
+ import.version = textAt(node->versionToken);
+ else if (import.type == QmlScriptParser::Import::Library) {
+ QmlError error;
+ error.setDescription(QCoreApplication::translate("QmlParser","Library import requires a version"));
+ error.setLine(node->importIdToken.startLine);
+ error.setColumn(node->importIdToken.startColumn);
+ _parser->_errors << error;
+ return false;
+ }
+
+ import.location = location(startLoc, endLoc);
+ import.uri = uri;
+
+ _parser->_imports << import;
+
+ return false;
+}
+
+bool ProcessAST::visit(AST::UiPublicMember *node)
+{
+ const struct TypeNameToType {
+ const char *name;
+ Object::DynamicProperty::Type type;
+ const char *qtName;
+ } propTypeNameToTypes[] = {
+ { "int", Object::DynamicProperty::Int, "int" },
+ { "bool", Object::DynamicProperty::Bool, "bool" },
+ { "double", Object::DynamicProperty::Real, "double" },
+ { "real", Object::DynamicProperty::Real, "qreal" },
+ { "string", Object::DynamicProperty::String, "QString" },
+ { "url", Object::DynamicProperty::Url, "QUrl" },
+ { "color", Object::DynamicProperty::Color, "QColor" },
+ { "date", Object::DynamicProperty::Date, "QDate" },
+ { "var", Object::DynamicProperty::Variant, "QVariant" },
+ { "variant", Object::DynamicProperty::Variant, "QVariant" }
+ };
+ const int propTypeNameToTypesCount = sizeof(propTypeNameToTypes) /
+ sizeof(propTypeNameToTypes[0]);
+
+ if(node->type == AST::UiPublicMember::Signal) {
+ const QString name = node->name->asString();
+
+ Object::DynamicSignal signal;
+ signal.name = name.toUtf8();
+
+ AST::UiParameterList *p = node->parameters;
+ while (p) {
+ const QString memberType = p->type->asString();
+ const char *qtType = 0;
+ for(int ii = 0; !qtType && ii < propTypeNameToTypesCount; ++ii) {
+ if(QLatin1String(propTypeNameToTypes[ii].name) == memberType)
+ qtType = propTypeNameToTypes[ii].qtName;
+ }
+
+ if (!qtType) {
+ QmlError error;
+ error.setDescription(QCoreApplication::translate("QmlParser","Expected parameter type"));
+ error.setLine(node->typeToken.startLine);
+ error.setColumn(node->typeToken.startColumn);
+ _parser->_errors << error;
+ return false;
+ }
+
+ signal.parameterTypes << qtType;
+ signal.parameterNames << p->name->asString().toUtf8();
+ p = p->finish();
+ }
+
+ _stateStack.top().object->dynamicSignals << signal;
+ } else {
+ const QString memberType = node->memberType->asString();
+ const QString name = node->name->asString();
+
+ bool typeFound = false;
+ Object::DynamicProperty::Type type;
+
+ if (memberType == QLatin1String("alias")) {
+ type = Object::DynamicProperty::Alias;
+ typeFound = true;
+ }
+
+ for(int ii = 0; !typeFound && ii < propTypeNameToTypesCount; ++ii) {
+ if(QLatin1String(propTypeNameToTypes[ii].name) == memberType) {
+ type = propTypeNameToTypes[ii].type;
+ typeFound = true;
+ }
+ }
+
+ if (!typeFound && memberType.at(0).isUpper()) {
+ QString typemodifier;
+ if(node->typeModifier)
+ typemodifier = node->typeModifier->asString();
+ if (typemodifier == QString()) {
+ type = Object::DynamicProperty::Custom;
+ } else if(typemodifier == QLatin1String("list")) {
+ type = Object::DynamicProperty::CustomList;
+ } else {
+ QmlError error;
+ error.setDescription(QCoreApplication::translate("QmlParser","Invalid property type modifier"));
+ error.setLine(node->typeModifierToken.startLine);
+ error.setColumn(node->typeModifierToken.startColumn);
+ _parser->_errors << error;
+ return false;
+ }
+ typeFound = true;
+ } else if (node->typeModifier) {
+ QmlError error;
+ error.setDescription(QCoreApplication::translate("QmlParser","Unexpected property type modifier"));
+ error.setLine(node->typeModifierToken.startLine);
+ error.setColumn(node->typeModifierToken.startColumn);
+ _parser->_errors << error;
+ return false;
+ }
+
+ if(!typeFound) {
+ QmlError error;
+ error.setDescription(QCoreApplication::translate("QmlParser","Expected property type"));
+ error.setLine(node->typeToken.startLine);
+ error.setColumn(node->typeToken.startColumn);
+ _parser->_errors << error;
+ return false;
+ }
+
+ if (node->isReadonlyMember) {
+ QmlError error;
+ error.setDescription(QCoreApplication::translate("QmlParser","Readonly not yet supported"));
+ error.setLine(node->readonlyToken.startLine);
+ error.setColumn(node->readonlyToken.startColumn);
+ _parser->_errors << error;
+ return false;
+
+ }
+ Object::DynamicProperty property;
+ property.isDefaultProperty = node->isDefaultMember;
+ property.type = type;
+ if (type >= Object::DynamicProperty::Custom) {
+ QmlScriptParser::TypeReference *typeRef =
+ _parser->findOrCreateType(memberType);
+ typeRef->refObjects.append(_stateStack.top().object);
+ property.customType = memberType.toUtf8();
+ }
+ property.name = name.toUtf8();
+ property.location = location(node->firstSourceLocation(),
+ node->lastSourceLocation());
+
+ if (node->expression) { // default value
+ property.defaultValue = new Property;
+ property.defaultValue->parent = _stateStack.top().object;
+ Value *value = new Value;
+ value->location = location(node->expression->firstSourceLocation(),
+ node->expression->lastSourceLocation());
+ value->value = getVariant(node->expression);
+ property.defaultValue->values << value;
+ }
+
+ _stateStack.top().object->dynamicProperties << property;
+ }
+
+ return true;
+}
+
+
+// UiObjectMember: UiQualifiedId UiObjectInitializer ;
+bool ProcessAST::visit(AST::UiObjectDefinition *node)
+{
+ LocationSpan l = location(node->firstSourceLocation(),
+ node->lastSourceLocation());
+
+ defineObjectBinding(/*propertyName = */ 0,
+ node->qualifiedTypeNameId,
+ l,
+ node->initializer);
+
+ return false;
+}
+
+
+// UiObjectMember: UiQualifiedId T_COLON UiQualifiedId UiObjectInitializer ;
+bool ProcessAST::visit(AST::UiObjectBinding *node)
+{
+ LocationSpan l = location(node->qualifiedTypeNameId->identifierToken,
+ node->initializer->rbraceToken);
+
+ defineObjectBinding(node->qualifiedId,
+ node->qualifiedTypeNameId,
+ l,
+ node->initializer);
+
+ return false;
+}
+
+QmlParser::Variant ProcessAST::getVariant(AST::ExpressionNode *expr)
+{
+ if (AST::StringLiteral *lit = AST::cast<AST::StringLiteral *>(expr)) {
+ return QmlParser::Variant(lit->value->asString());
+ } else if (expr->kind == AST::Node::Kind_TrueLiteral) {
+ return QmlParser::Variant(true);
+ } else if (expr->kind == AST::Node::Kind_FalseLiteral) {
+ return QmlParser::Variant(false);
+ } else if (AST::NumericLiteral *lit = AST::cast<AST::NumericLiteral *>(expr)) {
+ return QmlParser::Variant(lit->value, asString(expr));
+ } else {
+
+ if (AST::UnaryMinusExpression *unaryMinus = AST::cast<AST::UnaryMinusExpression *>(expr)) {
+ if (AST::NumericLiteral *lit = AST::cast<AST::NumericLiteral *>(unaryMinus->expression)) {
+ return QmlParser::Variant(-lit->value, asString(expr));
+ }
+ }
+
+ return QmlParser::Variant(asString(expr), expr);
+ }
+}
+
+
+// UiObjectMember: UiQualifiedId T_COLON Statement ;
+bool ProcessAST::visit(AST::UiScriptBinding *node)
+{
+ int propertyCount = 0;
+ AST::UiQualifiedId *propertyName = node->qualifiedId;
+ for (; propertyName; propertyName = propertyName->next){
+ ++propertyCount;
+ _stateStack.pushProperty(propertyName->name->asString(),
+ location(propertyName));
+ }
+
+ Property *prop = currentProperty();
+
+ QmlParser::Variant primitive;
+
+ if (AST::ExpressionStatement *stmt = AST::cast<AST::ExpressionStatement *>(node->statement)) {
+ primitive = getVariant(stmt->expression);
+ } else { // do binding
+ primitive = QmlParser::Variant(asString(node->statement),
+ node->statement);
+ }
+
+ prop->location.range.length = prop->location.range.offset + prop->location.range.length - node->qualifiedId->identifierToken.offset;
+ prop->location.range.offset = node->qualifiedId->identifierToken.offset;
+ Value *v = new Value;
+ v->value = primitive;
+ v->location = location(node->statement->firstSourceLocation(),
+ node->statement->lastSourceLocation());
+
+ prop->addValue(v);
+
+ while (propertyCount--)
+ _stateStack.pop();
+
+ return true;
+}
+
+static QList<int> collectCommas(AST::UiArrayMemberList *members)
+{
+ QList<int> commas;
+
+ if (members) {
+ for (AST::UiArrayMemberList *it = members->next; it; it = it->next) {
+ commas.append(it->commaToken.offset);
+ }
+ }
+
+ return commas;
+}
+
+// UiObjectMember: UiQualifiedId T_COLON T_LBRACKET UiArrayMemberList T_RBRACKET ;
+bool ProcessAST::visit(AST::UiArrayBinding *node)
+{
+ int propertyCount = 0;
+ AST::UiQualifiedId *propertyName = node->qualifiedId;
+ for (; propertyName; propertyName = propertyName->next){
+ ++propertyCount;
+ _stateStack.pushProperty(propertyName->name->asString(),
+ location(propertyName));
+ }
+
+ accept(node->members);
+
+ // For the DOM, store the position of the T_LBRACKET upto the T_RBRACKET as the range:
+ Property* prop = currentProperty();
+ prop->listValueRange.offset = node->lbracketToken.offset;
+ prop->listValueRange.length = node->rbracketToken.offset + node->rbracketToken.length - node->lbracketToken.offset;
+
+ // Store the positions of the comma token too, again for the DOM to be able to retreive it.
+ prop->listCommaPositions = collectCommas(node->members);
+
+ while (propertyCount--)
+ _stateStack.pop();
+
+ return false;
+}
+
+bool ProcessAST::visit(AST::UiSourceElement *node)
+{
+ QmlParser::Object *obj = currentObject();
+
+ bool isScript = (obj && obj->typeName == "Script");
+
+ if (!isScript) {
+
+ if (AST::FunctionDeclaration *funDecl = AST::cast<AST::FunctionDeclaration *>(node->sourceElement)) {
+
+ Object::DynamicSlot slot;
+
+ AST::FormalParameterList *f = funDecl->formals;
+ while (f) {
+ slot.parameterNames << f->name->asString().toUtf8();
+ f = f->finish();
+ }
+
+ QString body = textAt(funDecl->lbraceToken, funDecl->rbraceToken);
+ slot.name = funDecl->name->asString().toUtf8();
+ slot.body = body;
+ obj->dynamicSlots << slot;
+
+ } else {
+ QmlError error;
+ error.setDescription(QCoreApplication::translate("QmlParser","QmlJS declaration outside Script element"));
+ error.setLine(node->firstSourceLocation().startLine);
+ error.setColumn(node->firstSourceLocation().startColumn);
+ _parser->_errors << error;
+ }
+ return false;
+
+ } else {
+ QString source;
+
+ int line = 0;
+ if (AST::FunctionDeclaration *funDecl = AST::cast<AST::FunctionDeclaration *>(node->sourceElement)) {
+ line = funDecl->functionToken.startLine;
+ source = asString(funDecl);
+ } else if (AST::VariableStatement *varStmt = AST::cast<AST::VariableStatement *>(node->sourceElement)) {
+ // ignore variable declarations
+ line = varStmt->declarationKindToken.startLine;
+
+ QmlError error;
+ error.setDescription(QCoreApplication::translate("QmlParser", "Variable declarations not allow in inline Script blocks"));
+ error.setLine(node->firstSourceLocation().startLine);
+ error.setColumn(node->firstSourceLocation().startColumn);
+ _parser->_errors << error;
+ return false;
+ }
+
+ Value *value = new Value;
+ value->location = location(node->firstSourceLocation(),
+ node->lastSourceLocation());
+ value->value = QmlParser::Variant(source);
+
+ obj->getDefaultProperty()->addValue(value);
+ }
+
+ return false;
+}
+
+} // end of anonymous namespace
+
+
+QmlScriptParser::QmlScriptParser()
+: root(0), data(0)
+{
+
+}
+
+QmlScriptParser::~QmlScriptParser()
+{
+ clear();
+}
+
+class QmlScriptParserJsASTData
+{
+public:
+ QmlScriptParserJsASTData(const QString &filename)
+ : nodePool(filename, &engine) {}
+
+ Engine engine;
+ NodePool nodePool;
+};
+
+bool QmlScriptParser::parse(const QByteArray &qmldata, const QUrl &url)
+{
+#ifdef Q_ENABLE_PERFORMANCE_LOG
+ QFxPerfTimer<QFxPerf::QmlParsing> pt;
+#endif
+ clear();
+
+ const QString fileName = url.toString();
+
+ QTextStream stream(qmldata, QIODevice::ReadOnly);
+ stream.setCodec("UTF-8");
+ const QString code = stream.readAll();
+
+ data = new QmlScriptParserJsASTData(fileName);
+
+ Lexer lexer(&data->engine);
+ lexer.setCode(code, /*line = */ 1);
+
+ Parser parser(&data->engine);
+
+ if (! parser.parse() || !_errors.isEmpty()) {
+
+ // Extract errors from the parser
+ foreach (const DiagnosticMessage &m, parser.diagnosticMessages()) {
+
+ if (m.isWarning())
+ continue;
+
+ QmlError error;
+ error.setUrl(url);
+ error.setDescription(m.message);
+ error.setLine(m.loc.startLine);
+ error.setColumn(m.loc.startColumn);
+ _errors << error;
+
+ }
+ }
+
+ if (_errors.isEmpty()) {
+ ProcessAST process(this);
+ process(code, parser.ast());
+
+ // Set the url for process errors
+ for(int ii = 0; ii < _errors.count(); ++ii)
+ _errors[ii].setUrl(url);
+ }
+
+ return _errors.isEmpty();
+}
+
+QList<QmlScriptParser::TypeReference*> QmlScriptParser::referencedTypes() const
+{
+ return _refTypes;
+}
+
+QList<QUrl> QmlScriptParser::referencedResources() const
+{
+ return _refUrls;
+}
+
+Object *QmlScriptParser::tree() const
+{
+ return root;
+}
+
+QList<QmlScriptParser::Import> QmlScriptParser::imports() const
+{
+ return _imports;
+}
+
+QList<QmlError> QmlScriptParser::errors() const
+{
+ return _errors;
+}
+
+void QmlScriptParser::clear()
+{
+ if (root) {
+ root->release();
+ root = 0;
+ }
+ _imports.clear();
+ qDeleteAll(_refTypes);
+ _refTypes.clear();
+ _errors.clear();
+
+ if (data) {
+ delete data;
+ data = 0;
+ }
+}
+
+QmlScriptParser::TypeReference *QmlScriptParser::findOrCreateType(const QString &name)
+{
+ TypeReference *type = 0;
+ int i = 0;
+ for (; i < _refTypes.size(); ++i) {
+ if (_refTypes.at(i)->name == name) {
+ type = _refTypes.at(i);
+ break;
+ }
+ }
+ if (!type) {
+ type = new TypeReference(i, name);
+ _refTypes.append(type);
+ }
+
+ return type;
+}
+
+void QmlScriptParser::setTree(Object *tree)
+{
+ Q_ASSERT(! root);
+
+ root = tree;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlscriptparser_p.h b/src/declarative/qml/qmlscriptparser_p.h
new file mode 100644
index 0000000..b25d6bf
--- /dev/null
+++ b/src/declarative/qml/qmlscriptparser_p.h
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** 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 QMLSCRIPTPARSER_P_H
+#define QMLSCRIPTPARSER_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/QList>
+#include <QtCore/QUrl>
+#include <QtDeclarative/qmlerror.h>
+#include "qmlparser_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QByteArray;
+
+class QmlScriptParserJsASTData;
+class QmlScriptParser
+{
+public:
+ class Import
+ {
+ public:
+ Import() : type(Library) {}
+
+ enum Type { Library, File };
+ Type type;
+
+ QString uri;
+ QString qualifier;
+ QString version;
+
+ QmlParser::LocationSpan location;
+ };
+
+ class TypeReference
+ {
+ public:
+ TypeReference(int typeId, const QString &typeName) : id(typeId), name(typeName) {}
+
+ int id;
+ // type as it has been referenced in Qml
+ QString name;
+ // objects in parse tree referencing the type
+ QList<QmlParser::Object*> refObjects;
+ };
+
+ QmlScriptParser();
+ ~QmlScriptParser();
+
+ 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;
+
+ void clear();
+
+ QList<QmlError> errors() const;
+
+// ### private:
+ TypeReference *findOrCreateType(const QString &name);
+ void setTree(QmlParser::Object *tree);
+
+ void setScriptFile(const QString &filename) {_scriptFile = filename; }
+ QString scriptFile() const { return _scriptFile; }
+
+// ### private:
+ QList<QmlError> _errors;
+
+ QmlParser::Object *root;
+ QList<Import> _imports;
+ QList<TypeReference*> _refTypes;
+ QList<QUrl> _refUrls;
+ QString _scriptFile;
+ QmlScriptParserJsASTData *data;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLSCRIPTPARSER_P_H
diff --git a/src/declarative/qml/qmlscriptstring.cpp b/src/declarative/qml/qmlscriptstring.cpp
new file mode 100644
index 0000000..8a6afcc
--- /dev/null
+++ b/src/declarative/qml/qmlscriptstring.cpp
@@ -0,0 +1,154 @@
+/****************************************************************************
+**
+** 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 "qmlscriptstring.h"
+
+QT_BEGIN_NAMESPACE
+
+class QmlScriptStringPrivate : public QSharedData
+{
+public:
+ QmlScriptStringPrivate() : context(0), scope(0) {}
+
+ QmlContext *context;
+ QObject *scope;
+ QString script;
+};
+
+/*!
+\class QmlScriptString
+\brief The QmlScriptString class encapsulates a script and its context.
+
+The QmlScriptString is used by properties that want to accept a script "assignment" from QML.
+
+Normally, the following code would result in a binding being established for the \c script
+property. If the property had a type of QmlScriptString, the script - \e {print(1921)} - itself
+would be passed to the property and it could choose how to handle it.
+
+\code
+MyType {
+ script: print(1921)
+}
+\endcode
+*/
+
+/*!
+Construct an empty instance.
+*/
+QmlScriptString::QmlScriptString()
+: d(new QmlScriptStringPrivate)
+{
+}
+
+/*!
+Copy \a other.
+*/
+QmlScriptString::QmlScriptString(const QmlScriptString &other)
+: d(other.d)
+{
+}
+
+/*!
+\internal
+*/
+QmlScriptString::~QmlScriptString()
+{
+}
+
+/*!
+Assign \a other to this.
+*/
+QmlScriptString &QmlScriptString::operator=(const QmlScriptString &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+Return the context for the script.
+*/
+QmlContext *QmlScriptString::context() const
+{
+ return d->context;
+}
+
+/*!
+Sets the \a context for the script.
+*/
+void QmlScriptString::setContext(QmlContext *context)
+{
+ d->context = context;
+}
+
+/*!
+Returns the scope object for the script.
+*/
+QObject *QmlScriptString::scopeObject() const
+{
+ return d->scope;
+}
+
+/*!
+Sets the scope \a object for the script.
+*/
+void QmlScriptString::setScopeObject(QObject *object)
+{
+ d->scope = object;
+}
+
+/*!
+Returns the script text.
+*/
+QString QmlScriptString::script() const
+{
+ return d->script;
+}
+
+/*!
+Sets the \a script text.
+*/
+void QmlScriptString::setScript(const QString &script)
+{
+ d->script = script;
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/declarative/qml/qmlscriptstring.h b/src/declarative/qml/qmlscriptstring.h
new file mode 100644
index 0000000..c6067ce
--- /dev/null
+++ b/src/declarative/qml/qmlscriptstring.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** 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 QMLSCRIPTSTRING_H
+#define QMLSCRIPTSTRING_H
+
+#include <QtCore/qstring.h>
+#include <QtCore/qshareddata.h>
+#include <QtCore/qmetatype.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QObject;
+class QmlContext;
+class QmlScriptStringPrivate;
+class Q_DECLARATIVE_EXPORT QmlScriptString
+{
+public:
+ QmlScriptString();
+ QmlScriptString(const QmlScriptString &);
+ ~QmlScriptString();
+
+ QmlScriptString &operator=(const QmlScriptString &);
+
+ QmlContext *context() const;
+ void setContext(QmlContext *);
+
+ QObject *scopeObject() const;
+ void setScopeObject(QObject *);
+
+ QString script() const;
+ void setScript(const QString &);
+
+private:
+ QSharedDataPointer<QmlScriptStringPrivate> d;
+};
+
+Q_DECLARE_METATYPE(QmlScriptString);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMLSCRIPTSTRING_H
+
diff --git a/src/declarative/qml/qmlsqldatabase.cpp b/src/declarative/qml/qmlsqldatabase.cpp
new file mode 100644
index 0000000..9e39ffc
--- /dev/null
+++ b/src/declarative/qml/qmlsqldatabase.cpp
@@ -0,0 +1,369 @@
+/****************************************************************************
+**
+** 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 <QtCore/qobject.h>
+#include <QtDeclarative/qmlengine.h>
+#include <private/qmlengine_p.h>
+#include <QtScript/qscriptvalue.h>
+#include <QtScript/qscriptvalueiterator.h>
+#include <QtScript/qscriptcontext.h>
+#include <QtScript/qscriptengine.h>
+#include <QtScript/qscriptclasspropertyiterator.h>
+#include <QtSql/qsqldatabase.h>
+#include <QtSql/qsqlquery.h>
+#include <QtSql/qsqlerror.h>
+#include <QtSql/qsqlrecord.h>
+#include <private/qmlrefcount_p.h>
+#include <private/qmlengine_p.h>
+#include <QtCore/qstack.h>
+#include <QtCore/qcryptographichash.h>
+#include "qmlsqldatabase_p.h"
+#include <QtCore/qsettings.h>
+#include <QtCore/qdir.h>
+#include <QtCore/qdebug.h>
+
+Q_DECLARE_METATYPE(QSqlDatabase)
+Q_DECLARE_METATYPE(QSqlQuery)
+
+class QmlSqlQueryScriptClassPropertyIterator;
+
+class QmlSqlQueryScriptClass: public QScriptClass {
+public:
+ QmlSqlQueryScriptClass(QScriptEngine *engine) : QScriptClass(engine)
+ {
+ str_length = engine->toStringHandle(QLatin1String("length"));
+ str_forwardOnly = engine->toStringHandle(QLatin1String("forwardOnly")); // not in HTML5 (an optimization)
+ }
+
+ QueryFlags queryProperty(const QScriptValue &object,
+ const QScriptString &name,
+ QueryFlags flags, uint *id)
+ {
+ if (flags & HandlesReadAccess) {
+ if (name == str_length) {
+ return HandlesReadAccess;
+ } else if (name == str_forwardOnly) {
+ return flags;
+ } else {
+ bool ok;
+ qint32 pos = name.toString().toInt(&ok);
+ if (pos < 0 || !ok)
+ return 0;
+ QSqlQuery query = qscriptvalue_cast<QSqlQuery>(object.data());
+ *id = pos;
+ if (*id < (uint)query.size())
+ return HandlesReadAccess;
+ }
+ }
+ if (flags & HandlesWriteAccess)
+ if (name == str_forwardOnly)
+ return flags;
+ return 0;
+ }
+
+ QScriptValue property(const QScriptValue &object,
+ const QScriptString &name, uint id)
+ {
+ QSqlQuery query = qscriptvalue_cast<QSqlQuery>(object.data());
+ if (name == str_length) {
+ int s = query.size();
+ if (s<0) {
+ // Inefficient.
+ query.last();
+ return query.at()+1;
+ } else {
+ return s;
+ }
+ } else if (name == str_forwardOnly) {
+ return query.isForwardOnly();
+ } else {
+ if ((uint)query.at() == id || query.seek(id)) { // Qt 4.6 doesn't optimize seek(at())
+ QSqlRecord r = query.record();
+ QScriptValue row = engine()->newObject();
+ for (int j=0; j<r.count(); ++j) {
+ row.setProperty(r.fieldName(j), QScriptValue(engine(),r.value(j).toString())); // XXX only strings
+ }
+ return row;
+ }
+ }
+ return engine()->undefinedValue();
+ }
+
+ void setProperty(QScriptValue &object,
+ const QScriptString &name, uint, const QScriptValue & value)
+ {
+ if (name == str_forwardOnly) {
+ QSqlQuery query = qscriptvalue_cast<QSqlQuery>(object.data());
+ query.setForwardOnly(value.toBool());
+ }
+ }
+
+ QScriptValue::PropertyFlags propertyFlags(const QScriptValue &/*object*/, const QScriptString &name, uint /*id*/)
+ {
+ if (name == str_length) {
+ return QScriptValue::Undeletable
+ | QScriptValue::SkipInEnumeration;
+ }
+ return QScriptValue::Undeletable;
+ }
+
+ QScriptClassPropertyIterator *newIterator(const QScriptValue &object);
+
+private:
+ QScriptString str_length;
+ QScriptString str_forwardOnly;
+};
+
+class QmlSqlQueryScriptClassPropertyIterator : public QScriptClassPropertyIterator
+{
+public:
+ QmlSqlQueryScriptClassPropertyIterator(const QScriptValue &object)
+ : QScriptClassPropertyIterator(object)
+ {
+ toFront();
+ }
+
+ ~QmlSqlQueryScriptClassPropertyIterator()
+ {
+ }
+
+ bool hasNext() const
+ {
+ QSqlQuery query = qscriptvalue_cast<QSqlQuery>(object().data());
+ return query.at() == m_index || query.seek(m_index); // Qt 4.6 doesn't optimize seek(at())
+ }
+
+ void next()
+ {
+ m_last = m_index;
+ ++m_index;
+ }
+
+ bool hasPrevious() const
+ {
+ return (m_index > 0);
+ }
+
+ void previous()
+ {
+ --m_index;
+ m_last = m_index;
+ }
+
+ void toFront()
+ {
+ m_index = 0;
+ m_last = -1;
+ }
+
+ void toBack()
+ {
+ QSqlQuery query = qscriptvalue_cast<QSqlQuery>(object().data());
+ m_index = query.size();
+ m_last = -1;
+ }
+
+ QScriptString name() const
+ {
+ return object().engine()->toStringHandle(QString::number(m_last));
+ }
+
+ uint id() const
+ {
+ return m_last;
+ }
+
+private:
+ int m_index;
+ int m_last;
+};
+
+QScriptClassPropertyIterator *QmlSqlQueryScriptClass::newIterator(const QScriptValue &object)
+{
+ return new QmlSqlQueryScriptClassPropertyIterator(object);
+}
+
+
+
+static QScriptValue qmlsqldatabase_item(QScriptContext *context, QScriptEngine *engine)
+{
+ QSqlQuery query = qscriptvalue_cast<QSqlQuery>(context->thisObject().data());
+ int i = context->argument(0).toNumber();
+ if (query.at() == i || query.seek(i)) { // Qt 4.6 doesn't optimize seek(at())
+ QSqlRecord r = query.record();
+ QScriptValue row = engine->newObject();
+ for (int j=0; j<r.count(); ++j) {
+ row.setProperty(r.fieldName(j), QScriptValue(engine,r.value(j).toString()));
+ }
+ return row;
+ }
+ return engine->undefinedValue();
+}
+
+static QScriptValue qmlsqldatabase_executeSql(QScriptContext *context, QScriptEngine *engine)
+{
+ QSqlDatabase db = qscriptvalue_cast<QSqlDatabase>(context->thisObject());
+ QString sql = context->argument(0).toString();
+ QScriptValue values = context->argument(1);
+ QScriptValue cb = context->argument(2);
+ QScriptValue cberr = context->argument(3);
+ QSqlQuery query(db);
+ bool err = false;
+ if (query.prepare(sql)) {
+ if (values.isArray()) {
+ for (QScriptValueIterator it(values); it.hasNext();) {
+ it.next();
+ query.addBindValue(it.value().toVariant());
+ }
+ } else {
+ query.bindValue(0,values.toVariant());
+ }
+ if (query.exec()) {
+ QScriptValue rs = engine->newObject();
+ if (!QmlEnginePrivate::get(engine)->sqlQueryClass)
+ QmlEnginePrivate::get(engine)->sqlQueryClass= new QmlSqlQueryScriptClass(engine);
+ QScriptValue rows = engine->newObject(QmlEnginePrivate::get(engine)->sqlQueryClass);
+ rows.setData(engine->newVariant(qVariantFromValue(query)));
+ rows.setProperty(QLatin1String("item"), engine->newFunction(qmlsqldatabase_item,1), QScriptValue::SkipInEnumeration);
+ rs.setProperty(QLatin1String("rows"),rows);
+ rs.setProperty(QLatin1String("rowsAffected"),query.numRowsAffected());
+ rs.setProperty(QLatin1String("insertId"),query.lastInsertId().toString()); // XXX only string
+ cb.call(QScriptValue(), QScriptValueList() << context->thisObject() << rs);
+ } else {
+ err = true;
+ }
+ } else {
+ err = true;
+ }
+ if (err) {
+ QScriptValue error = engine->newObject();
+ error.setProperty(QLatin1String("message"), query.lastError().text());
+ cberr.call(QScriptValue(), QScriptValueList() << context->thisObject() << error);
+ }
+ return engine->undefinedValue();
+}
+
+static QScriptValue qmlsqldatabase_transaction(QScriptContext *context, QScriptEngine *engine)
+{
+ QSqlDatabase db = qscriptvalue_cast<QSqlDatabase>(context->thisObject());
+ if (context->argumentCount() < 1)
+ return engine->undefinedValue();
+ QScriptValue cb = context->argument(0);
+ if (!cb.isFunction())
+ return engine->undefinedValue();
+
+ // Call synchronously... - XXX could do asynch with threads
+ QScriptValue instance = engine->newObject();
+ instance.setProperty(QLatin1String("executeSql"), engine->newFunction(qmlsqldatabase_executeSql,4));
+ QScriptValue tx = engine->newVariant(instance,qVariantFromValue(db));
+
+ db.transaction();
+ cb.call(QScriptValue(), QScriptValueList() << tx);
+ if (engine->hasUncaughtException()) {
+ db.rollback();
+ QScriptValue cb = context->argument(1);
+ if (cb.isFunction())
+ cb.call();
+ } else {
+ db.commit();
+ QScriptValue cb = context->argument(2);
+ if (cb.isFunction())
+ cb.call();
+ }
+ return engine->undefinedValue();
+}
+
+
+/*
+ Currently documented in doc/src/declarastive/globalobject.qdoc
+*/
+static QScriptValue qmlsqldatabase_open(QScriptContext *context, QScriptEngine *engine)
+{
+ QSqlDatabase database;
+
+ QString dbname = context->argument(0).toString();
+ QString dbversion = context->argument(1).toString();
+ QString dbdescription = context->argument(2).toString();
+ int dbestimatedsize = context->argument(3).toNumber();
+
+ QCryptographicHash md5(QCryptographicHash::Md5);
+ md5.addData(dbname.toUtf8());
+ md5.addData(dbversion.toUtf8());
+ QString dbid(QLatin1String(md5.result().toHex()));
+
+ // Uses SQLLITE (like HTML5), but any could be used.
+
+ if (QSqlDatabase::connectionNames().contains(dbid)) {
+ database = QSqlDatabase::database(dbid);
+ } else {
+ database = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"), dbid);
+ }
+ if (!database.isOpen()) {
+ QString basename = QmlEnginePrivate::get(engine)->offlineStoragePath + QLatin1String("/Databases/");
+ QDir().mkpath(basename);
+ basename += dbid;
+ database.setDatabaseName(basename+QLatin1String(".sqlite"));
+ QSettings ini(basename+QLatin1String(".ini"),QSettings::IniFormat);
+ ini.setValue(QLatin1String("Name"), dbname);
+ ini.setValue(QLatin1String("Version"), dbversion);
+ ini.setValue(QLatin1String("Description"), dbdescription);
+ ini.setValue(QLatin1String("EstimatedSize"), dbestimatedsize);
+ ini.setValue(QLatin1String("DbType"), QLatin1String("QSQLITE"));
+ database.open();
+ }
+
+ QScriptValue instance = engine->newObject();
+ instance.setProperty(QLatin1String("transaction"), engine->newFunction(qmlsqldatabase_transaction,3));
+ return engine->newVariant(instance,qVariantFromValue(database));
+}
+
+void qt_add_qmlsqldatabase(QScriptEngine *engine)
+{
+ QScriptValue openDatabase = engine->newFunction(qmlsqldatabase_open, 4);
+ engine->globalObject().setProperty(QLatin1String("openDatabase"), openDatabase);
+}
+
+/*
+HTML5 "spec" says "rs.rows[n]", but WebKit only impelments "rs.rows.item(n)". We do both (and property iterator).
+We add a "forwardOnly" property that stops Qt caching results (code promises to only go forward
+through the data.
+*/
+
diff --git a/src/declarative/qml/qmlsqldatabase_p.h b/src/declarative/qml/qmlsqldatabase_p.h
new file mode 100644
index 0000000..f76a2fd
--- /dev/null
+++ b/src/declarative/qml/qmlsqldatabase_p.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** 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 QMLSQLDATABASE_P_H
+#define QMLSQLDATABASE_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.
+//
+
+class QScriptEngine;
+void qt_add_qmlsqldatabase(QScriptEngine *engine);
+
+#endif // QMLSQLDATABASE_P_H
+
diff --git a/src/declarative/qml/qmlstringconverters.cpp b/src/declarative/qml/qmlstringconverters.cpp
new file mode 100644
index 0000000..34025c5
--- /dev/null
+++ b/src/declarative/qml/qmlstringconverters.cpp
@@ -0,0 +1,241 @@
+/****************************************************************************
+**
+** 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 <QtGui/qcolor.h>
+#include <QtGui/qvector3d.h>
+#include <QtCore/qpoint.h>
+#include <QtCore/qrect.h>
+#include <QtCore/qsize.h>
+#include <QtCore/qvariant.h>
+#include "qmlstringconverters_p.h"
+
+QT_BEGIN_NAMESPACE
+
+static uchar fromHex(const uchar c, const uchar c2)
+{
+ uchar rv = 0;
+ if (c >= '0' && c <= '9')
+ rv += (c - '0') * 16;
+ else if (c >= 'A' && c <= 'F')
+ rv += (c - 'A' + 10) * 16;
+ else if (c >= 'a' && c <= 'f')
+ rv += (c - 'a' + 10) * 16;
+
+ if (c2 >= '0' && c2 <= '9')
+ rv += (c2 - '0');
+ else if (c2 >= 'A' && c2 <= 'F')
+ rv += (c2 - 'A' + 10);
+ else if (c2 >= 'a' && c2 <= 'f')
+ rv += (c2 - 'a' + 10);
+
+ return rv;
+}
+
+static uchar fromHex(const QString &s, int idx)
+{
+ uchar c = s.at(idx).toAscii();
+ uchar c2 = s.at(idx + 1).toAscii();
+ return fromHex(c, c2);
+}
+
+QVariant QmlStringConverters::variantFromString(const QString &s)
+{
+ if (s.isEmpty())
+ return QVariant(s);
+ if (s.startsWith(QLatin1Char('\'')) && s.endsWith(QLatin1Char('\''))) {
+ QString data = s.mid(1, s.length() - 2);
+ return QVariant(data);
+ }
+ bool ok = false;
+ QRectF r = rectFFromString(s, &ok);
+ if (ok) return QVariant(r);
+ QColor c = colorFromString(s, &ok);
+ if (ok) return QVariant(c);
+ QPointF p = pointFFromString(s, &ok);
+ if (ok) return QVariant(p);
+ QSizeF sz = sizeFFromString(s, &ok);
+ if (ok) return QVariant(sz);
+ bool b = boolFromString(s, &ok);
+ if (ok) return QVariant(b);
+ QVector3D v = vector3DFromString(s, &ok);
+ if (ok) return qVariantFromValue(v);
+
+ return QVariant(s);
+}
+
+QColor QmlStringConverters::colorFromString(const QString &s, bool *ok)
+{
+ if (s.startsWith(QLatin1Char('#')) && s.length() == 9) {
+ uchar a = fromHex(s, 1);
+ uchar r = fromHex(s, 3);
+ uchar g = fromHex(s, 5);
+ uchar b = fromHex(s, 7);
+ if (ok) *ok = true;
+ return QColor(r, g, b, a);
+ } else {
+ QColor rv;
+ if (s.startsWith(QLatin1Char('#')) || QColor::colorNames().contains(s.toLower()))
+ rv = QColor(s);
+ if (ok) *ok = rv.isValid();
+ return rv;
+ }
+}
+
+//expects input of "x,y"
+QPointF QmlStringConverters::pointFFromString(const QString &s, bool *ok)
+{
+ if (s.count(QLatin1Char(',')) != 1) {
+ if (ok)
+ *ok = false;
+ return QPointF();
+ }
+
+ bool xGood, yGood;
+ int index = s.indexOf(QLatin1Char(','));
+ qreal xCoord = s.left(index).toDouble(&xGood);
+ qreal yCoord = s.mid(index+1).toDouble(&yGood);
+ if (!xGood || !yGood) {
+ if (ok)
+ *ok = false;
+ return QPointF();
+ }
+
+ if (ok)
+ *ok = true;
+ return QPointF(xCoord, yCoord);
+}
+
+//expects input of "widthxheight"
+QSizeF QmlStringConverters::sizeFFromString(const QString &s, bool *ok)
+{
+ if (s.count(QLatin1Char('x')) != 1) {
+ if (ok)
+ *ok = false;
+ return QSizeF();
+ }
+
+ bool wGood, hGood;
+ int index = s.indexOf(QLatin1Char('x'));
+ qreal width = s.left(index).toDouble(&wGood);
+ qreal height = s.mid(index+1).toDouble(&hGood);
+ if (!wGood || !hGood) {
+ if (ok)
+ *ok = false;
+ return QSizeF();
+ }
+
+ if (ok)
+ *ok = true;
+ return QSizeF(width, height);
+}
+
+//expects input of "x,y,widthxheight" //### use space instead of second comma?
+QRectF QmlStringConverters::rectFFromString(const QString &s, bool *ok)
+{
+ if (s.count(QLatin1Char(',')) != 2 || s.count(QLatin1Char('x')) != 1) {
+ if (ok)
+ *ok = false;
+ return QRectF();
+ }
+
+ bool xGood, yGood, wGood, hGood;
+ int index = s.indexOf(QLatin1Char(','));
+ qreal x = s.left(index).toDouble(&xGood);
+ int index2 = s.indexOf(QLatin1Char(','), index+1);
+ qreal y = s.mid(index+1, index2-index-1).toDouble(&yGood);
+ index = s.indexOf(QLatin1Char('x'), index2+1);
+ qreal width = s.mid(index2+1, index-index2-1).toDouble(&wGood);
+ qreal height = s.mid(index+1).toDouble(&hGood);
+ if (!xGood || !yGood || !wGood || !hGood) {
+ if (ok)
+ *ok = false;
+ return QRectF();
+ }
+
+ if (ok)
+ *ok = true;
+ return QRectF(x, y, width, height);
+}
+
+bool QmlStringConverters::boolFromString(const QString &str, bool *ok)
+{
+ if (str.isEmpty() || str == QLatin1String("false") || str == QLatin1String("0")) {
+ if (ok)
+ *ok = true;
+ return false;
+ } else if (str == QLatin1String("true") || str == QLatin1String("1")) {
+ if (ok)
+ *ok = true;
+ return true;
+ }
+
+ if (ok)
+ *ok = false;
+ return true;
+}
+
+//expects input of "x,y,z"
+QVector3D QmlStringConverters::vector3DFromString(const QString &s, bool *ok)
+{
+ if (s.count(QLatin1Char(',')) != 2) {
+ if (ok)
+ *ok = false;
+ return QVector3D();
+ }
+
+ bool xGood, yGood, zGood;
+ int index = s.indexOf(QLatin1Char(','));
+ int index2 = s.indexOf(QLatin1Char(','), index+1);
+ qreal xCoord = s.left(index).toDouble(&xGood);
+ qreal yCoord = s.mid(index+1, index2-index-1).toDouble(&yGood);
+ qreal zCoord = s.mid(index2+1).toDouble(&zGood);
+ if (!xGood || !yGood || !zGood) {
+ if (ok)
+ *ok = false;
+ return QVector3D();
+ }
+
+ if (ok)
+ *ok = true;
+ return QVector3D(xCoord, yCoord, zCoord);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlstringconverters_p.h b/src/declarative/qml/qmlstringconverters_p.h
new file mode 100644
index 0000000..ab7448c
--- /dev/null
+++ b/src/declarative/qml/qmlstringconverters_p.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** 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 QMLSTRINGCONVERTERS_P_H
+#define QMLSTRINGCONVERTERS_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/qglobal.h>
+class QColor;
+class QPointF;
+class QSizeF;
+class QRectF;
+class QString;
+class QByteArray;
+class QVector3D;
+
+QT_BEGIN_NAMESPACE
+
+// XXX - Bauhaus currently uses these methods which is why they're exported
+namespace QmlStringConverters
+{
+ QVariant Q_DECLARATIVE_EXPORT variantFromString(const QString &);
+ QColor Q_DECLARATIVE_EXPORT colorFromString(const QString &, bool *ok = 0);
+ QPointF Q_DECLARATIVE_EXPORT pointFFromString(const QString &, bool *ok = 0);
+ QSizeF Q_DECLARATIVE_EXPORT sizeFFromString(const QString &, bool *ok = 0);
+ QRectF Q_DECLARATIVE_EXPORT rectFFromString(const QString &, bool *ok = 0);
+ bool Q_DECLARATIVE_EXPORT boolFromString(const QString &, bool *ok = 0);
+ QVector3D Q_DECLARATIVE_EXPORT vector3DFromString(const QString &, bool *ok = 0);
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLSTRINGCONVERTERS_P_H
diff --git a/src/declarative/qml/qmltypenamecache.cpp b/src/declarative/qml/qmltypenamecache.cpp
new file mode 100644
index 0000000..d706c63
--- /dev/null
+++ b/src/declarative/qml/qmltypenamecache.cpp
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** 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)
+: QmlCleanup(e), engine(e)
+{
+}
+
+QmlTypeNameCache::~QmlTypeNameCache()
+{
+ clear();
+}
+
+void QmlTypeNameCache::clear()
+{
+ qDeleteAll(stringCache);
+ stringCache.clear();
+ identifierCache.clear();
+ engine = 0;
+}
+
+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..ec1e79d
--- /dev/null
+++ b/src/declarative/qml/qmltypenamecache_p.h
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** 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>
+#include <private/qmlcleanup_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlType;
+class QmlEngine;
+class QmlTypeNameCache : public QmlRefCount, public QmlCleanup
+{
+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;
+
+protected:
+ virtual void clear();
+
+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..7a14432
--- /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
+ QByteArray enumName = strName.toUtf8();
+ 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.constData());
+ 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/qmlvaluetype.cpp b/src/declarative/qml/qmlvaluetype.cpp
new file mode 100644
index 0000000..84c9ecb
--- /dev/null
+++ b/src/declarative/qml/qmlvaluetype.cpp
@@ -0,0 +1,569 @@
+/****************************************************************************
+**
+** 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 "qmlvaluetype_p.h"
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+QmlValueTypeFactory::QmlValueTypeFactory()
+{
+ // ### Optimize
+ for (unsigned int ii = 0; ii < (QVariant::UserType - 1); ++ii)
+ valueTypes[ii] = valueType(ii);
+}
+
+QmlValueTypeFactory::~QmlValueTypeFactory()
+{
+ for (unsigned int ii = 0; ii < (QVariant::UserType - 1); ++ii)
+ delete valueTypes[ii];
+}
+
+QmlValueType *QmlValueTypeFactory::valueType(int t)
+{
+ switch (t) {
+ case QVariant::Point:
+ return new QmlPointValueType;
+ case QVariant::PointF:
+ return new QmlPointFValueType;
+ case QVariant::Size:
+ return new QmlSizeValueType;
+ case QVariant::SizeF:
+ return new QmlSizeFValueType;
+ case QVariant::Rect:
+ return new QmlRectValueType;
+ case QVariant::RectF:
+ return new QmlRectFValueType;
+ case QVariant::Vector3D:
+ return new QmlVector3DValueType;
+ case QVariant::Font:
+ return new QmlFontValueType;
+ default:
+ return 0;
+ }
+}
+
+QmlValueType::QmlValueType(QObject *parent)
+: QObject(parent)
+{
+}
+
+QmlPointFValueType::QmlPointFValueType(QObject *parent)
+: QmlValueType(parent)
+{
+}
+
+void QmlPointFValueType::read(QObject *obj, int idx)
+{
+ void *a[] = { &point, 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
+}
+
+void QmlPointFValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags)
+{
+ int status = -1;
+ void *a[] = { &point, 0, &status, &flags };
+ QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
+}
+
+QVariant QmlPointFValueType::value()
+{
+ return QVariant(point);
+}
+
+void QmlPointFValueType::setValue(QVariant value)
+{
+ point = qvariant_cast<QPointF>(value);
+}
+
+qreal QmlPointFValueType::x() const
+{
+ return point.x();
+}
+
+qreal QmlPointFValueType::y() const
+{
+ return point.y();
+}
+
+void QmlPointFValueType::setX(qreal x)
+{
+ point.setX(x);
+}
+
+void QmlPointFValueType::setY(qreal y)
+{
+ point.setY(y);
+}
+
+QmlPointValueType::QmlPointValueType(QObject *parent)
+: QmlValueType(parent)
+{
+}
+
+void QmlPointValueType::read(QObject *obj, int idx)
+{
+ void *a[] = { &point, 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
+}
+
+void QmlPointValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags)
+{
+ int status = -1;
+ void *a[] = { &point, 0, &status, &flags };
+ QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
+}
+
+QVariant QmlPointValueType::value()
+{
+ return QVariant(point);
+}
+
+void QmlPointValueType::setValue(QVariant value)
+{
+ point = qvariant_cast<QPoint>(value);
+}
+
+int QmlPointValueType::x() const
+{
+ return point.x();
+}
+
+int QmlPointValueType::y() const
+{
+ return point.y();
+}
+
+void QmlPointValueType::setX(int x)
+{
+ point.setX(x);
+}
+
+void QmlPointValueType::setY(int y)
+{
+ point.setY(y);
+}
+
+QmlSizeFValueType::QmlSizeFValueType(QObject *parent)
+: QmlValueType(parent)
+{
+}
+
+void QmlSizeFValueType::read(QObject *obj, int idx)
+{
+ void *a[] = { &size, 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
+}
+
+void QmlSizeFValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags)
+{
+ int status = -1;
+ void *a[] = { &size, 0, &status, &flags };
+ QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
+}
+
+QVariant QmlSizeFValueType::value()
+{
+ return QVariant(size);
+}
+
+void QmlSizeFValueType::setValue(QVariant value)
+{
+ size = qvariant_cast<QSizeF>(value);
+}
+
+qreal QmlSizeFValueType::width() const
+{
+ return size.width();
+}
+
+qreal QmlSizeFValueType::height() const
+{
+ return size.height();
+}
+
+void QmlSizeFValueType::setWidth(qreal w)
+{
+ size.setWidth(w);
+}
+
+void QmlSizeFValueType::setHeight(qreal h)
+{
+ size.setHeight(h);
+}
+
+QmlSizeValueType::QmlSizeValueType(QObject *parent)
+: QmlValueType(parent)
+{
+}
+
+void QmlSizeValueType::read(QObject *obj, int idx)
+{
+ void *a[] = { &size, 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
+}
+
+void QmlSizeValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags)
+{
+ int status = -1;
+ void *a[] = { &size, 0, &status, &flags };
+ QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
+}
+
+QVariant QmlSizeValueType::value()
+{
+ return QVariant(size);
+}
+
+void QmlSizeValueType::setValue(QVariant value)
+{
+ size = qvariant_cast<QSize>(value);
+}
+
+int QmlSizeValueType::width() const
+{
+ return size.width();
+}
+
+int QmlSizeValueType::height() const
+{
+ return size.height();
+}
+
+void QmlSizeValueType::setWidth(int w)
+{
+ size.setWidth(w);
+}
+
+void QmlSizeValueType::setHeight(int h)
+{
+ size.setHeight(h);
+}
+
+QmlRectFValueType::QmlRectFValueType(QObject *parent)
+: QmlValueType(parent)
+{
+}
+
+void QmlRectFValueType::read(QObject *obj, int idx)
+{
+ void *a[] = { &rect, 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
+}
+
+void QmlRectFValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags)
+{
+ int status = -1;
+ void *a[] = { &rect, 0, &status, &flags };
+ QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
+}
+
+QVariant QmlRectFValueType::value()
+{
+ return QVariant(rect);
+}
+
+void QmlRectFValueType::setValue(QVariant value)
+{
+ rect = qvariant_cast<QRectF>(value);
+}
+
+qreal QmlRectFValueType::x() const
+{
+ return rect.x();
+}
+
+qreal QmlRectFValueType::y() const
+{
+ return rect.y();
+}
+
+void QmlRectFValueType::setX(qreal x)
+{
+ rect.moveLeft(x);
+}
+
+void QmlRectFValueType::setY(qreal y)
+{
+ rect.moveTop(y);
+}
+
+qreal QmlRectFValueType::width() const
+{
+ return rect.width();
+}
+
+qreal QmlRectFValueType::height() const
+{
+ return rect.height();
+}
+
+void QmlRectFValueType::setWidth(qreal w)
+{
+ rect.setWidth(w);
+}
+
+void QmlRectFValueType::setHeight(qreal h)
+{
+ rect.setHeight(h);
+}
+
+QmlRectValueType::QmlRectValueType(QObject *parent)
+: QmlValueType(parent)
+{
+}
+
+void QmlRectValueType::read(QObject *obj, int idx)
+{
+ void *a[] = { &rect, 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
+}
+
+void QmlRectValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags)
+{
+ int status = -1;
+ void *a[] = { &rect, 0, &status, &flags };
+ QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
+}
+
+QVariant QmlRectValueType::value()
+{
+ return QVariant(rect);
+}
+
+void QmlRectValueType::setValue(QVariant value)
+{
+ rect = qvariant_cast<QRect>(value);
+}
+
+int QmlRectValueType::x() const
+{
+ return rect.x();
+}
+
+int QmlRectValueType::y() const
+{
+ return rect.y();
+}
+
+void QmlRectValueType::setX(int x)
+{
+ rect.moveLeft(x);
+}
+
+void QmlRectValueType::setY(int y)
+{
+ rect.moveTop(y);
+}
+
+int QmlRectValueType::width() const
+{
+ return rect.width();
+}
+
+int QmlRectValueType::height() const
+{
+ return rect.height();
+}
+
+void QmlRectValueType::setWidth(int w)
+{
+ rect.setWidth(w);
+}
+
+void QmlRectValueType::setHeight(int h)
+{
+ rect.setHeight(h);
+}
+
+QmlVector3DValueType::QmlVector3DValueType(QObject *parent)
+: QmlValueType(parent)
+{
+}
+
+void QmlVector3DValueType::read(QObject *obj, int idx)
+{
+ void *a[] = { &vector, 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
+}
+
+void QmlVector3DValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags)
+{
+ int status = -1;
+ void *a[] = { &vector, 0, &status, &flags };
+ QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
+}
+
+QVariant QmlVector3DValueType::value()
+{
+ return QVariant(vector);
+}
+
+void QmlVector3DValueType::setValue(QVariant value)
+{
+ vector = qvariant_cast<QVector3D>(value);
+}
+
+qreal QmlVector3DValueType::x() const
+{
+ return vector.x();
+}
+
+qreal QmlVector3DValueType::y() const
+{
+ return vector.y();
+}
+
+qreal QmlVector3DValueType::z() const
+{
+ return vector.z();
+}
+
+void QmlVector3DValueType::setX(qreal x)
+{
+ vector.setX(x);
+}
+
+void QmlVector3DValueType::setY(qreal y)
+{
+ vector.setY(y);
+}
+
+void QmlVector3DValueType::setZ(qreal z)
+{
+ vector.setZ(z);
+}
+
+QmlFontValueType::QmlFontValueType(QObject *parent)
+: QmlValueType(parent), hasPixelSize(false)
+{
+}
+
+void QmlFontValueType::read(QObject *obj, int idx)
+{
+ void *a[] = { &font, 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
+}
+
+void QmlFontValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags)
+{
+ int status = -1;
+ void *a[] = { &font, 0, &status, &flags };
+ QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
+}
+
+QVariant QmlFontValueType::value()
+{
+ return QVariant(font);
+}
+
+void QmlFontValueType::setValue(QVariant value)
+{
+ font = qvariant_cast<QFont>(value);
+}
+
+
+QString QmlFontValueType::family() const
+{
+ return font.family();
+}
+
+void QmlFontValueType::setFamily(const QString &family)
+{
+ font.setFamily(family);
+}
+
+bool QmlFontValueType::bold() const
+{
+ return font.bold();
+}
+
+void QmlFontValueType::setBold(bool b)
+{
+ font.setBold(b);
+}
+
+bool QmlFontValueType::italic() const
+{
+ return font.italic();
+}
+
+void QmlFontValueType::setItalic(bool b)
+{
+ font.setItalic(b);
+}
+
+bool QmlFontValueType::underline() const
+{
+ return font.underline();
+}
+
+void QmlFontValueType::setUnderline(bool b)
+{
+ font.setUnderline(b);
+}
+
+qreal QmlFontValueType::pointSize() const
+{
+ return font.pointSizeF();
+}
+
+void QmlFontValueType::setPointSize(qreal size)
+{
+ if (hasPixelSize) {
+ qWarning() << "Both point size and pixel size set. Using pixel size.";
+ return;
+ }
+ font.setPointSizeF(size);
+}
+
+int QmlFontValueType::pixelSize() const
+{
+ return font.pixelSize();
+}
+
+void QmlFontValueType::setPixelSize(int size)
+{
+ font.setPixelSize(size);
+ hasPixelSize = true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlvaluetype_p.h b/src/declarative/qml/qmlvaluetype_p.h
new file mode 100644
index 0000000..d3adf1e
--- /dev/null
+++ b/src/declarative/qml/qmlvaluetype_p.h
@@ -0,0 +1,300 @@
+/****************************************************************************
+**
+** 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 QMLVALUETYPE_P_H
+#define QMLVALUETYPE_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/qobject.h>
+#include <QtCore/qrect.h>
+#include <QtCore/qvariant.h>
+#include <QtGui/qvector3d.h>
+#include <QtGui/qfont.h>
+#include <QmlMetaProperty>
+
+QT_BEGIN_NAMESPACE
+
+class QmlValueType : public QObject
+{
+ Q_OBJECT
+public:
+ QmlValueType(QObject *parent = 0);
+ virtual void read(QObject *, int) = 0;
+ virtual void write(QObject *, int, QmlMetaProperty::WriteFlags flags) = 0;
+ virtual QVariant value() = 0;
+ virtual void setValue(QVariant) = 0;
+};
+
+class QmlValueTypeFactory
+{
+public:
+ QmlValueTypeFactory();
+ ~QmlValueTypeFactory();
+ static QmlValueType *valueType(int);
+
+ QmlValueType *valueTypes[QVariant::UserType - 1];
+ QmlValueType *operator[](int idx) const { return valueTypes[idx]; }
+};
+
+class QmlPointFValueType : public QmlValueType
+{
+ Q_PROPERTY(qreal x READ x WRITE setX)
+ Q_PROPERTY(qreal y READ y WRITE setY)
+ Q_OBJECT
+public:
+ QmlPointFValueType(QObject *parent = 0);
+
+ virtual void read(QObject *, int);
+ virtual void write(QObject *, int, QmlMetaProperty::WriteFlags);
+ virtual QVariant value();
+ virtual void setValue(QVariant value);
+
+ qreal x() const;
+ qreal y() const;
+ void setX(qreal);
+ void setY(qreal);
+
+private:
+ QPointF point;
+};
+
+class QmlPointValueType : public QmlValueType
+{
+ Q_PROPERTY(int x READ x WRITE setX)
+ Q_PROPERTY(int y READ y WRITE setY)
+ Q_OBJECT
+public:
+ QmlPointValueType(QObject *parent = 0);
+
+ virtual void read(QObject *, int);
+ virtual void write(QObject *, int, QmlMetaProperty::WriteFlags);
+ virtual QVariant value();
+ virtual void setValue(QVariant value);
+
+ int x() const;
+ int y() const;
+ void setX(int);
+ void setY(int);
+
+private:
+ QPoint point;
+};
+
+class QmlSizeFValueType : public QmlValueType
+{
+ Q_PROPERTY(qreal width READ width WRITE setWidth)
+ Q_PROPERTY(qreal height READ height WRITE setHeight)
+ Q_OBJECT
+public:
+ QmlSizeFValueType(QObject *parent = 0);
+
+ virtual void read(QObject *, int);
+ virtual void write(QObject *, int, QmlMetaProperty::WriteFlags);
+ virtual QVariant value();
+ virtual void setValue(QVariant value);
+
+ qreal width() const;
+ qreal height() const;
+ void setWidth(qreal);
+ void setHeight(qreal);
+
+private:
+ QSizeF size;
+};
+
+class QmlSizeValueType : public QmlValueType
+{
+ Q_PROPERTY(int width READ width WRITE setWidth)
+ Q_PROPERTY(int height READ height WRITE setHeight)
+ Q_OBJECT
+public:
+ QmlSizeValueType(QObject *parent = 0);
+
+ virtual void read(QObject *, int);
+ virtual void write(QObject *, int, QmlMetaProperty::WriteFlags);
+ virtual QVariant value();
+ virtual void setValue(QVariant value);
+
+ int width() const;
+ int height() const;
+ void setWidth(int);
+ void setHeight(int);
+
+private:
+ QSize size;
+};
+
+class QmlRectFValueType : public QmlValueType
+{
+ Q_PROPERTY(qreal x READ x WRITE setX)
+ Q_PROPERTY(qreal y READ y WRITE setY)
+ Q_PROPERTY(qreal width READ width WRITE setWidth)
+ Q_PROPERTY(qreal height READ height WRITE setHeight)
+ Q_OBJECT
+public:
+ QmlRectFValueType(QObject *parent = 0);
+
+ virtual void read(QObject *, int);
+ virtual void write(QObject *, int, QmlMetaProperty::WriteFlags);
+ virtual QVariant value();
+ virtual void setValue(QVariant value);
+
+ qreal x() const;
+ qreal y() const;
+ void setX(qreal);
+ void setY(qreal);
+
+ qreal width() const;
+ qreal height() const;
+ void setWidth(qreal);
+ void setHeight(qreal);
+
+private:
+ QRectF rect;
+};
+
+class QmlRectValueType : public QmlValueType
+{
+ Q_PROPERTY(int x READ x WRITE setX)
+ Q_PROPERTY(int y READ y WRITE setY)
+ Q_PROPERTY(int width READ width WRITE setWidth)
+ Q_PROPERTY(int height READ height WRITE setHeight)
+ Q_OBJECT
+public:
+ QmlRectValueType(QObject *parent = 0);
+
+ virtual void read(QObject *, int);
+ virtual void write(QObject *, int, QmlMetaProperty::WriteFlags);
+ virtual QVariant value();
+ virtual void setValue(QVariant value);
+
+ int x() const;
+ int y() const;
+ void setX(int);
+ void setY(int);
+
+ int width() const;
+ int height() const;
+ void setWidth(int);
+ void setHeight(int);
+
+private:
+ QRect rect;
+};
+
+class QmlVector3DValueType : public QmlValueType
+{
+ Q_PROPERTY(qreal x READ x WRITE setX)
+ Q_PROPERTY(qreal y READ y WRITE setY)
+ Q_PROPERTY(qreal z READ z WRITE setZ)
+ Q_OBJECT
+public:
+ QmlVector3DValueType(QObject *parent = 0);
+
+ virtual void read(QObject *, int);
+ virtual void write(QObject *, int, QmlMetaProperty::WriteFlags);
+ virtual QVariant value();
+ virtual void setValue(QVariant value);
+
+ qreal x() const;
+ qreal y() const;
+ qreal z() const;
+ void setX(qreal);
+ void setY(qreal);
+ void setZ(qreal);
+
+private:
+ QVector3D vector;
+};
+
+class QmlFontValueType : public QmlValueType
+{
+ Q_OBJECT
+ Q_PROPERTY(QString family READ family WRITE setFamily)
+ Q_PROPERTY(bool bold READ bold WRITE setBold)
+ Q_PROPERTY(bool italic READ italic WRITE setItalic)
+ Q_PROPERTY(bool underline READ underline WRITE setUnderline)
+ Q_PROPERTY(qreal pointSize READ pointSize WRITE setPointSize)
+ Q_PROPERTY(int pixelSize READ pixelSize WRITE setPixelSize)
+public:
+ QmlFontValueType(QObject *parent = 0);
+
+ virtual void read(QObject *, int);
+ virtual void write(QObject *, int, QmlMetaProperty::WriteFlags);
+ virtual QVariant value();
+ virtual void setValue(QVariant value);
+
+ QString family() const;
+ void setFamily(const QString &);
+
+ bool bold() const;
+ void setBold(bool b);
+
+ bool italic() const;
+ void setItalic(bool b);
+
+ bool underline() const;
+ void setUnderline(bool b);
+
+ qreal pointSize() const;
+ void setPointSize(qreal size);
+
+ int pixelSize() const;
+ void setPixelSize(int size);
+
+private:
+ QFont font;
+ bool hasPixelSize;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLVALUETYPE_P_H
diff --git a/src/declarative/qml/qmlvaluetypescriptclass.cpp b/src/declarative/qml/qmlvaluetypescriptclass.cpp
new file mode 100644
index 0000000..6a7bdeb
--- /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, 0);
+}
+
+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
new file mode 100644
index 0000000..802a78f
--- /dev/null
+++ b/src/declarative/qml/qmlvme.cpp
@@ -0,0 +1,905 @@
+/****************************************************************************
+**
+** 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 "qmlvme_p.h"
+#include "qmlcompiler_p.h"
+#include <private/qfxperf_p.h>
+#include <private/qmlboundsignal_p.h>
+#include <private/qmlstringconverters_p.h>
+#include "private/qmetaobjectbuilder_p.h"
+#include "private/qmldeclarativedata_p.h"
+#include <qml.h>
+#include <private/qmlcustomparser_p.h>
+#include <QStack>
+#include <QWidget>
+#include <QColor>
+#include <QPointF>
+#include <QSizeF>
+#include <QRectF>
+#include <qmlengine.h>
+#include <qmlcontext.h>
+#include <qmlcomponent.h>
+#include <qmlbinding.h>
+#include <private/qmlengine_p.h>
+#include <private/qmlcomponent_p.h>
+#include "private/qmlvmemetaobject_p.h"
+#include <QtCore/qdebug.h>
+#include <QtCore/qvarlengtharray.h>
+#include <QtGui/qapplication.h>
+#include <private/qmlbinding_p.h>
+#include <private/qmlcontext_p.h>
+#include <private/qmlbindingoptimizations_p.h>
+#include <QtDeclarative/qmlscriptstring.h>
+
+QT_BEGIN_NAMESPACE
+
+QmlVME::QmlVME()
+{
+}
+
+#define VME_EXCEPTION(desc) \
+ { \
+ QmlError error; \
+ error.setDescription(desc.trimmed()); \
+ error.setLine(instr.line); \
+ error.setUrl(comp->url); \
+ vmeErrors << error; \
+ break; \
+ }
+
+struct ListInstance
+{
+ ListInstance() {}
+ ListInstance(QList<void *> *q, int t)
+ : type(t), qListInterface(q), qmlListInterface(0) {}
+ ListInstance(QmlPrivate::ListInterface *q, int t)
+ : type(t), qListInterface(0), qmlListInterface(q) {}
+
+ int type;
+ QList<void *> *qListInterface;
+ QmlPrivate::ListInterface *qmlListInterface;
+};
+
+QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledData *comp,
+ int start, int count,
+ const QBitField &bindingSkipList)
+{
+ QStack<QObject *> stack;
+
+ if (start == -1) start = 0;
+ if (count == -1) count = comp->bytecode.count();
+
+ return run(stack, ctxt, comp, start, count, bindingSkipList);
+}
+
+void QmlVME::runDeferred(QObject *object)
+{
+ QmlDeclarativeData *data = QmlDeclarativeData::get(object);
+
+ if (!data || !data->context || !data->deferredComponent)
+ return;
+
+ QmlContext *ctxt = data->context;
+ QmlCompiledData *comp = data->deferredComponent;
+ int start = data->deferredIdx + 1;
+ int count = data->deferredComponent->bytecode.at(data->deferredIdx).defer.deferCount;
+ QStack<QObject *> stack;
+ stack.push(object);
+
+ run(stack, ctxt, comp, start, count, QBitField());
+}
+
+QBitField bindingSkipList;
+QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt,
+ QmlCompiledData *comp,
+ int start, int count,
+ const QBitField &bindingSkipList)
+{
+ Q_ASSERT(comp);
+ Q_ASSERT(ctxt);
+ const QList<QmlCompiledData::TypeReference> &types = comp->types;
+ const QList<QString> &primitives = comp->primitives;
+ const QList<QByteArray> &datas = comp->datas;
+ 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;
+ QmlEnginePrivate::SimpleList<QmlParserStatus> parserStatus;
+
+ QStack<ListInstance> qliststack;
+
+ vmeErrors.clear();
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(ctxt->engine());
+ QmlContextPrivate *cp = (QmlContextPrivate *)QObjectPrivate::get(ctxt);
+
+ int status = -1; //for dbus
+ QmlMetaProperty::WriteFlags flags = QmlMetaProperty::BypassInterceptor;
+
+ for (int ii = start; !isError() && ii < (start + count); ++ii) {
+ QmlInstruction &instr = comp->bytecode[ii];
+
+ switch(instr.type) {
+ case QmlInstruction::Init:
+ {
+ if (instr.init.bindingsSize)
+ bindValues = QmlEnginePrivate::SimpleList<QmlAbstractBinding>(instr.init.bindingsSize);
+ if (instr.init.parserStatusSize)
+ parserStatus = QmlEnginePrivate::SimpleList<QmlParserStatus>(instr.init.parserStatusSize);
+
+ if (instr.init.contextCache != -1)
+ cp->setIdPropertyData(comp->contextCaches.at(instr.init.contextCache));
+ }
+ break;
+
+ case QmlInstruction::CreateObject:
+ {
+ QBitField bindings;
+ if (instr.create.bindingBits != -1) {
+ const QByteArray &bits = datas.at(instr.create.bindingBits);
+ bindings = QBitField((const quint32*)bits.constData(),
+ bits.size() * 8);
+ }
+ if (stack.isEmpty())
+ bindings = bindings.united(bindingSkipList);
+
+ QObject *o =
+ types.at(instr.create.type).createInstance(ctxt, bindings);
+ if (!o) {
+ if(types.at(instr.create.type).component)
+ vmeErrors << types.at(instr.create.type).component->errors();
+
+ VME_EXCEPTION(qApp->translate("QmlVME","Unable to create object of type %1").arg(QString::fromLatin1(types.at(instr.create.type).className)));
+ }
+
+ QmlDeclarativeData *ddata = QmlDeclarativeData::get(o);
+ Q_ASSERT(ddata);
+ ddata->outerContext = ctxt;
+ ddata->lineNumber = instr.line;
+ ddata->columnNumber = instr.create.column;
+
+ if (instr.create.data != -1) {
+ QmlCustomParser *customParser =
+ types.at(instr.create.type).type->customParser();
+ customParser->setCustomData(o, datas.at(instr.create.data));
+ }
+ if (!stack.isEmpty()) {
+ QObject *parent = stack.top();
+ if (o->isWidgetType()) {
+ QWidget *widget = static_cast<QWidget*>(o);
+ if (parent->isWidgetType()) {
+ QWidget *parentWidget = static_cast<QWidget*>(parent);
+ widget->setParent(parentWidget);
+ } else {
+ // TODO: parent might be a layout
+ }
+ } else {
+ o->setParent(parent);
+ }
+ }
+ stack.push(o);
+ }
+ break;
+
+ case QmlInstruction::SetId:
+ {
+ QObject *target = stack.top();
+// ctxt->setContextProperty(primitives.at(instr.setId.value), target);
+ cp->setIdProperty(primitives.at(instr.setId.value), instr.setId.index, target);
+ }
+ break;
+
+
+ case QmlInstruction::SetDefault:
+ {
+ QObject *target = stack.top();
+ ctxt->addDefaultObject(target);
+ }
+ break;
+
+ case QmlInstruction::CreateComponent:
+ {
+ QObject *qcomp = new QmlComponent(ctxt->engine(), comp, ii + 1, instr.createComponent.count, stack.isEmpty() ? 0 : stack.top());
+
+ QmlEngine::setContextForObject(qcomp, ctxt);
+ QmlDeclarativeData *ddata = QmlDeclarativeData::get(qcomp);
+ Q_ASSERT(ddata);
+ ddata->outerContext = ctxt;
+ ddata->lineNumber = instr.line;
+ ddata->columnNumber = instr.create.column;
+
+ stack.push(qcomp);
+ ii += instr.createComponent.count;
+ }
+ break;
+
+ case QmlInstruction::StoreMetaObject:
+ {
+ QObject *target = stack.top();
+
+ QMetaObject mo;
+ const QByteArray &metadata = datas.at(instr.storeMeta.data);
+ QMetaObjectBuilder::fromRelocatableData(&mo, 0, metadata);
+
+ 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;
+
+ case QmlInstruction::StoreVariant:
+ {
+ QObject *target = stack.top();
+ // XXX - can be more efficient
+ QVariant v = QmlStringConverters::variantFromString(primitives.at(instr.storeString.value));
+ void *a[] = { &v, 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeString.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreString:
+ {
+ QObject *target = stack.top();
+ void *a[] = { (void *)&primitives.at(instr.storeString.value), 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeString.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreUrl:
+ {
+ QObject *target = stack.top();
+ QUrl u(primitives.at(instr.storeUrl.value));
+ void *a[] = { &u, 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeUrl.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreFloat:
+ {
+ QObject *target = stack.top();
+ float f = instr.storeFloat.value;
+ void *a[] = { &f, 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeFloat.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreDouble:
+ {
+ QObject *target = stack.top();
+ double d = instr.storeDouble.value;
+ void *a[] = { &d, 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeDouble.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreBool:
+ {
+ QObject *target = stack.top();
+ void *a[] = { (void *)&instr.storeBool.value, 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeBool.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreInteger:
+ {
+ QObject *target = stack.top();
+ void *a[] = { (void *)&instr.storeInteger.value, 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeInteger.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreColor:
+ {
+ QObject *target = stack.top();
+ QColor c = QColor::fromRgba(instr.storeColor.value);
+ void *a[] = { &c, 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeColor.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreDate:
+ {
+ QObject *target = stack.top();
+ QDate d = QDate::fromJulianDay(instr.storeDate.value);
+ void *a[] = { &d, 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeDate.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreTime:
+ {
+ QObject *target = stack.top();
+ QTime t;
+ t.setHMS(intData.at(instr.storeTime.valueIndex),
+ intData.at(instr.storeTime.valueIndex+1),
+ intData.at(instr.storeTime.valueIndex+2),
+ intData.at(instr.storeTime.valueIndex+3));
+ void *a[] = { &t, 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeTime.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreDateTime:
+ {
+ QObject *target = stack.top();
+ QTime t;
+ t.setHMS(intData.at(instr.storeDateTime.valueIndex+1),
+ intData.at(instr.storeDateTime.valueIndex+2),
+ intData.at(instr.storeDateTime.valueIndex+3),
+ intData.at(instr.storeDateTime.valueIndex+4));
+ QDateTime dt(QDate::fromJulianDay(intData.at(instr.storeDateTime.valueIndex)), t);
+ void *a[] = { &dt, 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeDateTime.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StorePoint:
+ {
+ QObject *target = stack.top();
+ QPoint p = QPointF(floatData.at(instr.storeRealPair.valueIndex),
+ floatData.at(instr.storeRealPair.valueIndex+1)).toPoint();
+ void *a[] = { &p, 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeRealPair.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StorePointF:
+ {
+ QObject *target = stack.top();
+ QPointF p(floatData.at(instr.storeRealPair.valueIndex),
+ floatData.at(instr.storeRealPair.valueIndex+1));
+ void *a[] = { &p, 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeRealPair.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreSize:
+ {
+ QObject *target = stack.top();
+ QSize p = QSizeF(floatData.at(instr.storeRealPair.valueIndex),
+ floatData.at(instr.storeRealPair.valueIndex+1)).toSize();
+ void *a[] = { &p, 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeRealPair.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreSizeF:
+ {
+ QObject *target = stack.top();
+ QSizeF s(floatData.at(instr.storeRealPair.valueIndex),
+ floatData.at(instr.storeRealPair.valueIndex+1));
+ void *a[] = { &s, 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeRealPair.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreRect:
+ {
+ QObject *target = stack.top();
+ QRect r = QRectF(floatData.at(instr.storeRect.valueIndex),
+ floatData.at(instr.storeRect.valueIndex+1),
+ floatData.at(instr.storeRect.valueIndex+2),
+ floatData.at(instr.storeRect.valueIndex+3)).toRect();
+ void *a[] = { &r, 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeRect.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreRectF:
+ {
+ QObject *target = stack.top();
+ QRectF r(floatData.at(instr.storeRect.valueIndex),
+ floatData.at(instr.storeRect.valueIndex+1),
+ floatData.at(instr.storeRect.valueIndex+2),
+ floatData.at(instr.storeRect.valueIndex+3));
+ void *a[] = { &r, 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeRect.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreVector3D:
+ {
+ QObject *target = stack.top();
+ QVector3D p(floatData.at(instr.storeVector3D.valueIndex),
+ floatData.at(instr.storeVector3D.valueIndex+1),
+ floatData.at(instr.storeVector3D.valueIndex+2));
+ void *a[] = { &p, 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeVector3D.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreObject:
+ {
+ QObject *assignObj = stack.pop();
+ QObject *target = stack.top();
+
+ void *a[] = { (void *)&assignObj, 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeObject.propertyIndex, a);
+ }
+ break;
+
+
+ case QmlInstruction::AssignCustomType:
+ {
+ QObject *target = stack.top();
+ QmlCompiledData::CustomTypeData data = customTypeData.at(instr.assignCustomType.valueIndex);
+ const QString &primitive = primitives.at(data.index);
+ QmlMetaType::StringConverter converter =
+ QmlMetaType::customStringConverter(data.type);
+ QVariant v = (*converter)(primitive);
+
+ QMetaProperty prop =
+ target->metaObject()->property(instr.assignCustomType.propertyIndex);
+ if (v.isNull() || ((int)prop.type() != data.type && prop.userType() != data.type))
+ VME_EXCEPTION(qApp->translate("QmlVME","Cannot assign value %1 to property %2").arg(primitive).arg(QString::fromUtf8(prop.name())));
+
+ void *a[] = { (void *)v.data(), 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.assignCustomType.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::AssignSignalObject:
+ {
+ // XXX optimize
+
+ QObject *assign = stack.pop();
+ QObject *target = stack.top();
+ int sigIdx = instr.assignSignalObject.signal;
+ const QByteArray &pr = datas.at(sigIdx);
+
+ QmlMetaProperty prop(target, QString::fromUtf8(pr));
+ if (prop.type() & QmlMetaProperty::SignalProperty) {
+
+ QMetaMethod method = QmlMetaType::defaultMethod(assign);
+ if (method.signature() == 0)
+ VME_EXCEPTION(qApp->translate("QmlVME","Cannot assign object type %1 with no default method").arg(QString::fromLatin1(assign->metaObject()->className())));
+
+ if (!QMetaObject::checkConnectArgs(prop.method().signature(), method.signature()))
+ VME_EXCEPTION(qApp->translate("QmlVME","Cannot connect mismatched signal/slot %1 %vs. %2").arg(QString::fromLatin1(method.signature())).arg(QString::fromLatin1(prop.method().signature())));
+
+ QMetaObject::connect(target, prop.coreIndex(), assign, method.methodIndex());
+
+ } else {
+ VME_EXCEPTION(qApp->translate("QmlVME","Cannot assign an object to signal property %1").arg(QString::fromUtf8(pr)));
+ }
+
+
+ }
+ break;
+
+ case QmlInstruction::StoreSignal:
+ {
+ QObject *target = stack.top();
+ // XXX scope
+ QMetaMethod signal =
+ target->metaObject()->method(instr.storeSignal.signalIndex);
+
+ QmlBoundSignal *bs = new QmlBoundSignal(target, signal, target);
+ QmlExpression *expr =
+ new QmlExpression(ctxt, primitives.at(instr.storeSignal.value), target);
+ expr->setSourceLocation(comp->url, instr.line);
+ bs->setExpression(expr);
+ }
+ break;
+
+ case QmlInstruction::StoreScript:
+ {
+ QObject *target = stack.top();
+ cp->addScript(primitives.at(instr.storeScript.value), target,
+ primitives.at(instr.storeScript.fileName),
+ instr.storeScript.lineNumber);
+ }
+ break;
+
+ case QmlInstruction::StoreScriptString:
+ {
+ QObject *target = stack.top();
+ QObject *scope = stack.at(stack.count() - 1 - instr.storeScriptString.scope);
+ QmlScriptString ss;
+ ss.setContext(ctxt);
+ ss.setScopeObject(scope);
+ ss.setScript(primitives.at(instr.storeScriptString.value));
+
+ void *a[] = { &ss, 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeScriptString.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::BeginObject:
+ {
+ QObject *target = stack.top();
+ QmlParserStatus *status = reinterpret_cast<QmlParserStatus *>(reinterpret_cast<char *>(target) + instr.begin.castValue);
+ parserStatus.append(status);
+ status->d = &parserStatus.values[parserStatus.count - 1];
+
+ status->classBegin();
+ }
+ break;
+
+ case QmlInstruction::StoreBinding:
+ {
+ QObject *target =
+ stack.at(stack.count() - 1 - instr.assignBinding.owner);
+ QObject *context =
+ stack.at(stack.count() - 1 - instr.assignBinding.context);
+
+ QmlMetaProperty mp;
+ mp.restore(instr.assignBinding.property, target, ctxt);
+
+ int coreIndex = mp.coreIndex();
+
+ if (stack.count() == 1 && bindingSkipList.testBit(coreIndex))
+ break;
+
+ QmlBinding *bind = new QmlBinding((void *)datas.at(instr.assignBinding.value).constData(), comp, context, ctxt, comp->url, instr.line, 0);
+ bindValues.append(bind);
+ bind->m_mePtr = &bindValues.values[bindValues.count - 1];
+ bind->setTarget(mp);
+ bind->addToObject(target);
+ }
+ break;
+
+ case QmlInstruction::StoreIdOptBinding:
+ {
+ int coreIndex = instr.assignIdOptBinding.property;
+ if (stack.count() == 1 && bindingSkipList.testBit(coreIndex))
+ break;
+
+ QObject *target = stack.top();
+
+ QmlBinding_Id *bind =
+ new QmlBinding_Id(target, instr.assignIdOptBinding.property,
+ ctxt, instr.assignIdOptBinding.id);
+ bindValues.append(bind);
+ bind->m_mePtr = &bindValues.values[bindValues.count - 1];
+ bind->addToObject(target);
+ }
+ break;
+
+ case QmlInstruction::StoreObjPropBinding:
+ {
+ int coreIndex = instr.assignObjPropBinding.property;
+ if (stack.count() == 1 && bindingSkipList.testBit(coreIndex))
+ break;
+
+ QObject *target = stack.top();
+ QObject *context =
+ stack.at(stack.count() - 1 - instr.assignObjPropBinding.context);
+
+ QmlBinding_ObjProperty *bind =
+ new QmlBinding_ObjProperty(target, instr.assignObjPropBinding.property, context, instr.assignObjPropBinding.contextIdx, instr.assignObjPropBinding.notifyIdx);
+
+ bindValues.append(bind);
+ bind->m_mePtr = &bindValues.values[bindValues.count - 1];
+ bind->addToObject(target);
+ }
+ break;
+
+ case QmlInstruction::StoreValueSource:
+ {
+ QObject *obj = stack.pop();
+ QmlPropertyValueSource *vs = reinterpret_cast<QmlPropertyValueSource *>(reinterpret_cast<char *>(obj) + instr.assignValueSource.castValue);
+ QObject *target = stack.at(stack.count() - 1 - instr.assignValueSource.owner);
+ QmlMetaProperty prop;
+ prop.restore(instr.assignValueSource.property, target, ctxt);
+ obj->setParent(target);
+ vs->setTarget(prop);
+ }
+ break;
+
+ case QmlInstruction::StoreValueInterceptor:
+ {
+ QObject *obj = stack.pop();
+ QmlPropertyValueInterceptor *vi = reinterpret_cast<QmlPropertyValueInterceptor *>(reinterpret_cast<char *>(obj) + instr.assignValueInterceptor.castValue);
+ QObject *target = stack.at(stack.count() - 1 - instr.assignValueInterceptor.owner);
+ QmlMetaProperty prop;
+ prop.restore(instr.assignValueInterceptor.property, target, ctxt);
+ obj->setParent(target);
+ vi->setTarget(prop);
+ QmlVMEMetaObject *mo = static_cast<QmlVMEMetaObject *>((QMetaObject*)target->metaObject());
+ mo->registerInterceptor(prop.coreIndex(), prop.valueTypeCoreIndex(), vi);
+ }
+ break;
+
+ case QmlInstruction::StoreObjectQmlList:
+ {
+ QObject *assign = stack.pop();
+ const ListInstance &list = qliststack.top();
+
+ void *d = (void *)&assign;
+ list.qmlListInterface->append(d);
+ }
+ break;
+
+ case QmlInstruction::StoreObjectQList:
+ {
+ QObject *assign = stack.pop();
+
+ const ListInstance &list = qliststack.top();
+ list.qListInterface->append((void *)assign);
+ }
+ break;
+
+ case QmlInstruction::AssignObjectList:
+ {
+ // This is only used for assigning interfaces
+ QObject *assign = stack.pop();
+ const ListInstance &list = qliststack.top();
+
+ int type = list.type;
+
+ void *ptr = 0;
+
+ const char *iid = QmlMetaType::interfaceIId(type);
+ if (iid)
+ ptr = assign->qt_metacast(iid);
+ if (!ptr)
+ VME_EXCEPTION(qApp->translate("QmlVME","Cannot assign object to list"));
+
+
+ if (list.qmlListInterface) {
+ void *d = (void *)&ptr;
+ list.qmlListInterface->append(d);
+ } else {
+ list.qListInterface->append(ptr);
+ }
+ }
+ break;
+
+ case QmlInstruction::StoreVariantObject:
+ {
+ QObject *assign = stack.pop();
+ QObject *target = stack.top();
+
+ QVariant v = QVariant::fromValue(assign);
+ void *a[] = { &v, 0, &status, &flags };
+ QMetaObject::metacall(target, QMetaObject::WriteProperty,
+ instr.storeObject.propertyIndex, a);
+ }
+ break;
+
+ case QmlInstruction::StoreInterface:
+ {
+ QObject *assign = stack.pop();
+ QObject *target = stack.top();
+
+ int coreIdx = instr.storeObject.propertyIndex;
+ QMetaProperty prop = target->metaObject()->property(coreIdx);
+ int t = prop.userType();
+ const char *iid = QmlMetaType::interfaceIId(t);
+ bool ok = false;
+ if (iid) {
+ void *ptr = assign->qt_metacast(iid);
+ if (ptr) {
+ void *a[] = { &ptr, 0, &status, &flags };
+ QMetaObject::metacall(target,
+ QMetaObject::WriteProperty,
+ coreIdx, a);
+ ok = true;
+ }
+ }
+
+ if (!ok)
+ VME_EXCEPTION(qApp->translate("QmlVME","Cannot assign object to interface property"));
+ }
+ break;
+
+ case QmlInstruction::FetchAttached:
+ {
+ QObject *target = stack.top();
+
+ QObject *qmlObject = qmlAttachedPropertiesObjectById(instr.fetchAttached.id, target);
+
+ if (!qmlObject)
+ VME_EXCEPTION(qApp->translate("QmlVME","Unable to create attached object"));
+
+ stack.push(qmlObject);
+ }
+ break;
+
+ case QmlInstruction::FetchQmlList:
+ {
+ QObject *target = stack.top();
+
+ void *a[1];
+ // We know that QmlList<*> can be converted to
+ // QmlPrivate::ListInterface
+ QmlPrivate::ListInterface *list = 0;
+ a[0] = &list;
+ QMetaObject::metacall(target, QMetaObject::ReadProperty,
+ instr.fetchQmlList.property, a);
+ if (!list)
+ VME_EXCEPTION(qApp->translate("QmlVME","Cannot assign to null list"));
+
+ qliststack.push(ListInstance(list, instr.fetchQmlList.type));
+ }
+ break;
+
+ case QmlInstruction::FetchQList:
+ {
+ QObject *target = stack.top();
+
+ void *a[1];
+ // We know that QList<T *>* can be converted to
+ // QList<void *>*
+ QList<void *> *list = 0;
+ a[0] = &list;
+ QMetaObject::metacall(target, QMetaObject::ReadProperty,
+ instr.fetchQmlList.property, a);
+ if (!list)
+ VME_EXCEPTION(qApp->translate("QmlVME","Cannot assign to null list"));
+
+ qliststack.push(ListInstance(list, instr.fetchQmlList.type));
+ }
+ break;
+
+ case QmlInstruction::FetchObject:
+ {
+ QObject *target = stack.top();
+
+ QObject *obj = 0;
+ // NOTE: This assumes a cast to QObject does not alter the
+ // object pointer
+ void *a[1];
+ a[0] = &obj;
+ QMetaObject::metacall(target, QMetaObject::ReadProperty,
+ instr.fetch.property, a);
+
+ if (!obj)
+ VME_EXCEPTION(qApp->translate("QmlVME","Cannot set properties on %1 as it is null").arg(QString::fromUtf8(target->metaObject()->property(instr.fetch.property).name())));
+
+ stack.push(obj);
+ }
+ break;
+
+ case QmlInstruction::PopQList:
+ {
+ qliststack.pop();
+ }
+ break;
+
+ case QmlInstruction::Defer:
+ {
+ if (instr.defer.deferCount) {
+ QObject *target = stack.top();
+ QmlDeclarativeData *data =
+ QmlDeclarativeData::get(target, true);
+ comp->addref();
+ data->deferredComponent = comp;
+ data->deferredIdx = ii;
+ ii += instr.defer.deferCount;
+ }
+ }
+ break;
+
+ case QmlInstruction::PopFetchedObject:
+ {
+ stack.pop();
+ }
+ break;
+
+ case QmlInstruction::FetchValueType:
+ {
+ QObject *target = stack.top();
+ QmlValueType *valueHandler =
+ ep->valueTypes[instr.fetchValue.type];
+ valueHandler->read(target, instr.fetchValue.property);
+ stack.push(valueHandler);
+ }
+ break;
+
+ case QmlInstruction::PopValueType:
+ {
+ QmlValueType *valueHandler =
+ static_cast<QmlValueType *>(stack.pop());
+ QObject *target = stack.top();
+ valueHandler->write(target, instr.fetchValue.property, QmlMetaProperty::BypassInterceptor);
+ }
+ break;
+
+ default:
+ qFatal("QmlCompiledData: Internal error - unknown instruction %d", instr.type);
+ break;
+ }
+ }
+
+ if (isError()) {
+ if (!stack.isEmpty()) {
+ delete stack.at(0);
+ }
+
+ QmlEnginePrivate::clear(bindValues);
+ QmlEnginePrivate::clear(parserStatus);
+ return 0;
+ }
+
+ if (bindValues.count)
+ ep->bindValues << bindValues;
+ if (parserStatus.count)
+ ep->parserStatus << parserStatus;
+
+ if (stack.isEmpty())
+ return 0;
+ else
+ return stack.top();
+ return 0;
+}
+
+bool QmlVME::isError() const
+{
+ return !vmeErrors.isEmpty();
+}
+
+QList<QmlError> QmlVME::errors() const
+{
+ return vmeErrors;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlvme_p.h b/src/declarative/qml/qmlvme_p.h
new file mode 100644
index 0000000..38ba06f
--- /dev/null
+++ b/src/declarative/qml/qmlvme_p.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** 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 QMLVME_P_H
+#define QMLVME_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/QString>
+#include <QtCore/QStack>
+#include <QtDeclarative/qmlerror.h>
+#include <private/qbitfield_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QObject;
+class QmlInstruction;
+class QmlCompiledData;
+class QmlCompiledData;
+class QmlContext;
+
+class QmlVME
+{
+public:
+ QmlVME();
+
+ QObject *run(QmlContext *, QmlCompiledData *,
+ int start = -1, int count = -1,
+ const QBitField & = QBitField());
+ void runDeferred(QObject *);
+
+ bool isError() const;
+ QList<QmlError> errors() const;
+
+private:
+ QObject *run(QStack<QObject *> &, QmlContext *, QmlCompiledData *,
+ int start, int count, const QBitField &);
+ QList<QmlError> vmeErrors;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLVME_P_H
diff --git a/src/declarative/qml/qmlvmemetaobject.cpp b/src/declarative/qml/qmlvmemetaobject.cpp
new file mode 100644
index 0000000..a627bf9
--- /dev/null
+++ b/src/declarative/qml/qmlvmemetaobject.cpp
@@ -0,0 +1,311 @@
+/****************************************************************************
+**
+** 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 "qmlvmemetaobject_p.h"
+#include <qml.h>
+#include <private/qmlrefcount_p.h>
+#include <QColor>
+#include <QDate>
+#include <QtCore/qlist.h>
+#include <QtCore/qdebug.h>
+#include <qmlexpression.h>
+#include <private/qmlcontext_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QmlVMEMetaObject::QmlVMEMetaObject(QObject *obj,
+ const QMetaObject *other,
+ const QmlVMEMetaData *meta,
+ QmlRefCount *rc)
+: object(obj), ref(rc), ctxt(qmlContext(obj)), metaData(meta), parent(0)
+{
+ if (ref)
+ ref->addref();
+
+ *static_cast<QMetaObject *>(this) = *other;
+ this->d.superdata = obj->metaObject();
+
+ QObjectPrivate *op = QObjectPrivate::get(obj);
+ if (op->metaObject)
+ parent = static_cast<QAbstractDynamicMetaObject*>(op->metaObject);
+ op->metaObject = this;
+
+ propOffset = QAbstractDynamicMetaObject::propertyOffset();
+ methodOffset = QAbstractDynamicMetaObject::methodOffset();
+
+ data = new QVariant[metaData->propertyCount];
+ aConnected.resize(metaData->aliasCount);
+
+ int list_type = qMetaTypeId<QmlList<QObject*>* >();
+ // ### Optimize
+ for (int ii = 0; ii < metaData->propertyCount; ++ii) {
+ int t = (metaData->propertyData() + ii)->propertyType;
+ if (t == list_type) {
+ listProperties.append(new List(this, ii));
+ data[ii] = QVariant::fromValue((QmlList<QObject *>*)listProperties.last());
+ } else if (t != -1) {
+ data[ii] = QVariant((QVariant::Type)t);
+ }
+ }
+}
+
+QmlVMEMetaObject::~QmlVMEMetaObject()
+{
+ if (ref)
+ ref->release();
+ if (parent)
+ delete parent;
+ qDeleteAll(listProperties);
+ delete [] data;
+}
+
+int QmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
+{
+ int id = _id;
+ if(c == QMetaObject::WriteProperty) {
+ int flags = *reinterpret_cast<int*>(a[3]);
+ if (!(flags & QmlMetaProperty::BypassInterceptor)
+ && !aInterceptors.isEmpty()
+ && aInterceptors.testBit(id)) {
+ QPair<int, QmlPropertyValueInterceptor*> pair = interceptors.value(id);
+ int valueIndex = pair.first;
+ QmlPropertyValueInterceptor *vi = pair.second;
+ QVariant::Type type = QVariant::Invalid;
+ if (id >= propOffset) {
+ id -= propOffset;
+ if (id < metaData->propertyCount) {
+ type = data[id].type();
+ }
+ } else {
+ type = property(id).type();
+ }
+
+ if (type != QVariant::Invalid) {
+ if (valueIndex != -1) {
+ QmlEnginePrivate *ep = ctxt?QmlEnginePrivate::get(ctxt->engine()):0;
+ QmlValueType *valueType = 0;
+ if (ep) valueType = ep->valueTypes[type];
+ else valueType = QmlValueTypeFactory::valueType(type);
+ Q_ASSERT(valueType);
+
+ valueType->setValue(QVariant(type, a[0]));
+ QMetaProperty valueProp = valueType->metaObject()->property(valueIndex);
+ vi->write(valueProp.read(valueType));
+ return -1;
+ } else {
+ vi->write(QVariant(type, a[0]));
+ return -1;
+ }
+ }
+ }
+ }
+ if(c == QMetaObject::ReadProperty || c == QMetaObject::WriteProperty) {
+ if (id >= propOffset) {
+ id -= propOffset;
+
+ if (id < metaData->propertyCount) {
+ int t = (metaData->propertyData() + id)->propertyType;
+ bool needActivate = false;
+
+ if (t == -1) {
+
+ if (c == QMetaObject::ReadProperty) {
+ *reinterpret_cast<QVariant *>(a[0]) = data[id];
+ } else if (c == QMetaObject::WriteProperty) {
+ needActivate =
+ (data[id] != *reinterpret_cast<QVariant *>(a[0]));
+ data[id] = *reinterpret_cast<QVariant *>(a[0]);
+ }
+
+ } else {
+
+ if (c == QMetaObject::ReadProperty) {
+ switch(t) {
+ case QVariant::Int:
+ *reinterpret_cast<int *>(a[0]) = data[id].toInt();
+ break;
+ case QVariant::Bool:
+ *reinterpret_cast<bool *>(a[0]) = data[id].toBool();
+ break;
+ case QVariant::Double:
+ *reinterpret_cast<double *>(a[0]) = data[id].toDouble();
+ break;
+ case QVariant::String:
+ *reinterpret_cast<QString *>(a[0]) = data[id].toString();
+ break;
+ case QVariant::Url:
+ *reinterpret_cast<QUrl *>(a[0]) = data[id].toUrl();
+ break;
+ case QVariant::Color:
+ *reinterpret_cast<QColor *>(a[0]) = data[id].value<QColor>();
+ break;
+ case QVariant::Date:
+ *reinterpret_cast<QDate *>(a[0]) = data[id].toDate();
+ break;
+ case QMetaType::QObjectStar:
+ *reinterpret_cast<QObject **>(a[0]) = data[id].value<QObject*>();
+ break;
+ default:
+ break;
+ }
+ if (t == qMetaTypeId<QmlList<QObject*>* >()) {
+ *reinterpret_cast<QmlList<QObject *> **>(a[0]) = data[id].value<QmlList<QObject*>*>();
+ }
+
+ } else if (c == QMetaObject::WriteProperty) {
+
+ QVariant value = QVariant((QVariant::Type)data[id].type(), a[0]);
+ needActivate = (data[id] != value);
+ data[id] = value;
+ }
+
+ }
+
+ if (c == QMetaObject::WriteProperty && needActivate) {
+ activate(object, methodOffset + id, 0);
+ }
+
+ return -1;
+ }
+
+ id -= metaData->propertyCount;
+
+ if (id < metaData->aliasCount) {
+
+ if (!ctxt) return -1;
+ QmlVMEMetaData::AliasData *d = metaData->aliasData() + id;
+ QmlContextPrivate *ctxtPriv =
+ (QmlContextPrivate *)QObjectPrivate::get(ctxt);
+
+ QObject *target = ctxtPriv->idValues[d->contextIdx].data();
+ if (!target) {
+ if (d->propertyIdx == -1)
+ *reinterpret_cast<QObject **>(a[0]) = target;
+ return -1;
+ }
+
+ if (c == QMetaObject::ReadProperty && !aConnected.testBit(id)) {
+ int sigIdx = methodOffset + id + metaData->propertyCount;
+ QMetaObject::connect(ctxt, d->contextIdx + ctxtPriv->notifyIndex, object, sigIdx);
+
+ if (d->propertyIdx != -1) {
+ QMetaProperty prop =
+ target->metaObject()->property(d->propertyIdx);
+ if (prop.hasNotifySignal())
+ QMetaObject::connect(target, prop.notifySignalIndex(),
+ object, sigIdx);
+ }
+ aConnected.setBit(id);
+ }
+
+ if (d->propertyIdx == -1) {
+ *reinterpret_cast<QObject **>(a[0]) = target;
+ return -1;
+ } else {
+ return QMetaObject::metacall(target, c, d->propertyIdx, a);
+ }
+
+ }
+ return -1;
+
+ }
+
+ } else if(c == QMetaObject::InvokeMetaMethod) {
+
+ if (id >= methodOffset) {
+
+ id -= methodOffset;
+ int plainSignals = metaData->signalCount + metaData->propertyCount +
+ metaData->aliasCount;
+ if (id < plainSignals) {
+ QMetaObject::activate(object, _id, a);
+ return -1;
+ }
+
+ id -= plainSignals;
+
+ if (id < metaData->methodCount) {
+ QmlVMEMetaData::MethodData *data = metaData->methodData() + id;
+ const QChar *body =
+ (const QChar *)(((const char*)metaData) + data->bodyOffset);
+
+ QString code = QString::fromRawData(body, data->bodyLength);
+
+ if (0 == (metaData->methodData() + id)->parameterCount) {
+ QmlExpression expr(ctxt, code, object);
+ expr.setTrackChange(false);
+ expr.value();
+ } else {
+ QmlContext newCtxt(ctxt);
+ QMetaMethod m = method(_id);
+ QList<QByteArray> names = m.parameterNames();
+ for (int ii = 0; ii < names.count(); ++ii)
+ newCtxt.setContextProperty(names.at(ii), *(QVariant *)a[ii + 1]);
+ QmlExpression expr(&newCtxt, code, object);
+ expr.setTrackChange(false);
+ expr.value();
+ }
+ }
+ return -1;
+ }
+ }
+
+ if (parent)
+ return parent->metaCall(c, _id, a);
+ else
+ return object->qt_metacall(c, _id, a);
+}
+
+void QmlVMEMetaObject::listChanged(int id)
+{
+ activate(object, methodOffset + id, 0);
+}
+
+void QmlVMEMetaObject::registerInterceptor(int index, int valueIndex, QmlPropertyValueInterceptor *interceptor)
+{
+ if (aInterceptors.isEmpty())
+ aInterceptors.resize(propertyCount() + metaData->propertyCount);
+ aInterceptors.setBit(index);
+ interceptors.insert(index, qMakePair(valueIndex, interceptor));
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlvmemetaobject_p.h b/src/declarative/qml/qmlvmemetaobject_p.h
new file mode 100644
index 0000000..74b6d09
--- /dev/null
+++ b/src/declarative/qml/qmlvmemetaobject_p.h
@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** 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 QMLVMEMETAOBJECT_P_H
+#define QMLVMEMETAOBJECT_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 <QtDeclarative/qml.h>
+#include <QtCore/QMetaObject>
+#include <QtCore/QBitArray>
+#include <QtCore/QPair>
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+struct QmlVMEMetaData
+{
+ short propertyCount;
+ short aliasCount;
+ short signalCount;
+ short methodCount;
+
+ struct AliasData {
+ int contextIdx;
+ int propertyIdx;
+ };
+
+ struct PropertyData {
+ int propertyType;
+ };
+
+ struct MethodData {
+ int parameterCount;
+ int bodyOffset;
+ int bodyLength;
+ int _dummy;
+ };
+
+ PropertyData *propertyData() const {
+ return (PropertyData *)(((const char *)this) + sizeof(QmlVMEMetaData));
+ }
+
+ AliasData *aliasData() const {
+ return (AliasData *)(propertyData() + propertyCount);
+ }
+
+ MethodData *methodData() const {
+ return (MethodData *)(aliasData() + aliasCount);
+ }
+};
+
+class QmlRefCount;
+class QmlVMEMetaObject : public QAbstractDynamicMetaObject
+{
+public:
+ QmlVMEMetaObject(QObject *, const QMetaObject *, const QmlVMEMetaData *data,
+ QmlRefCount * = 0);
+ ~QmlVMEMetaObject();
+
+ void registerInterceptor(int index, int valueIndex, QmlPropertyValueInterceptor *interceptor);
+
+protected:
+ virtual int metaCall(QMetaObject::Call _c, int _id, void **_a);
+
+private:
+ QObject *object;
+ QmlRefCount *ref;
+ QGuard<QmlContext> ctxt;
+
+ const QmlVMEMetaData *metaData;
+ int propOffset;
+ int methodOffset;
+
+ QVariant *data;
+ QBitArray aConnected;
+ QBitArray aInterceptors;
+ QHash<int, QPair<int, QmlPropertyValueInterceptor*> > interceptors;
+
+ QAbstractDynamicMetaObject *parent;
+
+ void listChanged(int);
+ class List : public QmlConcreteList<QObject*>
+ {
+ public:
+ List(QmlVMEMetaObject *p, int propIdx)
+ : parent(p), parentProperty(propIdx) { }
+
+ virtual void append(QObject *v) {
+ QmlConcreteList<QObject*>::append(v);
+ parent->listChanged(parentProperty);
+ }
+ virtual void insert(int i, QObject *v) {
+ QmlConcreteList<QObject*>::insert(i, v);
+ parent->listChanged(parentProperty);
+ }
+ virtual void clear() {
+ QmlConcreteList<QObject*>::clear();
+ parent->listChanged(parentProperty);
+ }
+ virtual void removeAt(int i) {
+ QmlConcreteList<QObject*>::removeAt(i);
+ parent->listChanged(parentProperty);
+ }
+ private:
+ QmlVMEMetaObject *parent;
+ int parentProperty;
+ };
+ QList<List *> listProperties;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLVMEMETAOBJECT_P_H
diff --git a/src/declarative/qml/qmlwatcher.cpp b/src/declarative/qml/qmlwatcher.cpp
new file mode 100644
index 0000000..ca99472
--- /dev/null
+++ b/src/declarative/qml/qmlwatcher.cpp
@@ -0,0 +1,183 @@
+/****************************************************************************
+**
+** 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 <QtCore/qmetaobject.h>
+#include <QtCore/qdebug.h>
+#include <QtDeclarative/qmlexpression.h>
+#include <QtDeclarative/qmldebugservice.h>
+#include <QtDeclarative/qmlcontext.h>
+#include <QtDeclarative/qml.h>
+
+#include "qmlwatcher_p.h"
+
+QT_BEGIN_NAMESPACE
+
+
+class QmlWatchProxy : public QObject
+{
+ Q_OBJECT
+public:
+ QmlWatchProxy(int id,
+ QObject *object,
+ int debugId,
+ const QMetaProperty &prop,
+ QmlWatcher *parent = 0);
+
+ QmlWatchProxy(int id,
+ QmlExpression *exp,
+ int debugId,
+ QmlWatcher *parent = 0);
+
+public slots:
+ void notifyValueChanged();
+
+private:
+ friend class QmlWatcher;
+ int m_id;
+ QmlWatcher *m_watch;
+ QObject *m_object;
+ int m_debugId;
+ QMetaProperty m_property;
+
+ QmlExpression *m_expr;
+};
+
+QmlWatchProxy::QmlWatchProxy(int id,
+ QmlExpression *exp,
+ int debugId,
+ QmlWatcher *parent)
+: QObject(parent), m_id(id), m_watch(parent), m_object(0), m_debugId(debugId), m_expr(exp)
+{
+ QObject::connect(m_expr, SIGNAL(valueChanged()), this, SLOT(notifyValueChanged()));
+}
+
+QmlWatchProxy::QmlWatchProxy(int id,
+ QObject *object,
+ int debugId,
+ const QMetaProperty &prop,
+ QmlWatcher *parent)
+: QObject(parent), m_id(id), m_watch(parent), m_object(object), m_debugId(debugId), m_property(prop), m_expr(0)
+{
+ static int refreshIdx = -1;
+ if(refreshIdx == -1)
+ refreshIdx = QmlWatchProxy::staticMetaObject.indexOfMethod("notifyValueChanged()");
+
+ if (prop.hasNotifySignal())
+ QMetaObject::connect(m_object, prop.notifySignalIndex(), this, refreshIdx);
+}
+
+void QmlWatchProxy::notifyValueChanged()
+{
+ QVariant v;
+ if (m_expr)
+ v = m_expr->value();
+ else
+ v = m_property.read(m_object);
+
+ emit m_watch->propertyChanged(m_id, m_debugId, QByteArray(m_property.name()), v);
+}
+
+
+QmlWatcher::QmlWatcher(QObject *parent)
+ : QObject(parent)
+{
+}
+
+bool QmlWatcher::addWatch(int id, quint32 debugId)
+{
+ QObject *object = QmlDebugService::objectForId(debugId);
+ if (object) {
+ int propCount = object->metaObject()->propertyCount();
+ for (int ii=0; ii<propCount; ii++)
+ addPropertyWatch(id, object, debugId, object->metaObject()->property(ii));
+ return true;
+ }
+ return false;
+}
+
+bool QmlWatcher::addWatch(int id, quint32 debugId, const QByteArray &property)
+{
+ QObject *object = QmlDebugService::objectForId(debugId);
+ if (object) {
+ int index = object->metaObject()->indexOfProperty(property.constData());
+ if (index >= 0) {
+ addPropertyWatch(id, object, debugId, object->metaObject()->property(index));
+ return true;
+ }
+ }
+ return false;
+}
+
+bool QmlWatcher::addWatch(int id, quint32 objectId, const QString &expr)
+{
+ QObject *object = QmlDebugService::objectForId(objectId);
+ QmlContext *context = qmlContext(object);
+ if (context) {
+ QmlExpression *exprObj = new QmlExpression(context, expr, object);
+ QmlWatchProxy *proxy = new QmlWatchProxy(id, exprObj, objectId, this);
+ exprObj->setParent(proxy);
+ m_proxies[id].append(proxy);
+ proxy->notifyValueChanged();
+ return true;
+ }
+ return false;
+}
+
+void QmlWatcher::removeWatch(int id)
+{
+ if (!m_proxies.contains(id))
+ return;
+
+ QList<QPointer<QmlWatchProxy> > proxies = m_proxies.take(id);
+ qDeleteAll(proxies);
+}
+
+void QmlWatcher::addPropertyWatch(int id, QObject *object, quint32 debugId, const QMetaProperty &property)
+{
+ QmlWatchProxy *proxy = new QmlWatchProxy(id, object, debugId, property, this);
+ m_proxies[id].append(proxy);
+
+ proxy->notifyValueChanged();
+}
+
+QT_END_NAMESPACE
+
+#include "qmlwatcher.moc"
diff --git a/src/declarative/qml/qmlwatcher_p.h b/src/declarative/qml/qmlwatcher_p.h
new file mode 100644
index 0000000..99cae88
--- /dev/null
+++ b/src/declarative/qml/qmlwatcher_p.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** 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 QMLWATCHER_P_H
+#define QMLWATCHER_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/qobject.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qpair.h>
+#include <QtCore/qhash.h>
+#include <QtCore/qset.h>
+#include <QtCore/qpointer.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlWatchProxy;
+class QmlExpression;
+class QmlContext;
+
+class QmlWatcher : public QObject
+{
+ Q_OBJECT
+public:
+ QmlWatcher(QObject * = 0);
+
+ bool addWatch(int id, quint32 objectId);
+ bool addWatch(int id, quint32 objectId, const QByteArray &property);
+ bool addWatch(int id, quint32 objectId, const QString &expr);
+
+ void removeWatch(int id);
+
+Q_SIGNALS:
+ void propertyChanged(int id, int objectId, const QByteArray &property, const QVariant &value);
+
+private:
+ friend class QmlWatchProxy;
+ void addPropertyWatch(int id, QObject *object, quint32 objectId, const QMetaProperty &property);
+
+ QHash<int, QList<QPointer<QmlWatchProxy> > > m_proxies;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMLWATCHER_P_H
diff --git a/src/declarative/qml/qmlxmlhttprequest.cpp b/src/declarative/qml/qmlxmlhttprequest.cpp
new file mode 100644
index 0000000..5117a00
--- /dev/null
+++ b/src/declarative/qml/qmlxmlhttprequest.cpp
@@ -0,0 +1,1463 @@
+/****************************************************************************
+**
+** 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 <QtCore/qobject.h>
+#include <QtDeclarative/qmlengine.h>
+#include <private/qmlengine_p.h>
+#include <QtScript/qscriptvalue.h>
+#include <QtScript/qscriptcontext.h>
+#include <QtScript/qscriptengine.h>
+#include <QtNetwork/qnetworkreply.h>
+#include <QtCore/qxmlstream.h>
+#include <private/qmlrefcount_p.h>
+#include <private/qmlengine_p.h>
+#include <QtCore/qstack.h>
+#include "qmlxmlhttprequest_p.h"
+
+#include <QtCore/qdebug.h>
+
+// ### Find real values
+#define INVALID_STATE_ERR ((QScriptContext::Error)15)
+
+#define D(arg) (arg)->release()
+#define A(arg) (arg)->addref()
+
+namespace {
+
+class NodeImpl : public QmlRefCount
+{
+public:
+ NodeImpl() : type(Element), parent(0) {}
+ virtual ~NodeImpl() {
+ if (parent) D(parent);
+ for (int ii = 0; ii < children.count(); ++ii)
+ D(children.at(ii));
+ for (int ii = 0; ii < attributes.count(); ++ii)
+ D(attributes.at(ii));
+ }
+
+ // These numbers are copied from the Node IDL definition
+ enum Type {
+ Attr = 2,
+ CDATA = 4,
+ Comment = 8,
+ Document = 9,
+ DocumentFragment = 11,
+ DocumentType = 10,
+ Element = 1,
+ Entity = 6,
+ EntityReference = 5,
+ Notation = 12,
+ ProcessingInstruction = 7,
+ Text = 3
+ };
+ Type type;
+
+ QString namespaceUri;
+ QString name;
+
+ QString data;
+
+ NodeImpl *parent;
+
+ QList<NodeImpl *> children;
+ QList<NodeImpl *> attributes;
+};
+
+class DocumentImpl : public QmlRefCount
+{
+public:
+ DocumentImpl() : root(0) {}
+ virtual ~DocumentImpl() {
+ if (root) D(root);
+ }
+
+ QString version;
+ QString encoding;
+ bool isStandalone;
+
+ NodeImpl *root;
+};
+
+class NamedNodeMap
+{
+public:
+ // JS API
+ static QScriptValue length(QScriptContext *context, QScriptEngine *engine);
+
+ // C++ API
+ static QScriptValue prototype(QScriptEngine *);
+ static QScriptValue create(QScriptEngine *, NodeImpl *, QList<NodeImpl *> *);
+
+ NamedNodeMap();
+ NamedNodeMap(const NamedNodeMap &);
+ NamedNodeMap &operator=(const NamedNodeMap &);
+ ~NamedNodeMap();
+ bool isNull();
+
+ NodeImpl *d;
+ QList<NodeImpl *> *list;
+};
+
+class NamedNodeMapClass : public QScriptClass
+{
+public:
+ NamedNodeMapClass(QScriptEngine *engine) : QScriptClass(engine) {}
+
+ virtual QueryFlags queryProperty(const QScriptValue &object, const QScriptString &name, QueryFlags flags, uint *id);
+ virtual QScriptValue property(const QScriptValue &object, const QScriptString &name, uint id);
+};
+
+class NodeList
+{
+public:
+ // JS API
+ static QScriptValue length(QScriptContext *context, QScriptEngine *engine);
+ static QScriptValue item(QScriptContext *context, QScriptEngine *engine);
+
+ // C++ API
+ static QScriptValue prototype(QScriptEngine *);
+ static QScriptValue create(QScriptEngine *, NodeImpl *);
+
+ NodeList();
+ NodeList(const NodeList &);
+ NodeList &operator=(const NodeList &);
+ ~NodeList();
+ bool isNull();
+
+ NodeImpl *d;
+};
+
+class NodeListClass : public QScriptClass
+{
+public:
+ NodeListClass(QScriptEngine *engine) : QScriptClass(engine) {}
+ virtual QueryFlags queryProperty(const QScriptValue &object, const QScriptString &name, QueryFlags flags, uint *id);
+ virtual QScriptValue property(const QScriptValue &object, const QScriptString &name, uint id);
+};
+
+class Node
+{
+public:
+ // JS API
+ static QScriptValue nodeName(QScriptContext *context, QScriptEngine *engine);
+ static QScriptValue nodeValue(QScriptContext *context, QScriptEngine *engine);
+ static QScriptValue nodeType(QScriptContext *context, QScriptEngine *engine);
+
+ static QScriptValue parentNode(QScriptContext *context, QScriptEngine *engine);
+ static QScriptValue childNodes(QScriptContext *context, QScriptEngine *engine);
+ static QScriptValue firstChild(QScriptContext *context, QScriptEngine *engine);
+ static QScriptValue lastChild(QScriptContext *context, QScriptEngine *engine);
+ static QScriptValue previousSibling(QScriptContext *context, QScriptEngine *engine);
+ static QScriptValue nextSibling(QScriptContext *context, QScriptEngine *engine);
+ static QScriptValue attributes(QScriptContext *context, QScriptEngine *engine);
+
+ //static QScriptValue ownerDocument(QScriptContext *context, QScriptEngine *engine);
+ //static QScriptValue namespaceURI(QScriptContext *context, QScriptEngine *engine);
+ //static QScriptValue prefix(QScriptContext *context, QScriptEngine *engine);
+ //static QScriptValue localName(QScriptContext *context, QScriptEngine *engine);
+ //static QScriptValue baseURI(QScriptContext *context, QScriptEngine *engine);
+ //static QScriptValue textContent(QScriptContext *context, QScriptEngine *engine);
+
+ // C++ API
+ static QScriptValue prototype(QScriptEngine *);
+ static QScriptValue create(QScriptEngine *, NodeImpl *);
+
+ Node();
+ Node(const Node &o);
+ Node &operator=(const Node &);
+ ~Node();
+ bool isNull() const;
+
+ NodeImpl *d;
+};
+
+class Element : public Node
+{
+public:
+ static QScriptValue prototype(QScriptEngine *);
+};
+
+class CharacterData : public Node
+{
+public:
+ // JS API
+ static QScriptValue length(QScriptContext *context, QScriptEngine *engine);
+
+ // C++ API
+ static QScriptValue prototype(QScriptEngine *);
+};
+
+class Text : public CharacterData
+{
+public:
+ // JS API
+ static QScriptValue isElementContentWhitespace(QScriptContext *context, QScriptEngine *engine);
+ static QScriptValue wholeText(QScriptContext *context, QScriptEngine *engine);
+
+ // C++ API
+ static QScriptValue prototype(QScriptEngine *);
+};
+
+class CDATA : public Text
+{
+public:
+ // C++ API
+ static QScriptValue prototype(QScriptEngine *);
+};
+
+class Document : public Node
+{
+public:
+ // JS API
+ static QScriptValue xmlVersion(QScriptContext *context, QScriptEngine *engine);
+ static QScriptValue xmlEncoding(QScriptContext *context, QScriptEngine *engine);
+ static QScriptValue xmlStandalone(QScriptContext *context, QScriptEngine *engine);
+ static QScriptValue documentElement(QScriptContext *context, QScriptEngine *engine);
+
+ // C++ API
+ static QScriptValue prototype(QScriptEngine *);
+ static QScriptValue load(QScriptEngine *engine, const QString &data);
+
+ Document();
+ Document(const Document &);
+ Document &operator=(const Document &);
+ ~Document();
+ bool isNull() const;
+
+ DocumentImpl *d;
+private:
+ Document(DocumentImpl *);
+};
+
+};
+
+Q_DECLARE_METATYPE(Node);
+Q_DECLARE_METATYPE(NodeList);
+Q_DECLARE_METATYPE(NamedNodeMap);
+Q_DECLARE_METATYPE(Document);
+
+QScriptValue Node::nodeName(QScriptContext *context, QScriptEngine *engine)
+{
+ Node node = qscriptvalue_cast<Node>(context->thisObject());
+ if (node.isNull()) return engine->undefinedValue();
+ return QScriptValue(node.d->name);
+}
+
+QScriptValue Node::nodeValue(QScriptContext *context, QScriptEngine *engine)
+{
+ Node node = qscriptvalue_cast<Node>(context->thisObject());
+ if (node.isNull()) return engine->undefinedValue();
+
+ return QScriptValue(node.d->data);
+}
+
+QScriptValue Node::nodeType(QScriptContext *context, QScriptEngine *engine)
+{
+ Node node = qscriptvalue_cast<Node>(context->thisObject());
+ if (node.isNull()) return engine->undefinedValue();
+ return QScriptValue(node.d->type);
+}
+
+QScriptValue Node::parentNode(QScriptContext *context, QScriptEngine *engine)
+{
+ Node node = qscriptvalue_cast<Node>(context->thisObject());
+ if (node.isNull()) return engine->undefinedValue();
+
+ if (node.d->parent) return Node::create(engine, node.d->parent);
+ else return engine->nullValue();
+}
+
+QScriptValue Node::childNodes(QScriptContext *context, QScriptEngine *engine)
+{
+ Node node = qscriptvalue_cast<Node>(context->thisObject());
+ if (node.isNull()) return engine->undefinedValue();
+
+ return NodeList::create(engine, node.d);
+}
+
+QScriptValue Node::firstChild(QScriptContext *context, QScriptEngine *engine)
+{
+ Node node = qscriptvalue_cast<Node>(context->thisObject());
+ if (node.isNull()) return engine->undefinedValue();
+
+ if (node.d->children.isEmpty()) return engine->nullValue();
+ else return Node::create(engine, node.d->children.first());
+}
+
+QScriptValue Node::lastChild(QScriptContext *context, QScriptEngine *engine)
+{
+ Node node = qscriptvalue_cast<Node>(context->thisObject());
+ if (node.isNull()) return engine->undefinedValue();
+
+ if (node.d->children.isEmpty()) return engine->nullValue();
+ else return Node::create(engine, node.d->children.last());
+}
+
+QScriptValue Node::previousSibling(QScriptContext *context, QScriptEngine *engine)
+{
+ Node node = qscriptvalue_cast<Node>(context->thisObject());
+ if (node.isNull()) return engine->undefinedValue();
+
+ if (!node.d->parent) return engine->nullValue();
+
+ for (int ii = 0; ii < node.d->parent->children.count(); ++ii) {
+ if (node.d->parent->children.at(ii) == node.d) {
+ if (ii == 0) return engine->nullValue();
+ else return Node::create(engine, node.d->parent->children.at(ii - 1));
+ }
+ }
+
+ return engine->nullValue();
+}
+
+QScriptValue Node::nextSibling(QScriptContext *context, QScriptEngine *engine)
+{
+ Node node = qscriptvalue_cast<Node>(context->thisObject());
+ if (node.isNull()) return engine->undefinedValue();
+
+ if (!node.d->parent) return engine->nullValue();
+
+ for (int ii = 0; ii < node.d->parent->children.count(); ++ii) {
+ if (node.d->parent->children.at(ii) == node.d) {
+ if ((ii + 1) == node.d->parent->children.count()) return engine->nullValue();
+ else return Node::create(engine, node.d->parent->children.at(ii + 1));
+ }
+ }
+
+ return engine->nullValue();
+}
+
+QScriptValue Node::attributes(QScriptContext *context, QScriptEngine *engine)
+{
+ Node node = qscriptvalue_cast<Node>(context->thisObject());
+ if (node.isNull()) return engine->undefinedValue();
+
+ if (node.d->type != NodeImpl::Element)
+ return engine->nullValue();
+ else
+ return NamedNodeMap::create(engine, node.d, &node.d->attributes);
+}
+
+QScriptValue Node::prototype(QScriptEngine *engine)
+{
+ QScriptValue proto = engine->newObject();
+
+ proto.setProperty(QLatin1String("nodeName"), engine->newFunction(nodeName), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+ proto.setProperty(QLatin1String("nodeValue"), engine->newFunction(nodeValue), QScriptValue::ReadOnly | QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
+ proto.setProperty(QLatin1String("nodeType"), engine->newFunction(nodeType), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+ proto.setProperty(QLatin1String("parentNode"), engine->newFunction(parentNode), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+ proto.setProperty(QLatin1String("childNodes"), engine->newFunction(childNodes), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+ proto.setProperty(QLatin1String("firstChild"), engine->newFunction(firstChild), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+ proto.setProperty(QLatin1String("lastChild"), engine->newFunction(lastChild), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+ proto.setProperty(QLatin1String("previousSibling"), engine->newFunction(previousSibling), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+ proto.setProperty(QLatin1String("nextSibling"), engine->newFunction(nextSibling), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+ proto.setProperty(QLatin1String("attributes"), engine->newFunction(attributes), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+
+ return proto;
+}
+
+QScriptValue Node::create(QScriptEngine *engine, NodeImpl *data)
+{
+ QScriptValue instance = engine->newObject();
+
+ switch (data->type) {
+ case NodeImpl::Attr:
+ case NodeImpl::Comment:
+ case NodeImpl::Document:
+ case NodeImpl::DocumentFragment:
+ case NodeImpl::DocumentType:
+ case NodeImpl::Entity:
+ case NodeImpl::EntityReference:
+ case NodeImpl::Notation:
+ case NodeImpl::CDATA:
+ instance.setPrototype(CDATA::prototype(engine));
+ break;
+ case NodeImpl::ProcessingInstruction:
+ instance.setPrototype(Node::prototype(engine));
+ break;
+ case NodeImpl::Text:
+ instance.setPrototype(Text::prototype(engine));
+ break;
+ case NodeImpl::Element:
+ instance.setPrototype(Element::prototype(engine));
+ break;
+ }
+
+ Node node;
+ node.d = data;
+ if (data) A(data);
+
+ return engine->newVariant(instance, qVariantFromValue(node));
+}
+
+QScriptValue Element::prototype(QScriptEngine *engine)
+{
+ QScriptValue proto = engine->newObject();
+ proto.setPrototype(Node::prototype(engine));
+
+ proto.setProperty(QLatin1String("tagName"), engine->newFunction(nodeName), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+
+ return proto;
+}
+
+QScriptValue CharacterData::length(QScriptContext *context, QScriptEngine *engine)
+{
+ Node node = qscriptvalue_cast<Node>(context->thisObject());
+ if (node.isNull()) return engine->undefinedValue();
+
+ return QScriptValue(node.d->data.length());
+}
+
+QScriptValue CharacterData::prototype(QScriptEngine *engine)
+{
+ QScriptValue proto = engine->newObject();
+ proto.setPrototype(Node::prototype(engine));
+
+ proto.setProperty(QLatin1String("data"), engine->newFunction(nodeValue), QScriptValue::ReadOnly | QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
+ proto.setProperty(QLatin1String("length"), engine->newFunction(length), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+
+ return proto;
+}
+
+QScriptValue Text::isElementContentWhitespace(QScriptContext *context, QScriptEngine *engine)
+{
+ Node node = qscriptvalue_cast<Node>(context->thisObject());
+ if (node.isNull()) return engine->undefinedValue();
+
+ // ### implement
+ return QScriptValue(false);
+}
+
+QScriptValue Text::wholeText(QScriptContext *context, QScriptEngine *engine)
+{
+ Node node = qscriptvalue_cast<Node>(context->thisObject());
+ if (node.isNull()) return engine->undefinedValue();
+
+ // ### implement
+ return QScriptValue(QString());
+}
+
+QScriptValue Text::prototype(QScriptEngine *engine)
+{
+ QScriptValue proto = engine->newObject();
+ proto.setPrototype(CharacterData::prototype(engine));
+
+ proto.setProperty(QLatin1String("isElementContentWhitespace"), engine->newFunction(isElementContentWhitespace), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+ proto.setProperty(QLatin1String("wholeText"), engine->newFunction(wholeText), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+
+ return proto;
+}
+
+QScriptValue CDATA::prototype(QScriptEngine *engine)
+{
+ QScriptValue proto = engine->newObject();
+ proto.setPrototype(Text::prototype(engine));
+ return proto;
+}
+
+QScriptValue Document::prototype(QScriptEngine *engine)
+{
+ QScriptValue proto = engine->newObject();
+ proto.setPrototype(Node::prototype(engine));
+
+ proto.setProperty(QLatin1String("xmlVersion"), engine->newFunction(xmlVersion), QScriptValue::ReadOnly | QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
+ proto.setProperty(QLatin1String("xmlEncoding"), engine->newFunction(xmlEncoding), QScriptValue::ReadOnly | QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
+ proto.setProperty(QLatin1String("xmlStandalone"), engine->newFunction(xmlStandalone), QScriptValue::ReadOnly | QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
+ proto.setProperty(QLatin1String("documentElement"), engine->newFunction(documentElement), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+
+ return proto;
+}
+
+QScriptValue Document::load(QScriptEngine *engine, const QString &data)
+{
+ Q_ASSERT(engine);
+
+ DocumentImpl *document = 0;
+ QStack<NodeImpl *> nodeStack;
+
+ QXmlStreamReader reader(data);
+
+ while (!reader.atEnd()) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::NoToken:
+ break;
+ case QXmlStreamReader::Invalid:
+ break;
+ case QXmlStreamReader::StartDocument:
+ Q_ASSERT(!document);
+ document = new DocumentImpl;
+ document->version = reader.documentVersion().toString();
+ document->encoding = reader.documentEncoding().toString();
+ document->isStandalone = reader.isStandaloneDocument();
+ break;
+ case QXmlStreamReader::EndDocument:
+ break;
+ case QXmlStreamReader::StartElement:
+ {
+ Q_ASSERT(document);
+ NodeImpl *node = new NodeImpl;
+ node->namespaceUri = reader.namespaceUri().toString();
+ node->name = reader.name().toString();
+ if (nodeStack.isEmpty()) {
+ document->root = node;
+ } else {
+ node->parent = nodeStack.top();
+ A(node->parent);
+ node->parent->children.append(node);
+ }
+ nodeStack.append(node);
+
+ foreach (const QXmlStreamAttribute &a, reader.attributes()) {
+ NodeImpl *attr = new NodeImpl;
+ attr->type = NodeImpl::Attr;
+ attr->namespaceUri = a.namespaceUri().toString();
+ attr->name = a.name().toString();
+ attr->data = a.value().toString();
+ node->attributes.append(attr);
+ }
+ }
+ break;
+ case QXmlStreamReader::EndElement:
+ nodeStack.pop();
+ break;
+ case QXmlStreamReader::Characters:
+ {
+ NodeImpl *node = new NodeImpl;
+ node->type = reader.isCDATA()?NodeImpl::CDATA:NodeImpl::Text;
+ node->parent = nodeStack.top();
+ A(node->parent);
+ node->parent->children.append(node);
+ node->data = reader.text().toString();
+ }
+ break;
+ case QXmlStreamReader::Comment:
+ break;
+ case QXmlStreamReader::DTD:
+ break;
+ case QXmlStreamReader::EntityReference:
+ break;
+ case QXmlStreamReader::ProcessingInstruction:
+ break;
+ }
+ }
+
+ if (!document || reader.hasError()) {
+ if (document) D(document);
+ return engine->nullValue();
+ }
+
+ QScriptValue instance = engine->newObject();
+ instance.setPrototype(Document::prototype(engine));
+ return engine->newVariant(instance, qVariantFromValue(Document(document)));
+}
+
+Node::Node()
+: d(0)
+{
+}
+
+Node::Node(const Node &o)
+: d(o.d)
+{
+ if (d) A(d);
+}
+
+Node &Node::operator=(const Node &o)
+{
+ if (o.d) A(o.d);
+ if (d) D(d);
+ d = o.d;
+ return *this;
+}
+
+Node::~Node()
+{
+ if (d) D(d);
+}
+
+bool Node::isNull() const
+{
+ return d == 0;
+}
+
+QScriptValue NamedNodeMap::length(QScriptContext *context, QScriptEngine *engine)
+{
+ NamedNodeMap map = qscriptvalue_cast<NamedNodeMap>(context->thisObject().data());
+ if (map.isNull()) return engine->undefinedValue();
+
+ return QScriptValue(map.list->count());
+}
+
+QScriptValue NamedNodeMap::prototype(QScriptEngine *engine)
+{
+ QScriptValue proto = engine->newObject();
+
+ proto.setProperty(QLatin1String("length"), engine->newFunction(length), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+
+ return proto;
+}
+
+QScriptValue NamedNodeMap::create(QScriptEngine *engine, NodeImpl *data, QList<NodeImpl *> *list)
+{
+ QScriptValue instance = engine->newObject();
+ instance.setPrototype(NamedNodeMap::prototype(engine));
+
+ NamedNodeMap map;
+ map.d = data;
+ map.list = list;
+ if (data) A(data);
+
+ instance.setData(engine->newVariant(qVariantFromValue(map)));
+
+ if (!QmlEnginePrivate::get(engine)->namedNodeMapClass)
+ QmlEnginePrivate::get(engine)->namedNodeMapClass= new NamedNodeMapClass(engine);
+
+ instance.setScriptClass(QmlEnginePrivate::get(engine)->namedNodeMapClass);
+
+ return instance;
+}
+
+NamedNodeMap::NamedNodeMap()
+: d(0), list(0)
+{
+}
+
+NamedNodeMap::NamedNodeMap(const NamedNodeMap &o)
+: d(o.d), list(o.list)
+{
+ if (d) A(d);
+}
+
+NamedNodeMap &NamedNodeMap::operator=(const NamedNodeMap &o)
+{
+ if (o.d) A(o.d);
+ if (d) D(d);
+ d = o.d;
+ list = o.list;
+ return *this;
+}
+
+NamedNodeMap::~NamedNodeMap()
+{
+ if (d) D(d);
+}
+
+bool NamedNodeMap::isNull()
+{
+ return d == 0;
+}
+
+QScriptValue NodeList::item(QScriptContext *context, QScriptEngine *engine)
+{
+ NodeList list = qscriptvalue_cast<NodeList>(context->thisObject().data());
+ if (list.isNull() || context->argumentCount() != 1)
+ return engine->undefinedValue();
+
+ qint32 index = context->argument(0).toInt32();
+
+ if (index >= list.d->children.count())
+ return engine->undefinedValue(); // ### Exception
+ else
+ return Node::create(engine, list.d->children.at(index));
+}
+
+QScriptValue NodeList::length(QScriptContext *context, QScriptEngine *engine)
+{
+ NodeList list = qscriptvalue_cast<NodeList>(context->thisObject().data());
+ if (list.isNull()) return engine->undefinedValue();
+
+ return QScriptValue(list.d->children.count());
+}
+
+QScriptValue NodeList::prototype(QScriptEngine *engine)
+{
+ QScriptValue proto = engine->newObject();
+
+ proto.setProperty(QLatin1String("length"), engine->newFunction(length), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+ proto.setProperty(QLatin1String("item"), engine->newFunction(item, 1), QScriptValue::ReadOnly);
+
+ return proto;
+}
+
+QScriptValue NodeList::create(QScriptEngine *engine, NodeImpl *data)
+{
+ QScriptValue instance = engine->newObject();
+ instance.setPrototype(NodeList::prototype(engine));
+
+ NodeList list;
+ list.d = data;
+ if (data) A(data);
+
+ instance.setData(engine->newVariant(qVariantFromValue(list)));
+
+ if (!QmlEnginePrivate::get(engine)->nodeListClass)
+ QmlEnginePrivate::get(engine)->nodeListClass= new NodeListClass(engine);
+
+ instance.setScriptClass(QmlEnginePrivate::get(engine)->nodeListClass);
+
+ return instance;
+}
+
+NodeList::NodeList()
+: d(0)
+{
+}
+
+NodeList::NodeList(const NodeList &o)
+: d(o.d)
+{
+ if (d) A(d);
+}
+
+NodeList &NodeList::operator=(const NodeList &o)
+{
+ if (o.d) A(o.d);
+ if (d) D(d);
+ d = o.d;
+ return *this;
+}
+
+NodeList::~NodeList()
+{
+ if (d) D(d);
+}
+
+bool NodeList::isNull()
+{
+ return d == 0;
+}
+
+NamedNodeMapClass::QueryFlags NamedNodeMapClass::queryProperty(const QScriptValue &object, const QScriptString &name, QueryFlags flags, uint *id)
+{
+ if (!(flags & HandlesReadAccess))
+ return 0;
+
+ bool ok = false;
+ uint index = name.toString().toUInt(&ok);
+ if (!ok)
+ return 0;
+
+ NamedNodeMap map = qscriptvalue_cast<NamedNodeMap>(object.data());
+ if (map.isNull() || (uint)map.list->count() <= index)
+ return 0; // ### I think we're meant to raise an exception
+
+ *id = index;
+ return HandlesReadAccess;
+}
+
+QScriptValue NamedNodeMapClass::property(const QScriptValue &object, const QScriptString &, uint id)
+{
+ NamedNodeMap map = qscriptvalue_cast<NamedNodeMap>(object.data());
+ return Node::create(engine(), map.list->at(id));
+}
+
+NodeListClass::QueryFlags NodeListClass::queryProperty(const QScriptValue &object, const QScriptString &name, QueryFlags flags, uint *id)
+{
+ if (!(flags & HandlesReadAccess))
+ return 0;
+
+ bool ok = false;
+ uint index = name.toString().toUInt(&ok);
+ if (!ok)
+ return 0;
+
+ NodeList list = qscriptvalue_cast<NodeList>(object.data());
+ if (list.isNull() || (uint)list.d->children.count() <= index)
+ return 0; // ### I think we're meant to raise an exception
+
+ *id = index;
+ return HandlesReadAccess;
+}
+
+QScriptValue NodeListClass::property(const QScriptValue &object, const QScriptString &, uint id)
+{
+ NodeList list = qscriptvalue_cast<NodeList>(object.data());
+ return Node::create(engine(), list.d->children.at(id));
+}
+
+Document::Document()
+: d(0)
+{
+}
+
+Document::Document(DocumentImpl *data)
+: d(data)
+{
+}
+
+Document::Document(const Document &o)
+: Node(o), d(o.d)
+{
+ if (d) A(d);
+}
+
+Document &Document::operator=(const Document &o)
+{
+ if (o.d) A(o.d);
+ if (d) D(d);
+ d = o.d;
+ return *this;
+}
+
+Document::~Document()
+{
+ if (d) D(d);
+}
+
+bool Document::isNull() const
+{
+ return d == 0;
+}
+
+QScriptValue Document::documentElement(QScriptContext *context, QScriptEngine *engine)
+{
+ Document document = qscriptvalue_cast<Document>(context->thisObject());
+ if (document.isNull()) return engine->undefinedValue();
+
+ if (!document.d->root) return engine->nullValue();
+
+ return Node::create(engine, document.d->root);
+}
+
+QScriptValue Document::xmlStandalone(QScriptContext *context, QScriptEngine *engine)
+{
+ Document document = qscriptvalue_cast<Document>(context->thisObject());
+ if (document.isNull()) return engine->undefinedValue();
+
+ if (context->argumentCount())
+ document.d->isStandalone = context->argument(0).toBool();
+
+ return QScriptValue(document.d->isStandalone);
+}
+
+QScriptValue Document::xmlVersion(QScriptContext *context, QScriptEngine *engine)
+{
+ Document document = qscriptvalue_cast<Document>(context->thisObject());
+ if (document.isNull()) return engine->undefinedValue();
+
+ if (context->argumentCount())
+ document.d->version = context->argument(0).toString();
+
+ return QScriptValue(document.d->version);
+}
+
+QScriptValue Document::xmlEncoding(QScriptContext *context, QScriptEngine *engine)
+{
+ Document document = qscriptvalue_cast<Document>(context->thisObject());
+ if (document.isNull()) return engine->undefinedValue();
+
+ if (context->argumentCount())
+ document.d->encoding = context->argument(0).toString();
+
+ return QScriptValue(document.d->encoding);
+}
+
+class QmlXMLHttpRequest : public QObject
+{
+Q_OBJECT
+public:
+ enum State { Unsent = 0,
+ Opened = 1, HeadersReceived = 2,
+ Loading = 3, Done = 4 };
+
+ QmlXMLHttpRequest(QmlEngine *engine);
+ virtual ~QmlXMLHttpRequest();
+
+ QScriptValue callback() const;
+ void setCallback(const QScriptValue &);
+
+ bool sendFlag() const;
+ bool errorFlag() const;
+ quint32 readyState() const;
+ int replyStatus() const;
+ QString replyStatusText() const;
+
+ void open(const QString &, const QUrl &);
+ void addHeader(const QString &, const QString &);
+ QString header(const QString &name);
+ QString headers();
+ void send(const QByteArray &);
+ void abort();
+
+ QString responseBody() const;
+private slots:
+ void downloadProgress(qint64);
+ void error(QNetworkReply::NetworkError);
+ void finished();
+
+private:
+ QmlEngine *m_engine;
+
+ State m_state;
+ bool m_errorFlag;
+ bool m_sendFlag;
+ QString m_method;
+ QUrl m_url;
+ QByteArray m_responseEntityBody;
+
+ typedef QPair<QByteArray, QByteArray> HeaderPair;
+ typedef QList<HeaderPair> HeadersList;
+ HeadersList m_headersList;
+ void fillHeadersList();
+
+ void dispatchCallback();
+ QScriptValue m_callback;
+
+ int m_status;
+ QString m_statusText;
+ QNetworkRequest m_request;
+ QNetworkReply *m_network;
+ void destroyNetwork();
+};
+
+QmlXMLHttpRequest::QmlXMLHttpRequest(QmlEngine *engine)
+: m_engine(engine), m_state(Unsent), m_errorFlag(false), m_sendFlag(false),
+ m_network(0)
+{
+ Q_ASSERT(m_engine);
+}
+
+QmlXMLHttpRequest::~QmlXMLHttpRequest()
+{
+ destroyNetwork();
+}
+
+QScriptValue QmlXMLHttpRequest::callback() const
+{
+ return m_callback;
+}
+
+void QmlXMLHttpRequest::setCallback(const QScriptValue &c)
+{
+ m_callback = c;
+}
+
+bool QmlXMLHttpRequest::sendFlag() const
+{
+ return m_sendFlag;
+}
+
+bool QmlXMLHttpRequest::errorFlag() const
+{
+ return m_errorFlag;
+}
+
+quint32 QmlXMLHttpRequest::readyState() const
+{
+ return m_state;
+}
+
+int QmlXMLHttpRequest::replyStatus() const
+{
+ return m_status;
+}
+
+QString QmlXMLHttpRequest::replyStatusText() const
+{
+ return m_statusText;
+}
+
+void QmlXMLHttpRequest::open(const QString &method, const QUrl &url)
+{
+ destroyNetwork();
+ m_sendFlag = false;
+ m_errorFlag = false;
+ m_responseEntityBody = QByteArray();
+ m_method = method;
+ m_url = url;
+ m_state = Opened;
+ dispatchCallback();
+}
+
+void QmlXMLHttpRequest::addHeader(const QString &name, const QString &value)
+{
+ QByteArray utfname = name.toUtf8();
+
+ if (m_request.hasRawHeader(utfname)) {
+ m_request.setRawHeader(utfname, m_request.rawHeader(utfname) + "," + value.toUtf8());
+ } else {
+ m_request.setRawHeader(utfname, value.toUtf8());
+ }
+}
+
+QString QmlXMLHttpRequest::header(const QString &name)
+{
+ QByteArray utfname = name.toUtf8();
+
+ foreach (const HeaderPair &header, m_headersList) {
+ if (header.first == utfname)
+ return QString::fromUtf8(header.second);
+ }
+ return QString();
+}
+
+QString QmlXMLHttpRequest::headers()
+{
+ QString ret;
+
+ foreach (const HeaderPair &header, m_headersList) {
+ if (ret.length())
+ ret.append(QString::fromUtf8("\r\n"));
+ ret.append(QString::fromUtf8(header.first));
+ ret.append(QString::fromUtf8(": "));
+ ret.append(QString::fromUtf8(header.second));
+ }
+ return ret;
+}
+
+void QmlXMLHttpRequest::fillHeadersList()
+{
+ QList<QByteArray> headerList = m_network->rawHeaderList();
+
+ m_headersList.clear();
+ foreach (const QByteArray &header, headerList) {
+ HeaderPair pair (header, m_network->rawHeader(header));
+ m_headersList << pair;
+ }
+}
+
+void QmlXMLHttpRequest::send(const QByteArray &data)
+{
+ m_errorFlag = false;
+ m_sendFlag = true;
+
+ dispatchCallback();
+
+ m_request.setUrl(m_url);
+
+ if (m_method == QLatin1String("GET"))
+ m_network = m_engine->networkAccessManager()->get(m_request);
+ else if (m_method == QLatin1String("HEAD"))
+ m_network = m_engine->networkAccessManager()->head(m_request);
+ else if(m_method == QLatin1String("POST"))
+ m_network = m_engine->networkAccessManager()->post(m_request, data);
+ else if(m_method == QLatin1String("PUT"))
+ m_network = m_engine->networkAccessManager()->put(m_request, data);
+
+ QObject::connect(m_network, SIGNAL(downloadProgress(qint64,qint64)),
+ this, SLOT(downloadProgress(qint64)));
+ QObject::connect(m_network, SIGNAL(error(QNetworkReply::NetworkError)),
+ this, SLOT(error(QNetworkReply::NetworkError)));
+ QObject::connect(m_network, SIGNAL(finished()),
+ this, SLOT(finished()));
+}
+
+void QmlXMLHttpRequest::abort()
+{
+ destroyNetwork();
+ m_responseEntityBody = QByteArray();
+ m_errorFlag = true;
+ m_request = QNetworkRequest();
+
+ if (!(m_state == Unsent ||
+ (m_state == Opened && !m_sendFlag) ||
+ m_state == Done)) {
+
+ m_state = Done;
+ m_sendFlag = false;
+ dispatchCallback();
+ }
+
+ m_state = Unsent;
+}
+
+void QmlXMLHttpRequest::downloadProgress(qint64 bytes)
+{
+ m_status =
+ m_network->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
+ m_statusText =
+ QString::fromUtf8(m_network->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray());
+
+ // ### We assume if this is called the headers are now available
+ if (m_state < HeadersReceived) {
+ m_state = HeadersReceived;
+ fillHeadersList ();
+ dispatchCallback();
+ }
+
+ bool wasEmpty = m_responseEntityBody.isEmpty();
+ m_responseEntityBody.append(m_network->readAll());
+ if (wasEmpty && !m_responseEntityBody.isEmpty()) {
+ m_state = Loading;
+ dispatchCallback();
+ }
+}
+
+void QmlXMLHttpRequest::error(QNetworkReply::NetworkError error)
+{
+ m_status =
+ m_network->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
+ m_statusText =
+ QString::fromUtf8(m_network->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray());
+
+ m_responseEntityBody = QByteArray();
+ m_errorFlag = true;
+ m_request = QNetworkRequest();
+
+ destroyNetwork();
+
+ m_state = Done;
+ dispatchCallback();
+}
+
+void QmlXMLHttpRequest::finished()
+{
+ // ### We need to transparently redirect as dictated by the spec
+
+ m_status =
+ m_network->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
+ m_statusText =
+ QString::fromUtf8(m_network->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray());
+
+ if (m_state < HeadersReceived) {
+ m_state = HeadersReceived;
+ fillHeadersList ();
+ dispatchCallback();
+ }
+ m_responseEntityBody.append(m_network->readAll());
+ destroyNetwork();
+ if (m_state < Loading) {
+ m_state = Loading;
+ dispatchCallback();
+ }
+ m_state = Done;
+ dispatchCallback();
+}
+
+
+QString QmlXMLHttpRequest::responseBody() const
+{
+ return QString::fromUtf8(m_responseEntityBody);
+}
+
+void QmlXMLHttpRequest::dispatchCallback()
+{
+ m_callback.call();
+}
+
+void QmlXMLHttpRequest::destroyNetwork()
+{
+ if (m_network) {
+ m_network->disconnect();
+ m_network->deleteLater();
+ m_network = 0;
+ }
+}
+
+// XMLHttpRequest methods
+static QScriptValue qmlxmlhttprequest_open(QScriptContext *context, QScriptEngine *engine)
+{
+ QmlXMLHttpRequest *request = qobject_cast<QmlXMLHttpRequest *>(context->thisObject().data().toQObject());
+ if (!request) return context->throwError(QScriptContext::ReferenceError, QLatin1String("Not an XMLHttpRequest object"));
+
+ if (context->argumentCount() < 2 || context->argumentCount() > 5)
+ return context->throwError(QScriptContext::SyntaxError, QLatin1String("Incorrect argument count"));
+
+ // Argument 0 - Method
+ QString method = context->argument(0).toString().toUpper();
+ if (method != QLatin1String("GET") &&
+ method != QLatin1String("PUT") &&
+ method != QLatin1String("HEAD") &&
+ method != QLatin1String("POST"))
+ return context->throwError(QScriptContext::SyntaxError, QLatin1String("Unsupported method"));
+
+
+ // Argument 1 - URL
+ QUrl url(context->argument(1).toString()); // ### Need to resolve correctly
+
+ if (url.isRelative()) {
+ QmlContext *ctxt = QmlEnginePrivate::get(engine)->currentExpression?QmlEnginePrivate::get(engine)->currentExpression->context():0;
+ if (ctxt)
+ url = ctxt->resolvedUrl(url);
+ else
+ 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, QLatin1String("Synchronous call not supported"));
+
+
+ // Argument 3/4 - user/pass (optional)
+ QString username, password;
+ if (context->argumentCount() > 3)
+ username = context->argument(3).toString();
+ if (context->argumentCount() > 4)
+ password = context->argument(4).toString();
+
+
+ // Clear the fragment (if any)
+ url.setFragment(QString());
+ // Set username/password
+ if (!username.isNull()) url.setUserName(username);
+ if (!password.isNull()) url.setPassword(password);
+
+ request->open(method, url);
+
+ return engine->undefinedValue();
+}
+
+static QScriptValue qmlxmlhttprequest_setRequestHeader(QScriptContext *context, QScriptEngine *engine)
+{
+ QmlXMLHttpRequest *request = qobject_cast<QmlXMLHttpRequest *>(context->thisObject().data().toQObject());
+ if (!request) return context->throwError(QScriptContext::ReferenceError, QLatin1String("Not an XMLHttpRequest object"));
+
+ if (context->argumentCount() != 2)
+ return context->throwError(QScriptContext::SyntaxError, QLatin1String("Incorrect argument count"));
+
+
+ if (request->readyState() != QmlXMLHttpRequest::Opened ||
+ request->sendFlag())
+ return context->throwError(INVALID_STATE_ERR, QLatin1String("Invalid state"));
+
+
+ QString name = context->argument(0).toString();
+ QString value = context->argument(1).toString();
+
+ // ### Check that name and value are well formed
+
+ QString nameUpper = name.toUpper();
+ if (nameUpper == QLatin1String("ACCEPT-CHARSET") ||
+ nameUpper == QLatin1String("ACCEPT-ENCODING") ||
+ nameUpper == QLatin1String("CONNECTION") ||
+ nameUpper == QLatin1String("CONTENT-LENGTH") ||
+ nameUpper == QLatin1String("COOKIE") ||
+ nameUpper == QLatin1String("COOKIE2") ||
+ nameUpper == QLatin1String("CONTENT-TRANSFER-ENCODING") ||
+ nameUpper == QLatin1String("DATE") ||
+ nameUpper == QLatin1String("EXPECT") ||
+ nameUpper == QLatin1String("HOST") ||
+ nameUpper == QLatin1String("KEEP-ALIVE") ||
+ nameUpper == QLatin1String("REFERER") ||
+ nameUpper == QLatin1String("TE") ||
+ nameUpper == QLatin1String("TRAILER") ||
+ nameUpper == QLatin1String("TRANSFER-ENCODING") ||
+ nameUpper == QLatin1String("UPGRADE") ||
+ nameUpper == QLatin1String("USER-AGENT") ||
+ nameUpper == QLatin1String("VIA") ||
+ nameUpper.startsWith(QLatin1String("PROXY-")) ||
+ nameUpper.startsWith(QLatin1String("SEC-")))
+ return engine->undefinedValue();
+
+ request->addHeader(nameUpper, value);
+
+ return engine->undefinedValue();
+}
+
+static QScriptValue qmlxmlhttprequest_send(QScriptContext *context, QScriptEngine *engine)
+{
+ QmlXMLHttpRequest *request = qobject_cast<QmlXMLHttpRequest *>(context->thisObject().data().toQObject());
+ if (!request) return context->throwError(QScriptContext::ReferenceError, QLatin1String("Not an XMLHttpRequest object"));
+
+ if (request->readyState() != QmlXMLHttpRequest::Opened)
+ return context->throwError(INVALID_STATE_ERR, QLatin1String("Invalid state"));
+
+ if (request->sendFlag())
+ return context->throwError(INVALID_STATE_ERR, QLatin1String("Invalid state"));
+
+ QByteArray data;
+ if (context->argumentCount() > 0)
+ data = context->argument(0).toString().toUtf8();
+
+ request->send(data);
+
+ return engine->undefinedValue();
+}
+
+static QScriptValue qmlxmlhttprequest_abort(QScriptContext *context, QScriptEngine *engine)
+{
+ QmlXMLHttpRequest *request = qobject_cast<QmlXMLHttpRequest *>(context->thisObject().data().toQObject());
+ if (!request) return context->throwError(QScriptContext::ReferenceError, QLatin1String("Not an XMLHttpRequest object"));
+
+ request->abort();
+
+ return engine->undefinedValue();
+}
+
+static QScriptValue qmlxmlhttprequest_getResponseHeader(QScriptContext *context, QScriptEngine *engine)
+{
+ QmlXMLHttpRequest *request = qobject_cast<QmlXMLHttpRequest *>(context->thisObject().data().toQObject());
+ if (!request) return context->throwError(QScriptContext::ReferenceError, QLatin1String("Not an XMLHttpRequest object"));
+
+ if (context->argumentCount() != 1)
+ return context->throwError(QScriptContext::SyntaxError, QLatin1String("Incorrect argument count"));
+
+ if (request->readyState() != QmlXMLHttpRequest::Loading &&
+ request->readyState() != QmlXMLHttpRequest::Done &&
+ request->readyState() != QmlXMLHttpRequest::HeadersReceived)
+ return context->throwError(INVALID_STATE_ERR, QLatin1String("Invalid state"));
+
+ QString headerName = context->argument(0).toString();
+
+ return QScriptValue(request->header(headerName));
+}
+
+static QScriptValue qmlxmlhttprequest_getAllResponseHeaders(QScriptContext *context, QScriptEngine *engine)
+{
+ QmlXMLHttpRequest *request = qobject_cast<QmlXMLHttpRequest *>(context->thisObject().data().toQObject());
+ if (!request) return context->throwError(QScriptContext::ReferenceError, QLatin1String("Not an XMLHttpRequest object"));
+
+ if (context->argumentCount() != 0)
+ return context->throwError(QScriptContext::SyntaxError, QLatin1String("Incorrect argument count"));
+
+ if (request->readyState() != QmlXMLHttpRequest::Loading &&
+ request->readyState() != QmlXMLHttpRequest::Done &&
+ request->readyState() != QmlXMLHttpRequest::HeadersReceived)
+ return context->throwError(INVALID_STATE_ERR, QLatin1String("Invalid state"));
+
+ return QScriptValue(request->headers());
+}
+
+// XMLHttpRequest properties
+static QScriptValue qmlxmlhttprequest_readyState(QScriptContext *context, QScriptEngine *engine)
+{
+ QmlXMLHttpRequest *request = qobject_cast<QmlXMLHttpRequest *>(context->thisObject().data().toQObject());
+ if (!request) return context->throwError(QScriptContext::ReferenceError, QLatin1String("Not an XMLHttpRequest object"));
+
+ return QScriptValue(request->readyState());
+}
+
+static QScriptValue qmlxmlhttprequest_status(QScriptContext *context, QScriptEngine *engine)
+{
+ QmlXMLHttpRequest *request = qobject_cast<QmlXMLHttpRequest *>(context->thisObject().data().toQObject());
+ if (!request) return context->throwError(QScriptContext::ReferenceError, QLatin1String("Not an XMLHttpRequest object"));
+
+ if (request->readyState() == QmlXMLHttpRequest::Unsent ||
+ request->readyState() == QmlXMLHttpRequest::Opened)
+ return context->throwError(INVALID_STATE_ERR, QLatin1String("Invalid state"));
+
+ if (request->errorFlag())
+ return QScriptValue(0);
+ else
+ return QScriptValue(request->replyStatus());
+}
+
+static QScriptValue qmlxmlhttprequest_statusText(QScriptContext *context, QScriptEngine *engine)
+{
+ QmlXMLHttpRequest *request = qobject_cast<QmlXMLHttpRequest *>(context->thisObject().data().toQObject());
+ if (!request) return context->throwError(QScriptContext::ReferenceError, QLatin1String("Not an XMLHttpRequest object"));
+
+ if (request->readyState() == QmlXMLHttpRequest::Unsent ||
+ request->readyState() == QmlXMLHttpRequest::Opened)
+ return context->throwError(INVALID_STATE_ERR, QLatin1String("Invalid state"));
+
+ if (request->errorFlag())
+ return QScriptValue(0);
+ else
+ return QScriptValue(request->replyStatusText());
+}
+
+static QScriptValue qmlxmlhttprequest_responseText(QScriptContext *context, QScriptEngine *engine)
+{
+ QmlXMLHttpRequest *request = qobject_cast<QmlXMLHttpRequest *>(context->thisObject().data().toQObject());
+ if (!request) return context->throwError(QScriptContext::ReferenceError, QLatin1String("Not an XMLHttpRequest object"));
+
+ if (request->readyState() != QmlXMLHttpRequest::Loading &&
+ request->readyState() != QmlXMLHttpRequest::Done)
+ return QScriptValue(QString());
+ else
+ return QScriptValue(request->responseBody());
+}
+
+static QScriptValue qmlxmlhttprequest_responseXML(QScriptContext *context, QScriptEngine *engine)
+{
+ QmlXMLHttpRequest *request = qobject_cast<QmlXMLHttpRequest *>(context->thisObject().data().toQObject());
+ if (!request) return context->throwError(QScriptContext::ReferenceError, QLatin1String("Not an XMLHttpRequest object"));
+
+ if (request->readyState() != QmlXMLHttpRequest::Loading &&
+ request->readyState() != QmlXMLHttpRequest::Done)
+ return engine->nullValue();
+ else
+ return Document::load(engine, request->responseBody());
+}
+
+static QScriptValue qmlxmlhttprequest_onreadystatechange(QScriptContext *context, QScriptEngine *engine)
+{
+ QmlXMLHttpRequest *request = qobject_cast<QmlXMLHttpRequest *>(context->thisObject().data().toQObject());
+ if (!request) return context->throwError(QScriptContext::ReferenceError, QLatin1String("Not an XMLHttpRequest object"));
+
+ if (context->argumentCount())
+ request->setCallback(context->argument(0));
+
+ return request->callback();
+}
+
+// Constructor
+static QScriptValue qmlxmlhttprequest_new(QScriptContext *context, QScriptEngine *engine)
+{
+ if (context->isCalledAsConstructor()) {
+ context->thisObject().setData(engine->newQObject(new QmlXMLHttpRequest(QmlEnginePrivate::getEngine(engine)), QScriptEngine::ScriptOwnership));
+ }
+ return engine->undefinedValue();
+}
+
+void qt_add_qmlxmlhttprequest(QScriptEngine *engine)
+{
+ QScriptValue prototype = engine->newObject();
+
+ // Methods
+ prototype.setProperty(QLatin1String("open"), engine->newFunction(qmlxmlhttprequest_open, 2));
+ prototype.setProperty(QLatin1String("setRequestHeader"), engine->newFunction(qmlxmlhttprequest_setRequestHeader, 2));
+ prototype.setProperty(QLatin1String("send"), engine->newFunction(qmlxmlhttprequest_send));
+ prototype.setProperty(QLatin1String("abort"), engine->newFunction(qmlxmlhttprequest_abort));
+ prototype.setProperty(QLatin1String("getResponseHeader"), engine->newFunction(qmlxmlhttprequest_getResponseHeader, 1));
+ prototype.setProperty(QLatin1String("getAllResponseHeaders"), engine->newFunction(qmlxmlhttprequest_getAllResponseHeaders));
+
+ // Read-only properties
+ prototype.setProperty(QLatin1String("readyState"), engine->newFunction(qmlxmlhttprequest_readyState), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+ prototype.setProperty(QLatin1String("status"), engine->newFunction(qmlxmlhttprequest_status), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+ prototype.setProperty(QLatin1String("statusText"), engine->newFunction(qmlxmlhttprequest_statusText), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+ prototype.setProperty(QLatin1String("responseText"), engine->newFunction(qmlxmlhttprequest_responseText), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+ prototype.setProperty(QLatin1String("responseXML"), engine->newFunction(qmlxmlhttprequest_responseXML), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
+ prototype.setProperty(QLatin1String("onreadystatechange"), engine->newFunction(qmlxmlhttprequest_onreadystatechange), QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
+
+ // Constructor
+ QScriptValue constructor = engine->newFunction(qmlxmlhttprequest_new, prototype);
+ constructor.setProperty(QLatin1String("UNSENT"), 0, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ constructor.setProperty(QLatin1String("OPENED"), 1, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ constructor.setProperty(QLatin1String("HEADERS_RECEIVED"), 2, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ constructor.setProperty(QLatin1String("LOADING"), 3, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ constructor.setProperty(QLatin1String("DONE"), 4, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ engine->globalObject().setProperty(QLatin1String("XMLHttpRequest"), constructor);
+}
+
+#include "qmlxmlhttprequest.moc"
diff --git a/src/declarative/qml/qmlxmlhttprequest_p.h b/src/declarative/qml/qmlxmlhttprequest_p.h
new file mode 100644
index 0000000..2142bc6
--- /dev/null
+++ b/src/declarative/qml/qmlxmlhttprequest_p.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** 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 QMLXMLHTTPREQUEST_P_H
+#define QMLXMLHTTPREQUEST_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.
+//
+
+class QScriptEngine;
+void qt_add_qmlxmlhttprequest(QScriptEngine *engine);
+
+#endif // QMLXMLHTTPREQUEST_P_H
+
diff --git a/src/declarative/qml/qpodvector_p.h b/src/declarative/qml/qpodvector_p.h
new file mode 100644
index 0000000..77f7425
--- /dev/null
+++ b/src/declarative/qml/qpodvector_p.h
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** 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 QPODVECTOR_P_H
+#define QPODVECTOR_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/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+template<class T>
+class QPODVector
+{
+public:
+ QPODVector()
+ : m_count(0), m_capacity(0), m_data(0) {}
+ ~QPODVector() { if (m_data) ::free(m_data); }
+
+ const T &at(int idx) const {
+ return m_data[idx];
+ }
+
+ T &operator[](int idx) {
+ return m_data[idx];
+ }
+
+ void clear() {
+ m_count = 0;
+ }
+
+ void prepend(const T &v) {
+ insert(0, v);
+ }
+
+ void append(const T &v) {
+ insert(m_count, v);
+ }
+
+ void insert(int idx, const T &v) {
+ if (m_count == m_capacity) {
+ m_capacity += 1024;
+ m_data = (T *)realloc(m_data, m_capacity * sizeof(T));
+ }
+ int moveCount = m_count - idx;
+ if (moveCount)
+ ::memmove(m_data + idx + 1, m_data + idx, moveCount * sizeof(T));
+ m_count++;
+ m_data[idx] = v;
+ }
+
+ void insertBlank(int idx, int count) {
+ int newSize = m_count + count;
+ if (newSize >= m_capacity) {
+ m_capacity = (newSize + 1023) & 0xFFFFFC00;
+ m_data = (T *)realloc(m_data, m_capacity * sizeof(T));
+ }
+
+ int moveCount = m_count - idx;
+ if (moveCount)
+ ::memmove(m_data + idx + count, m_data + idx,
+ moveCount * sizeof(T));
+ m_count = newSize;
+ }
+
+ void remove(int idx, int count = 1) {
+ int moveCount = m_count - (idx + count);
+ if (moveCount)
+ ::memmove(m_data + idx, m_data + idx + count,
+ moveCount * sizeof(T));
+ m_count -= count;
+ }
+
+ int count() const {
+ return m_count;
+ }
+
+ void copyAndClear(QPODVector<T> &other) {
+ if (other.m_data) ::free(other.m_data);
+ other.m_count = m_count;
+ other.m_capacity = m_capacity;
+ other.m_data = m_data;
+ m_count = 0;
+ m_capacity = 0;
+ m_data = 0;
+ }
+
+ QPODVector<T> &operator<<(const T &v) { append(v); return *this; }
+private:
+ QPODVector(const QPODVector &);
+ QPODVector &operator=(const QPODVector &);
+ int m_count;
+ int m_capacity;
+ T *m_data;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/declarative/qml/rewriter/rewriter.cpp b/src/declarative/qml/rewriter/rewriter.cpp
new file mode 100644
index 0000000..1248a1c
--- /dev/null
+++ b/src/declarative/qml/rewriter/rewriter.cpp
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** 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 "rewriter_p.h"
+#include "qmljsast_p.h"
+
+QT_QML_BEGIN_NAMESPACE
+
+using namespace QmlJS;
+
+void Rewriter::replace(const AST::SourceLocation &loc, const QString &text)
+{ replace(loc.offset, loc.length, text); }
+
+void Rewriter::remove(const AST::SourceLocation &loc)
+{ return replace(loc.offset, loc.length, QString()); }
+
+void Rewriter::remove(const AST::SourceLocation &firstLoc, const AST::SourceLocation &lastLoc)
+{ return replace(firstLoc.offset, lastLoc.offset + lastLoc.length - firstLoc.offset, QString()); }
+
+void Rewriter::insertTextBefore(const AST::SourceLocation &loc, const QString &text)
+{ replace(loc.offset, 0, text); }
+
+void Rewriter::insertTextAfter(const AST::SourceLocation &loc, const QString &text)
+{ replace(loc.offset + loc.length, 0, text); }
+
+void Rewriter::replace(int offset, int length, const QString &text)
+{ textWriter.replace(offset, length, text); }
+
+void Rewriter::insertText(int offset, const QString &text)
+{ replace(offset, 0, text); }
+
+void Rewriter::removeText(int offset, int length)
+{ replace(offset, length, QString()); }
+
+QString Rewriter::textAt(const AST::SourceLocation &loc) const
+{ return _code.mid(loc.offset, loc.length); }
+
+QString Rewriter::textAt(const AST::SourceLocation &firstLoc, const AST::SourceLocation &lastLoc) const
+{ return _code.mid(firstLoc.offset, lastLoc.offset + lastLoc.length - firstLoc.offset); }
+
+void Rewriter::accept(QmlJS::AST::Node *node)
+{ QmlJS::AST::Node::acceptChild(node, this); }
+
+void Rewriter::moveTextBefore(const AST::SourceLocation &firstLoc,
+ const AST::SourceLocation &lastLoc,
+ const AST::SourceLocation &loc)
+{
+ move(firstLoc.offset, lastLoc.offset + lastLoc.length - firstLoc.offset, loc.offset);
+}
+
+void Rewriter::moveTextAfter(const AST::SourceLocation &firstLoc,
+ const AST::SourceLocation &lastLoc,
+ const AST::SourceLocation &loc)
+{
+ move(firstLoc.offset, lastLoc.offset + lastLoc.length - firstLoc.offset, loc.offset + loc.length);
+}
+
+void Rewriter::move(int pos, int length, int to)
+{
+ textWriter.move(pos, length, to);
+}
+
+QT_QML_END_NAMESPACE
diff --git a/src/declarative/qml/rewriter/rewriter.pri b/src/declarative/qml/rewriter/rewriter.pri
new file mode 100644
index 0000000..550741b
--- /dev/null
+++ b/src/declarative/qml/rewriter/rewriter.pri
@@ -0,0 +1,11 @@
+
+INCLUDEPATH += $$PWD
+DEPENDPATH += $$PWD
+
+HEADERS += $$PWD/textwriter_p.h
+SOURCES += $$PWD/textwriter.cpp
+
+!no_ast_rewriter {
+ HEADERS += $$PWD/rewriter_p.h
+ SOURCES += $$PWD/rewriter.cpp
+}
diff --git a/src/declarative/qml/rewriter/rewriter_p.h b/src/declarative/qml/rewriter/rewriter_p.h
new file mode 100644
index 0000000..ae59226
--- /dev/null
+++ b/src/declarative/qml/rewriter/rewriter_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 REWRITER_H
+#define REWRITER_H
+
+#include <QtCore/QList>
+#include <QtCore/QString>
+
+#include "textwriter_p.h"
+#include "qmljsastvisitor_p.h"
+
+QT_BEGIN_HEADER
+QT_QML_BEGIN_NAMESPACE
+
+namespace QmlJS {
+
+////////////////////////////////////////////////////////////////////////////////
+// Replacement
+////////////////////////////////////////////////////////////////////////////////
+class Replacement
+{
+ int _offset;
+ int _length;
+ QString _text;
+
+public:
+ Replacement(int offset = 0, int length = 0, const QString &text = QString())
+ : _offset(offset), _length(length), _text(text)
+ { }
+
+ bool isNull() const { return _offset == _length; }
+ operator bool() const { return ! isNull(); }
+
+ int offset() const { return _offset; }
+ int length() const { return _length; }
+ QString text() const { return _text; }
+};
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Rewriter
+////////////////////////////////////////////////////////////////////////////////
+class Rewriter: public AST::Visitor
+{
+protected:
+ TextWriter textWriter;
+public:
+ //
+ // Token based API
+ //
+
+ /// Returns the text of the token at the given \a location.
+ QString textAt(const AST::SourceLocation &location) const;
+
+ QString textAt(const AST::SourceLocation &firstLoc,
+ const AST::SourceLocation &lastLoc) const;
+
+ /// Replace the token at \a loc with the given \a text.
+ void replace(const AST::SourceLocation &loc, const QString &text);
+
+ /// Remove the token at the given \a location.
+ void remove(const AST::SourceLocation &location);
+
+ /// Remove all tokens in the range [\a firstLoc, \a lastLoc].
+ void remove(const AST::SourceLocation &firstLoc, const AST::SourceLocation &lastLoc);
+
+ /// Insert \a text before the token at the given \a location.
+ void insertTextBefore(const AST::SourceLocation &location, const QString &text);
+
+ /// Insert \a text after the token at the given \a location.
+ void insertTextAfter(const AST::SourceLocation &loc, const QString &text);
+
+ void moveTextBefore(const AST::SourceLocation &firstLoc,
+ const AST::SourceLocation &lastLoc,
+ const AST::SourceLocation &loc);
+
+ void moveTextAfter(const AST::SourceLocation &firstLoc,
+ const AST::SourceLocation &lastLoc,
+ const AST::SourceLocation &loc);
+
+ //
+ // low-level offset based API
+ //
+ virtual void replace(int offset, int length, const QString &text);
+ virtual void move(int pos, int length, int to);
+ void insertText(int offset, const QString &text);
+ void removeText(int offset, int length);
+
+ /// Visit the given \a node.
+ void accept(AST::Node *node);
+
+ /// Returns the original unchanged source code.
+ QString code() const { return _code; }
+
+ /// Returns the list of replacements.
+ QList<Replacement> replacementList() const { return _replacementList; }
+
+protected:
+ /// \internal
+ void setCode(const QString &code) { _code = code; }
+
+private:
+ QString _code;
+ QList<Replacement> _replacementList;
+};
+
+} // end of namespace QmlJS
+
+QT_QML_END_NAMESPACE
+QT_END_HEADER
+
+#endif // REWRITER_H
diff --git a/src/declarative/qml/rewriter/textwriter.cpp b/src/declarative/qml/rewriter/textwriter.cpp
new file mode 100644
index 0000000..1ec0675
--- /dev/null
+++ b/src/declarative/qml/rewriter/textwriter.cpp
@@ -0,0 +1,217 @@
+/****************************************************************************
+**
+** 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 "textwriter_p.h"
+
+QT_QML_BEGIN_NAMESPACE
+
+using namespace QmlJS;
+
+TextWriter::TextWriter()
+ :string(0), cursor(0)
+{
+}
+
+static bool overlaps(int posA, int lengthA, int posB, int lengthB) {
+ return (posA < posB + lengthB && posA + lengthA > posB + lengthB)
+ || (posA < posB && posA + lengthA > posB);
+}
+
+bool TextWriter::hasOverlap(int pos, int length)
+{
+ {
+ QListIterator<Replace> i(replaceList);
+ while (i.hasNext()) {
+ const Replace &cmd = i.next();
+ if (overlaps(pos, length, cmd.pos, cmd.length))
+ return true;
+ }
+ }
+ {
+ QListIterator<Move> i(moveList);
+ while (i.hasNext()) {
+ const Move &cmd = i.next();
+ if (overlaps(pos, length, cmd.pos, cmd.length))
+ return true;
+ }
+ return false;
+ }
+}
+
+bool TextWriter::hasMoveInto(int pos, int length)
+{
+ QListIterator<Move> i(moveList);
+ while (i.hasNext()) {
+ const Move &cmd = i.next();
+ if (cmd.to >= pos && cmd.to < pos + length)
+ return true;
+ }
+ return false;
+}
+
+void TextWriter::replace(int pos, int length, const QString &replacement)
+{
+ Q_ASSERT(!hasOverlap(pos, length));
+ Q_ASSERT(!hasMoveInto(pos, length));
+
+ Replace cmd;
+ cmd.pos = pos;
+ cmd.length = length;
+ cmd.replacement = replacement;
+ replaceList += cmd;
+}
+
+void TextWriter::move(int pos, int length, int to)
+{
+ Q_ASSERT(!hasOverlap(pos, length));
+
+ Move cmd;
+ cmd.pos = pos;
+ cmd.length = length;
+ cmd.to = to;
+ moveList += cmd;
+}
+
+void TextWriter::doReplace(const Replace &replace)
+{
+ int diff = replace.replacement.size() - replace.length;
+ {
+ QMutableListIterator<Replace> i(replaceList);
+ while (i.hasNext()) {
+ Replace &c = i.next();
+ if (replace.pos < c.pos)
+ c.pos += diff;
+ else if (replace.pos + replace.length < c.pos + c.length)
+ c.length += diff;
+ }
+ }
+ {
+ QMutableListIterator<Move> i(moveList);
+ while (i.hasNext()) {
+ Move &c = i.next();
+ if (replace.pos < c.pos)
+ c.pos += diff;
+ else if (replace.pos + replace.length < c.pos + c.length)
+ c.length += diff;
+
+ if (replace.pos < c.to)
+ c.to += diff;
+ }
+ }
+
+ if (string) {
+ string->replace(replace.pos, replace.length, replace.replacement);
+ } else if (cursor) {
+ cursor->setPosition(replace.pos);
+ cursor->setPosition(replace.pos + replace.length, QTextCursor::KeepAnchor);
+ cursor->insertText(replace.replacement);
+ }
+}
+
+void TextWriter::doMove(const Move &move)
+{
+ QString text;
+ if (string) {
+ text = string->mid(move.pos, move.length);
+ } else if (cursor) {
+ cursor->setPosition(move.pos);
+ cursor->setPosition(move.pos + move.length, QTextCursor::KeepAnchor);
+ text = cursor->selectedText();
+ }
+
+ Replace cut;
+ cut.pos = move.pos;
+ cut.length = move.length;
+ Replace paste;
+ paste.pos = move.to;
+ paste.length = 0;
+ paste.replacement = text;
+
+ replaceList.append(cut);
+ replaceList.append(paste);
+
+ Replace cmd;
+ while (!replaceList.isEmpty()) {
+ cmd = replaceList.first();
+ replaceList.removeFirst();
+ doReplace(cmd);
+ }
+}
+
+void TextWriter::write(QString *s)
+{
+ string = s;
+ write_helper();
+ string = 0;
+}
+
+void TextWriter::write(QTextCursor *textCursor)
+{
+ cursor = textCursor;
+ write_helper();
+ cursor = 0;
+}
+
+void TextWriter::write_helper()
+{
+ if (cursor)
+ cursor->beginEditBlock();
+ {
+ Replace cmd;
+ while (!replaceList.isEmpty()) {
+ cmd = replaceList.first();
+ replaceList.removeFirst();
+ doReplace(cmd);
+ }
+ }
+ {
+ Move cmd;
+ while (!moveList.isEmpty()) {
+ cmd = moveList.first();
+ moveList.removeFirst();
+ doMove(cmd);
+ }
+ }
+ if (cursor)
+ cursor->endEditBlock();
+}
+
+QT_QML_END_NAMESPACE
diff --git a/src/declarative/qml/rewriter/textwriter_p.h b/src/declarative/qml/rewriter/textwriter_p.h
new file mode 100644
index 0000000..5894e6c
--- /dev/null
+++ b/src/declarative/qml/rewriter/textwriter_p.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** 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 TEXTWRITER_H
+#define TEXTWRITER_H
+
+#include <QtCore/QString>
+#include <QtCore/QList>
+#include <QtGui/QTextCursor>
+
+#include "qmljsglobal_p.h"
+
+QT_BEGIN_HEADER
+QT_QML_BEGIN_NAMESPACE
+
+namespace QmlJS {
+
+class TextWriter
+{
+ QString *string;
+ QTextCursor *cursor;
+
+ struct Replace {
+ int pos;
+ int length;
+ QString replacement;
+ };
+
+ QList<Replace> replaceList;
+
+ struct Move {
+ int pos;
+ int length;
+ int to;
+ };
+
+ QList<Move> moveList;
+
+ bool hasOverlap(int pos, int length);
+ bool hasMoveInto(int pos, int length);
+
+ void doReplace(const Replace &replace);
+ void doMove(const Move &move);
+
+ void write_helper();
+
+public:
+ TextWriter();
+
+ void replace(int pos, int length, const QString &replacement);
+ void move(int pos, int length, int to);
+
+ void write(QString *s);
+ void write(QTextCursor *textCursor);
+
+};
+
+} // end of namespace QmlJS
+
+QT_QML_END_NAMESPACE
+QT_END_HEADER
+
+#endif // TEXTWRITER_H