diff options
author | Qt Continuous Integration System <qt-info@nokia.com> | 2010-08-31 05:54:11 (GMT) |
---|---|---|
committer | Qt Continuous Integration System <qt-info@nokia.com> | 2010-08-31 05:54:11 (GMT) |
commit | cf28f6cacf59d434072656af05466541ba69e8ae (patch) | |
tree | ee8cd94426004623da1abaea6861a5a214214688 | |
parent | b705fec8d093d06adbbd1baf461948b95a031759 (diff) | |
parent | 6a40104d587211dc740232fed908e29f0b58e2d9 (diff) | |
download | Qt-cf28f6cacf59d434072656af05466541ba69e8ae.zip Qt-cf28f6cacf59d434072656af05466541ba69e8ae.tar.gz Qt-cf28f6cacf59d434072656af05466541ba69e8ae.tar.bz2 |
Merge branch '4.7' of scm.dev.nokia.troll.no:qt/qt-qml into 4.7-integration
* '4.7' of scm.dev.nokia.troll.no:qt/qt-qml:
Don't double call classBegin()
Notify QML internal notifiers of item geometry changes before QML signal handlers.
Revert "Add 'cached' property to Image."
Add 'cached' property to Image.
Ensure Flickable visibleArea is updated when view height changes
Improve calling QML functions from C++ docs.
Add missing license headers
Remove debug.
Snake: Don't use Behavior with states.
QML Viewer should be put under QtDemos instead of QtExamples folder in Symbian app menu
Fix application exiting in embedded qml examples
QDeclarativeDebug: Destroy incoming connections if already connected
Simplify type management code
QML JavaScript .import parser
Fix VisualDataModel model update handling when rootIndex is specified.
Improve test reliability when running in parallel with other tests.
Improve stability of test on loaded hw.
Improve stability of test on loaded hw.
61 files changed, 2135 insertions, 1224 deletions
diff --git a/demos/declarative/snake/content/Cookie.qml b/demos/declarative/snake/content/Cookie.qml index e67a7af..eb57fd2 100644 --- a/demos/declarative/snake/content/Cookie.qml +++ b/demos/declarative/snake/content/Cookie.qml @@ -59,7 +59,6 @@ Item { anchors.fill: parent source: "pics/cookie.png" opacity: 0 - Behavior on opacity { NumberAnimation { duration: 100 } } Text { font.bold: true anchors.verticalCenter: parent.verticalCenter @@ -87,4 +86,9 @@ Item { PropertyChanges { target: img; opacity: 0 } } ] + transitions: [ + Transition { + NumberAnimation { target: img; property: "opacity"; duration: 100 } + } + ] } diff --git a/demos/declarative/snake/content/Link.qml b/demos/declarative/snake/content/Link.qml index 9aa6006..942008d 100644 --- a/demos/declarative/snake/content/Link.qml +++ b/demos/declarative/snake/content/Link.qml @@ -86,7 +86,6 @@ Item { id:link } opacity: 0 - Behavior on opacity { NumberAnimation { duration: 200 } } } @@ -114,4 +113,11 @@ Item { id:link PropertyChanges { target: img; opacity: 0 } } ] + + transitions: [ + Transition { + NumberAnimation { target: img; property: "opacity"; duration: 200 } + } + ] + } diff --git a/demos/declarative/snake/content/snake.js b/demos/declarative/snake/content/snake.js index fab7834..c2e9d3a 100644 --- a/demos/declarative/snake/content/snake.js +++ b/demos/declarative/snake/content/snake.js @@ -35,7 +35,7 @@ function startNewGame() if (heartbeat.running) { endGame(); startNewGameTimer.running = true; - state = "starting"; + state = ""; return; } diff --git a/demos/declarative/snake/snake.qml b/demos/declarative/snake/snake.qml index 12ad71c..4d989df 100644 --- a/demos/declarative/snake/snake.qml +++ b/demos/declarative/snake/snake.qml @@ -106,7 +106,6 @@ Rectangle { anchors.fill: parent anchors.horizontalCenter: parent.horizontalCenter anchors.verticalCenter: parent.verticalCenter - Behavior on opacity { NumberAnimation { duration: 500 } } Text { color: "white" @@ -236,7 +235,10 @@ Rectangle { from: "*" to: "starting" NumberAnimation { target: progressIndicator; property: "width"; duration: 1000 } - + NumberAnimation { target: title; property: "opacity"; duration: 500 } + }, + Transition { + NumberAnimation { target: title; property: "opacity"; duration: 500 } } ] diff --git a/demos/embedded/qmlcalculator/qmlcalculator.cpp b/demos/embedded/qmlcalculator/qmlcalculator.cpp index 3030e81..6c41e61 100644 --- a/demos/embedded/qmlcalculator/qmlcalculator.cpp +++ b/demos/embedded/qmlcalculator/qmlcalculator.cpp @@ -42,6 +42,7 @@ #include <QtCore/QFileInfo> #include <QtGui/QApplication> #include <QtDeclarative/QDeclarativeView> +#include <QtDeclarative/QDeclarativeEngine> #if defined(Q_OS_SYMBIAN) #include <eikenv.h> @@ -58,7 +59,8 @@ int main(int argc, char *argv[]) QDeclarativeView view; view.setSource(QUrl(mainQmlApp)); view.setResizeMode(QDeclarativeView::SizeRootObjectToView); - + QObject::connect(view.engine(), SIGNAL(quit()), &application, SLOT(quit())); + #if defined(QT_KEYPAD_NAVIGATION) QApplication::setNavigationMode(Qt::NavigationModeCursorAuto); #endif // QT_KEYPAD_NAVIGATION diff --git a/demos/embedded/qmlclocks/qmlclocks.cpp b/demos/embedded/qmlclocks/qmlclocks.cpp index d94cbdd..a09801b 100644 --- a/demos/embedded/qmlclocks/qmlclocks.cpp +++ b/demos/embedded/qmlclocks/qmlclocks.cpp @@ -42,6 +42,7 @@ #include <QtCore/QFileInfo> #include <QtGui/QApplication> #include <QtDeclarative/QDeclarativeView> +#include <QtDeclarative/QDeclarativeEngine> #if defined(Q_OS_SYMBIAN) #include <eikenv.h> @@ -58,6 +59,7 @@ int main(int argc, char *argv[]) QDeclarativeView view; view.setSource(QUrl(mainQmlApp)); view.setResizeMode(QDeclarativeView::SizeRootObjectToView); + QObject::connect(view.engine(), SIGNAL(quit()), &application, SLOT(quit())); #if defined(QT_KEYPAD_NAVIGATION) QApplication::setNavigationMode(Qt::NavigationModeCursorAuto); diff --git a/demos/embedded/qmldialcontrol/qmldialcontrol.cpp b/demos/embedded/qmldialcontrol/qmldialcontrol.cpp index 311cee0..56b21d7 100644 --- a/demos/embedded/qmldialcontrol/qmldialcontrol.cpp +++ b/demos/embedded/qmldialcontrol/qmldialcontrol.cpp @@ -42,6 +42,7 @@ #include <QtCore/QFileInfo> #include <QtGui/QApplication> #include <QtDeclarative/QDeclarativeView> +#include <QtDeclarative/QDeclarativeEngine> int main(int argc, char *argv[]) { @@ -51,6 +52,7 @@ int main(int argc, char *argv[]) QDeclarativeView view; view.setSource(QUrl(mainQmlApp)); view.setResizeMode(QDeclarativeView::SizeRootObjectToView); + QObject::connect(view.engine(), SIGNAL(quit()), &application, SLOT(quit())); #if defined(QT_KEYPAD_NAVIGATION) QApplication::setNavigationMode(Qt::NavigationModeCursorAuto); diff --git a/demos/embedded/qmleasing/deployment.pri b/demos/embedded/qmleasing/deployment.pri index 984f5c8..d3621cb 100644 --- a/demos/embedded/qmleasing/deployment.pri +++ b/demos/embedded/qmleasing/deployment.pri @@ -4,5 +4,5 @@ symbian { qmleasing_uid3 = A000E3FE qmleasing_files.path = $$APP_PRIVATE_DIR_BASE/$$qmleasing_uid3 } -qmleasing_files.sources = $$qmleasing_src/easing.qml +qmleasing_files.sources = $$qmleasing_src/easing.qml $$qmleasing_src/content DEPLOYMENT += qmleasing_files diff --git a/demos/embedded/qmleasing/qmleasing.cpp b/demos/embedded/qmleasing/qmleasing.cpp index d326468..713fe67 100644 --- a/demos/embedded/qmleasing/qmleasing.cpp +++ b/demos/embedded/qmleasing/qmleasing.cpp @@ -42,6 +42,7 @@ #include <QtCore/QFileInfo> #include <QtGui/QApplication> #include <QtDeclarative/QDeclarativeView> +#include <QtDeclarative/QDeclarativeEngine> int main(int argc, char *argv[]) { @@ -51,6 +52,7 @@ int main(int argc, char *argv[]) QDeclarativeView view; view.setSource(QUrl(mainQmlApp)); view.setResizeMode(QDeclarativeView::SizeRootObjectToView); + QObject::connect(view.engine(), SIGNAL(quit()), &application, SLOT(quit())); #if defined(QT_KEYPAD_NAVIGATION) QApplication::setNavigationMode(Qt::NavigationModeCursorAuto); diff --git a/demos/embedded/qmlflickr/qmlflickr.cpp b/demos/embedded/qmlflickr/qmlflickr.cpp index 7068f88..c05806c 100644 --- a/demos/embedded/qmlflickr/qmlflickr.cpp +++ b/demos/embedded/qmlflickr/qmlflickr.cpp @@ -48,6 +48,7 @@ #include <QtNetwork/QNetworkConfiguration> #include <QtNetwork/QNetworkConfigurationManager> #include <QtNetwork/QNetworkAccessManager> +#include <QtDeclarative/QDeclarativeEngine> // Factory to create QNetworkAccessManagers that use the saved network configuration; otherwise // the system default. @@ -95,7 +96,8 @@ int main(int argc, char *argv[]) view.engine()->setNetworkAccessManagerFactory(&networkAccessManagerFactory); view.setSource(QUrl(mainQmlApp)); view.setResizeMode(QDeclarativeView::SizeRootObjectToView); - + QObject::connect(view.engine(), SIGNAL(quit()), &application, SLOT(quit())); + #if defined(Q_OS_SYMBIAN) view.showFullScreen(); #else // Q_OS_SYMBIAN diff --git a/demos/embedded/qmlphotoviewer/qmlphotoviewer.cpp b/demos/embedded/qmlphotoviewer/qmlphotoviewer.cpp index 2b9db5e..d9cf67c 100644 --- a/demos/embedded/qmlphotoviewer/qmlphotoviewer.cpp +++ b/demos/embedded/qmlphotoviewer/qmlphotoviewer.cpp @@ -96,6 +96,8 @@ int main(int argc, char *argv[]) view.setSource(QUrl(mainQmlApp)); view.setResizeMode(QDeclarativeView::SizeRootObjectToView); + QObject::connect(view.engine(), SIGNAL(quit()), &application, SLOT(quit())); + #if defined(Q_OS_SYMBIAN) view.showFullScreen(); #else // Q_OS_SYMBIAN diff --git a/demos/embedded/qmltwitter/qmltwitter.cpp b/demos/embedded/qmltwitter/qmltwitter.cpp index c53098a4..30c4601 100644 --- a/demos/embedded/qmltwitter/qmltwitter.cpp +++ b/demos/embedded/qmltwitter/qmltwitter.cpp @@ -95,7 +95,8 @@ int main(int argc, char *argv[]) view.engine()->setNetworkAccessManagerFactory(&networkAccessManagerFactory); view.setSource(QUrl(mainQmlApp)); view.setResizeMode(QDeclarativeView::SizeRootObjectToView); - + QObject::connect(view.engine(), SIGNAL(quit()), &application, SLOT(quit())); + #if defined(Q_OS_SYMBIAN) view.showFullScreen(); #else // Q_OS_SYMBIAN diff --git a/doc/src/declarative/extending.qdoc b/doc/src/declarative/extending.qdoc index 5c4d5e7..6388764 100644 --- a/doc/src/declarative/extending.qdoc +++ b/doc/src/declarative/extending.qdoc @@ -965,6 +965,20 @@ Item { } \endcode +This may be connected to via QObject::connect() or called directly from C++ using +QMetaObject::invokeMethod(): + +\code + QDeclarativeEngine engine; + QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext()); + QDeclarativeComponent component(&engine, QUrl::fromLocalFile("main.qml")); + QObject *object = component.create(context); + QVariant str("Hello"); + QMetaObject::invokeMethod(object, "say", Q_ARG(QVariant, str)); +\endcode + +Return values of type QVariant are also supported via Q_RETURN_ARG. + \section1 Defining new Components \target components diff --git a/examples/declarative/animation/easing/content/QuitButton.qml b/examples/declarative/animation/easing/content/QuitButton.qml new file mode 100644 index 0000000..039694d --- /dev/null +++ b/examples/declarative/animation/easing/content/QuitButton.qml @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import Qt 4.7 +Image { + source: "quit.png" + scale: quitMouse.pressed ? 0.8 : 1.0 + smooth: quitMouse.pressed + MouseArea { + id: quitMouse + anchors.fill: parent + anchors.margins: -10 + onClicked: Qt.quit() + } +}
\ No newline at end of file diff --git a/examples/declarative/animation/easing/content/quit.png b/examples/declarative/animation/easing/content/quit.png Binary files differnew file mode 100644 index 0000000..b822057 --- /dev/null +++ b/examples/declarative/animation/easing/content/quit.png diff --git a/examples/declarative/animation/easing/easing.qml b/examples/declarative/animation/easing/easing.qml index 9cdbad1..b53cb98 100644 --- a/examples/declarative/animation/easing/easing.qml +++ b/examples/declarative/animation/easing/easing.qml @@ -39,6 +39,7 @@ ****************************************************************************/ import Qt 4.7 +import "content" Rectangle { id: window @@ -134,11 +135,23 @@ Rectangle { } Flickable { - anchors.fill: parent; contentHeight: layout.height - + anchors.fill: parent + contentHeight: layout.height + Rectangle { + id: titlePane + color: "#444444" + height: 35 + anchors { top: parent.top; left: parent.left; right: parent.right } + QuitButton { + id: quitButton + anchors.verticalCenter: parent.verticalCenter + anchors.right: parent.right + anchors.rightMargin: 10 + } + } Column { id: layout - anchors.left: parent.left; anchors.right: parent.right + anchors { top: titlePane.bottom; topMargin: 10; left: parent.left; right: parent.right } Repeater { model: easingTypes; delegate: delegate } } } diff --git a/examples/declarative/toys/clocks/clocks.qml b/examples/declarative/toys/clocks/clocks.qml index 124e391..82a1dbf 100644 --- a/examples/declarative/toys/clocks/clocks.qml +++ b/examples/declarative/toys/clocks/clocks.qml @@ -51,4 +51,9 @@ Rectangle { Clock { city: "Mumbai"; shift: 5.5 } Clock { city: "Tokyo"; shift: 9 } } + QuitButton { + anchors.right: parent.right + anchors.top: parent.top + anchors.margins: 10 + } } diff --git a/examples/declarative/toys/clocks/content/QuitButton.qml b/examples/declarative/toys/clocks/content/QuitButton.qml new file mode 100644 index 0000000..039694d --- /dev/null +++ b/examples/declarative/toys/clocks/content/QuitButton.qml @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import Qt 4.7 +Image { + source: "quit.png" + scale: quitMouse.pressed ? 0.8 : 1.0 + smooth: quitMouse.pressed + MouseArea { + id: quitMouse + anchors.fill: parent + anchors.margins: -10 + onClicked: Qt.quit() + } +}
\ No newline at end of file diff --git a/examples/declarative/toys/clocks/content/quit.png b/examples/declarative/toys/clocks/content/quit.png Binary files differnew file mode 100644 index 0000000..b822057 --- /dev/null +++ b/examples/declarative/toys/clocks/content/quit.png diff --git a/examples/declarative/ui-components/dialcontrol/content/QuitButton.qml b/examples/declarative/ui-components/dialcontrol/content/QuitButton.qml new file mode 100644 index 0000000..039694d --- /dev/null +++ b/examples/declarative/ui-components/dialcontrol/content/QuitButton.qml @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import Qt 4.7 +Image { + source: "quit.png" + scale: quitMouse.pressed ? 0.8 : 1.0 + smooth: quitMouse.pressed + MouseArea { + id: quitMouse + anchors.fill: parent + anchors.margins: -10 + onClicked: Qt.quit() + } +}
\ No newline at end of file diff --git a/examples/declarative/ui-components/dialcontrol/content/quit.png b/examples/declarative/ui-components/dialcontrol/content/quit.png Binary files differnew file mode 100644 index 0000000..b822057 --- /dev/null +++ b/examples/declarative/ui-components/dialcontrol/content/quit.png diff --git a/examples/declarative/ui-components/dialcontrol/dialcontrol.qml b/examples/declarative/ui-components/dialcontrol/dialcontrol.qml index 46cc3e6..a7da5c6 100644 --- a/examples/declarative/ui-components/dialcontrol/dialcontrol.qml +++ b/examples/declarative/ui-components/dialcontrol/dialcontrol.qml @@ -88,5 +88,10 @@ Rectangle { } } } + QuitButton { + anchors.right: parent.right + anchors.top: parent.top + anchors.margins: 10 + } } //! [0] diff --git a/src/declarative/debugger/qdeclarativedebugservice.cpp b/src/declarative/debugger/qdeclarativedebugservice.cpp index dca2695..1bbfcf4 100644 --- a/src/declarative/debugger/qdeclarativedebugservice.cpp +++ b/src/declarative/debugger/qdeclarativedebugservice.cpp @@ -128,6 +128,8 @@ void QDeclarativeDebugServer::newConnection() if (d->connection) { qWarning("QDeclarativeDebugServer error: another client is already connected"); + QTcpSocket *faultyConnection = d->tcpServer->nextPendingConnection(); + delete faultyConnection; return; } diff --git a/src/declarative/graphicsitems/qdeclarativeflickable.cpp b/src/declarative/graphicsitems/qdeclarativeflickable.cpp index a710190..63a2a77 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable.cpp +++ b/src/declarative/graphicsitems/qdeclarativeflickable.cpp @@ -1001,12 +1001,16 @@ void QDeclarativeFlickable::geometryChanged(const QRectF &newGeometry, bool changed = false; if (newGeometry.width() != oldGeometry.width()) { + if (xflick()) + changed = true; if (d->hData.viewSize < 0) { d->contentItem->setWidth(width()); emit contentWidthChanged(); } } if (newGeometry.height() != oldGeometry.height()) { + if (yflick()) + changed = true; if (d->vData.viewSize < 0) { d->contentItem->setHeight(height()); emit contentHeightChanged(); diff --git a/src/declarative/graphicsitems/qdeclarativeitem.cpp b/src/declarative/graphicsitems/qdeclarativeitem.cpp index 1054898..aca2bb7 100644 --- a/src/declarative/graphicsitems/qdeclarativeitem.cpp +++ b/src/declarative/graphicsitems/qdeclarativeitem.cpp @@ -1883,6 +1883,12 @@ void QDeclarativeItem::geometryChanged(const QRectF &newGeometry, } } + for(int ii = 0; ii < d->changeListeners.count(); ++ii) { + const QDeclarativeItemPrivate::ChangeListener &change = d->changeListeners.at(ii); + if (change.types & QDeclarativeItemPrivate::Geometry) + change.listener->itemGeometryChanged(this, newGeometry, oldGeometry); + } + if (newGeometry.x() != oldGeometry.x()) emit xChanged(); if (newGeometry.width() != oldGeometry.width()) @@ -1891,12 +1897,6 @@ void QDeclarativeItem::geometryChanged(const QRectF &newGeometry, emit yChanged(); if (newGeometry.height() != oldGeometry.height()) emit heightChanged(); - - for(int ii = 0; ii < d->changeListeners.count(); ++ii) { - const QDeclarativeItemPrivate::ChangeListener &change = d->changeListeners.at(ii); - if (change.types & QDeclarativeItemPrivate::Geometry) - change.listener->itemGeometryChanged(this, newGeometry, oldGeometry); - } } void QDeclarativeItemPrivate::removeItemChangeListener(QDeclarativeItemChangeListener *listener, ChangeTypes types) diff --git a/src/declarative/graphicsitems/qdeclarativelistview.cpp b/src/declarative/graphicsitems/qdeclarativelistview.cpp index d3d46f7..ef28ab2 100644 --- a/src/declarative/graphicsitems/qdeclarativelistview.cpp +++ b/src/declarative/graphicsitems/qdeclarativelistview.cpp @@ -2454,6 +2454,16 @@ void QDeclarativeListView::keyPressEvent(QKeyEvent *event) QDeclarativeFlickable::keyPressEvent(event); } +void QDeclarativeListView::geometryChanged(const QRectF &newGeometry, + const QRectF &oldGeometry) +{ + Q_D(QDeclarativeListView); + d->maxExtentDirty = true; + d->minExtentDirty = true; + QDeclarativeFlickable::geometryChanged(newGeometry, oldGeometry); +} + + /*! \qmlmethod ListView::incrementCurrentIndex() diff --git a/src/declarative/graphicsitems/qdeclarativelistview_p.h b/src/declarative/graphicsitems/qdeclarativelistview_p.h index 8fbff49..735b248 100644 --- a/src/declarative/graphicsitems/qdeclarativelistview_p.h +++ b/src/declarative/graphicsitems/qdeclarativelistview_p.h @@ -246,6 +246,7 @@ protected: virtual qreal minXExtent() const; virtual qreal maxXExtent() const; virtual void keyPressEvent(QKeyEvent *); + virtual void geometryChanged(const QRectF &newGeometry,const QRectF &oldGeometry); virtual void componentComplete(); private Q_SLOTS: diff --git a/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp b/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp index b4e8bda..a46ee73 100644 --- a/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp +++ b/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp @@ -1305,24 +1305,27 @@ void QDeclarativeVisualDataModel::_q_itemsMoved(int from, int to, int count) void QDeclarativeVisualDataModel::_q_rowsInserted(const QModelIndex &parent, int begin, int end) { - if (!parent.isValid()) + Q_D(QDeclarativeVisualDataModel); + if (parent == d->m_root) _q_itemsInserted(begin, end - begin + 1); } void QDeclarativeVisualDataModel::_q_rowsRemoved(const QModelIndex &parent, int begin, int end) { - if (!parent.isValid()) + Q_D(QDeclarativeVisualDataModel); + if (parent == d->m_root) _q_itemsRemoved(begin, end - begin + 1); } void QDeclarativeVisualDataModel::_q_rowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow) { + Q_D(QDeclarativeVisualDataModel); const int count = sourceEnd - sourceStart + 1; - if (!destinationParent.isValid() && !sourceParent.isValid()) { + if (destinationParent == d->m_root && sourceParent == d->m_root) { _q_itemsMoved(sourceStart, destinationRow, count); - } else if (!sourceParent.isValid()) { + } else if (sourceParent == d->m_root) { _q_itemsRemoved(sourceStart, count); - } else if (!destinationParent.isValid()) { + } else if (destinationParent == d->m_root) { _q_itemsInserted(destinationRow, count); } } @@ -1330,7 +1333,7 @@ void QDeclarativeVisualDataModel::_q_rowsMoved(const QModelIndex &sourceParent, void QDeclarativeVisualDataModel::_q_dataChanged(const QModelIndex &begin, const QModelIndex &end) { Q_D(QDeclarativeVisualDataModel); - if (!begin.parent().isValid()) + if (begin.parent() == d->m_root) _q_itemsChanged(begin.row(), end.row() - begin.row() + 1, d->m_roles); } diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp index f044e1a..5bfe5b2 100644 --- a/src/declarative/qml/qdeclarativecompiler.cpp +++ b/src/declarative/qml/qdeclarativecompiler.cpp @@ -41,7 +41,6 @@ #include "private/qdeclarativecompiler_p.h" -#include "private/qdeclarativecompositetypedata_p.h" #include "private/qdeclarativeparser_p.h" #include "private/qdeclarativescriptparser_p.h" #include "qdeclarativepropertyvaluesource.h" @@ -562,7 +561,7 @@ void QDeclarativeCompiler::reset(QDeclarativeCompiledData *data) on a successful compiler. */ bool QDeclarativeCompiler::compile(QDeclarativeEngine *engine, - QDeclarativeCompositeTypeData *unit, + QDeclarativeTypeData *unit, QDeclarativeCompiledData *out) { exceptions.clear(); @@ -573,10 +572,15 @@ bool QDeclarativeCompiler::compile(QDeclarativeEngine *engine, output = out; // Compile types - for (int ii = 0; ii < unit->types.count(); ++ii) { - QDeclarativeCompositeTypeData::TypeReference &tref = unit->types[ii]; + const QList<QDeclarativeTypeData::TypeReference> &resolvedTypes = unit->resolvedTypes(); + QList<QDeclarativeScriptParser::TypeReference *> referencedTypes = unit->parser().referencedTypes(); + + for (int ii = 0; ii < resolvedTypes.count(); ++ii) { QDeclarativeCompiledData::TypeReference ref; - QDeclarativeScriptParser::TypeReference *parserRef = unit->data.referencedTypes().at(ii); + + const QDeclarativeTypeData::TypeReference &tref = resolvedTypes.at(ii); + QDeclarativeScriptParser::TypeReference *parserRef = referencedTypes.at(ii); + if (tref.type) { ref.type = tref.type; if (!ref.type->isCreatable()) { @@ -585,33 +589,16 @@ bool QDeclarativeCompiler::compile(QDeclarativeEngine *engine, err = tr( "Element is not creatable."); COMPILE_EXCEPTION(parserRef->refObjects.first(), err); } - } else if (tref.unit) { - ref.component = tref.unit->toComponent(engine); - - if (ref.component->isError()) { - QDeclarativeError error; - error.setUrl(output->url); - error.setDescription(QLatin1String("Unable to create type ") + - parserRef->name); - if (!parserRef->refObjects.isEmpty()) { - QDeclarativeParser::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; + } else if (tref.typeData) { + ref.component = tref.typeData->component(); + ref.ref = tref.typeData; ref.ref->addref(); } ref.className = parserRef->name.toUtf8(); out->types << ref; } - Object *root = unit->data.tree(); + Object *root = unit->parser().tree(); Q_ASSERT(root); this->engine = engine; @@ -664,17 +651,17 @@ void QDeclarativeCompiler::compileTree(Object *tree) QHash<QString, Object::ScriptBlock> importedScripts; QStringList importedScriptIndexes; - for (int ii = 0; ii < unit->scripts.count(); ++ii) { - QString scriptCode = QString::fromUtf8(unit->scripts.at(ii).resource->data); - Object::ScriptBlock::Pragmas pragmas = QDeclarativeScriptParser::extractPragmas(scriptCode); + foreach (const QDeclarativeTypeData::ScriptReference &script, unit->resolvedScripts()) { + QString scriptCode = script.script->scriptSource(); + Object::ScriptBlock::Pragmas pragmas = script.script->pragmas(); - Q_ASSERT(!importedScripts.contains(unit->scripts.at(ii).qualifier)); + Q_ASSERT(!importedScripts.contains(script.qualifier)); if (!scriptCode.isEmpty()) { - Object::ScriptBlock &scriptBlock = importedScripts[unit->scripts.at(ii).qualifier]; + Object::ScriptBlock &scriptBlock = importedScripts[script.qualifier]; scriptBlock.code = scriptCode; - scriptBlock.file = unit->scripts.at(ii).resource->url; + scriptBlock.file = script.script->finalUrl().toString(); scriptBlock.pragmas = pragmas; } } @@ -704,7 +691,7 @@ void QDeclarativeCompiler::compileTree(Object *tree) for (int ii = 0; ii < importedScriptIndexes.count(); ++ii) output->importCache->add(importedScriptIndexes.at(ii), ii); - unit->imports.populateCache(output->importCache, engine); + unit->imports().populateCache(output->importCache, engine); Q_ASSERT(tree->metatype); @@ -987,7 +974,7 @@ void QDeclarativeCompiler::genObject(QDeclarativeParser::Object *obj) } // Begin the class - if (obj->parserStatusCast != -1) { + if (tr.type && obj->parserStatusCast != -1) { QDeclarativeInstruction begin; begin.type = QDeclarativeInstruction::BeginObject; begin.begin.castValue = obj->parserStatusCast; @@ -1404,7 +1391,7 @@ bool QDeclarativeCompiler::buildProperty(QDeclarativeParser::Property *prop, QDeclarativeType *type = 0; QDeclarativeImportedNamespace *typeNamespace = 0; - unit->imports.resolveType(prop->name, &type, 0, 0, 0, &typeNamespace); + unit->imports().resolveType(prop->name, &type, 0, 0, 0, &typeNamespace); if (typeNamespace) { // ### We might need to indicate that this property is a namespace @@ -1512,7 +1499,7 @@ bool QDeclarativeCompiler::buildPropertyInNamespace(QDeclarativeImportedNamespac // Setup attached property data QDeclarativeType *type = 0; - unit->imports.resolveType(ns, prop->name, &type, 0, 0, 0); + unit->imports().resolveType(ns, prop->name, &type, 0, 0, 0); if (!type || !type->attachedPropertiesType()) COMPILE_EXCEPTION(prop, tr("Non-existent attached object")); @@ -2139,7 +2126,7 @@ bool QDeclarativeCompiler::testQualifiedEnumAssignment(const QMetaProperty &prop QString typeName = parts.at(0); QDeclarativeType *type = 0; - unit->imports.resolveType(typeName.toUtf8(), &type, 0, 0, 0, 0); + unit->imports().resolveType(typeName.toUtf8(), &type, 0, 0, 0, 0); if (!type || obj->typeName != type->qmlTypeName()) return true; @@ -2166,7 +2153,7 @@ int QDeclarativeCompiler::evaluateEnum(const QByteArray& script) const int dot = script.indexOf('.'); if (dot > 0) { QDeclarativeType *type = 0; - unit->imports.resolveType(script.left(dot), &type, 0, 0, 0, 0); + unit->imports().resolveType(script.left(dot), &type, 0, 0, 0, 0); if (!type) return -1; const QMetaObject *mo = type->metaObject(); @@ -2184,7 +2171,7 @@ int QDeclarativeCompiler::evaluateEnum(const QByteArray& script) const const QMetaObject *QDeclarativeCompiler::resolveType(const QByteArray& name) const { QDeclarativeType *qmltype = 0; - if (!unit->imports.resolveType(name, &qmltype, 0, 0, 0, 0)) + if (!unit->imports().resolveType(name, &qmltype, 0, 0, 0, 0)) return 0; if (!qmltype) return 0; @@ -2342,16 +2329,18 @@ bool QDeclarativeCompiler::buildDynamicMeta(QDeclarativeParser::Object *obj, Dyn QByteArray customTypeName; QDeclarativeType *qmltype = 0; QUrl url; - if (!unit->imports.resolveType(p.customType, &qmltype, &url, 0, 0, 0)) + if (!unit->imports().resolveType(p.customType, &qmltype, &url, 0, 0, 0)) COMPILE_EXCEPTION(&p, tr("Invalid property type")); if (!qmltype) { - QDeclarativeCompositeTypeData *tdata = enginePrivate->typeManager.get(url); + QDeclarativeTypeData *tdata = enginePrivate->typeLoader.get(url); Q_ASSERT(tdata); - Q_ASSERT(tdata->status == QDeclarativeCompositeTypeData::Complete); + Q_ASSERT(tdata->isComplete()); - QDeclarativeCompiledData *data = tdata->toCompiledComponent(engine); + QDeclarativeCompiledData *data = tdata->compiledData(); customTypeName = data->root->className(); + data->release(); + tdata->release(); } else { customTypeName = qmltype->typeName(); } @@ -2746,7 +2735,7 @@ bool QDeclarativeCompiler::completeComponentBuild() expr.context = binding.bindingContext.object; expr.property = binding.property; expr.expression = binding.expression; - expr.imports = unit->imports; + expr.imports = unit->imports(); int index = bindingCompiler.compile(expr, enginePrivate); if (index != -1) { diff --git a/src/declarative/qml/qdeclarativecompiler_p.h b/src/declarative/qml/qdeclarativecompiler_p.h index 49dc53f..89eef09 100644 --- a/src/declarative/qml/qdeclarativecompiler_p.h +++ b/src/declarative/qml/qdeclarativecompiler_p.h @@ -56,13 +56,13 @@ #include "qdeclarative.h" #include "qdeclarativeerror.h" #include "private/qdeclarativeinstruction_p.h" -#include "private/qdeclarativecompositetypemanager_p.h" #include "private/qdeclarativeparser_p.h" #include "private/qdeclarativeengine_p.h" #include "private/qbitfield_p.h" #include "private/qdeclarativepropertycache_p.h" #include "private/qdeclarativeintegercache_p.h" #include "private/qdeclarativetypenamecache_p.h" +#include "private/qdeclarativetypeloader_p.h" #include <QtCore/qbytearray.h> #include <QtCore/qset.h> @@ -152,7 +152,7 @@ class Q_AUTOTEST_EXPORT QDeclarativeCompiler public: QDeclarativeCompiler(); - bool compile(QDeclarativeEngine *, QDeclarativeCompositeTypeData *, QDeclarativeCompiledData *); + bool compile(QDeclarativeEngine *, QDeclarativeTypeData *, QDeclarativeCompiledData *); bool isError() const; QList<QDeclarativeError> errors() const; @@ -338,7 +338,7 @@ private: QDeclarativeEngine *engine; QDeclarativeEnginePrivate *enginePrivate; QDeclarativeParser::Object *unitRoot; - QDeclarativeCompositeTypeData *unit; + QDeclarativeTypeData *unit; }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativecomponent.cpp b/src/declarative/qml/qdeclarativecomponent.cpp index d2d1f19..75bb5db 100644 --- a/src/declarative/qml/qdeclarativecomponent.cpp +++ b/src/declarative/qml/qdeclarativecomponent.cpp @@ -44,7 +44,6 @@ #include "private/qdeclarativecompiler_p.h" #include "private/qdeclarativecontext_p.h" -#include "private/qdeclarativecompositetypedata_p.h" #include "private/qdeclarativeengine_p.h" #include "private/qdeclarativevme_p.h" #include "qdeclarative.h" @@ -197,7 +196,7 @@ class QByteArray; \value Error An error has occurred. Call errors() to retrieve a list of \{QDeclarativeError}{errors}. */ -void QDeclarativeComponentPrivate::typeDataReady() +void QDeclarativeComponentPrivate::typeDataReady(QDeclarativeTypeData *) { Q_Q(QDeclarativeComponent); @@ -209,28 +208,25 @@ void QDeclarativeComponentPrivate::typeDataReady() emit q->statusChanged(q->status()); } -void QDeclarativeComponentPrivate::updateProgress(qreal p) +void QDeclarativeComponentPrivate::typeDataProgress(QDeclarativeTypeData *, qreal p) { Q_Q(QDeclarativeComponent); progress = p; + emit q->progressChanged(p); } -void QDeclarativeComponentPrivate::fromTypeData(QDeclarativeCompositeTypeData *data) +void QDeclarativeComponentPrivate::fromTypeData(QDeclarativeTypeData *data) { - url = data->imports.baseUrl(); - QDeclarativeCompiledData *c = data->toCompiledComponent(engine); + url = data->finalUrl(); + QDeclarativeCompiledData *c = data->compiledData(); if (!c) { - Q_ASSERT(data->status == QDeclarativeCompositeTypeData::Error); - - state.errors = data->errors; - + Q_ASSERT(data->isError()); + state.errors = data->errors(); } else { - cc = c; - } data->release(); @@ -239,7 +235,7 @@ void QDeclarativeComponentPrivate::fromTypeData(QDeclarativeCompositeTypeData *d void QDeclarativeComponentPrivate::clear() { if (typeData) { - typeData->remWaiter(this); + typeData->unregisterCallback(this); typeData->release(); typeData = 0; } @@ -271,7 +267,7 @@ QDeclarativeComponent::~QDeclarativeComponent() } if (d->typeData) { - d->typeData->remWaiter(d); + d->typeData->unregisterCallback(d); d->typeData->release(); } if (d->cc) @@ -443,19 +439,13 @@ void QDeclarativeComponent::setData(const QByteArray &data, const QUrl &url) d->url = url; - QDeclarativeCompositeTypeData *typeData = - QDeclarativeEnginePrivate::get(d->engine)->typeManager.getImmediate(data, url); + QDeclarativeTypeData *typeData = QDeclarativeEnginePrivate::get(d->engine)->typeLoader.get(data, url); - if (typeData->status == QDeclarativeCompositeTypeData::Waiting - || typeData->status == QDeclarativeCompositeTypeData::WaitingResources) - { - d->typeData = typeData; - d->typeData->addWaiter(d); - - } else { - + if (typeData->isCompleteOrError()) { d->fromTypeData(typeData); - + } else { + d->typeData = typeData; + d->typeData->registerCallback(d); } d->progress = 1.0; @@ -501,18 +491,15 @@ void QDeclarativeComponent::loadUrl(const QUrl &url) return; } - QDeclarativeCompositeTypeData *data = - QDeclarativeEnginePrivate::get(d->engine)->typeManager.get(d->url); + QDeclarativeTypeData *data = QDeclarativeEnginePrivate::get(d->engine)->typeLoader.get(d->url); - if (data->status == QDeclarativeCompositeTypeData::Waiting - || data->status == QDeclarativeCompositeTypeData::WaitingResources) - { - d->typeData = data; - d->typeData->addWaiter(d); - d->progress = data->progress; - } else { + if (data->isCompleteOrError()) { d->fromTypeData(data); d->progress = 1.0; + } else { + d->typeData = data; + d->typeData->registerCallback(d); + d->progress = data->progress(); } emit statusChanged(status()); diff --git a/src/declarative/qml/qdeclarativecomponent.h b/src/declarative/qml/qdeclarativecomponent.h index 1d1fca7..fd9cb2b 100644 --- a/src/declarative/qml/qdeclarativecomponent.h +++ b/src/declarative/qml/qdeclarativecomponent.h @@ -117,6 +117,7 @@ private: Q_DISABLE_COPY(QDeclarativeComponent) friend class QDeclarativeVME; friend class QDeclarativeCompositeTypeData; + friend class QDeclarativeTypeData; }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativecomponent_p.h b/src/declarative/qml/qdeclarativecomponent_p.h index 2a7d633..1b1454b 100644 --- a/src/declarative/qml/qdeclarativecomponent_p.h +++ b/src/declarative/qml/qdeclarativecomponent_p.h @@ -56,7 +56,7 @@ #include "qdeclarativecomponent.h" #include "private/qdeclarativeengine_p.h" -#include "private/qdeclarativecompositetypemanager_p.h" +#include "private/qdeclarativetypeloader_p.h" #include "private/qbitfield_p.h" #include "qdeclarativeerror.h" #include "qdeclarative.h" @@ -74,7 +74,7 @@ class QDeclarativeEngine; class QDeclarativeCompiledData; class QDeclarativeComponentAttached; -class QDeclarativeComponentPrivate : public QObjectPrivate +class QDeclarativeComponentPrivate : public QObjectPrivate, public QDeclarativeTypeData::TypeDataCallback { Q_DECLARE_PUBLIC(QDeclarativeComponent) @@ -85,11 +85,11 @@ public: QObject *beginCreate(QDeclarativeContextData *, const QBitField &); void completeCreate(); - QDeclarativeCompositeTypeData *typeData; - void typeDataReady(); - void updateProgress(qreal); + QDeclarativeTypeData *typeData; + virtual void typeDataReady(QDeclarativeTypeData *); + virtual void typeDataProgress(QDeclarativeTypeData *, qreal); - void fromTypeData(QDeclarativeCompositeTypeData *data); + void fromTypeData(QDeclarativeTypeData *data); QUrl url; qreal progress; diff --git a/src/declarative/qml/qdeclarativecompositetypedata_p.h b/src/declarative/qml/qdeclarativecompositetypedata_p.h deleted file mode 100644 index a0e4cc2..0000000 --- a/src/declarative/qml/qdeclarativecompositetypedata_p.h +++ /dev/null @@ -1,161 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (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 Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QDECLARATIVECOMPOSITETYPEDATA_P_H -#define QDECLARATIVECOMPOSITETYPEDATA_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/qdeclarativeengine_p.h" - -#include <QtCore/qglobal.h> - -QT_BEGIN_NAMESPACE - -class QDeclarativeCompositeTypeResource; -class QDeclarativeCompositeTypeData : public QDeclarativeRefCount -{ -public: - QDeclarativeCompositeTypeData(); - virtual ~QDeclarativeCompositeTypeData(); - - enum Status { - Invalid, - Complete, - Error, - Waiting, - WaitingResources - }; - Status status; - enum ErrorType { - NoError, - AccessError, - GeneralError - }; - ErrorType errorType; - - QList<QDeclarativeError> errors; - - QDeclarativeImports imports; - - QList<QDeclarativeCompositeTypeData *> dependants; - - // Return a QDeclarativeComponent if the QDeclarativeCompositeTypeData is not in the Waiting - // state. The QDeclarativeComponent is owned by the QDeclarativeCompositeTypeData, so a - // reference should be kept to keep the QDeclarativeComponent alive. - QDeclarativeComponent *toComponent(QDeclarativeEngine *); - // Return a QDeclarativeCompiledData if possible, or 0 if an error - // occurs - QDeclarativeCompiledData *toCompiledComponent(QDeclarativeEngine *); - - struct TypeReference - { - TypeReference(); - - QDeclarativeType *type; - QDeclarativeCompositeTypeData *unit; - }; - - struct ScriptReference - { - ScriptReference(); - - QString qualifier; - QDeclarativeCompositeTypeResource *resource; - }; - - QList<TypeReference> types; - QList<ScriptReference> scripts; - QList<QDeclarativeCompositeTypeResource *> resources; - - // Add or remove p as a waiter. When the QDeclarativeCompositeTypeData becomes - // ready, the QDeclarativeComponentPrivate::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(QDeclarativeComponentPrivate *p); - void remWaiter(QDeclarativeComponentPrivate *p); - - qreal progress; - -private: - friend class QDeclarativeCompositeTypeManager; - friend class QDeclarativeCompiler; - friend class QDeclarativeDomDocument; - - QDeclarativeScriptParser data; - QList<QDeclarativeComponentPrivate *> waiters; - QDeclarativeComponent *component; - QDeclarativeCompiledData *compiledComponent; -}; - -class QDeclarativeCompositeTypeResource : public QDeclarativeRefCount -{ -public: - QDeclarativeCompositeTypeResource(); - virtual ~QDeclarativeCompositeTypeResource(); - - enum Status { - Invalid, - Complete, - Error, - Waiting - }; - Status status; - - QList<QDeclarativeCompositeTypeData *> dependants; - - QString url; - QByteArray data; -}; - -QT_END_NAMESPACE - -#endif // QDECLARATIVECOMPOSITETYPEDATA_P_H - diff --git a/src/declarative/qml/qdeclarativecompositetypemanager.cpp b/src/declarative/qml/qdeclarativecompositetypemanager.cpp deleted file mode 100644 index cc8f887..0000000 --- a/src/declarative/qml/qdeclarativecompositetypemanager.cpp +++ /dev/null @@ -1,778 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (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 Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "private/qdeclarativecompositetypemanager_p.h" - -#include "private/qdeclarativecompositetypedata_p.h" -#include "private/qdeclarativescriptparser_p.h" -#include "qdeclarativeengine.h" -#include "private/qdeclarativeengine_p.h" -#include "qdeclarativecomponent.h" -#include "private/qdeclarativecomponent_p.h" -#include "private/qdeclarativecompiler_p.h" - -#include <QtNetwork/qnetworkreply.h> -#include <QtCore/qdebug.h> -#include <QtCore/qfile.h> - -QT_BEGIN_NAMESPACE - -QDeclarativeCompositeTypeData::QDeclarativeCompositeTypeData() -: status(Invalid), errorType(NoError), component(0), compiledComponent(0) -{ -} - -QDeclarativeCompositeTypeData::~QDeclarativeCompositeTypeData() -{ - 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; -} - -QDeclarativeCompositeTypeResource::QDeclarativeCompositeTypeResource() -{ -} - -QDeclarativeCompositeTypeResource::~QDeclarativeCompositeTypeResource() -{ - for (int ii = 0; ii < dependants.count(); ++ii) - dependants.at(ii)->release(); -} - -void QDeclarativeCompositeTypeData::addWaiter(QDeclarativeComponentPrivate *p) -{ - waiters << p; -} - -void QDeclarativeCompositeTypeData::remWaiter(QDeclarativeComponentPrivate *p) -{ - waiters.removeAll(p); -} - -QDeclarativeComponent *QDeclarativeCompositeTypeData::toComponent(QDeclarativeEngine *engine) -{ - if (!component) { - - QDeclarativeCompiledData *cc = toCompiledComponent(engine); - if (cc) { - component = new QDeclarativeComponent(engine, cc, -1, -1, 0); - cc->release(); - } else { - component = new QDeclarativeComponent(engine, 0); - component->d_func()->url = imports.baseUrl(); - component->d_func()->state.errors = errors; - } - - } - - return component; -} - -QDeclarativeCompiledData * -QDeclarativeCompositeTypeData::toCompiledComponent(QDeclarativeEngine *engine) -{ - if (status == Complete && !compiledComponent) { - - // Build script imports - foreach (const QDeclarativeScriptParser::Import &import, data.imports()) { - if (import.type == QDeclarativeScriptParser::Import::Script) { - QString url = imports.baseUrl().resolved(QUrl(import.uri)).toString(); - - ScriptReference ref; - ref.qualifier = import.qualifier; - - for (int ii = 0; ii < resources.count(); ++ii) { - if (resources.at(ii)->url == url) { - ref.resource = resources.at(ii); - break; - } - } - - Q_ASSERT(ref.resource); - - scripts << ref; - } - } - - compiledComponent = new QDeclarativeCompiledData(engine); - compiledComponent->url = imports.baseUrl(); - compiledComponent->name = compiledComponent->url.toString(); - - QDeclarativeCompiler 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; -} - -QDeclarativeCompositeTypeData::TypeReference::TypeReference() -: type(0), unit(0) -{ -} - -QDeclarativeCompositeTypeData::ScriptReference::ScriptReference() -: resource(0) -{ -} - -QDeclarativeCompositeTypeManager::QDeclarativeCompositeTypeManager(QDeclarativeEngine *e) -: engine(e), redirectCount(0) -{ -} - -QDeclarativeCompositeTypeManager::~QDeclarativeCompositeTypeManager() -{ - 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); - } -} - -QDeclarativeCompositeTypeData *QDeclarativeCompositeTypeManager::get(const QUrl &url) -{ - Redirects::Iterator redir = redirects.find(url); - if (redir != redirects.end()) - return get(*redir); - - QDeclarativeCompositeTypeData *unit = components.value(url); - - if (!unit) { - unit = new QDeclarativeCompositeTypeData; - unit->status = QDeclarativeCompositeTypeData::Waiting; - unit->progress = 0.0; - unit->imports.setBaseUrl(url); - components.insert(url, unit); - - loadSource(unit); - } - - unit->addref(); - return unit; -} - -QDeclarativeCompositeTypeData * -QDeclarativeCompositeTypeManager::getImmediate(const QByteArray &data, const QUrl &url) -{ - QDeclarativeCompositeTypeData *unit = new QDeclarativeCompositeTypeData; - unit->status = QDeclarativeCompositeTypeData::Waiting; - unit->imports.setBaseUrl(url); - setData(unit, data, url); - return unit; -} - -void QDeclarativeCompositeTypeManager::clearCache() -{ - for (Components::Iterator iter = components.begin(); iter != components.end();) { - if ((*iter)->status != QDeclarativeCompositeTypeData::Waiting) { - (*iter)->release(); - iter = components.erase(iter); - } else { - ++iter; - } - } - - for (Resources::Iterator iter = resources.begin(); iter != resources.end();) { - if ((*iter)->status != QDeclarativeCompositeTypeResource::Waiting) { - (*iter)->release(); - iter = resources.erase(iter); - } else { - ++iter; - } - } -} - -#define TYPEMANAGER_MAXIMUM_REDIRECT_RECURSION 16 - -void QDeclarativeCompositeTypeManager::replyFinished() -{ - QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); - - QDeclarativeCompositeTypeData *unit = components.value(reply->url()); - Q_ASSERT(unit); - - redirectCount++; - if (redirectCount < TYPEMANAGER_MAXIMUM_REDIRECT_RECURSION) { - QVariant redirect = reply->attribute(QNetworkRequest::RedirectionTargetAttribute); - if (redirect.isValid()) { - QUrl url = reply->url().resolved(redirect.toUrl()); - redirects.insert(reply->url(),url); - unit->imports.setBaseUrl(url); - components.remove(reply->url()); - components.insert(url, unit); - reply->deleteLater(); - 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))); - return; - } - } - redirectCount = 0; - - if (reply->error() != QNetworkReply::NoError) { - QString errorDescription; - // ### - Fill in error - errorDescription = QLatin1String("Network error for URL ") + - reply->url().toString(); - - unit->status = QDeclarativeCompositeTypeData::Error; - // ### FIXME - QDeclarativeError error; - error.setDescription(errorDescription); - unit->errorType = QDeclarativeCompositeTypeData::AccessError; - unit->errors << error; - doComplete(unit); - - } else { - QByteArray data = reply->readAll(); - - setData(unit, data, reply->url()); - } - - reply->deleteLater(); -} - -void QDeclarativeCompositeTypeManager::resourceReplyFinished() -{ - QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); - - QDeclarativeCompositeTypeResource *resource = resources.value(reply->url()); - Q_ASSERT(resource); - - redirectCount++; - if (redirectCount < TYPEMANAGER_MAXIMUM_REDIRECT_RECURSION) { - QVariant redirect = reply->attribute(QNetworkRequest::RedirectionTargetAttribute); - if (redirect.isValid()) { - QUrl url = reply->url().resolved(redirect.toUrl()); - redirects.insert(reply->url(),url); - resource->url = url.toString(); - resources.remove(reply->url()); - resources.insert(url, resource); - reply->deleteLater(); - reply = engine->networkAccessManager()->get(QNetworkRequest(url)); - QObject::connect(reply, SIGNAL(finished()), - this, SLOT(resourceReplyFinished())); - return; - } - } - redirectCount = 0; - - if (reply->error() != QNetworkReply::NoError) { - - resource->status = QDeclarativeCompositeTypeResource::Error; - - } else { - - resource->status = QDeclarativeCompositeTypeResource::Complete; - resource->data = reply->readAll(); - - } - - doComplete(resource); - reply->deleteLater(); -} - -void QDeclarativeCompositeTypeManager::loadResource(QDeclarativeCompositeTypeResource *resource) -{ - QUrl url(resource->url); - - QString lf = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url); - if (!lf.isEmpty()) { - - QFile file(lf); - if (file.open(QFile::ReadOnly)) { - resource->data = file.readAll(); - resource->status = QDeclarativeCompositeTypeResource::Complete; - } else { - resource->status = QDeclarativeCompositeTypeResource::Error; - } - } else if (url.scheme().isEmpty()) { - - // We can't open this, so just declare as an error - resource->status = QDeclarativeCompositeTypeResource::Error; - } else { - - QNetworkReply *reply = - engine->networkAccessManager()->get(QNetworkRequest(url)); - QObject::connect(reply, SIGNAL(finished()), - this, SLOT(resourceReplyFinished())); - - } -} - -void QDeclarativeCompositeTypeManager::loadSource(QDeclarativeCompositeTypeData *unit) -{ - QUrl url(unit->imports.baseUrl()); - - QString lf = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url); - if (!lf.isEmpty()) { - - QFile file(lf); - if (file.open(QFile::ReadOnly)) { - QByteArray data = file.readAll(); - setData(unit, data, url); - return; // success - } - } else if (!url.scheme().isEmpty()) { - 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))); - return; // waiting - } - - // error happened - QString errorDescription; - // ### - Fill in error - errorDescription = QLatin1String("File error for URL ") + url.toString(); - unit->status = QDeclarativeCompositeTypeData::Error; - // ### FIXME - QDeclarativeError error; - error.setDescription(errorDescription); - unit->errorType = QDeclarativeCompositeTypeData::AccessError; - unit->errors << error; - doComplete(unit); -} - -void QDeclarativeCompositeTypeManager::requestProgress(qint64 received, qint64 total) -{ - if (total <= 0) - return; - QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); - - QDeclarativeCompositeTypeData *unit = components.value(reply->url()); - Q_ASSERT(unit); - - unit->progress = qreal(received)/total; - - foreach (QDeclarativeComponentPrivate *comp, unit->waiters) - comp->updateProgress(unit->progress); -} - -void QDeclarativeCompositeTypeManager::setData(QDeclarativeCompositeTypeData *unit, - const QByteArray &data, - const QUrl &url) -{ - bool ok = true; - if (!unit->data.parse(data, url)) { - ok = false; - unit->errors << unit->data.errors(); - } - - if (ok) { - compile(unit); - } else { - unit->status = QDeclarativeCompositeTypeData::Error; - unit->errorType = QDeclarativeCompositeTypeData::GeneralError; - doComplete(unit); - } -} - -void QDeclarativeCompositeTypeManager::doComplete(QDeclarativeCompositeTypeData *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()) { - QDeclarativeComponentPrivate *p = unit->waiters.takeFirst(); - p->typeDataReady(); - } -} - -void QDeclarativeCompositeTypeManager::doComplete(QDeclarativeCompositeTypeResource *resource) -{ - for (int ii = 0; ii < resource->dependants.count(); ++ii) { - checkComplete(resource->dependants.at(ii)); - resource->dependants.at(ii)->release(); - } - resource->dependants.clear(); -} - -void QDeclarativeCompositeTypeManager::checkComplete(QDeclarativeCompositeTypeData *unit) -{ - if (unit->status != QDeclarativeCompositeTypeData::Waiting - && unit->status != QDeclarativeCompositeTypeData::WaitingResources) - return; - - int waiting = 0; - for (int ii = 0; ii < unit->resources.count(); ++ii) { - QDeclarativeCompositeTypeResource *r = unit->resources.at(ii); - - if (!r) - continue; - - if (r->status == QDeclarativeCompositeTypeResource::Error) { - unit->status = QDeclarativeCompositeTypeData::Error; - QDeclarativeError error; - error.setUrl(unit->imports.baseUrl()); - error.setDescription(tr("Resource %1 unavailable").arg(r->url)); - unit->errors << error; - doComplete(unit); - return; - } else if (r->status == QDeclarativeCompositeTypeResource::Waiting) { - waiting++; - } - } - - if (waiting == 0) { - if (unit->status == QDeclarativeCompositeTypeData::WaitingResources) { - waiting += resolveTypes(unit); - if (unit->status != QDeclarativeCompositeTypeData::Error) { - if (waiting) - unit->status = QDeclarativeCompositeTypeData::Waiting; - } else { - return; - } - } else { - for (int ii = 0; ii < unit->types.count(); ++ii) { - QDeclarativeCompositeTypeData *u = unit->types.at(ii).unit; - - if (!u) - continue; - - if (u->status == QDeclarativeCompositeTypeData::Error) { - unit->status = QDeclarativeCompositeTypeData::Error; - unit->errors = u->errors; - doComplete(unit); - return; - } else if (u->status == QDeclarativeCompositeTypeData::Waiting - || u->status == QDeclarativeCompositeTypeData::WaitingResources) - { - waiting++; - } - } - } - } - - if (!waiting) { - unit->status = QDeclarativeCompositeTypeData::Complete; - doComplete(unit); - } -} - -int QDeclarativeCompositeTypeManager::resolveTypes(QDeclarativeCompositeTypeData *unit) -{ - // not called until all resources are loaded (they include import URLs) - int waiting = 0; - - QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine); - QDeclarativeImportDatabase *importDatabase = &ep->importDatabase; - - // For local urls, add an implicit import "." as first (most overridden) lookup. - // This will also trigger the loading of the qmldir and the import of any native - // types from available plugins. - { - QDeclarativeDirComponents qmldircomponentsnetwork; - if (QDeclarativeCompositeTypeResource *resource - = resources.value(unit->imports.baseUrl().resolved(QUrl(QLatin1String("./qmldir"))))) { - QDeclarativeDirParser parser; - parser.setSource(QString::fromUtf8(resource->data)); - parser.parse(); - qmldircomponentsnetwork = parser.components(); - } - - unit->imports.addImport(importDatabase, - QLatin1String("."), QString(), -1, -1, QDeclarativeScriptParser::Import::File, - qmldircomponentsnetwork, - 0); // error ignored (just means no fallback) - } - - - foreach (const QDeclarativeScriptParser::Import &imp, unit->data.imports()) { - QDeclarativeDirComponents qmldircomponentsnetwork; - if (imp.type == QDeclarativeScriptParser::Import::Script) - continue; - - if (imp.type == QDeclarativeScriptParser::Import::File && imp.qualifier.isEmpty()) { - QString importUrl = unit->imports.baseUrl().resolved(QUrl(imp.uri + QLatin1String("/qmldir"))).toString(); - for (int ii = 0; ii < unit->resources.count(); ++ii) { - if (unit->resources.at(ii)->url == importUrl) { - QDeclarativeDirParser parser; - parser.setSource(QString::fromUtf8(unit->resources.at(ii)->data)); - parser.parse(); - qmldircomponentsnetwork = parser.components(); - break; - } - } - } - - - int vmaj = -1; - int vmin = -1; - if (!imp.version.isEmpty()) { - int dot = imp.version.indexOf(QLatin1Char('.')); - if (dot < 0) { - vmaj = imp.version.toInt(); - vmin = 0; - } else { - vmaj = imp.version.left(dot).toInt(); - vmin = imp.version.mid(dot+1).toInt(); - } - } - - QString errorString; - if (!unit->imports.addImport(importDatabase, - imp.uri, imp.qualifier, vmaj, vmin, imp.type, - qmldircomponentsnetwork, &errorString)) { - QDeclarativeError error; - error.setUrl(unit->imports.baseUrl()); - error.setDescription(errorString); - error.setLine(imp.location.start.line); - error.setColumn(imp.location.start.column); - unit->status = QDeclarativeCompositeTypeData::Error; - unit->errorType = QDeclarativeCompositeTypeData::GeneralError; - unit->errors << error; - doComplete(unit); - return 0; - } - } - - - QList<QDeclarativeScriptParser::TypeReference*> types = unit->data.referencedTypes(); - - for (int ii = 0; ii < types.count(); ++ii) { - QDeclarativeScriptParser::TypeReference *parserRef = types.at(ii); - QByteArray typeName = parserRef->name.toUtf8(); - - QDeclarativeCompositeTypeData::TypeReference ref; - - QUrl url; - int majorVersion; - int minorVersion; - QDeclarativeImportedNamespace *typeNamespace = 0; - QString errorString; - if (!unit->imports.resolveType(typeName, &ref.type, &url, &majorVersion, &minorVersion, - &typeNamespace, &errorString) || typeNamespace) { - // Known to not be a type: - // - known to be a namespace (Namespace {}) - // - type with unknown namespace (UnknownNamespace.SomeType {}) - QDeclarativeError error; - error.setUrl(unit->imports.baseUrl()); - QString userTypeName = QString::fromUtf8(typeName); - userTypeName.replace(QLatin1Char('/'),QLatin1Char('.')); - if (typeNamespace) - error.setDescription(tr("Namespace %1 cannot be used as a type").arg(userTypeName)); - else - error.setDescription(tr("%1 %2").arg(userTypeName).arg(errorString)); - - if (!parserRef->refObjects.isEmpty()) { - QDeclarativeParser::Object *obj = parserRef->refObjects.first(); - error.setLine(obj->location.start.line); - error.setColumn(obj->location.start.column); - } - unit->status = QDeclarativeCompositeTypeData::Error; - unit->errorType = QDeclarativeCompositeTypeData::GeneralError; - unit->errors << error; - doComplete(unit); - return 0; - } - - if (ref.type) { - foreach (QDeclarativeParser::Object *obj, parserRef->refObjects) { - // store namespace for DOM - obj->majorVersion = majorVersion; - obj->minorVersion = minorVersion; - } - unit->types << ref; - continue; - } - - Redirects::Iterator redir = redirects.find(url); - if (redir != redirects.end()) - url = *redir; - - QDeclarativeCompositeTypeData *urlUnit = components.value(url); - - if (!urlUnit) { - urlUnit = new QDeclarativeCompositeTypeData; - urlUnit->status = QDeclarativeCompositeTypeData::Waiting; - urlUnit->imports.setBaseUrl(url); - components.insert(url, urlUnit); - - loadSource(urlUnit); - } - - ref.unit = urlUnit; - switch(urlUnit->status) { - case QDeclarativeCompositeTypeData::Invalid: - case QDeclarativeCompositeTypeData::Error: - unit->status = QDeclarativeCompositeTypeData::Error; - { - QDeclarativeError error; - error.setUrl(unit->imports.baseUrl()); - error.setDescription(tr("Type %1 unavailable").arg(QString::fromUtf8(typeName))); - if (!parserRef->refObjects.isEmpty()) { - QDeclarativeParser::Object *obj = parserRef->refObjects.first(); - error.setLine(obj->location.start.line); - error.setColumn(obj->location.start.column); - } - unit->errors << error; - } - if (urlUnit->errorType != QDeclarativeCompositeTypeData::AccessError) - unit->errors << urlUnit->errors; - doComplete(unit); - return 0; - - case QDeclarativeCompositeTypeData::Complete: - break; - - case QDeclarativeCompositeTypeData::Waiting: - case QDeclarativeCompositeTypeData::WaitingResources: - unit->addref(); - ref.unit->dependants << unit; - waiting++; - break; - } - - unit->types << ref; - } - return waiting; -} - -// ### Check ref counting in here -void QDeclarativeCompositeTypeManager::compile(QDeclarativeCompositeTypeData *unit) -{ - int waiting = 0; - - QList<QUrl> resourceList = unit->data.referencedResources(); - - foreach (QDeclarativeScriptParser::Import imp, unit->data.imports()) { - if (imp.type == QDeclarativeScriptParser::Import::File && imp.qualifier.isEmpty()) { - QUrl importUrl = unit->imports.baseUrl().resolved(QUrl(imp.uri + QLatin1String("/qmldir"))); - if (QDeclarativeEnginePrivate::urlToLocalFileOrQrc(importUrl).isEmpty()) { - // Import requires remote qmldir - resourceList.prepend(importUrl); - } - } - } - - QUrl importUrl; - if (!unit->imports.baseUrl().scheme().isEmpty()) - importUrl = unit->imports.baseUrl().resolved(QUrl(QLatin1String("qmldir"))); - if (!importUrl.scheme().isEmpty() && QDeclarativeEnginePrivate::urlToLocalFileOrQrc(importUrl).isEmpty()) - resourceList.prepend(importUrl); - - for (int ii = 0; ii < resourceList.count(); ++ii) { - QUrl url = unit->imports.baseUrl().resolved(resourceList.at(ii)); - - QDeclarativeCompositeTypeResource *resource = resources.value(url); - - if (!resource) { - resource = new QDeclarativeCompositeTypeResource; - resource->status = QDeclarativeCompositeTypeResource::Waiting; - resource->url = url.toString(); - resources.insert(url, resource); - - loadResource(resource); - } - - switch(resource->status) { - case QDeclarativeCompositeTypeResource::Invalid: - case QDeclarativeCompositeTypeResource::Error: - unit->status = QDeclarativeCompositeTypeData::Error; - { - QDeclarativeError error; - error.setUrl(unit->imports.baseUrl()); - error.setDescription(tr("Resource %1 unavailable").arg(resource->url)); - unit->errors << error; - } - doComplete(unit); - return; - - case QDeclarativeCompositeTypeData::Complete: - break; - - case QDeclarativeCompositeTypeData::Waiting: - unit->addref(); - resource->dependants << unit; - waiting++; - break; - } - - resource->addref(); - unit->resources << resource; - } - - if (waiting == 0) { - waiting += resolveTypes(unit); - if (unit->status != QDeclarativeCompositeTypeData::Error) { - if (!waiting) { - unit->status = QDeclarativeCompositeTypeData::Complete; - doComplete(unit); - } else { - unit->status = QDeclarativeCompositeTypeData::Waiting; - } - } - } else { - unit->status = QDeclarativeCompositeTypeData::WaitingResources; - } -} - -QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativecompositetypemanager_p.h b/src/declarative/qml/qdeclarativecompositetypemanager_p.h deleted file mode 100644 index 5c82c4c..0000000 --- a/src/declarative/qml/qdeclarativecompositetypemanager_p.h +++ /dev/null @@ -1,120 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (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 Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QDECLARATIVECOMPOSITETYPEMANAGER_P_H -#define QDECLARATIVECOMPOSITETYPEMANAGER_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/qdeclarativescriptparser_p.h" -#include "private/qdeclarativerefcount_p.h" -#include "qdeclarativeerror.h" -#include "qdeclarativeengine.h" - -#include <QtCore/qglobal.h> - -QT_BEGIN_NAMESPACE - -class QDeclarativeCompiledData; -class QDeclarativeComponentPrivate; -class QDeclarativeComponent; -class QDeclarativeDomDocument; - -class QDeclarativeCompositeTypeData; -class QDeclarativeCompositeTypeResource; - -class QDeclarativeCompositeTypeManager : public QObject -{ - Q_OBJECT -public: - QDeclarativeCompositeTypeManager(QDeclarativeEngine *); - ~QDeclarativeCompositeTypeManager(); - - // Return a QDeclarativeCompositeTypeData for url. The QDeclarativeCompositeTypeData may be - // cached. - QDeclarativeCompositeTypeData *get(const QUrl &url); - // Return a QDeclarativeCompositeTypeData for data, with the provided base url. The - // QDeclarativeCompositeTypeData will not be cached. - QDeclarativeCompositeTypeData *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(QDeclarativeCompositeTypeData *); - void loadResource(QDeclarativeCompositeTypeResource *); - void compile(QDeclarativeCompositeTypeData *); - void setData(QDeclarativeCompositeTypeData *, const QByteArray &, const QUrl &); - - void doComplete(QDeclarativeCompositeTypeData *); - void doComplete(QDeclarativeCompositeTypeResource *); - void checkComplete(QDeclarativeCompositeTypeData *); - int resolveTypes(QDeclarativeCompositeTypeData *); - - QDeclarativeEngine *engine; - typedef QHash<QUrl, QDeclarativeCompositeTypeData *> Components; - Components components; - typedef QHash<QUrl, QDeclarativeCompositeTypeResource *> Resources; - Resources resources; - typedef QHash<QUrl, QUrl> Redirects; - Redirects redirects; - int redirectCount; -}; - -QT_END_NAMESPACE - -#endif // QDECLARATIVECOMPOSITETYPEMANAGER_P_H - diff --git a/src/declarative/qml/qdeclarativedom.cpp b/src/declarative/qml/qdeclarativedom.cpp index 5b30bde..1a9b501 100644 --- a/src/declarative/qml/qdeclarativedom.cpp +++ b/src/declarative/qml/qdeclarativedom.cpp @@ -42,7 +42,6 @@ #include "private/qdeclarativedom_p.h" #include "private/qdeclarativedom_p_p.h" -#include "private/qdeclarativecompositetypedata_p.h" #include "private/qdeclarativecompiler_p.h" #include "private/qdeclarativeengine_p.h" #include "private/qdeclarativescriptparser_p.h" @@ -145,37 +144,23 @@ bool QDeclarativeDomDocument::load(QDeclarativeEngine *engine, const QByteArray d->errors.clear(); d->imports.clear(); - QDeclarativeCompiledData *component = new QDeclarativeCompiledData(engine); - QDeclarativeCompiler compiler; + QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine); + QDeclarativeTypeData *td = ep->typeLoader.get(data, url, QDeclarativeTypeLoader::PreserveParser); - QDeclarativeCompositeTypeData *td = ((QDeclarativeEnginePrivate *)QDeclarativeEnginePrivate::get(engine))->typeManager.getImmediate(data, url); - - if(td->status == QDeclarativeCompositeTypeData::Error) { - d->errors = td->errors; + if(td->isError()) { + d->errors = td->errors(); td->release(); - component->release(); return false; - } else if(td->status == QDeclarativeCompositeTypeData::Waiting || - td->status == QDeclarativeCompositeTypeData::WaitingResources) { + } else if(!td->isCompleteOrError()) { QDeclarativeError error; error.setDescription(QLatin1String("QDeclarativeDomDocument 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) { - QDeclarativeScriptParser::Import parserImport = td->data.imports().at(i); + for (int i = 0; i < td->parser().imports().size(); ++i) { + QDeclarativeScriptParser::Import parserImport = td->parser().imports().at(i); QDeclarativeDomImport domImport; domImport.d->type = static_cast<QDeclarativeDomImportPrivate::Type>(parserImport.type); domImport.d->uri = parserImport.uri; @@ -184,12 +169,12 @@ bool QDeclarativeDomDocument::load(QDeclarativeEngine *engine, const QByteArray d->imports += domImport; } - if (td->data.tree()) { - d->root = td->data.tree(); + if (td->parser().tree()) { + d->root = td->parser().tree(); d->root->addref(); } - component->release(); + td->release(); return true; } diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp index c5a5c18..8461368 100644 --- a/src/declarative/qml/qdeclarativeengine.cpp +++ b/src/declarative/qml/qdeclarativeengine.cpp @@ -259,7 +259,7 @@ QDeclarativeEnginePrivate::QDeclarativeEnginePrivate(QDeclarativeEngine *e) objectClass(0), valueTypeClass(0), globalClass(0), cleanup(0), erroredBindings(0), inProgressCreations(0), scriptEngine(this), workerScriptEngine(0), componentAttached(0), inBeginCreate(false), networkAccessManager(0), networkAccessManagerFactory(0), - typeManager(e), importDatabase(e), uniqueId(1) + typeLoader(e), importDatabase(e), uniqueId(1) { if (!qt_QmlQtModule_registered) { qt_QmlQtModule_registered = true; @@ -565,7 +565,7 @@ QDeclarativeEngine::~QDeclarativeEngine() void QDeclarativeEngine::clearComponentCache() { Q_D(QDeclarativeEngine); - d->typeManager.clearCache(); + d->typeLoader.clearCache(); } /*! @@ -1716,6 +1716,9 @@ void QDeclarativeEnginePrivate::sendQuit() { Q_Q(QDeclarativeEngine); emit q->quit(); + if (q->receivers(SIGNAL(quit())) == 0) { + qWarning("Signal QDeclarativeEngine::quit() emitted, but no receivers connected to handle it."); + } } static void dumpwarning(const QDeclarativeError &error) diff --git a/src/declarative/qml/qdeclarativeengine_p.h b/src/declarative/qml/qdeclarativeengine_p.h index db2db35..dc7315d 100644 --- a/src/declarative/qml/qdeclarativeengine_p.h +++ b/src/declarative/qml/qdeclarativeengine_p.h @@ -56,7 +56,7 @@ #include "qdeclarativeengine.h" #include "private/qdeclarativeclassfactory_p.h" -#include "private/qdeclarativecompositetypemanager_p.h" +#include "private/qdeclarativetypeloader_p.h" #include "private/qdeclarativeimport_p.h" #include "private/qpodvector_p.h" #include "qdeclarative.h" @@ -239,7 +239,7 @@ public: mutable QMutex mutex; - QDeclarativeCompositeTypeManager typeManager; + QDeclarativeTypeLoader typeLoader; QDeclarativeImportDatabase importDatabase; QString offlineStoragePath; diff --git a/src/declarative/qml/qdeclarativeproperty.cpp b/src/declarative/qml/qdeclarativeproperty.cpp index 515c4d6..d0dd2e8 100644 --- a/src/declarative/qml/qdeclarativeproperty.cpp +++ b/src/declarative/qml/qdeclarativeproperty.cpp @@ -42,7 +42,6 @@ #include "qdeclarativeproperty.h" #include "private/qdeclarativeproperty_p.h" -#include "private/qdeclarativecompositetypedata_p.h" #include "qdeclarative.h" #include "private/qdeclarativebinding_p.h" #include "qdeclarativecontext.h" diff --git a/src/declarative/qml/qdeclarativescriptparser.cpp b/src/declarative/qml/qdeclarativescriptparser.cpp index 0b3b35f..c956051 100644 --- a/src/declarative/qml/qdeclarativescriptparser.cpp +++ b/src/declarative/qml/qdeclarativescriptparser.cpp @@ -387,7 +387,6 @@ bool ProcessAST::visit(AST::UiImport *node) if (uri.endsWith(QLatin1String(".js"))) { import.type = QDeclarativeScriptParser::Import::Script; - _parser->_refUrls << QUrl(uri); } else { import.type = QDeclarativeScriptParser::Import::File; } @@ -878,11 +877,6 @@ QList<QDeclarativeScriptParser::TypeReference*> QDeclarativeScriptParser::refere return _refTypes; } -QList<QUrl> QDeclarativeScriptParser::referencedResources() const -{ - return _refUrls; -} - Object *QDeclarativeScriptParser::tree() const { return root; @@ -960,6 +954,217 @@ QDeclarativeParser::Object::ScriptBlock::Pragmas QDeclarativeScriptParser::extra return rv; } +#define CHECK_LINE if(l.currentLineNo() != startLine) return rv; +#define CHECK_TOKEN(t) if (token != QDeclarativeJSGrammar:: t) return rv; + +static const int uriTokens[] = { + QDeclarativeJSGrammar::T_IDENTIFIER, + QDeclarativeJSGrammar::T_PROPERTY, + QDeclarativeJSGrammar::T_SIGNAL, + QDeclarativeJSGrammar::T_READONLY, + QDeclarativeJSGrammar::T_ON, + QDeclarativeJSGrammar::T_BREAK, + QDeclarativeJSGrammar::T_CASE, + QDeclarativeJSGrammar::T_CATCH, + QDeclarativeJSGrammar::T_CONTINUE, + QDeclarativeJSGrammar::T_DEFAULT, + QDeclarativeJSGrammar::T_DELETE, + QDeclarativeJSGrammar::T_DO, + QDeclarativeJSGrammar::T_ELSE, + QDeclarativeJSGrammar::T_FALSE, + QDeclarativeJSGrammar::T_FINALLY, + QDeclarativeJSGrammar::T_FOR, + QDeclarativeJSGrammar::T_FUNCTION, + QDeclarativeJSGrammar::T_IF, + QDeclarativeJSGrammar::T_IN, + QDeclarativeJSGrammar::T_INSTANCEOF, + QDeclarativeJSGrammar::T_NEW, + QDeclarativeJSGrammar::T_NULL, + QDeclarativeJSGrammar::T_RETURN, + QDeclarativeJSGrammar::T_SWITCH, + QDeclarativeJSGrammar::T_THIS, + QDeclarativeJSGrammar::T_THROW, + QDeclarativeJSGrammar::T_TRUE, + QDeclarativeJSGrammar::T_TRY, + QDeclarativeJSGrammar::T_TYPEOF, + QDeclarativeJSGrammar::T_VAR, + QDeclarativeJSGrammar::T_VOID, + QDeclarativeJSGrammar::T_WHILE, + QDeclarativeJSGrammar::T_CONST, + QDeclarativeJSGrammar::T_DEBUGGER, + QDeclarativeJSGrammar::T_RESERVED_WORD, + QDeclarativeJSGrammar::T_WITH, + + QDeclarativeJSGrammar::EOF_SYMBOL +}; +static inline bool isUriToken(int token) +{ + const int *current = uriTokens; + while (*current != QDeclarativeJSGrammar::EOF_SYMBOL) { + if (*current == token) + return true; + ++current; + } + return false; +} + +QDeclarativeScriptParser::JavaScriptMetaData QDeclarativeScriptParser::extractMetaData(QString &script) +{ + JavaScriptMetaData rv; + + QDeclarativeParser::Object::ScriptBlock::Pragmas &pragmas = rv.pragmas; + + const QString pragma(QLatin1String("pragma")); + const QString js(QLatin1String(".js")); + const QString library(QLatin1String("library")); + + QDeclarativeJS::Lexer l(0); + l.setCode(script, 0); + + int token = l.lex(); + + while (true) { + if (token != QDeclarativeJSGrammar::T_DOT) + return rv; + + int startOffset = l.tokenOffset(); + int startLine = l.currentLineNo(); + + token = l.lex(); + + CHECK_LINE; + + if (token == QDeclarativeJSGrammar::T_IMPORT) { + + // .import <URI> <Version> as <Identifier> + // .import <file.js> as <Identifier> + + token = l.lex(); + + CHECK_LINE; + + if (token == QDeclarativeJSGrammar::T_STRING_LITERAL) { + + QString file(l.characterBuffer(), l.characterCount()); + if (!file.endsWith(js)) + return rv; + + token = l.lex(); + + CHECK_TOKEN(T_AS); + CHECK_LINE; + + token = l.lex(); + + CHECK_TOKEN(T_IDENTIFIER); + CHECK_LINE; + + int endOffset = l.tokenLength() + l.tokenOffset(); + + QString importId = script.mid(l.tokenOffset(), l.tokenLength()); + + if (!importId.at(0).isUpper()) + return rv; + + token = l.lex(); + if (l.currentLineNo() == startLine) + return rv; + + replaceWithSpace(script, startOffset, endOffset - startOffset); + + Import import; + import.type = Import::Script; + import.uri = file; + import.qualifier = importId; + + rv.imports << import; + + } else { + // URI + QString uri; + QString version; + + while (true) { + if (!isUriToken(token)) + return rv; + + uri.append(QString(l.characterBuffer(), l.characterCount())); + + token = l.lex(); + CHECK_LINE; + if (token != QDeclarativeJSGrammar::T_DOT) + break; + + uri.append(QLatin1Char('.')); + + token = l.lex(); + CHECK_LINE; + } + + CHECK_TOKEN(T_NUMERIC_LITERAL); + version = script.mid(l.tokenOffset(), l.tokenLength()); + + token = l.lex(); + + CHECK_TOKEN(T_AS); + CHECK_LINE; + + token = l.lex(); + + CHECK_TOKEN(T_IDENTIFIER); + CHECK_LINE; + + int endOffset = l.tokenLength() + l.tokenOffset(); + + QString importId = script.mid(l.tokenOffset(), l.tokenLength()); + + if (!importId.at(0).isUpper()) + return rv; + + token = l.lex(); + if (l.currentLineNo() == startLine) + return rv; + + replaceWithSpace(script, startOffset, endOffset - startOffset); + + Import import; + import.type = Import::Library; + import.uri = uri; + import.version = version; + import.qualifier = importId; + + rv.imports << import; + } + + } else if (token == QDeclarativeJSGrammar::T_IDENTIFIER && + script.mid(l.tokenOffset(), l.tokenLength()) == pragma) { + + token = l.lex(); + + CHECK_TOKEN(T_IDENTIFIER); + CHECK_LINE; + + QString pragmaValue = script.mid(l.tokenOffset(), l.tokenLength()); + int endOffset = l.tokenLength() + l.tokenOffset(); + + if (pragmaValue == QLatin1String("library")) { + pragmas |= QDeclarativeParser::Object::ScriptBlock::Shared; + replaceWithSpace(script, startOffset, endOffset - startOffset); + } else { + return rv; + } + + token = l.lex(); + if (l.currentLineNo() == startLine) + return rv; + + } else { + return rv; + } + } + return rv; +} + void QDeclarativeScriptParser::clear() { if (root) { diff --git a/src/declarative/qml/qdeclarativescriptparser_p.h b/src/declarative/qml/qdeclarativescriptparser_p.h index 28e960b..6319e11 100644 --- a/src/declarative/qml/qdeclarativescriptparser_p.h +++ b/src/declarative/qml/qdeclarativescriptparser_p.h @@ -103,7 +103,6 @@ public: bool parse(const QByteArray &data, const QUrl &url = QUrl()); QList<TypeReference*> referencedTypes() const; - QList<QUrl> referencedResources() const; QDeclarativeParser::Object *tree() const; QList<Import> imports() const; @@ -112,7 +111,18 @@ public: QList<QDeclarativeError> errors() const; + class JavaScriptMetaData { + public: + JavaScriptMetaData() + : pragmas(QDeclarativeParser::Object::ScriptBlock::None) {} + + QDeclarativeParser::Object::ScriptBlock::Pragmas pragmas; + QList<Import> imports; + }; + static QDeclarativeParser::Object::ScriptBlock::Pragmas extractPragmas(QString &); + static JavaScriptMetaData extractMetaData(QString &); + // ### private: TypeReference *findOrCreateType(const QString &name); @@ -127,7 +137,6 @@ public: QDeclarativeParser::Object *root; QList<Import> _imports; QList<TypeReference*> _refTypes; - QList<QUrl> _refUrls; QString _scriptFile; QDeclarativeScriptParserJsASTData *data; }; diff --git a/src/declarative/qml/qdeclarativetypeloader.cpp b/src/declarative/qml/qdeclarativetypeloader.cpp new file mode 100644 index 0000000..8c291f2 --- /dev/null +++ b/src/declarative/qml/qdeclarativetypeloader.cpp @@ -0,0 +1,1070 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (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 Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativetypeloader_p.h" + +#include <private/qdeclarativeengine_p.h> +#include <private/qdeclarativecompiler_p.h> +#include <private/qdeclarativecomponent_p.h> + +#include <QtDeclarative/qdeclarativecomponent.h> +#include <QtCore/qdebug.h> +#include <QtCore/qdir.h> +#include <QtCore/qfile.h> + +QT_BEGIN_NAMESPACE + +/*! +\class QDeclarativeDataBlob +\brief The QDeclarativeDataBlob encapsulates a data request that can be issued to a QDeclarativeDataLoader. +\internal + +QDeclarativeDataBlob's are loaded by a QDeclarativeDataLoader. The user creates the QDeclarativeDataBlob +and then calls QDeclarativeDataLoader::load() or QDeclarativeDataLoader::loadWithStaticData() to load it. +The QDeclarativeDataLoader invokes callbacks on the QDeclarativeDataBlob as data becomes available. +*/ + +/*! +\enum QDeclarativeDataBlob::Status + +\o Null The blob has not yet been loaded by a QDeclarativeDataLoader +\o Loading The blob is loading network data. The QDeclarativeDataBlob::setData() callback has not yet been +invoked or has not yet returned. +\o WaitingForDependencies The blob is waiting for dependencies to be done before continueing. This status +only occurs after the QDeclarativeDataBlob::setData() callback has been made, and when the blob has outstanding +dependencies. +\o Complete The blob's data has been loaded and all dependencies are done. +\o Error An error has been set on this blob. +*/ + +/*! +\enum QDeclarativeDataBlob::Type +\o QmlFile This is a QDeclarativeTypeData +\o JavaScriptFile This is a QDeclarativeScriptData +\o QmldirFile This is a QDeclarativeQmldirData +*/ + +/*! +Create a new QDeclarativeDataBlob for \a url and of the provided \a type. +*/ +QDeclarativeDataBlob::QDeclarativeDataBlob(const QUrl &url, Type type) +: m_type(type), m_status(Null), m_progress(0), m_url(url), m_finalUrl(url), m_manager(0), + m_redirectCount(0), m_inCallback(false), m_isDone(false) +{ +} + +/*! \internal */ +QDeclarativeDataBlob::~QDeclarativeDataBlob() +{ + Q_ASSERT(m_waitingOnMe.isEmpty()); + + cancelAllWaitingFor(); +} + +/*! +Returns the type provided to the constructor. +*/ +QDeclarativeDataBlob::Type QDeclarativeDataBlob::type() const +{ + return m_type; +} + +/*! +Returns the blob's status. +*/ +QDeclarativeDataBlob::Status QDeclarativeDataBlob::status() const +{ + return m_status; +} + +/*! +Returns true if the status is Null. +*/ +bool QDeclarativeDataBlob::isNull() const +{ + return m_status == Null; +} + +/*! +Returns true if the status is Loading. +*/ +bool QDeclarativeDataBlob::isLoading() const +{ + return m_status == Loading; +} + +/*! +Returns true if the status is WaitingForDependencies. +*/ +bool QDeclarativeDataBlob::isWaiting() const +{ + return m_status == WaitingForDependencies; +} + +/*! +Returns true if the status is Complete. +*/ +bool QDeclarativeDataBlob::isComplete() const +{ + return m_status == Complete; +} + +/*! +Returns true if the status is Error. +*/ +bool QDeclarativeDataBlob::isError() const +{ + return m_status == Error; +} + +/*! +Returns true if the status is Complete or Error. +*/ +bool QDeclarativeDataBlob::isCompleteOrError() const +{ + return isComplete() || isError(); +} + +/*! +Returns the data download progress from 0 to 1. +*/ +qreal QDeclarativeDataBlob::progress() const +{ + return m_progress; +} + +/*! +Returns the blob url passed to the constructor. If a network redirect +happens while fetching the data, this url remains the same. + +\sa finalUrl() +*/ +QUrl QDeclarativeDataBlob::url() const +{ + return m_url; +} + +/*! +Returns the final url of the data. Initially this is the same as +url(), but if a network redirect happens while fetching the data, this url +is updated to reflect the new location. +*/ +QUrl QDeclarativeDataBlob::finalUrl() const +{ + return m_finalUrl; +} + +/*! +Return the errors on this blob. +*/ +QList<QDeclarativeError> QDeclarativeDataBlob::errors() const +{ + return m_errors; +} + +/*! +Mark this blob as having \a errors. + +All outstanding dependencies will be cancelled. Requests to add new dependencies +will be ignored. Entry into the Error state is irreversable, although you can change the +specific errors by additional calls to setError. +*/ +void QDeclarativeDataBlob::setError(const QDeclarativeError &errors) +{ + QList<QDeclarativeError> l; + l << errors; + setError(l); +} + +/*! +\override +*/ +void QDeclarativeDataBlob::setError(const QList<QDeclarativeError> &errors) +{ + m_status = Error; + m_errors = errors; + + cancelAllWaitingFor(); + + if (!m_inCallback) + tryDone(); +} + +/*! +Wait for \a blob to become complete or to error. If \a blob is already +complete or in error, or this blob is already complete, this has no effect. +*/ +void QDeclarativeDataBlob::addDependency(QDeclarativeDataBlob *blob) +{ + Q_ASSERT(status() != Null); + + if (!blob || + blob->status() == Error || blob->status() == Complete || + status() == Error || status() == Complete || + m_waitingFor.contains(blob)) + return; + + blob->addref(); + m_status = WaitingForDependencies; + m_waitingFor.append(blob); + blob->m_waitingOnMe.append(this); +} + +/*! +\fn void QDeclarativeDataBlob::dataReceived(const QByteArray &data) + +Invoked when data for the blob is received. Implementors should use this callback +to determine a blob's dependencies. Within this callback you may call setError() +or addDependency(). +*/ + +/*! +Invoked once data has either been received or a network error occurred, and all +dependencies are complete. + +You can set an error in this method, but you cannot add new dependencies. Implementors +should use this callback to finalize processing of data. + +The default implementation does nothing. +*/ +void QDeclarativeDataBlob::done() +{ +} + +/*! +Invoked if there is a network error while fetching this blob. + +The default implementation sets an appropriate QDeclarativeError. +*/ +void QDeclarativeDataBlob::networkError(QNetworkReply::NetworkError networkError) +{ + Q_UNUSED(networkError); + + QDeclarativeError error; + error.setUrl(m_finalUrl); + + const char *errorString = 0; + switch (networkError) { + default: + errorString = "Network error"; + break; + case QNetworkReply::ConnectionRefusedError: + errorString = "Connection refused"; + break; + case QNetworkReply::RemoteHostClosedError: + errorString = "Remote host closed the connection"; + break; + case QNetworkReply::HostNotFoundError: + errorString = "Host not found"; + break; + case QNetworkReply::TimeoutError: + errorString = "Timeout"; + break; + case QNetworkReply::ProxyConnectionRefusedError: + case QNetworkReply::ProxyConnectionClosedError: + case QNetworkReply::ProxyNotFoundError: + case QNetworkReply::ProxyTimeoutError: + case QNetworkReply::ProxyAuthenticationRequiredError: + case QNetworkReply::UnknownProxyError: + errorString = "Proxy error"; + break; + case QNetworkReply::ContentAccessDenied: + errorString = "Access denied"; + break; + case QNetworkReply::ContentNotFoundError: + errorString = "File not found"; + break; + case QNetworkReply::AuthenticationRequiredError: + errorString = "Authentication required"; + break; + }; + + error.setDescription(QLatin1String(errorString)); + + setError(error); +} + +/*! +Called if \a blob, which was previously waited for, has an error. + +The default implementation does nothing. +*/ +void QDeclarativeDataBlob::dependencyError(QDeclarativeDataBlob *blob) +{ + Q_UNUSED(blob); +} + +/*! +Called if \a blob, which was previously waited for, has completed. + +The default implementation does nothing. +*/ +void QDeclarativeDataBlob::dependencyComplete(QDeclarativeDataBlob *blob) +{ + Q_UNUSED(blob); +} + +/*! +Called when all blobs waited for have completed. This occurs regardless of +whether they are in error, or complete state. + +The default implementation does nothing. +*/ +void QDeclarativeDataBlob::allDependenciesDone() +{ +} + +/*! +Called when the download progress of this blob changes. \a progress goes +from 0 to 1. +*/ +void QDeclarativeDataBlob::downloadProgressChanged(qreal progress) +{ + Q_UNUSED(progress); +} + +void QDeclarativeDataBlob::tryDone() +{ + if (status() != Loading && m_waitingFor.isEmpty() && !m_isDone) { + if (status() != Error) + m_status = Complete; + + m_isDone = true; + done(); + notifyAllWaitingOnMe(); + } +} + +void QDeclarativeDataBlob::cancelAllWaitingFor() +{ + while (m_waitingFor.count()) { + QDeclarativeDataBlob *blob = m_waitingFor.takeLast(); + + Q_ASSERT(blob->m_waitingOnMe.contains(this)); + + blob->m_waitingOnMe.removeOne(this); + + blob->release(); + } +} + +void QDeclarativeDataBlob::notifyAllWaitingOnMe() +{ + while (m_waitingOnMe.count()) { + QDeclarativeDataBlob *blob = m_waitingOnMe.takeLast(); + + Q_ASSERT(blob->m_waitingFor.contains(this)); + + blob->notifyComplete(this); + } +} + +void QDeclarativeDataBlob::notifyComplete(QDeclarativeDataBlob *blob) +{ + Q_ASSERT(m_waitingFor.contains(blob)); + Q_ASSERT(blob->status() == Error || blob->status() == Complete); + + m_inCallback = true; + + if (blob->status() == Error) { + dependencyError(blob); + } else if (blob->status() == Complete) { + dependencyComplete(blob); + } + + m_waitingFor.removeOne(blob); + blob->release(); + + if (!isError() && m_waitingFor.isEmpty()) + allDependenciesDone(); + + m_inCallback = false; + + tryDone(); +} + +/*! +\class QDeclarativeDataLoader +\brief The QDeclarativeDataLoader class abstracts loading files and their dependecies over the network. +\internal + +The QDeclarativeDataLoader class is provided for the exclusive use of the QDeclarativeTypeLoader class. + +Clients create QDeclarativeDataBlob instances and submit them to the QDeclarativeDataLoader class +through the QDeclarativeDataLoader::load() or QDeclarativeDataLoader::loadWithStaticData() methods. +The loader then fetches the data over the network or from the local file system in an efficient way. +QDeclarativeDataBlob is an abstract class, so should always be specialized. + +Once data is received, the QDeclarativeDataBlob::dataReceived() method is invoked on the blob. The +derived class should use this callback to process the received data. Processing of the data can +result in an error being set (QDeclarativeDataBlob::setError()), or one or more dependencies being +created (QDeclarativeDataBlob::addDependency()). Dependencies are other QDeclarativeDataBlob's that +are required before processing can fully complete. + +To complete processing, the QDeclarativeDataBlob::done() callback is invoked. done() is called when +one of these three preconditions are met. + +1. The QDeclarativeDataBlob has no dependencies. +2. The QDeclarativeDataBlob has an error set. +3. All the QDeclarativeDataBlob's dependencies are themselves "done()". + +Thus QDeclarativeDataBlob::done() will always eventually be called, even if the blob has an error set. +*/ + +/*! +Create a new QDeclarativeDataLoader for \a engine. +*/ +QDeclarativeDataLoader::QDeclarativeDataLoader(QDeclarativeEngine *engine) +: m_engine(engine) +{ +} + +/*! \internal */ +QDeclarativeDataLoader::~QDeclarativeDataLoader() +{ + for (NetworkReplies::Iterator iter = m_networkReplies.begin(); iter != m_networkReplies.end(); ++iter) + (*iter)->release(); +} + +/*! +Load the provided \a blob from the network or filesystem. +*/ +void QDeclarativeDataLoader::load(QDeclarativeDataBlob *blob) +{ + Q_ASSERT(blob->status() == QDeclarativeDataBlob::Null); + Q_ASSERT(blob->m_manager == 0); + + blob->m_status = QDeclarativeDataBlob::Loading; + + if (blob->m_url.isEmpty()) { + QDeclarativeError error; + error.setDescription(QLatin1String("Invalid null URL")); + blob->setError(error); + return; + } + + QString lf = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(blob->m_url); + + if (!lf.isEmpty()) { + QFile file(lf); + if (file.open(QFile::ReadOnly)) { + QByteArray data = file.readAll(); + + blob->m_progress = 1.; + blob->downloadProgressChanged(1.); + + setData(blob, data); + } else { + blob->networkError(QNetworkReply::ContentNotFoundError); + } + + } else { + + blob->m_manager = this; + QNetworkReply *reply = m_engine->networkAccessManager()->get(QNetworkRequest(blob->m_url)); + QObject::connect(reply, SIGNAL(downloadProgress(qint64,qint64)), + this, SLOT(networkReplyProgress(qint64,qint64))); + QObject::connect(reply, SIGNAL(finished()), + this, SLOT(networkReplyFinished())); + m_networkReplies.insert(reply, blob); + + blob->addref(); + } +} + +#define DATALOADER_MAXIMUM_REDIRECT_RECURSION 16 + +void QDeclarativeDataLoader::networkReplyFinished() +{ + QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); + reply->deleteLater(); + + QDeclarativeDataBlob *blob = m_networkReplies.take(reply); + + Q_ASSERT(blob); + + blob->m_redirectCount++; + + if (blob->m_redirectCount < DATALOADER_MAXIMUM_REDIRECT_RECURSION) { + QVariant redirect = reply->attribute(QNetworkRequest::RedirectionTargetAttribute); + if (redirect.isValid()) { + QUrl url = reply->url().resolved(redirect.toUrl()); + blob->m_finalUrl = url; + + QNetworkReply *reply = m_engine->networkAccessManager()->get(QNetworkRequest(url)); + QObject::connect(reply, SIGNAL(finished()), this, SLOT(networkReplyFinished())); + m_networkReplies.insert(reply, blob); + return; + } + } + + if (reply->error()) { + blob->networkError(reply->error()); + } else { + QByteArray data = reply->readAll(); + setData(blob, data); + } + + blob->release(); +} + +void QDeclarativeDataLoader::networkReplyProgress(qint64 bytesReceived, qint64 bytesTotal) +{ + QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); + QDeclarativeDataBlob *blob = m_networkReplies.value(reply); + + Q_ASSERT(blob); + + if (bytesTotal != 0) { + blob->m_progress = bytesReceived / bytesTotal; + blob->downloadProgressChanged(blob->m_progress); + } +} + +/*! +Load the provided \a blob with \a data. The blob's URL is not used by the data loader in this case. +*/ +void QDeclarativeDataLoader::loadWithStaticData(QDeclarativeDataBlob *blob, const QByteArray &data) +{ + Q_ASSERT(blob->status() == QDeclarativeDataBlob::Null); + Q_ASSERT(blob->m_manager == 0); + + blob->m_status = QDeclarativeDataBlob::Loading; + + setData(blob, data); +} + +/*! +Return the QDeclarativeEngine associated with this loader +*/ +QDeclarativeEngine *QDeclarativeDataLoader::engine() const +{ + return m_engine; +} + +void QDeclarativeDataLoader::setData(QDeclarativeDataBlob *blob, const QByteArray &data) +{ + blob->m_inCallback = true; + + blob->dataReceived(data); + + if (!blob->isError() && !blob->isWaiting()) + blob->allDependenciesDone(); + + if (blob->status() != QDeclarativeDataBlob::Error) + blob->m_status = QDeclarativeDataBlob::WaitingForDependencies; + + blob->m_inCallback = false; + + blob->tryDone(); +} + +/*! +\class QDeclarativeTypeLoader +*/ +QDeclarativeTypeLoader::QDeclarativeTypeLoader(QDeclarativeEngine *engine) +: QDeclarativeDataLoader(engine) +{ +} + +QDeclarativeTypeLoader::~QDeclarativeTypeLoader() +{ + clearCache(); +} + +/*! +Return a QDeclarativeTypeData for \a url. The QDeclarativeTypeData may be cached. +*/ +QDeclarativeTypeData *QDeclarativeTypeLoader::get(const QUrl &url) +{ + Q_ASSERT(!url.isRelative() && + (QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url).isEmpty() || + !QDir::isRelativePath(QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url)))); + + QDeclarativeTypeData *typeData = m_typeCache.value(url); + + if (!typeData) { + typeData = new QDeclarativeTypeData(url, None, this); + m_typeCache.insert(url, typeData); + QDeclarativeDataLoader::load(typeData); + } + + typeData->addref(); + return typeData; +} + +/*! +Return a QDeclarativeTypeData for \a data with the provided base \a url. The +QDeclarativeTypeData will not be cached. +*/ +QDeclarativeTypeData *QDeclarativeTypeLoader::get(const QByteArray &data, const QUrl &url, Options options) +{ + QDeclarativeTypeData *typeData = new QDeclarativeTypeData(url, options, this); + QDeclarativeDataLoader::loadWithStaticData(typeData, data); + return typeData; +} + +/*! +Return a QDeclarativeScriptData for \a url. The QDeclarativeScriptData may be cached. +*/ +QDeclarativeScriptData *QDeclarativeTypeLoader::getScript(const QUrl &url) +{ + Q_ASSERT(!url.isRelative() && + (QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url).isEmpty() || + !QDir::isRelativePath(QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url)))); + + QDeclarativeScriptData *scriptData = m_scriptCache.value(url); + + if (!scriptData) { + scriptData = new QDeclarativeScriptData(url); + m_scriptCache.insert(url, scriptData); + QDeclarativeDataLoader::load(scriptData); + } + + scriptData->addref(); + return scriptData; +} + +/*! +Return a QDeclarativeQmldirData for \a url. The QDeclarativeQmldirData may be cached. +*/ +QDeclarativeQmldirData *QDeclarativeTypeLoader::getQmldir(const QUrl &url) +{ + Q_ASSERT(!url.isRelative() && + (QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url).isEmpty() || + !QDir::isRelativePath(QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url)))); + + QDeclarativeQmldirData *qmldirData = m_qmldirCache.value(url); + + if (!qmldirData) { + qmldirData = new QDeclarativeQmldirData(url); + m_qmldirCache.insert(url, qmldirData); + QDeclarativeDataLoader::load(qmldirData); + } + + qmldirData->addref(); + return qmldirData; +} + +void QDeclarativeTypeLoader::clearCache() +{ + for (TypeCache::Iterator iter = m_typeCache.begin(); iter != m_typeCache.end(); ++iter) + (*iter)->release(); + for (ScriptCache::Iterator iter = m_scriptCache.begin(); iter != m_scriptCache.end(); ++iter) + (*iter)->release(); + for (QmldirCache::Iterator iter = m_qmldirCache.begin(); iter != m_qmldirCache.end(); ++iter) + (*iter)->release(); + + m_typeCache.clear(); + m_scriptCache.clear(); + m_qmldirCache.clear(); +} + + +QDeclarativeTypeData::QDeclarativeTypeData(const QUrl &url, QDeclarativeTypeLoader::Options options, + QDeclarativeTypeLoader *manager) +: QDeclarativeDataBlob(url, QmlFile), m_options(options), m_typesResolved(false), + m_compiledData(0), m_component(0), m_typeLoader(manager) +{ +} + +QDeclarativeTypeData::~QDeclarativeTypeData() +{ + for (int ii = 0; ii < m_scripts.count(); ++ii) + m_scripts.at(ii).script->release(); + for (int ii = 0; ii < m_qmldirs.count(); ++ii) + m_qmldirs.at(ii)->release(); + for (int ii = 0; ii < m_types.count(); ++ii) + if (m_types.at(ii).typeData) m_types.at(ii).typeData->release(); + if (m_compiledData) + m_compiledData->release(); +} + +QDeclarativeTypeLoader *QDeclarativeTypeData::typeLoader() const +{ + return m_typeLoader; +} + +const QDeclarativeImports &QDeclarativeTypeData::imports() const +{ + return m_imports; +} + +const QDeclarativeScriptParser &QDeclarativeTypeData::parser() const +{ + return scriptParser; +} + +const QList<QDeclarativeTypeData::TypeReference> &QDeclarativeTypeData::resolvedTypes() const +{ + return m_types; +} + +const QList<QDeclarativeTypeData::ScriptReference> &QDeclarativeTypeData::resolvedScripts() const +{ + return m_scripts; +} + +QDeclarativeCompiledData *QDeclarativeTypeData::compiledData() const +{ + if (m_compiledData) + m_compiledData->addref(); + + return m_compiledData; +} + +QDeclarativeComponent *QDeclarativeTypeData::component() const +{ + if (!m_component) { + + if (m_compiledData) { + m_component = new QDeclarativeComponent(typeLoader()->engine(), m_compiledData, -1, -1, 0); + } else { + m_component = new QDeclarativeComponent(typeLoader()->engine()); + QDeclarativeComponentPrivate::get(m_component)->url = finalUrl(); + QDeclarativeComponentPrivate::get(m_component)->state.errors = errors(); + } + + } + + return m_component; +} + +void QDeclarativeTypeData::registerCallback(TypeDataCallback *callback) +{ + Q_ASSERT(!m_callbacks.contains(callback)); + m_callbacks.append(callback); +} + +void QDeclarativeTypeData::unregisterCallback(TypeDataCallback *callback) +{ + Q_ASSERT(m_callbacks.contains(callback)); + m_callbacks.removeOne(callback); + Q_ASSERT(!m_callbacks.contains(callback)); +} + +void QDeclarativeTypeData::done() +{ + addref(); + + // Check all script dependencies for errors + for (int ii = 0; !isError() && ii < m_scripts.count(); ++ii) { + const ScriptReference &script = m_scripts.at(ii); + Q_ASSERT(script.script->isCompleteOrError()); + if (script.script->isError()) { + QList<QDeclarativeError> errors = script.script->errors(); + QDeclarativeError error; + error.setUrl(finalUrl()); + error.setLine(script.location.line); + error.setColumn(script.location.column); + error.setDescription(typeLoader()->tr("Script %1 unavailable").arg(script.script->url().toString())); + errors.prepend(error); + setError(errors); + } + } + + // Check all type dependencies for errors + for (int ii = 0; !isError() && ii < m_types.count(); ++ii) { + const TypeReference &type = m_types.at(ii); + Q_ASSERT(!type.typeData || type.typeData->isCompleteOrError()); + if (type.typeData && type.typeData->isError()) { + QString typeName = scriptParser.referencedTypes().at(ii)->name; + + QList<QDeclarativeError> errors = type.typeData->errors(); + QDeclarativeError error; + error.setUrl(finalUrl()); + error.setLine(type.location.line); + error.setColumn(type.location.column); + error.setDescription(typeLoader()->tr("Type %1 unavailable").arg(typeName)); + errors.prepend(error); + setError(errors); + } + } + + // Compile component + if (!isError()) + compile(); + + if (!(m_options & QDeclarativeTypeLoader::PreserveParser)) + scriptParser.clear(); + + // Notify callbacks + while (!m_callbacks.isEmpty()) { + TypeDataCallback *callback = m_callbacks.takeFirst(); + callback->typeDataReady(this); + } + + release(); +} + +void QDeclarativeTypeData::dataReceived(const QByteArray &data) +{ + if (!scriptParser.parse(data, finalUrl())) { + setError(scriptParser.errors()); + return; + } + + m_imports.setBaseUrl(finalUrl()); + + foreach (const QDeclarativeScriptParser::Import &import, scriptParser.imports()) { + if (import.type == QDeclarativeScriptParser::Import::File && import.qualifier.isEmpty()) { + QUrl importUrl = finalUrl().resolved(QUrl(import.uri + QLatin1String("/qmldir"))); + if (QDeclarativeEnginePrivate::urlToLocalFileOrQrc(importUrl).isEmpty()) { + QDeclarativeQmldirData *data = typeLoader()->getQmldir(importUrl); + addDependency(data); + m_qmldirs << data; + } + } else if (import.type == QDeclarativeScriptParser::Import::Script) { + QUrl scriptUrl = finalUrl().resolved(QUrl(import.uri)); + QDeclarativeScriptData *data = typeLoader()->getScript(scriptUrl); + addDependency(data); + + ScriptReference ref; + ref.location = import.location.start; + ref.qualifier = import.qualifier; + ref.script = data; + m_scripts << ref; + + } + } + + if (!finalUrl().scheme().isEmpty()) { + QUrl importUrl = finalUrl().resolved(QUrl(QLatin1String("qmldir"))); + if (QDeclarativeEnginePrivate::urlToLocalFileOrQrc(importUrl).isEmpty()) { + QDeclarativeQmldirData *data = typeLoader()->getQmldir(importUrl); + addDependency(data); + m_qmldirs << data; + } + } +} + +void QDeclarativeTypeData::allDependenciesDone() +{ + if (!m_typesResolved) { + resolveTypes(); + m_typesResolved = true; + } +} + +void QDeclarativeTypeData::downloadProgressChanged(qreal p) +{ + for (int ii = 0; ii < m_callbacks.count(); ++ii) { + TypeDataCallback *callback = m_callbacks.at(ii); + callback->typeDataProgress(this, p); + } +} + +void QDeclarativeTypeData::compile() +{ + Q_ASSERT(m_compiledData == 0); + + m_compiledData = new QDeclarativeCompiledData(typeLoader()->engine()); + m_compiledData->url = m_imports.baseUrl(); + m_compiledData->name = m_compiledData->url.toString(); + + QDeclarativeCompiler compiler; + if (!compiler.compile(typeLoader()->engine(), this, m_compiledData)) { + setError(compiler.errors()); + m_compiledData->release(); + m_compiledData = 0; + } +} + +void QDeclarativeTypeData::resolveTypes() +{ + QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(m_typeLoader->engine()); + QDeclarativeImportDatabase *importDatabase = &ep->importDatabase; + + // For local urls, add an implicit import "." as first (most overridden) lookup. + // This will also trigger the loading of the qmldir and the import of any native + // types from available plugins. + if (QDeclarativeQmldirData *qmldir = qmldirForUrl(finalUrl().resolved(QUrl(QLatin1String("./qmldir"))))) { + m_imports.addImport(importDatabase, QLatin1String("."), + QString(), -1, -1, QDeclarativeScriptParser::Import::File, + qmldir->dirComponents(), 0); + } else { + m_imports.addImport(importDatabase, QLatin1String("."), + QString(), -1, -1, QDeclarativeScriptParser::Import::File, + QDeclarativeDirComponents(), 0); + } + + foreach (const QDeclarativeScriptParser::Import &import, scriptParser.imports()) { + QDeclarativeDirComponents qmldircomponentsnetwork; + if (import.type == QDeclarativeScriptParser::Import::Script) + continue; + + if (import.type == QDeclarativeScriptParser::Import::File && import.qualifier.isEmpty()) { + QUrl qmldirUrl = finalUrl().resolved(QUrl(import.uri + QLatin1String("/qmldir"))); + if (QDeclarativeQmldirData *qmldir = qmldirForUrl(qmldirUrl)) + qmldircomponentsnetwork = qmldir->dirComponents(); + } + + int vmaj = -1; + int vmin = -1; + + if (!import.version.isEmpty()) { + int dot = import.version.indexOf(QLatin1Char('.')); + if (dot < 0) { + vmaj = import.version.toInt(); + vmin = 0; + } else { + vmaj = import.version.left(dot).toInt(); + vmin = import.version.mid(dot+1).toInt(); + } + } + + QString errorString; + if (!m_imports.addImport(importDatabase, import.uri, import.qualifier, + vmaj, vmin, import.type, qmldircomponentsnetwork, &errorString)) { + QDeclarativeError error; + error.setUrl(m_imports.baseUrl()); + error.setDescription(errorString); + error.setLine(import.location.start.line); + error.setColumn(import.location.start.column); + + setError(error); + return; + } + } + + foreach (QDeclarativeScriptParser::TypeReference *parserRef, scriptParser.referencedTypes()) { + QByteArray typeName = parserRef->name.toUtf8(); + + TypeReference ref; + + QUrl url; + int majorVersion; + int minorVersion; + QDeclarativeImportedNamespace *typeNamespace = 0; + QString errorString; + + if (!m_imports.resolveType(typeName, &ref.type, &url, &majorVersion, &minorVersion, + &typeNamespace, &errorString) || typeNamespace) { + // Known to not be a type: + // - known to be a namespace (Namespace {}) + // - type with unknown namespace (UnknownNamespace.SomeType {}) + QDeclarativeError error; + error.setUrl(m_imports.baseUrl()); + QString userTypeName = parserRef->name; + userTypeName.replace(QLatin1Char('/'),QLatin1Char('.')); + if (typeNamespace) + error.setDescription(typeLoader()->tr("Namespace %1 cannot be used as a type").arg(userTypeName)); + else + error.setDescription(typeLoader()->tr("%1 %2").arg(userTypeName).arg(errorString)); + + if (!parserRef->refObjects.isEmpty()) { + QDeclarativeParser::Object *obj = parserRef->refObjects.first(); + error.setLine(obj->location.start.line); + error.setColumn(obj->location.start.column); + } + + setError(error); + return; + } + + if (ref.type) { + foreach (QDeclarativeParser::Object *obj, parserRef->refObjects) { + // store namespace for DOM + obj->majorVersion = majorVersion; + obj->minorVersion = minorVersion; + } + } else { + ref.typeData = typeLoader()->get(url); + addDependency(ref.typeData); + } + + if (parserRef->refObjects.count()) + ref.location = parserRef->refObjects.first()->location.start; + + m_types << ref; + } +} + +QDeclarativeQmldirData *QDeclarativeTypeData::qmldirForUrl(const QUrl &url) +{ + for (int ii = 0; ii < m_qmldirs.count(); ++ii) { + if (m_qmldirs.at(ii)->url() == url) + return m_qmldirs.at(ii); + } + return 0; +} + +QDeclarativeScriptData::QDeclarativeScriptData(const QUrl &url) +: QDeclarativeDataBlob(url, JavaScriptFile), m_pragmas(QDeclarativeParser::Object::ScriptBlock::None) +{ +} + +QDeclarativeParser::Object::ScriptBlock::Pragmas QDeclarativeScriptData::pragmas() const +{ + return m_pragmas; +} + +QString QDeclarativeScriptData::scriptSource() const +{ + return m_source; +} + +void QDeclarativeScriptData::dataReceived(const QByteArray &data) +{ + m_source = QString::fromUtf8(data); + m_pragmas = QDeclarativeScriptParser::extractPragmas(m_source); +} + +QDeclarativeQmldirData::QDeclarativeQmldirData(const QUrl &url) +: QDeclarativeDataBlob(url, QmldirFile) +{ +} + +const QDeclarativeDirComponents &QDeclarativeQmldirData::dirComponents() const +{ + return m_components; +} + +void QDeclarativeQmldirData::dataReceived(const QByteArray &data) +{ + QDeclarativeDirParser parser; + parser.setSource(QString::fromUtf8(data)); + parser.parse(); + m_components = parser.components(); +} + +QT_END_NAMESPACE + diff --git a/src/declarative/qml/qdeclarativetypeloader_p.h b/src/declarative/qml/qdeclarativetypeloader_p.h new file mode 100644 index 0000000..7381f28 --- /dev/null +++ b/src/declarative/qml/qdeclarativetypeloader_p.h @@ -0,0 +1,321 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (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 Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVETYPELOADER_P_H +#define QDECLARATIVETYPELOADER_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 <QtNetwork/qnetworkreply.h> +#include <QtDeclarative/qdeclarativeerror.h> +#include <QtDeclarative/qdeclarativeengine.h> +#include <private/qdeclarativescriptparser_p.h> +#include <private/qdeclarativedirparser_p.h> +#include <private/qdeclarativeimport_p.h> + +QT_BEGIN_NAMESPACE + +class QDeclarativeScriptData; +class QDeclarativeQmldirData; +class QDeclarativeTypeLoader; +class QDeclarativeCompiledData; +class QDeclarativeComponentPrivate; +class QDeclarativeTypeData; +class QDeclarativeDataLoader; + +class Q_AUTOTEST_EXPORT QDeclarativeDataBlob : public QDeclarativeRefCount +{ +public: + enum Status { + Null, // Prior to QDeclarativeDataLoader::load() + Loading, // Prior to data being received and dataReceived() being called + WaitingForDependencies, // While there are outstanding addDependency()s + Complete, // Finished + Error, // Error + }; + + enum Type { + QmlFile, + JavaScriptFile, + QmldirFile + }; + + QDeclarativeDataBlob(const QUrl &, Type); + virtual ~QDeclarativeDataBlob(); + + Type type() const; + + Status status() const; + bool isNull() const; + bool isLoading() const; + bool isWaiting() const; + bool isComplete() const; + bool isError() const; + bool isCompleteOrError() const; + + qreal progress() const; + + QUrl url() const; + QUrl finalUrl() const; + + QList<QDeclarativeError> errors() const; + + void setError(const QDeclarativeError &); + void setError(const QList<QDeclarativeError> &errors); + + void addDependency(QDeclarativeDataBlob *); + +protected: + virtual void dataReceived(const QByteArray &) = 0; + + virtual void done(); + virtual void networkError(QNetworkReply::NetworkError); + + virtual void dependencyError(QDeclarativeDataBlob *); + virtual void dependencyComplete(QDeclarativeDataBlob *); + virtual void allDependenciesDone(); + + virtual void downloadProgressChanged(qreal); + +private: + friend class QDeclarativeDataLoader; + void tryDone(); + void cancelAllWaitingFor(); + void notifyAllWaitingOnMe(); + void notifyComplete(QDeclarativeDataBlob *); + + Type m_type; + Status m_status; + qreal m_progress; + + QUrl m_url; + QUrl m_finalUrl; + + // List of QDeclarativeDataBlob's that are waiting for me to complete. + QList<QDeclarativeDataBlob *> m_waitingOnMe; + + // List of QDeclarativeDataBlob's that I am waiting for to complete. + QList<QDeclarativeDataBlob *> m_waitingFor; + + // Manager that is currently fetching data for me + QDeclarativeDataLoader *m_manager; + int m_redirectCount:30; + bool m_inCallback:1; + bool m_isDone:1; + + QList<QDeclarativeError> m_errors; +}; + +class Q_AUTOTEST_EXPORT QDeclarativeDataLoader : public QObject +{ + Q_OBJECT +public: + QDeclarativeDataLoader(QDeclarativeEngine *); + ~QDeclarativeDataLoader(); + + void load(QDeclarativeDataBlob *); + void loadWithStaticData(QDeclarativeDataBlob *, const QByteArray &); + + QDeclarativeEngine *engine() const; + +private slots: + void networkReplyFinished(); + void networkReplyProgress(qint64,qint64); + +private: + void setData(QDeclarativeDataBlob *, const QByteArray &); + + QDeclarativeEngine *m_engine; + typedef QHash<QNetworkReply *, QDeclarativeDataBlob *> NetworkReplies; + NetworkReplies m_networkReplies; +}; + + +class Q_AUTOTEST_EXPORT QDeclarativeTypeLoader : public QDeclarativeDataLoader +{ + Q_OBJECT +public: + QDeclarativeTypeLoader(QDeclarativeEngine *); + ~QDeclarativeTypeLoader(); + + enum Option { + None, + PreserveParser + }; + Q_DECLARE_FLAGS(Options, Option) + + QDeclarativeTypeData *get(const QUrl &url); + QDeclarativeTypeData *get(const QByteArray &, const QUrl &url, Options = None); + void clearCache(); + + QDeclarativeScriptData *getScript(const QUrl &); + QDeclarativeQmldirData *getQmldir(const QUrl &); +private: + typedef QHash<QUrl, QDeclarativeTypeData *> TypeCache; + typedef QHash<QUrl, QDeclarativeScriptData *> ScriptCache; + typedef QHash<QUrl, QDeclarativeQmldirData *> QmldirCache; + + TypeCache m_typeCache; + ScriptCache m_scriptCache; + QmldirCache m_qmldirCache; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QDeclarativeTypeLoader::Options) + +class Q_AUTOTEST_EXPORT QDeclarativeTypeData : public QDeclarativeDataBlob +{ +public: + struct TypeReference + { + TypeReference() : type(0), typeData(0) {} + + QDeclarativeParser::Location location; + QDeclarativeType *type; + QDeclarativeTypeData *typeData; + }; + + struct ScriptReference + { + ScriptReference() : script(0) {} + + QDeclarativeParser::Location location; + QString qualifier; + QDeclarativeScriptData *script; + }; + + QDeclarativeTypeData(const QUrl &, QDeclarativeTypeLoader::Options, QDeclarativeTypeLoader *); + ~QDeclarativeTypeData(); + + QDeclarativeTypeLoader *typeLoader() const; + + const QDeclarativeImports &imports() const; + const QDeclarativeScriptParser &parser() const; + + const QList<TypeReference> &resolvedTypes() const; + const QList<ScriptReference> &resolvedScripts() const; + + QDeclarativeCompiledData *compiledData() const; + QDeclarativeComponent *component() const; + + // Used by QDeclarativeComponent to get notifications + struct TypeDataCallback { + ~TypeDataCallback() {} + virtual void typeDataProgress(QDeclarativeTypeData *, qreal) {} + virtual void typeDataReady(QDeclarativeTypeData *) {} + }; + void registerCallback(TypeDataCallback *); + void unregisterCallback(TypeDataCallback *); + +protected: + virtual void done(); + virtual void dataReceived(const QByteArray &); + virtual void allDependenciesDone(); + virtual void downloadProgressChanged(qreal); + +private: + void resolveTypes(); + void compile(); + + QDeclarativeTypeLoader::Options m_options; + + QDeclarativeQmldirData *qmldirForUrl(const QUrl &); + + QDeclarativeScriptParser scriptParser; + QDeclarativeImports m_imports; + + QList<ScriptReference> m_scripts; + QList<QDeclarativeQmldirData *> m_qmldirs; + + QList<TypeReference> m_types; + bool m_typesResolved:1; + + QDeclarativeCompiledData *m_compiledData; + mutable QDeclarativeComponent *m_component; + + QList<TypeDataCallback *> m_callbacks; + + QDeclarativeTypeLoader *m_typeLoader; +}; + +class Q_AUTOTEST_EXPORT QDeclarativeScriptData : public QDeclarativeDataBlob +{ +public: + QDeclarativeScriptData(const QUrl &); + + QDeclarativeParser::Object::ScriptBlock::Pragmas pragmas() const; + QString scriptSource() const; + +protected: + virtual void dataReceived(const QByteArray &); + +private: + QDeclarativeParser::Object::ScriptBlock::Pragmas m_pragmas; + QString m_source; +}; + +class Q_AUTOTEST_EXPORT QDeclarativeQmldirData : public QDeclarativeDataBlob +{ +public: + QDeclarativeQmldirData(const QUrl &); + + const QDeclarativeDirComponents &dirComponents() const; + +protected: + virtual void dataReceived(const QByteArray &); + +private: + QDeclarativeDirComponents m_components; + +}; + +QT_END_NAMESPACE + +#endif // QDECLARATIVETYPELOADER_P_H diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri index 12f9794..687ff52 100644 --- a/src/declarative/qml/qml.pri +++ b/src/declarative/qml/qml.pri @@ -24,7 +24,7 @@ SOURCES += \ $$PWD/qdeclarativestringconverters.cpp \ $$PWD/qdeclarativeclassfactory.cpp \ $$PWD/qdeclarativeparserstatus.cpp \ - $$PWD/qdeclarativecompositetypemanager.cpp \ + $$PWD/qdeclarativetypeloader.cpp \ $$PWD/qdeclarativeinfo.cpp \ $$PWD/qdeclarativeerror.cpp \ $$PWD/qdeclarativescriptparser.cpp \ @@ -94,8 +94,7 @@ HEADERS += \ $$PWD/qdeclarativeproperty_p.h \ $$PWD/qdeclarativecontext_p.h \ $$PWD/qdeclarativeinclude_p.h \ - $$PWD/qdeclarativecompositetypedata_p.h \ - $$PWD/qdeclarativecompositetypemanager_p.h \ + $$PWD/qdeclarativetypeloader_p.h \ $$PWD/qdeclarativelist.h \ $$PWD/qdeclarativelist_p.h \ $$PWD/qdeclarativedata_p.h \ diff --git a/tests/auto/declarative/qdeclarativebehaviors/data/qtbug12295.qml b/tests/auto/declarative/qdeclarativebehaviors/data/qtbug12295.qml index 804559c..d41add3 100644 --- a/tests/auto/declarative/qdeclarativebehaviors/data/qtbug12295.qml +++ b/tests/auto/declarative/qdeclarativebehaviors/data/qtbug12295.qml @@ -11,7 +11,7 @@ Rectangle { width: 100 height: 100 Behavior on x { - NumberAnimation {} + NumberAnimation { duration: 500 } } } } diff --git a/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp b/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp index 896d69e..d4d8bf6 100644 --- a/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp +++ b/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp @@ -655,6 +655,15 @@ void tst_QDeclarativeGridView::currentIndex() gridview->setFlow(QDeclarativeGridView::TopToBottom); + qApp->setActiveWindow(canvas); +#ifdef Q_WS_X11 + // to be safe and avoid failing setFocus with window managers + qt_x11_wait_for_window_manager(canvas); +#endif + QTRY_VERIFY(canvas->hasFocus()); + QTRY_VERIFY(canvas->scene()->hasFocus()); + qApp->processEvents(); + QTest::keyClick(canvas, Qt::Key_Right); QCOMPARE(gridview->currentIndex(), 5); diff --git a/tests/auto/declarative/qdeclarativeimageprovider/tst_qdeclarativeimageprovider.cpp b/tests/auto/declarative/qdeclarativeimageprovider/tst_qdeclarativeimageprovider.cpp index 6d5a357..d0afc8a 100644 --- a/tests/auto/declarative/qdeclarativeimageprovider/tst_qdeclarativeimageprovider.cpp +++ b/tests/auto/declarative/qdeclarativeimageprovider/tst_qdeclarativeimageprovider.cpp @@ -389,6 +389,7 @@ void tst_qdeclarativeimageprovider::threadTest() } provider->ok = true; provider->cond.wakeAll(); + QTest::qWait(250); foreach(QDeclarativeImage *img, images) { TRY_WAIT(img->status() == QDeclarativeImage::Ready); } diff --git a/tests/auto/declarative/qdeclarativelanguage/data/DontDoubleCallClassBeginItem.qml b/tests/auto/declarative/qdeclarativelanguage/data/DontDoubleCallClassBeginItem.qml new file mode 100644 index 0000000..1f8eac8 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/DontDoubleCallClassBeginItem.qml @@ -0,0 +1,4 @@ +import Test 1.0 + +MyParserStatus { +} diff --git a/tests/auto/declarative/qdeclarativelanguage/data/dontDoubleCallClassBegin.qml b/tests/auto/declarative/qdeclarativelanguage/data/dontDoubleCallClassBegin.qml new file mode 100644 index 0000000..df048cc --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/dontDoubleCallClassBegin.qml @@ -0,0 +1,5 @@ +import Qt 4.7 + +Item { + property QtObject object: DontDoubleCallClassBeginItem {} +} diff --git a/tests/auto/declarative/qdeclarativelanguage/data/nestedErrors.errors.txt b/tests/auto/declarative/qdeclarativelanguage/data/nestedErrors.errors.txt index 6e11786..53e752b 100644 --- a/tests/auto/declarative/qdeclarativelanguage/data/nestedErrors.errors.txt +++ b/tests/auto/declarative/qdeclarativelanguage/data/nestedErrors.errors.txt @@ -1,2 +1,2 @@ -4:5:Unable to create type NestedErrorsType +4:5:Type NestedErrorsType unavailable 4:8:Invalid property assignment: number expected diff --git a/tests/auto/declarative/qdeclarativelanguage/testtypes.cpp b/tests/auto/declarative/qdeclarativelanguage/testtypes.cpp index 5d87404..20cd976 100644 --- a/tests/auto/declarative/qdeclarativelanguage/testtypes.cpp +++ b/tests/auto/declarative/qdeclarativelanguage/testtypes.cpp @@ -50,6 +50,7 @@ void registerTypes() qmlRegisterType<MyDotPropertyObject>("Test",1,0,"MyDotPropertyObject"); qmlRegisterType<MyNamespace::MyNamespacedType>("Test",1,0,"MyNamespacedType"); qmlRegisterType<MyNamespace::MySecondNamespacedType>("Test",1,0,"MySecondNamespacedType"); + qmlRegisterType<MyParserStatus>("Test",1,0,"MyParserStatus"); qmlRegisterType<MyGroupedObject>(); qmlRegisterCustomType<MyCustomParserType>("Test", 1, 0, "MyCustomParserType", new MyCustomParserTypeParser); diff --git a/tests/auto/declarative/qdeclarativelanguage/testtypes.h b/tests/auto/declarative/qdeclarativelanguage/testtypes.h index acbe219..19790f1 100644 --- a/tests/auto/declarative/qdeclarativelanguage/testtypes.h +++ b/tests/auto/declarative/qdeclarativelanguage/testtypes.h @@ -170,7 +170,6 @@ private: QML_DECLARE_TYPE(MyQmlObject) QML_DECLARE_TYPEINFO(MyQmlObject, QML_HAS_ATTACHED_PROPERTIES) - class MyGroupedObject : public QObject { Q_OBJECT @@ -576,6 +575,22 @@ public: void setCustomData(QObject *, const QByteArray &) {} }; +class MyParserStatus : public QObject, public QDeclarativeParserStatus +{ + Q_OBJECT +public: + MyParserStatus() : m_cbc(0), m_ccc(0) {} + + int classBeginCount() const { return m_cbc; } + int componentCompleteCount() const { return m_ccc; } + + virtual void classBegin() { m_cbc++; } + virtual void componentComplete() { m_ccc++; } +private: + int m_cbc; + int m_ccc; +}; + void registerTypes(); #endif // TESTTYPES_H diff --git a/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp b/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp index fcdf926..b43fbf4 100644 --- a/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp +++ b/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp @@ -126,6 +126,7 @@ private slots: void scriptString(); void defaultPropertyListOrder(); void declaredPropertyValues(); + void dontDoubleCallClassBegin(); void basicRemote_data(); void basicRemote(); @@ -1192,6 +1193,20 @@ void tst_qdeclarativelanguage::declaredPropertyValues() VERIFY_ERRORS(0); } +void tst_qdeclarativelanguage::dontDoubleCallClassBegin() +{ + QDeclarativeComponent component(&engine, TEST_FILE("dontDoubleCallClassBegin.qml")); + QObject *o = component.create(); + QVERIFY(o); + + MyParserStatus *o2 = qobject_cast<MyParserStatus *>(qvariant_cast<QObject *>(o->property("object"))); + QVERIFY(o2); + QCOMPARE(o2->classBeginCount(), 1); + QCOMPARE(o2->componentCompleteCount(), 1); + + delete o; +} + // Check that first child of qml is of given type. Empty type insists on error. void tst_qdeclarativelanguage::testType(const QString& qml, const QString& type, const QString& expectederror) { diff --git a/tests/auto/declarative/qdeclarativelistview/data/listviewtest.qml b/tests/auto/declarative/qdeclarativelistview/data/listviewtest.qml index 3b2db5e..d5d3365 100644 --- a/tests/auto/declarative/qdeclarativelistview/data/listviewtest.qml +++ b/tests/auto/declarative/qdeclarativelistview/data/listviewtest.qml @@ -4,6 +4,12 @@ Rectangle { width: 240 height: 320 color: "#ffffff" + + property real hr: list.visibleArea.heightRatio + function heightRatio() { + return list.visibleArea.heightRatio + } + function checkProperties() { testObject.error = false; if (list.model != testModel) { diff --git a/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp b/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp index bf4754d..377a9e5 100644 --- a/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp +++ b/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp @@ -98,6 +98,7 @@ private slots: void manualHighlight(); void QTBUG_11105(); void footer(); + void resizeView(); private: template <class T> void items(); @@ -1591,6 +1592,48 @@ void tst_QDeclarativeListView::footer() QTRY_COMPARE(footer->y(), 0.0); } +void tst_QDeclarativeListView::resizeView() +{ + QDeclarativeView *canvas = createView(); + + TestModel model; + for (int i = 0; i < 40; i++) + model.addItem("Item" + QString::number(i), ""); + + QDeclarativeContext *ctxt = canvas->rootContext(); + ctxt->setContextProperty("testModel", &model); + + TestObject *testObject = new TestObject; + ctxt->setContextProperty("testObject", testObject); + + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/listviewtest.qml")); + qApp->processEvents(); + + QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list"); + QTRY_VERIFY(listview != 0); + + QDeclarativeItem *contentItem = listview->contentItem(); + QTRY_VERIFY(contentItem != 0); + + // Confirm items positioned correctly + int itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count(); + for (int i = 0; i < model.count() && i < itemCount; ++i) { + QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i); + if (!item) qWarning() << "Item" << i << "not found"; + QTRY_VERIFY(item); + QTRY_COMPARE(item->y(), i*20.); + } + + QVariant heightRatio; + QMetaObject::invokeMethod(canvas->rootObject(), "heightRatio", Q_RETURN_ARG(QVariant, heightRatio)); + QCOMPARE(heightRatio.toReal(), 0.4); + + listview->setHeight(200); + + QMetaObject::invokeMethod(canvas->rootObject(), "heightRatio", Q_RETURN_ARG(QVariant, heightRatio)); + QCOMPARE(heightRatio.toReal(), 0.25); +} + void tst_QDeclarativeListView::qListModelInterface_items() { items<TestModel>(); diff --git a/tests/auto/declarative/qdeclarativeloader/tst_qdeclarativeloader.cpp b/tests/auto/declarative/qdeclarativeloader/tst_qdeclarativeloader.cpp index b0b7a3b..3baf848 100644 --- a/tests/auto/declarative/qdeclarativeloader/tst_qdeclarativeloader.cpp +++ b/tests/auto/declarative/qdeclarativeloader/tst_qdeclarativeloader.cpp @@ -146,7 +146,7 @@ void tst_QDeclarativeLoader::component() void tst_QDeclarativeLoader::invalidUrl() { - QTest::ignoreMessage(QtWarningMsg, QString("<Unknown File>: File error for URL " + QUrl::fromLocalFile(SRCDIR "/data/IDontExist.qml").toString()).toUtf8().constData()); + QTest::ignoreMessage(QtWarningMsg, QString(QUrl::fromLocalFile(SRCDIR "/data/IDontExist.qml").toString() + ": File not found").toUtf8().constData()); QDeclarativeComponent component(&engine); component.setData(QByteArray("import Qt 4.7\nLoader { source: \"IDontExist.qml\" }"), TEST_FILE("")); @@ -508,7 +508,7 @@ void tst_QDeclarativeLoader::failNetworkRequest() QVERIFY(server.isValid()); server.serveDirectory(SRCDIR "/data"); - QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: Network error for URL http://127.0.0.1:14450/IDontExist.qml"); + QTest::ignoreMessage(QtWarningMsg, "http://127.0.0.1:14450/IDontExist.qml: File not found"); QDeclarativeComponent component(&engine); component.setData(QByteArray("import Qt 4.7\nLoader { property int did_load: 123; source: \"http://127.0.0.1:14450/IDontExist.qml\"; onLoaded: did_load=456 }"), QUrl::fromLocalFile("http://127.0.0.1:14450/dummy.qml")); diff --git a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp index 56a3121..84f4230 100644 --- a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp +++ b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp @@ -777,7 +777,7 @@ void tst_qdeclarativetextedit::delegateLoading_data() // import installed QTest::newRow("pass") << "cursorHttpTestPass.qml" << ""; - QTest::newRow("fail1") << "cursorHttpTestFail1.qml" << "<Unknown File>: Network error for URL http://localhost:42332/FailItem.qml "; + QTest::newRow("fail1") << "cursorHttpTestFail1.qml" << "http://localhost:42332/FailItem.qml: Remote host closed the connection "; QTest::newRow("fail2") << "cursorHttpTestFail2.qml" << "http://localhost:42332/ErrItem.qml:4:5: Fungus is not a type "; } diff --git a/tests/auto/declarative/qdeclarativevisualdatamodel/data/datalist.qml b/tests/auto/declarative/qdeclarativevisualdatamodel/data/datalist.qml index a798f77..c5e945a 100644 --- a/tests/auto/declarative/qdeclarativevisualdatamodel/data/datalist.qml +++ b/tests/auto/declarative/qdeclarativevisualdatamodel/data/datalist.qml @@ -4,12 +4,16 @@ ListView { width: 100 height: 100 anchors.fill: parent - model: myModel - delegate: Component { - Rectangle { - height: 25 - width: 100 - Text { objectName: "display"; text: display } + model: VisualDataModel { + id: visualModel + objectName: "visualModel" + model: myModel + delegate: Component { + Rectangle { + height: 25 + width: 100 + Text { objectName: "display"; text: display } + } } } } diff --git a/tests/auto/declarative/qdeclarativevisualdatamodel/tst_qdeclarativevisualdatamodel.cpp b/tests/auto/declarative/qdeclarativevisualdatamodel/tst_qdeclarativevisualdatamodel.cpp index 3cd786f..95ef4fc 100644 --- a/tests/auto/declarative/qdeclarativevisualdatamodel/tst_qdeclarativevisualdatamodel.cpp +++ b/tests/auto/declarative/qdeclarativevisualdatamodel/tst_qdeclarativevisualdatamodel.cpp @@ -84,6 +84,7 @@ public: private slots: void rootIndex(); void updateLayout(); + void childChanged(); void objectListModel(); private: @@ -174,22 +175,82 @@ void tst_qdeclarativevisualdatamodel::updateLayout() QVERIFY(contentItem != 0); QDeclarativeText *name = findItem<QDeclarativeText>(contentItem, "display", 0); + QVERIFY(name); QCOMPARE(name->text(), QString("Row 1 Item")); name = findItem<QDeclarativeText>(contentItem, "display", 1); + QVERIFY(name); QCOMPARE(name->text(), QString("Row 2 Item")); name = findItem<QDeclarativeText>(contentItem, "display", 2); + QVERIFY(name); QCOMPARE(name->text(), QString("Row 3 Item")); model.invisibleRootItem()->sortChildren(0, Qt::DescendingOrder); name = findItem<QDeclarativeText>(contentItem, "display", 0); + QVERIFY(name); QCOMPARE(name->text(), QString("Row 3 Item")); name = findItem<QDeclarativeText>(contentItem, "display", 1); + QVERIFY(name); QCOMPARE(name->text(), QString("Row 2 Item")); name = findItem<QDeclarativeText>(contentItem, "display", 2); + QVERIFY(name); QCOMPARE(name->text(), QString("Row 1 Item")); } +void tst_qdeclarativevisualdatamodel::childChanged() +{ + QDeclarativeView view; + + QStandardItemModel model; + initStandardTreeModel(&model); + + view.rootContext()->setContextProperty("myModel", &model); + + view.setSource(QUrl::fromLocalFile(SRCDIR "/data/datalist.qml")); + + QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(view.rootObject()); + QVERIFY(listview != 0); + + QDeclarativeItem *contentItem = listview->contentItem(); + QVERIFY(contentItem != 0); + + QDeclarativeVisualDataModel *vdm = listview->findChild<QDeclarativeVisualDataModel*>("visualModel"); + vdm->setRootIndex(QVariant::fromValue(model.indexFromItem(model.item(1,0)))); + + QDeclarativeText *name = findItem<QDeclarativeText>(contentItem, "display", 0); + QVERIFY(name); + QCOMPARE(name->text(), QString("Row 2 Child Item")); + + model.item(1,0)->child(0,0)->setText("Row 2 updated child"); + + name = findItem<QDeclarativeText>(contentItem, "display", 0); + QVERIFY(name); + QCOMPARE(name->text(), QString("Row 2 updated child")); + + model.item(1,0)->appendRow(new QStandardItem(QLatin1String("Row 2 Child Item 2"))); + QTest::qWait(300); + + name = findItem<QDeclarativeText>(contentItem, "display", 1); + QVERIFY(name != 0); + QCOMPARE(name->text(), QString("Row 2 Child Item 2")); + + model.item(1,0)->takeRow(1); + name = findItem<QDeclarativeText>(contentItem, "display", 1); + QVERIFY(name == 0); + + vdm->setRootIndex(QVariant::fromValue(QModelIndex())); + QTest::qWait(300); + name = findItem<QDeclarativeText>(contentItem, "display", 0); + QVERIFY(name); + QCOMPARE(name->text(), QString("Row 1 Item")); + name = findItem<QDeclarativeText>(contentItem, "display", 1); + QVERIFY(name); + QCOMPARE(name->text(), QString("Row 2 Item")); + name = findItem<QDeclarativeText>(contentItem, "display", 2); + QVERIFY(name); + QCOMPARE(name->text(), QString("Row 3 Item")); +} + void tst_qdeclarativevisualdatamodel::objectListModel() { QDeclarativeView view; diff --git a/tools/qml/qml.pro b/tools/qml/qml.pro index d794005..3927dd6 100644 --- a/tools/qml/qml.pro +++ b/tools/qml/qml.pro @@ -34,7 +34,7 @@ maemo5 { } symbian { TARGET.UID3 = 0x20021317 - include($$QT_SOURCE_TREE/examples/symbianpkgrules.pri) + include($$QT_SOURCE_TREE/demos/symbianpkgrules.pri) TARGET.EPOCHEAPSIZE = 0x20000 0x4000000 TARGET.CAPABILITY = NetworkServices ReadUserData !contains(S60_VERSION, 3.1):!contains(S60_VERSION, 3.2) { |