From 2f1726c4e10a6fbafb4953d68946d5501f5e0c8c Mon Sep 17 00:00:00 2001 From: Joona Petrell Date: Fri, 29 Oct 2010 11:40:39 +1000 Subject: Fix zooming in declarative webbrowser demo Task-number: Reviewed-by: Martin Jones --- demos/declarative/webbrowser/content/FlickableWebView.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demos/declarative/webbrowser/content/FlickableWebView.qml b/demos/declarative/webbrowser/content/FlickableWebView.qml index 6f4e09c..a82a151 100644 --- a/demos/declarative/webbrowser/content/FlickableWebView.qml +++ b/demos/declarative/webbrowser/content/FlickableWebView.qml @@ -128,7 +128,7 @@ Flickable { if (!heuristicZoom(clickX,clickY,2.5)) { var zf = flickable.width / contentsSize.width if (zf >= contentsScale) - zf = 2.0/zoomFactor // zoom in (else zooming out) + zf = 2.0*contentsScale // zoom in (else zooming out) doZoom(zf,clickX*zf,clickY*zf) } } -- cgit v0.12 From deea8d2b324ca98d48c931c6d3a14ec197388f50 Mon Sep 17 00:00:00 2001 From: Joona Petrell Date: Fri, 29 Oct 2010 13:05:16 +1000 Subject: Suppress current item null warnings when running Browser.qml Task-number: Reviewed-by: Martin Jones --- tools/qml/browser/Browser.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/qml/browser/Browser.qml b/tools/qml/browser/Browser.qml index ebed72f..b9573da 100644 --- a/tools/qml/browser/Browser.qml +++ b/tools/qml/browser/Browser.qml @@ -180,7 +180,7 @@ Rectangle { GradientStop { id: t1; position: 0.0; color: palette.highlight } GradientStop { id: t2; position: 1.0; color: Qt.lighter(palette.highlight) } } - width: view1.currentItem.width + width: view1.currentItem == null ? 0 : view1.currentItem.width } highlightMoveSpeed: 1000 pressDelay: 100 @@ -230,7 +230,7 @@ Rectangle { GradientStop { id: t1; position: 0.0; color: palette.highlight } GradientStop { id: t2; position: 1.0; color: Qt.lighter(palette.highlight) } } - width: view1.currentItem.width + width: view1.currentItem == null ? 0 : view1.currentItem.width } highlightMoveSpeed: 1000 pressDelay: 100 -- cgit v0.12 From 56ae8da559b3d225698eb79b78eec44a8b62239d Mon Sep 17 00:00:00 2001 From: Joona Petrell Date: Mon, 1 Nov 2010 18:00:40 +1000 Subject: Increase cachebuffer in Flickr demo to quarantee expanded delegate is not deleted the during device orientation change Task-number: QT-3824 Reviewed-by: Martin Jones --- demos/declarative/flickr/flickr.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demos/declarative/flickr/flickr.qml b/demos/declarative/flickr/flickr.qml index 740ee35..9387948 100644 --- a/demos/declarative/flickr/flickr.qml +++ b/demos/declarative/flickr/flickr.qml @@ -62,7 +62,7 @@ Item { GridView { id: photoGridView; model: rssModel; delegate: Mobile.GridDelegate {} - cacheBuffer: 100 + cacheBuffer: 1000 cellWidth: (parent.width-2)/4; cellHeight: cellWidth; width: parent.width; height: parent.height } -- cgit v0.12 From aa43c2150e48af27bbb623aae57c2d48bccbdde0 Mon Sep 17 00:00:00 2001 From: Joona Petrell Date: Tue, 2 Nov 2010 11:37:38 +1000 Subject: Fix QML calculator demo being wrongly rotated for landscape devices Task-number: QTBUG-14909 Reviewed-by: Martin Jones --- demos/declarative/calculator/calculator.qml | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/demos/declarative/calculator/calculator.qml b/demos/declarative/calculator/calculator.qml index 3e1c650..b3e4f2f 100644 --- a/demos/declarative/calculator/calculator.qml +++ b/demos/declarative/calculator/calculator.qml @@ -46,7 +46,7 @@ import "Core/calculator.js" as CalcEngine Rectangle { id: window - width: 480; height: 360 + width: 360; height: 480 color: "#282828" property string rotateLeft: "\u2939" @@ -63,7 +63,15 @@ Rectangle { id: main state: "orientation " + runtime.orientation - width: parent.width; height: parent.height; anchors.centerIn: parent + property bool landscapeWindow: window.width > window.height + property real baseWidth: landscapeWindow ? window.height : window.width + property real baseHeight: landscapeWindow ? window.width : window.height + property real rotationDelta: landscapeWindow ? -90 : 0 + + rotation: rotationDelta + width: main.baseWidth + height: main.baseHeight + anchors.centerIn: parent Column { id: box; spacing: 8 @@ -132,24 +140,20 @@ Rectangle { states: [ State { name: "orientation " + Orientation.Landscape - PropertyChanges { target: main; rotation: 90; width: window.height; height: window.width } - PropertyChanges { target: rotateButton; operation: rotateLeft } + PropertyChanges { target: main; rotation: 90 + rotationDelta; width: main.baseHeight; height: main.baseWidth } }, State { name: "orientation " + Orientation.PortraitInverted - PropertyChanges { target: main; rotation: 180; } - PropertyChanges { target: rotateButton; operation: rotateRight } + PropertyChanges { target: main; rotation: 180 + rotationDelta; } }, State { name: "orientation " + Orientation.LandscapeInverted - PropertyChanges { target: main; rotation: 270; width: window.height; height: window.width } - PropertyChanges { target: rotateButton; operation: rotateLeft } + PropertyChanges { target: main; rotation: 270 + rotationDelta; width: main.baseHeight; height: main.baseWidth } } ] transitions: Transition { SequentialAnimation { - PropertyAction { target: rotateButton; property: "operation" } RotationAnimation { direction: RotationAnimation.Shortest; duration: 300; easing.type: Easing.InOutQuint } NumberAnimation { properties: "x,y,width,height"; duration: 300; easing.type: Easing.InOutQuint } } -- cgit v0.12 From 54ca4ebba8aa5c26516424a952f8e6d4ab919f6e Mon Sep 17 00:00:00 2001 From: Joona Petrell Date: Tue, 2 Nov 2010 19:44:06 +1000 Subject: Make it possible to add your own graphics scene to QDeclarativeView Task-number: QTBUG-14771 Reviewed-by: Martin Jones --- src/declarative/util/qdeclarativeview.cpp | 24 ++++++++++++---------- .../qdeclarativeview/tst_qdeclarativeview.cpp | 21 +++++++++++++++++++ 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/src/declarative/util/qdeclarativeview.cpp b/src/declarative/util/qdeclarativeview.cpp index 2381172..6864a8b 100644 --- a/src/declarative/util/qdeclarativeview.cpp +++ b/src/declarative/util/qdeclarativeview.cpp @@ -76,7 +76,7 @@ DEFINE_BOOL_CONFIG_OPTION(frameRateDebug, QML_SHOW_FRAMERATE) class QDeclarativeScene : public QGraphicsScene { public: - QDeclarativeScene(); + QDeclarativeScene(QObject *parent = 0); protected: virtual void keyPressEvent(QKeyEvent *); @@ -87,7 +87,7 @@ protected: virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *); }; -QDeclarativeScene::QDeclarativeScene() +QDeclarativeScene::QDeclarativeScene(QObject *parent) : QGraphicsScene(parent) { } @@ -131,7 +131,8 @@ class QDeclarativeViewPrivate : public QGraphicsViewPrivate, public QDeclarative Q_DECLARE_PUBLIC(QDeclarativeView) public: QDeclarativeViewPrivate() - : root(0), declarativeItemRoot(0), graphicsWidgetRoot(0), component(0), resizeMode(QDeclarativeView::SizeViewToRootObject), initialSize(0,0) {} + : root(0), declarativeItemRoot(0), graphicsWidgetRoot(0), component(0), + resizeMode(QDeclarativeView::SizeViewToRootObject), initialSize(0,0) {} ~QDeclarativeViewPrivate() { delete root; delete engine; } void execute(); void itemGeometryChanged(QDeclarativeItem *item, const QRectF &newGeometry, const QRectF &oldGeometry); @@ -154,8 +155,6 @@ public: QElapsedTimer frameTimer; void init(); - - QDeclarativeScene scene; }; void QDeclarativeViewPrivate::execute() @@ -233,6 +232,9 @@ void QDeclarativeViewPrivate::itemGeometryChanged(QDeclarativeItem *resizeItem, you can connect to the statusChanged() signal and monitor for QDeclarativeView::Error. The errors are available via QDeclarativeView::errors(). + If you're using your own QGraphicsScene-based scene with QDeclarativeView, remember to + enable scene's sticky focus mode and to set itemIndexMethod to QGraphicsScene::NoIndex. + \sa {Integrating QML with existing Qt UI code}, {Using QML in C++ Applications} */ @@ -276,7 +278,7 @@ void QDeclarativeViewPrivate::init() { Q_Q(QDeclarativeView); engine = new QDeclarativeEngine(); - q->setScene(&scene); + q->setScene(new QDeclarativeScene(q)); q->setOptimizationFlags(QGraphicsView::DontSavePainterState); q->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); @@ -285,11 +287,11 @@ void QDeclarativeViewPrivate::init() // These seem to give the best performance q->setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate); - scene.setItemIndexMethod(QGraphicsScene::NoIndex); + q->scene()->setItemIndexMethod(QGraphicsScene::NoIndex); q->viewport()->setFocusPolicy(Qt::NoFocus); q->setFocusPolicy(Qt::StrongFocus); - scene.setStickyFocus(true); //### needed for correct focus handling + q->scene()->setStickyFocus(true); //### needed for correct focus handling } /*! @@ -555,14 +557,14 @@ void QDeclarativeView::continueExecute() void QDeclarativeView::setRootObject(QObject *obj) { Q_D(QDeclarativeView); - if (d->root == obj) + if (d->root == obj || !scene()) return; if (QDeclarativeItem *declarativeItem = qobject_cast(obj)) { - d->scene.addItem(declarativeItem); + scene()->addItem(declarativeItem); d->root = declarativeItem; d->declarativeItemRoot = declarativeItem; } else if (QGraphicsObject *graphicsObject = qobject_cast(obj)) { - d->scene.addItem(graphicsObject); + scene()->addItem(graphicsObject); d->root = graphicsObject; if (graphicsObject->isWidget()) { d->graphicsWidgetRoot = static_cast(graphicsObject); diff --git a/tests/auto/declarative/qdeclarativeview/tst_qdeclarativeview.cpp b/tests/auto/declarative/qdeclarativeview/tst_qdeclarativeview.cpp index 9ac79e4..efa5a9b 100644 --- a/tests/auto/declarative/qdeclarativeview/tst_qdeclarativeview.cpp +++ b/tests/auto/declarative/qdeclarativeview/tst_qdeclarativeview.cpp @@ -60,6 +60,7 @@ public: tst_QDeclarativeView(); private slots: + void scene(); void resizemodedeclarativeitem(); void resizemodegraphicswidget(); void errors(); @@ -74,6 +75,26 @@ tst_QDeclarativeView::tst_QDeclarativeView() { } +void tst_QDeclarativeView::scene() +{ + // QTBUG-14771 + QGraphicsScene scene; + scene.setItemIndexMethod(QGraphicsScene::NoIndex); + scene.setStickyFocus(true); + + QDeclarativeView *view = new QDeclarativeView(); + QVERIFY(view); + QVERIFY(view->scene()); + view->setScene(&scene); + QCOMPARE(view->scene(), &scene); + + view->setSource(QUrl::fromLocalFile(SRCDIR "/data/resizemodedeclarativeitem.qml")); + QDeclarativeItem* declarativeItem = qobject_cast(view->rootObject()); + QVERIFY(declarativeItem); + QVERIFY(scene.items().count() > 0); + QCOMPARE(scene.items().at(0), declarativeItem); +} + void tst_QDeclarativeView::resizemodedeclarativeitem() { QWidget window; -- cgit v0.12 From 1d228b5d532dc158d1c9ac3347168cdc11378779 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Thu, 11 Nov 2010 13:41:38 +1000 Subject: Performance fix We weren't always taking advantage of the property cache for model data when we should have been. Reviewed-by: Martin Jones --- src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp b/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp index 1f01a45..9b5a072 100644 --- a/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp +++ b/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp @@ -557,8 +557,9 @@ QDeclarativeVisualDataModelData::~QDeclarativeVisualDataModelData() void QDeclarativeVisualDataModelData::ensureProperties() { QDeclarativeVisualDataModelPrivate *modelPriv = QDeclarativeVisualDataModelPrivate::get(m_model); - if (modelPriv->m_metaDataCacheable && !modelPriv->m_metaDataCreated) { - modelPriv->createMetaData(); + if (modelPriv->m_metaDataCacheable) { + if (!modelPriv->m_metaDataCreated) + modelPriv->createMetaData(); if (modelPriv->m_metaDataCreated) m_meta->setCached(true); } -- cgit v0.12 From af60542fc4214cc716ffb1bdc46e2e7f6b5a6b8a Mon Sep 17 00:00:00 2001 From: Yann Bodson Date: Fri, 12 Nov 2010 13:02:58 +1000 Subject: Add 'cached' property to Image element Setting cached to false is useful when dealing with large images, to make sure that they aren't cached at the expense of small 'ui element' images. Task-number: QTBUG-7300 Reviewed-by: Aaron Kennedy --- .../photoviewer/PhotoViewerCore/PhotoDelegate.qml | 4 +-- .../graphicsitems/qdeclarativeborderimage.cpp | 14 +++++++++-- .../graphicsitems/qdeclarativeimage.cpp | 9 +++++++ .../graphicsitems/qdeclarativeimagebase.cpp | 25 ++++++++++++++++++- .../graphicsitems/qdeclarativeimagebase_p.h | 5 ++++ .../graphicsitems/qdeclarativeimagebase_p_p.h | 4 ++- src/declarative/util/qdeclarativepixmapcache.cpp | 22 ++++++++-------- src/declarative/util/qdeclarativepixmapcache_p.h | 12 +++++++-- .../qdeclarativeimage/tst_qdeclarativeimage.cpp | 29 +++++++++++++++------- 9 files changed, 97 insertions(+), 27 deletions(-) diff --git a/demos/declarative/photoviewer/PhotoViewerCore/PhotoDelegate.qml b/demos/declarative/photoviewer/PhotoViewerCore/PhotoDelegate.qml index 5948b5d..856a2c7 100644 --- a/demos/declarative/photoviewer/PhotoViewerCore/PhotoDelegate.qml +++ b/demos/declarative/photoviewer/PhotoViewerCore/PhotoDelegate.qml @@ -88,11 +88,11 @@ Package { } BusyIndicator { anchors.centerIn: parent; on: originalImage.status != Image.Ready } Image { - id: originalImage; smooth: true; source: "http://" + Script.getImagePath(content) + id: originalImage; smooth: true; source: "http://" + Script.getImagePath(content); cached: false fillMode: Image.PreserveAspectFit; width: photoWrapper.width; height: photoWrapper.height } Image { - id: hqImage; smooth: true; source: ""; visible: false + id: hqImage; smooth: true; source: ""; visible: false; cached: false fillMode: Image.PreserveAspectFit; width: photoWrapper.width; height: photoWrapper.height } Binding { diff --git a/src/declarative/graphicsitems/qdeclarativeborderimage.cpp b/src/declarative/graphicsitems/qdeclarativeborderimage.cpp index 649c8fb..4e35f87 100644 --- a/src/declarative/graphicsitems/qdeclarativeborderimage.cpp +++ b/src/declarative/graphicsitems/qdeclarativeborderimage.cpp @@ -290,7 +290,12 @@ void QDeclarativeBorderImage::load() } } else { - d->pix.load(qmlEngine(this), d->url, d->async); + QDeclarativePixmap::Options options; + if (d->async) + options |= QDeclarativePixmap::Asynchronous; + if (d->cached) + options |= QDeclarativePixmap::Cached; + d->pix.load(qmlEngine(this), d->url, options); if (d->pix.isLoading()) { d->pix.connectFinished(this, SLOT(requestFinished())); @@ -413,7 +418,12 @@ void QDeclarativeBorderImage::setGridScaledImage(const QDeclarativeGridScaledIma d->sciurl = d->url.resolved(QUrl(sci.pixmapUrl())); - d->pix.load(qmlEngine(this), d->sciurl, d->async); + QDeclarativePixmap::Options options; + if (d->async) + options |= QDeclarativePixmap::Asynchronous; + if (d->cached) + options |= QDeclarativePixmap::Cached; + d->pix.load(qmlEngine(this), d->sciurl, options); if (d->pix.isLoading()) { static int thisRequestProgress = -1; diff --git a/src/declarative/graphicsitems/qdeclarativeimage.cpp b/src/declarative/graphicsitems/qdeclarativeimage.cpp index 3b08a9b..c9eb258 100644 --- a/src/declarative/graphicsitems/qdeclarativeimage.cpp +++ b/src/declarative/graphicsitems/qdeclarativeimage.cpp @@ -458,6 +458,15 @@ QRectF QDeclarativeImage::boundingRect() const are always loaded asynchonously. */ +/*! + \qmlproperty bool Image::cached + \since Quick 1.1 + + Specifies that the image should be cached. The default value is + true. Setting \a cached to false is useful when dealing with large images, + to make sure that they aren't cached at the expense of small 'ui element' images. +*/ + void QDeclarativeImage::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *) { Q_D(QDeclarativeImage); diff --git a/src/declarative/graphicsitems/qdeclarativeimagebase.cpp b/src/declarative/graphicsitems/qdeclarativeimagebase.cpp index c3bac2d..37b0734 100644 --- a/src/declarative/graphicsitems/qdeclarativeimagebase.cpp +++ b/src/declarative/graphicsitems/qdeclarativeimagebase.cpp @@ -128,6 +128,24 @@ QSize QDeclarativeImageBase::sourceSize() const return QSize(width != -1 ? width : implicitWidth(), height != -1 ? height : implicitHeight()); } +bool QDeclarativeImageBase::cached() const +{ + Q_D(const QDeclarativeImageBase); + return d->cached; +} + +void QDeclarativeImageBase::setCached(bool cached) +{ + Q_D(QDeclarativeImageBase); + if (d->cached == cached) + return; + + d->cached = cached; + emit cachedChanged(); + if (isComponentComplete()) + load(); +} + void QDeclarativeImageBase::load() { Q_D(QDeclarativeImageBase); @@ -143,7 +161,12 @@ void QDeclarativeImageBase::load() pixmapChange(); update(); } else { - d->pix.load(qmlEngine(this), d->url, d->explicitSourceSize ? sourceSize() : QSize(), d->async); + QDeclarativePixmap::Options options; + if (d->async) + options |= QDeclarativePixmap::Asynchronous; + if (d->cached) + options |= QDeclarativePixmap::Cached; + d->pix.load(qmlEngine(this), d->url, d->explicitSourceSize ? sourceSize() : QSize(), options); if (d->pix.isLoading()) { d->progress = 0.0; diff --git a/src/declarative/graphicsitems/qdeclarativeimagebase_p.h b/src/declarative/graphicsitems/qdeclarativeimagebase_p.h index 68eb8d0..d25f7c3 100644 --- a/src/declarative/graphicsitems/qdeclarativeimagebase_p.h +++ b/src/declarative/graphicsitems/qdeclarativeimagebase_p.h @@ -58,6 +58,7 @@ class Q_AUTOTEST_EXPORT QDeclarativeImageBase : public QDeclarativeItem Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged) Q_PROPERTY(qreal progress READ progress NOTIFY progressChanged) Q_PROPERTY(bool asynchronous READ asynchronous WRITE setAsynchronous NOTIFY asynchronousChanged) + Q_PROPERTY(bool cached READ cached WRITE setCached NOTIFY cachedChanged) // ### VERSIONING: Only in QtQuick 1.1 Q_PROPERTY(QSize sourceSize READ sourceSize WRITE setSourceSize NOTIFY sourceSizeChanged) public: @@ -72,6 +73,9 @@ public: bool asynchronous() const; void setAsynchronous(bool); + bool cached() const; + void setCached(bool); + virtual void setSourceSize(const QSize&); QSize sourceSize() const; @@ -81,6 +85,7 @@ Q_SIGNALS: void statusChanged(QDeclarativeImageBase::Status); void progressChanged(qreal progress); void asynchronousChanged(); + void cachedChanged(); protected: virtual void load(); diff --git a/src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h b/src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h index 3d23ba9..a539649 100644 --- a/src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h @@ -70,7 +70,8 @@ public: : status(QDeclarativeImageBase::Null), progress(0.0), explicitSourceSize(false), - async(false) + async(false), + cached(true) { QGraphicsItemPrivate::flags = QGraphicsItemPrivate::flags & ~QGraphicsItem::ItemHasNoContents; } @@ -82,6 +83,7 @@ public: QSize sourcesize; bool explicitSourceSize : 1; bool async : 1; + bool cached : 1; }; QT_END_NAMESPACE diff --git a/src/declarative/util/qdeclarativepixmapcache.cpp b/src/declarative/util/qdeclarativepixmapcache.cpp index a07b1bb..5ef568f 100644 --- a/src/declarative/util/qdeclarativepixmapcache.cpp +++ b/src/declarative/util/qdeclarativepixmapcache.cpp @@ -959,20 +959,20 @@ QRect QDeclarativePixmap::rect() const void QDeclarativePixmap::load(QDeclarativeEngine *engine, const QUrl &url) { - load(engine, url, QSize(), false); + load(engine, url, QSize(), QDeclarativePixmap::Cached); } -void QDeclarativePixmap::load(QDeclarativeEngine *engine, const QUrl &url, bool async) +void QDeclarativePixmap::load(QDeclarativeEngine *engine, const QUrl &url, QDeclarativePixmap::Options options) { - load(engine, url, QSize(), async); + load(engine, url, QSize(), options); } void QDeclarativePixmap::load(QDeclarativeEngine *engine, const QUrl &url, const QSize &size) { - load(engine, url, size, false); + load(engine, url, size, QDeclarativePixmap::Cached); } -void QDeclarativePixmap::load(QDeclarativeEngine *engine, const QUrl &url, const QSize &requestSize, bool async) +void QDeclarativePixmap::load(QDeclarativeEngine *engine, const QUrl &url, const QSize &requestSize, QDeclarativePixmap::Options options) { if (d) { d->release(); d = 0; } @@ -982,19 +982,20 @@ void QDeclarativePixmap::load(QDeclarativeEngine *engine, const QUrl &url, const QHash::Iterator iter = store->m_cache.find(key); if (iter == store->m_cache.end()) { - if (async) { + if (options & QDeclarativePixmap::Asynchronous) { // pixmaps can only be loaded synchronously if (url.scheme() == QLatin1String("image") && QDeclarativeEnginePrivate::get(engine)->getImageProviderType(url) == QDeclarativeImageProvider::Pixmap) { - async = false; + options &= ~QDeclarativePixmap::Asynchronous; } } - if (!async) { + if (!(options & QDeclarativePixmap::Asynchronous)) { bool ok = false; d = createPixmapDataSync(engine, url, requestSize, &ok); if (ok) { - d->addToCache(); + if (options & QDeclarativePixmap::Cached) + d->addToCache(); return; } if (d) // loadable, but encountered error while loading @@ -1007,7 +1008,8 @@ void QDeclarativePixmap::load(QDeclarativeEngine *engine, const QUrl &url, const QDeclarativePixmapReader *reader = QDeclarativePixmapReader::instance(engine); d = new QDeclarativePixmapData(url, requestSize); - d->addToCache(); + if (options & QDeclarativePixmap::Cached) + d->addToCache(); d->reply = reader->getImage(d); } else { diff --git a/src/declarative/util/qdeclarativepixmapcache_p.h b/src/declarative/util/qdeclarativepixmapcache_p.h index 2e83cc4..9e1016f 100644 --- a/src/declarative/util/qdeclarativepixmapcache_p.h +++ b/src/declarative/util/qdeclarativepixmapcache_p.h @@ -66,6 +66,12 @@ public: enum Status { Null, Ready, Error, Loading }; + enum Option { + Asynchronous = 0x00000001, + Cached = 0x00000002 + }; + Q_DECLARE_FLAGS(Options, Option) + bool isNull() const; bool isReady() const; bool isError() const; @@ -85,9 +91,9 @@ public: inline operator const QPixmap &() const; void load(QDeclarativeEngine *, const QUrl &); - void load(QDeclarativeEngine *, const QUrl &, bool); + void load(QDeclarativeEngine *, const QUrl &, QDeclarativePixmap::Options options); void load(QDeclarativeEngine *, const QUrl &, const QSize &); - void load(QDeclarativeEngine *, const QUrl &, const QSize &, bool); + void load(QDeclarativeEngine *, const QUrl &, const QSize &, QDeclarativePixmap::Options options); void clear(); void clear(QObject *); @@ -107,6 +113,8 @@ inline QDeclarativePixmap::operator const QPixmap &() const return pixmap(); } +Q_DECLARE_OPERATORS_FOR_FLAGS(QDeclarativePixmap::Options) + QT_END_NAMESPACE QT_END_HEADER diff --git a/tests/auto/declarative/qdeclarativeimage/tst_qdeclarativeimage.cpp b/tests/auto/declarative/qdeclarativeimage/tst_qdeclarativeimage.cpp index bf779ad..3cee976 100644 --- a/tests/auto/declarative/qdeclarativeimage/tst_qdeclarativeimage.cpp +++ b/tests/auto/declarative/qdeclarativeimage/tst_qdeclarativeimage.cpp @@ -123,19 +123,21 @@ void tst_qdeclarativeimage::imageSource_data() QTest::addColumn("height"); QTest::addColumn("remote"); QTest::addColumn("async"); + QTest::addColumn("cached"); QTest::addColumn("error"); - QTest::newRow("local") << QUrl::fromLocalFile(SRCDIR "/data/colors.png").toString() << 120.0 << 120.0 << false << false << ""; - QTest::newRow("local async") << QUrl::fromLocalFile(SRCDIR "/data/colors1.png").toString() << 120.0 << 120.0 << false << true << ""; + QTest::newRow("local") << QUrl::fromLocalFile(SRCDIR "/data/colors.png").toString() << 120.0 << 120.0 << false << false << true << ""; + QTest::newRow("local no cache") << QUrl::fromLocalFile(SRCDIR "/data/colors.png").toString() << 120.0 << 120.0 << false << false << false << ""; + QTest::newRow("local async") << QUrl::fromLocalFile(SRCDIR "/data/colors1.png").toString() << 120.0 << 120.0 << false << true << true << ""; QTest::newRow("local not found") << QUrl::fromLocalFile(SRCDIR "/data/no-such-file.png").toString() << 0.0 << 0.0 << false - << false << "file::2:1: QML Image: Cannot open: " + QUrl::fromLocalFile(SRCDIR "/data/no-such-file.png").toString(); + << false << true << "file::2:1: QML Image: Cannot open: " + QUrl::fromLocalFile(SRCDIR "/data/no-such-file.png").toString(); QTest::newRow("local async not found") << QUrl::fromLocalFile(SRCDIR "/data/no-such-file-1.png").toString() << 0.0 << 0.0 << false - << true << "file::2:1: QML Image: Cannot open: " + QUrl::fromLocalFile(SRCDIR "/data/no-such-file-1.png").toString(); - QTest::newRow("remote") << SERVER_ADDR "/colors.png" << 120.0 << 120.0 << true << false << ""; - QTest::newRow("remote redirected") << SERVER_ADDR "/oldcolors.png" << 120.0 << 120.0 << true << false << ""; - QTest::newRow("remote svg") << SERVER_ADDR "/heart.svg" << 550.0 << 500.0 << true << false << ""; + << true << true << "file::2:1: QML Image: Cannot open: " + QUrl::fromLocalFile(SRCDIR "/data/no-such-file-1.png").toString(); + QTest::newRow("remote") << SERVER_ADDR "/colors.png" << 120.0 << 120.0 << true << false << true << ""; + QTest::newRow("remote redirected") << SERVER_ADDR "/oldcolors.png" << 120.0 << 120.0 << true << false << false << ""; + QTest::newRow("remote svg") << SERVER_ADDR "/heart.svg" << 550.0 << 500.0 << true << false << false << ""; QTest::newRow("remote not found") << SERVER_ADDR "/no-such-file.png" << 0.0 << 0.0 << true - << false << "file::2:1: QML Image: Error downloading " SERVER_ADDR "/no-such-file.png - server replied: Not found"; + << false << true << "file::2:1: QML Image: Error downloading " SERVER_ADDR "/no-such-file.png - server replied: Not found"; } @@ -146,6 +148,7 @@ void tst_qdeclarativeimage::imageSource() QFETCH(double, height); QFETCH(bool, remote); QFETCH(bool, async); + QFETCH(bool, cached); QFETCH(QString, error); TestHTTPServer server(SERVER_PORT); @@ -159,7 +162,8 @@ void tst_qdeclarativeimage::imageSource() QTest::ignoreMessage(QtWarningMsg, error.toUtf8()); QString componentStr = "import QtQuick 1.0\nImage { source: \"" + source + "\"; asynchronous: " - + (async ? QLatin1String("true") : QLatin1String("false")) + " }"; + + (async ? QLatin1String("true") : QLatin1String("false")) + "; cached: " + + (cached ? QLatin1String("true") : QLatin1String("false")) + " }"; QDeclarativeComponent component(&engine); component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); QDeclarativeImage *obj = qobject_cast(component.create()); @@ -167,6 +171,13 @@ void tst_qdeclarativeimage::imageSource() if (async) QVERIFY(obj->asynchronous() == true); + else + QVERIFY(obj->asynchronous() == false); + + if (cached) + QVERIFY(obj->cached() == true); + else + QVERIFY(obj->cached() == false); if (remote || async) QTRY_VERIFY(obj->status() == QDeclarativeImage::Loading); -- cgit v0.12 From f809dc1b16d6a56c1a2d57997748bddb313f7f4c Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Fri, 12 Nov 2010 13:44:06 +1000 Subject: Small optimization of enum detection in script. Reviewed-by: Martin Jones --- src/declarative/qml/qdeclarativetypenamescriptclass.cpp | 5 ++--- src/script/bridge/qscriptdeclarativeclass.cpp | 8 ++++++++ src/script/bridge/qscriptdeclarativeclass_p.h | 1 + 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/declarative/qml/qdeclarativetypenamescriptclass.cpp b/src/declarative/qml/qdeclarativetypenamescriptclass.cpp index cba7b4a..e93aae2 100644 --- a/src/declarative/qml/qdeclarativetypenamescriptclass.cpp +++ b/src/declarative/qml/qdeclarativetypenamescriptclass.cpp @@ -109,9 +109,8 @@ QDeclarativeTypeNameScriptClass::queryProperty(Object *obj, const Identifier &na } else if (data->type) { - QString strName = toString(name); - - if (strName.at(0).isUpper()) { + if (startsWithUpper(name)) { + QString strName = toString(name); // Must be an enum if (data->mode == IncludeEnums) { // ### Optimize diff --git a/src/script/bridge/qscriptdeclarativeclass.cpp b/src/script/bridge/qscriptdeclarativeclass.cpp index 8080b9f..92248a0 100644 --- a/src/script/bridge/qscriptdeclarativeclass.cpp +++ b/src/script/bridge/qscriptdeclarativeclass.cpp @@ -468,6 +468,14 @@ QString QScriptDeclarativeClass::toString(const Identifier &identifier) return QString((QChar *)r->data(), r->size()); } +bool QScriptDeclarativeClass::startsWithUpper(const Identifier &identifier) +{ + JSC::UString::Rep *r = (JSC::UString::Rep *)identifier; + if (r->size() < 1) + return false; + return QChar::category(r->data()[0]) == QChar::Letter_Uppercase; +} + quint32 QScriptDeclarativeClass::toArrayIndex(const Identifier &identifier, bool *ok) { JSC::UString::Rep *r = (JSC::UString::Rep *)identifier; diff --git a/src/script/bridge/qscriptdeclarativeclass_p.h b/src/script/bridge/qscriptdeclarativeclass_p.h index 420b133..fe38eeb 100644 --- a/src/script/bridge/qscriptdeclarativeclass_p.h +++ b/src/script/bridge/qscriptdeclarativeclass_p.h @@ -126,6 +126,7 @@ public: PersistentIdentifier createPersistentIdentifier(const Identifier &); QString toString(const Identifier &); + bool startsWithUpper(const Identifier &); quint32 toArrayIndex(const Identifier &, bool *ok); virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &, -- cgit v0.12 From f2cd51abd592a4da45892e42f0d38803e7c1620e Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Tue, 16 Nov 2010 10:15:05 +1000 Subject: Treat easing.type: Easing.InOutQuad as a literal assignment, not binding This was already being done for most enum assignments, but wasn't being done for value types. This patch extends the optimization for enums in a value type. Reviewed-by: Martin Jones --- src/declarative/qml/qdeclarativecompiler.cpp | 34 ++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp index b2740b8..b371f52 100644 --- a/src/declarative/qml/qdeclarativecompiler.cpp +++ b/src/declarative/qml/qdeclarativecompiler.cpp @@ -1836,14 +1836,22 @@ bool QDeclarativeCompiler::buildValueTypeProperty(QObject *type, COMPILE_EXCEPTION(prop, tr("Unexpected object assignment")); } else if (value->value.isScript()) { // ### Check for writability - BindingReference reference; - reference.expression = value->value; - reference.property = prop; - reference.value = value; - reference.bindingContext = ctxt; - reference.bindingContext.owner++; - addBindingReference(reference); - value->type = Value::PropertyBinding; + + //optimization for . enum assignments + bool isEnumAssignment = false; + COMPILE_CHECK(testQualifiedEnumAssignment(p, obj, value, &isEnumAssignment)); + if (isEnumAssignment) { + value->type = Value::Literal; + } else { + BindingReference reference; + reference.expression = value->value; + reference.property = prop; + reference.value = value; + reference.bindingContext = ctxt; + reference.bindingContext.owner++; + addBindingReference(reference); + value->type = Value::PropertyBinding; + } } else { COMPILE_CHECK(testLiteralAssignment(p, value)); value->type = Value::Literal; @@ -2138,7 +2146,15 @@ bool QDeclarativeCompiler::testQualifiedEnumAssignment(const QMetaProperty &prop QDeclarativeType *type = 0; unit->imports().resolveType(typeName.toUtf8(), &type, 0, 0, 0, 0); - if (!type || obj->typeName != type->qmlTypeName()) + //handle enums on value types (where obj->typeName is empty) + QByteArray objTypeName = obj->typeName; + if (objTypeName.isEmpty()) { + QDeclarativeType *objType = toQmlType(obj); + if (objType) + objTypeName = objType->qmlTypeName(); + } + + if (!type || objTypeName != type->qmlTypeName()) return true; QString enumValue = parts.at(1); -- cgit v0.12 From 463786121871c7b0934949f4fcb8ef8b4d64712f Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Tue, 16 Nov 2010 15:44:11 +1000 Subject: Optimize string->color conversion in QML. Reviewed-by: Martin Jones --- src/declarative/qml/qdeclarativestringconverters.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/declarative/qml/qdeclarativestringconverters.cpp b/src/declarative/qml/qdeclarativestringconverters.cpp index 7534a2c..55fae87 100644 --- a/src/declarative/qml/qdeclarativestringconverters.cpp +++ b/src/declarative/qml/qdeclarativestringconverters.cpp @@ -136,7 +136,7 @@ QVariant QDeclarativeStringConverters::variantFromString(const QString &s, int p QColor QDeclarativeStringConverters::colorFromString(const QString &s, bool *ok) { - if (s.startsWith(QLatin1Char('#')) && s.length() == 9) { + if (s.length() == 9 && s.startsWith(QLatin1Char('#'))) { uchar a = fromHex(s, 1); uchar r = fromHex(s, 3); uchar g = fromHex(s, 5); @@ -144,9 +144,7 @@ QColor QDeclarativeStringConverters::colorFromString(const QString &s, bool *ok) if (ok) *ok = true; return QColor(r, g, b, a); } else { - QColor rv; - if (s.startsWith(QLatin1Char('#')) || QColor::colorNames().contains(s.toLower())) - rv = QColor(s); + QColor rv(s); if (ok) *ok = rv.isValid(); return rv; } -- cgit v0.12 From e8e28735046d419463e235a58a7c4c88d04163db Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Tue, 16 Nov 2010 15:46:39 +1000 Subject: Optimize test for sharable bindings. Reviewed-by: Martin Jones --- src/declarative/qml/qdeclarativecompiler.cpp | 7 ++----- src/declarative/qml/qdeclarativerewrite.cpp | 13 +++++++++++-- src/declarative/qml/qdeclarativerewrite_p.h | 3 ++- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp index b371f52..3e63bb1 100644 --- a/src/declarative/qml/qdeclarativecompiler.cpp +++ b/src/declarative/qml/qdeclarativecompiler.cpp @@ -2800,13 +2800,10 @@ bool QDeclarativeCompiler::completeComponentBuild() // Pre-rewrite the expression QString expression = binding.expression.asScript(); - // ### Optimize - QDeclarativeRewrite::SharedBindingTester sharableTest; - bool isSharable = sharableTest.isSharable(expression); - QDeclarativeRewrite::RewriteBinding rewriteBinding; rewriteBinding.setName('$'+binding.property->name); - expression = rewriteBinding(expression); + bool isSharable = false; + expression = rewriteBinding(expression,0,&isSharable); quint32 length = expression.length(); quint32 pc; diff --git a/src/declarative/qml/qdeclarativerewrite.cpp b/src/declarative/qml/qdeclarativerewrite.cpp index bc9a114..80b9ab2 100644 --- a/src/declarative/qml/qdeclarativerewrite.cpp +++ b/src/declarative/qml/qdeclarativerewrite.cpp @@ -62,12 +62,17 @@ bool SharedBindingTester::isSharable(const QString &code) if (!parser.statement()) return false; + return isSharable(parser.statement()); +} + +bool SharedBindingTester::isSharable(AST::Statement *statement) +{ _sharable = true; - AST::Node::acceptChild(parser.statement(), this); + AST::Node::acceptChild(statement, this); return _sharable; } -QString RewriteBinding::operator()(const QString &code, bool *ok) +QString RewriteBinding::operator()(const QString &code, bool *ok, bool *sharable) { Engine engine; NodePool pool(QString(), &engine); @@ -80,6 +85,10 @@ QString RewriteBinding::operator()(const QString &code, bool *ok) return QString(); } else { if (ok) *ok = true; + if (sharable) { + SharedBindingTester tester; + *sharable = tester.isSharable(parser.statement()); + } } return rewrite(code, 0, parser.statement()); } diff --git a/src/declarative/qml/qdeclarativerewrite_p.h b/src/declarative/qml/qdeclarativerewrite_p.h index 6f3c46e..40c8321 100644 --- a/src/declarative/qml/qdeclarativerewrite_p.h +++ b/src/declarative/qml/qdeclarativerewrite_p.h @@ -68,6 +68,7 @@ class SharedBindingTester : protected AST::Visitor bool _sharable; public: bool isSharable(const QString &code); + bool isSharable(AST::Statement *statement); virtual bool visit(AST::FunctionDeclaration *) { _sharable = false; return false; } virtual bool visit(AST::FunctionExpression *) { _sharable = false; return false; } @@ -81,7 +82,7 @@ class RewriteBinding: protected AST::Visitor QByteArray _name; public: - QString operator()(const QString &code, bool *ok = 0); + QString operator()(const QString &code, bool *ok = 0, bool *sharable = 0); //name of the function: used for the debugger void setName(const QByteArray &name) { _name = name; } -- cgit v0.12 From 03c671e557a59a2c908cb8241c7ad5c31536841d Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Thu, 18 Nov 2010 14:26:33 +1000 Subject: Optimize binding rewrites. Use the existing AST rather than recreating it. Task-number: QTBUG-15331 Reviewed-by: Aaron Kennedy --- src/declarative/qml/qdeclarativecompiler.cpp | 2 +- src/declarative/qml/qdeclarativerewrite.cpp | 53 ++++++++++++++++++++++++++-- src/declarative/qml/qdeclarativerewrite_p.h | 3 +- 3 files changed, 54 insertions(+), 4 deletions(-) diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp index 3e63bb1..d590d11 100644 --- a/src/declarative/qml/qdeclarativecompiler.cpp +++ b/src/declarative/qml/qdeclarativecompiler.cpp @@ -2803,7 +2803,7 @@ bool QDeclarativeCompiler::completeComponentBuild() QDeclarativeRewrite::RewriteBinding rewriteBinding; rewriteBinding.setName('$'+binding.property->name); bool isSharable = false; - expression = rewriteBinding(expression,0,&isSharable); + expression = rewriteBinding(binding.expression.asAST(), expression, &isSharable); quint32 length = expression.length(); quint32 pc; diff --git a/src/declarative/qml/qdeclarativerewrite.cpp b/src/declarative/qml/qdeclarativerewrite.cpp index 80b9ab2..219674f 100644 --- a/src/declarative/qml/qdeclarativerewrite.cpp +++ b/src/declarative/qml/qdeclarativerewrite.cpp @@ -65,10 +65,10 @@ bool SharedBindingTester::isSharable(const QString &code) return isSharable(parser.statement()); } -bool SharedBindingTester::isSharable(AST::Statement *statement) +bool SharedBindingTester::isSharable(AST::Node *node) { _sharable = true; - AST::Node::acceptChild(statement, this); + AST::Node::acceptChild(node, this); return _sharable; } @@ -93,6 +93,55 @@ QString RewriteBinding::operator()(const QString &code, bool *ok, bool *sharable return rewrite(code, 0, parser.statement()); } +QString RewriteBinding::operator()(QDeclarativeJS::AST::Node *node, const QString &code, bool *sharable) +{ + if (!node) + return code; + + if (sharable) { + SharedBindingTester tester; + *sharable = tester.isSharable(node); + } + + QDeclarativeJS::AST::ExpressionNode *expression = node->expressionCast(); + QDeclarativeJS::AST::Statement *statement = node->statementCast(); + if(!expression && !statement) + return code; + + TextWriter w; + _writer = &w; + _position = expression ? expression->firstSourceLocation().begin() : statement->firstSourceLocation().begin(); + _inLoop = 0; + + accept(node); + + unsigned startOfStatement = 0; + unsigned endOfStatement = (expression ? expression->lastSourceLocation().end() : statement->lastSourceLocation().end()) - _position; + + QString startString = QLatin1String("(function ") + QString::fromUtf8(_name) + QLatin1String("() { "); + if (expression) + startString += QLatin1String("return "); + _writer->replace(startOfStatement, 0, startString); + _writer->replace(endOfStatement, 0, QLatin1String(" })")); + + if (rewriteDump()) { + qWarning() << "============================================================="; + qWarning() << "Rewrote:"; + qWarning() << qPrintable(code); + } + + QString codeCopy = code; + w.write(&codeCopy); + + if (rewriteDump()) { + qWarning() << "To:"; + qWarning() << qPrintable(code); + qWarning() << "============================================================="; + } + + return codeCopy; +} + void RewriteBinding::accept(AST::Node *node) { AST::Node::acceptChild(node, this); diff --git a/src/declarative/qml/qdeclarativerewrite_p.h b/src/declarative/qml/qdeclarativerewrite_p.h index 40c8321..310ef3c 100644 --- a/src/declarative/qml/qdeclarativerewrite_p.h +++ b/src/declarative/qml/qdeclarativerewrite_p.h @@ -68,7 +68,7 @@ class SharedBindingTester : protected AST::Visitor bool _sharable; public: bool isSharable(const QString &code); - bool isSharable(AST::Statement *statement); + bool isSharable(AST::Node *Node); virtual bool visit(AST::FunctionDeclaration *) { _sharable = false; return false; } virtual bool visit(AST::FunctionExpression *) { _sharable = false; return false; } @@ -83,6 +83,7 @@ class RewriteBinding: protected AST::Visitor public: QString operator()(const QString &code, bool *ok = 0, bool *sharable = 0); + QString operator()(QDeclarativeJS::AST::Node *node, const QString &code, bool *sharable = 0); //name of the function: used for the debugger void setName(const QByteArray &name) { _name = name; } -- cgit v0.12 From 3d100ab29820b4dcf14afbcadb05d0bf40fdacbc Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Fri, 29 Oct 2010 15:44:21 +1000 Subject: Add a private high-performance timer for profiling. --- src/declarative/qml/qml.pri | 9 +- src/declarative/qml/qperformancetimer.cpp | 226 +++++++++++++++++++++ src/declarative/qml/qperformancetimer_p.h | 79 +++++++ .../qperformancetimer/qperformancetimer.pro | 7 + .../qperformancetimer/tst_qperformancetimer.cpp | 68 +++++++ .../qperformancetimer/qperformancetimer.pro | 8 + .../qperformancetimer/tst_qperformancetimer.cpp | 89 ++++++++ 7 files changed, 484 insertions(+), 2 deletions(-) create mode 100644 src/declarative/qml/qperformancetimer.cpp create mode 100644 src/declarative/qml/qperformancetimer_p.h create mode 100644 tests/auto/declarative/qperformancetimer/qperformancetimer.pro create mode 100644 tests/auto/declarative/qperformancetimer/tst_qperformancetimer.cpp create mode 100644 tests/benchmarks/declarative/qperformancetimer/qperformancetimer.pro create mode 100644 tests/benchmarks/declarative/qperformancetimer/tst_qperformancetimer.cpp diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri index 66b69f9..bf9e54a 100644 --- a/src/declarative/qml/qml.pri +++ b/src/declarative/qml/qml.pri @@ -55,7 +55,8 @@ SOURCES += \ $$PWD/qdeclarativedirparser.cpp \ $$PWD/qdeclarativeextensionplugin.cpp \ $$PWD/qdeclarativeimport.cpp \ - $$PWD/qdeclarativelist.cpp + $$PWD/qdeclarativelist.cpp \ + $$PWD/qperformancetimer.cpp HEADERS += \ $$PWD/qdeclarativeparser_p.h \ @@ -129,8 +130,12 @@ HEADERS += \ $$PWD/qdeclarativedirparser_p.h \ $$PWD/qdeclarativeextensioninterface.h \ $$PWD/qdeclarativeimport_p.h \ - $$PWD/qdeclarativeextensionplugin.h + $$PWD/qdeclarativeextensionplugin.h \ + $$PWD/qperformancetimer_p.h QT += sql include(parser/parser.pri) include(rewriter/rewriter.pri) + +# mirrors logic in corelib/kernel/kernel.pri +unix:!symbian: contains(QT_CONFIG, clock-gettime):include($$QT_SOURCE_TREE/config.tests/unix/clock-gettime/clock-gettime.pri) diff --git a/src/declarative/qml/qperformancetimer.cpp b/src/declarative/qml/qperformancetimer.cpp new file mode 100644 index 0000000..1d7ca80 --- /dev/null +++ b/src/declarative/qml/qperformancetimer.cpp @@ -0,0 +1,226 @@ +/**************************************************************************** +** +** 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 "qperformancetimer_p.h" + +#if defined(Q_OS_MAC) +#include +#include +#include +#elif defined(Q_OS_UNIX) +#include +#include +#include +#elif defined(Q_OS_SYMBIAN) +#include +#include +#include +#elif defined(Q_OS_WIN) +#include +#endif + +// mac/unix code heavily copied from QElapsedTimer + +QT_BEGIN_NAMESPACE + +////////////////////////////// Mac ////////////////////////////// +#if defined(Q_OS_MAC) + +static mach_timebase_info_data_t info = {0,0}; +static qint64 absoluteToNSecs(qint64 cpuTime) +{ + if (info.denom == 0) + mach_timebase_info(&info); + qint64 nsecs = cpuTime * info.numer / info.denom; + return nsecs; +} + +void QPerformanceTimer::start() +{ + t1 = mach_absolute_time(); +} + +qint64 QPerformanceTimer::elapsed() const +{ + uint64_t cpu_time = mach_absolute_time(); + return absoluteToNSecs(cpu_time - t1); +} + +////////////////////////////// Unix ////////////////////////////// +#elif defined(Q_OS_UNIX) + +#if defined(QT_NO_CLOCK_MONOTONIC) || defined(QT_BOOTSTRAPPED) +// turn off the monotonic clock +# ifdef _POSIX_MONOTONIC_CLOCK +# undef _POSIX_MONOTONIC_CLOCK +# endif +# define _POSIX_MONOTONIC_CLOCK -1 +#endif + +#if (_POSIX_MONOTONIC_CLOCK-0 != 0) +static const bool monotonicClockChecked = true; +static const bool monotonicClockAvailable = _POSIX_MONOTONIC_CLOCK > 0; +#else +static int monotonicClockChecked = false; +static int monotonicClockAvailable = false; +#endif + +#ifdef Q_CC_GNU +# define is_likely(x) __builtin_expect((x), 1) +#else +# define is_likely(x) (x) +#endif +#define load_acquire(x) ((volatile const int&)(x)) +#define store_release(x,v) ((volatile int&)(x) = (v)) + +static void unixCheckClockType() +{ +#if (_POSIX_MONOTONIC_CLOCK-0 == 0) + if (is_likely(load_acquire(monotonicClockChecked))) + return; + +# if defined(_SC_MONOTONIC_CLOCK) + // detect if the system support monotonic timers + long x = sysconf(_SC_MONOTONIC_CLOCK); + store_release(monotonicClockAvailable, x >= 200112L); +# endif + + store_release(monotonicClockChecked, true); +#endif +} + +static inline void do_gettime(qint64 *sec, qint64 *frac) +{ +#if (_POSIX_MONOTONIC_CLOCK-0 >= 0) + unixCheckClockType(); + if (is_likely(monotonicClockAvailable)) { + timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + *sec = ts.tv_sec; + *frac = ts.tv_nsec; + return; + } +#endif + *sec = 0; + *frac = 0; +} + +void QPerformanceTimer::start() +{ + do_gettime(&t1, &t2); +} + +qint64 QPerformanceTimer::elapsed() const +{ + qint64 sec, frac; + do_gettime(&sec, &frac); + sec = sec - t1; + frac = frac - t2; + + return sec * Q_INT64_C(1000000000) + frac; +} + +////////////////////////////// Symbian ////////////////////////////// +#elif defined(Q_OS_SYMBIAN) + +static qint64 getTimeFromTick(quint64 elapsed) +{ + static TInt freq; + if (!freq) + HAL::Get(HALData::EFastCounterFrequency, freq); + + // ### not sure on units + return elapsed / freq; +} + +void QPerformanceTimer::start() +{ + t1 = User::FastCounter(); +} + +qint64 QPerformanceTimer::elapsed() const +{ + return getTimeFromTick(User::FastCounter() - t1); +} + +////////////////////////////// Windows ////////////////////////////// +#elif defined(Q_OS_WIN) + +static qint64 getTimeFromTick(quint64 elapsed) +{ + static LARGE_INTEGER freq; + if (!freq.QuadPart) + QueryPerformanceFrequency(&freq); + return 1000000000 * elapsed / freq.QuadPart; +} + +void QPerformanceTimer::start() +{ + LARGE_INTEGER li; + QueryPerformanceCounter(&li); + t1 = li.QuadPart; +} + +qint64 QPerformanceTimer::elapsed() const +{ + LARGE_INTEGER li; + QueryPerformanceCounter(&li); + return getTimeFromTick(li.QuadPart - t1); +} + +////////////////////////////// Default ////////////////////////////// +#else + +// default implementation (no hi-perf timer) does nothing +void QPerformanceTimer::start() +{ +} + +qint64 QPerformanceTimer::elapsed() const +{ + return 0; +} + +#endif + +QT_END_NAMESPACE + + diff --git a/src/declarative/qml/qperformancetimer_p.h b/src/declarative/qml/qperformancetimer_p.h new file mode 100644 index 0000000..14310bf --- /dev/null +++ b/src/declarative/qml/qperformancetimer_p.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** 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 QPERFORMANCETIMER_P_H +#define QPERFORMANCETIMER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of moc. This header file may change from version to version without notice, +// or even be removed. +// +// We mean it. +// + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class Q_AUTOTEST_EXPORT QPerformanceTimer +{ +public: + void start(); + qint64 elapsed() const; + +private: + qint64 t1; + qint64 t2; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QPERFORMANCETIMER_P_H diff --git a/tests/auto/declarative/qperformancetimer/qperformancetimer.pro b/tests/auto/declarative/qperformancetimer/qperformancetimer.pro new file mode 100644 index 0000000..656bf68 --- /dev/null +++ b/tests/auto/declarative/qperformancetimer/qperformancetimer.pro @@ -0,0 +1,7 @@ +load(qttest_p4) +contains(QT_CONFIG,declarative): QT += declarative +SOURCES += tst_qperformancetimer.cpp +macx:CONFIG -= app_bundle + +CONFIG += parallel_test + diff --git a/tests/auto/declarative/qperformancetimer/tst_qperformancetimer.cpp b/tests/auto/declarative/qperformancetimer/tst_qperformancetimer.cpp new file mode 100644 index 0000000..2029c8a --- /dev/null +++ b/tests/auto/declarative/qperformancetimer/tst_qperformancetimer.cpp @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** 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 test suite 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 +#include +#include + +class tst_qperformancetimer : public QObject +{ + Q_OBJECT + +public: + tst_qperformancetimer() {} + +private slots: + void units(); +}; + +void tst_qperformancetimer::units() +{ + QPerformanceTimer timer; + timer.start(); + QTest::qWait(300); + qint64 elapsed = timer.elapsed(); + QVERIFY(elapsed > 300000000 && elapsed < 310000000); +} + +QTEST_MAIN(tst_qperformancetimer) + +#include "tst_qperformancetimer.moc" diff --git a/tests/benchmarks/declarative/qperformancetimer/qperformancetimer.pro b/tests/benchmarks/declarative/qperformancetimer/qperformancetimer.pro new file mode 100644 index 0000000..a39cd3d --- /dev/null +++ b/tests/benchmarks/declarative/qperformancetimer/qperformancetimer.pro @@ -0,0 +1,8 @@ +load(qttest_p4) +QT += declarative +TEMPLATE = app +TARGET = tst_qperformancetimer +macx:CONFIG -= app_bundle + +SOURCES += tst_qperformancetimer.cpp + diff --git a/tests/benchmarks/declarative/qperformancetimer/tst_qperformancetimer.cpp b/tests/benchmarks/declarative/qperformancetimer/tst_qperformancetimer.cpp new file mode 100644 index 0000000..04737e7 --- /dev/null +++ b/tests/benchmarks/declarative/qperformancetimer/tst_qperformancetimer.cpp @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** 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 test suite 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 +#include +#include + +class tst_qperformancetimer : public QObject +{ + Q_OBJECT + +public: + tst_qperformancetimer() {} + +private slots: + void all(); + void startElapsed(); + void doubleElapsed(); +}; + +void tst_qperformancetimer::all() +{ + QBENCHMARK { + QPerformanceTimer t; + t.start(); + t.elapsed(); + } +} + +void tst_qperformancetimer::startElapsed() +{ + QPerformanceTimer t; + QBENCHMARK { + t.start(); + t.elapsed(); + } +} + +void tst_qperformancetimer::doubleElapsed() +{ + QPerformanceTimer t; + t.start(); + QBENCHMARK { + t.elapsed(); + t.elapsed(); + } +} + +QTEST_MAIN(tst_qperformancetimer) + +#include "tst_qperformancetimer.moc" -- cgit v0.12 From 458c237ea807330de8b15cb2b6e99f564bb7fd66 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Wed, 3 Nov 2010 10:24:29 +1000 Subject: Use high performance timer for profiling. Add binding profile info. --- src/declarative/debugger/qdeclarativedebugtrace_p.h | 5 +++-- src/declarative/qml/qdeclarativebinding.cpp | 15 +++++++++++++++ src/declarative/qml/qdeclarativecompiledbindings.cpp | 3 +++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/declarative/debugger/qdeclarativedebugtrace_p.h b/src/declarative/debugger/qdeclarativedebugtrace_p.h index 704c49a..d6fe0b0 100644 --- a/src/declarative/debugger/qdeclarativedebugtrace_p.h +++ b/src/declarative/debugger/qdeclarativedebugtrace_p.h @@ -43,7 +43,7 @@ #define QDECLARATIVEDEBUGTRACE_P_H #include -#include +#include QT_BEGIN_HEADER @@ -74,6 +74,7 @@ public: Painting, Compiling, Creating, + Binding, MaximumRangeType }; @@ -90,7 +91,7 @@ private: void startRangeImpl(RangeType); void rangeDataImpl(RangeType, const QUrl &); void endRangeImpl(RangeType); - QElapsedTimer m_timer; + QPerformanceTimer m_timer; }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativebinding.cpp b/src/declarative/qml/qdeclarativebinding.cpp index cb6ad8c..2a1abd0 100644 --- a/src/declarative/qml/qdeclarativebinding.cpp +++ b/src/declarative/qml/qdeclarativebinding.cpp @@ -49,6 +49,7 @@ #include "private/qdeclarativedata_p.h" #include "private/qdeclarativestringconverters_p.h" #include "private/qdeclarativestate_p_p.h" +#include "private/qdeclarativedebugtrace_p.h" #include #include @@ -114,6 +115,19 @@ QDeclarativeProperty QDeclarativeBinding::property() const return d->property; } +class QDeclarativeBindingProfiler { +public: + QDeclarativeBindingProfiler() + { + QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Binding); + } + + ~QDeclarativeBindingProfiler() + { + QDeclarativeDebugTrace::endRange(QDeclarativeDebugTrace::Binding); + } +}; + void QDeclarativeBinding::update(QDeclarativePropertyPrivate::WriteFlags flags) { Q_D(QDeclarativeBinding); @@ -122,6 +136,7 @@ void QDeclarativeBinding::update(QDeclarativePropertyPrivate::WriteFlags flags) return; if (!d->updating) { + QDeclarativeBindingProfiler prof; d->updating = true; bool wasDeleted = false; d->deleted = &wasDeleted; diff --git a/src/declarative/qml/qdeclarativecompiledbindings.cpp b/src/declarative/qml/qdeclarativecompiledbindings.cpp index 5f0fd56..77fb48e 100644 --- a/src/declarative/qml/qdeclarativecompiledbindings.cpp +++ b/src/declarative/qml/qdeclarativecompiledbindings.cpp @@ -54,6 +54,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -316,7 +317,9 @@ int QDeclarativeCompiledBindingsPrivate::Binding::propertyIndex() void QDeclarativeCompiledBindingsPrivate::Binding::update(QDeclarativePropertyPrivate::WriteFlags flags) { + QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Binding); parent->run(this, flags); + QDeclarativeDebugTrace::endRange(QDeclarativeDebugTrace::Binding); } void QDeclarativeCompiledBindingsPrivate::Binding::destroy() -- cgit v0.12 From 1a8bf28261facf1e97cecf842fcbfff48b383984 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Wed, 3 Nov 2010 12:53:41 +1000 Subject: Add support for a record-then-send debug process. --- .../debugger/qdeclarativedebugtrace.cpp | 55 ++++++++++++++++++---- .../debugger/qdeclarativedebugtrace_p.h | 7 +++ 2 files changed, 53 insertions(+), 9 deletions(-) diff --git a/src/declarative/debugger/qdeclarativedebugtrace.cpp b/src/declarative/debugger/qdeclarativedebugtrace.cpp index 03e2d56..5edc3b6 100644 --- a/src/declarative/debugger/qdeclarativedebugtrace.cpp +++ b/src/declarative/debugger/qdeclarativedebugtrace.cpp @@ -43,11 +43,13 @@ #include #include +#include Q_GLOBAL_STATIC(QDeclarativeDebugTrace, traceInstance); QDeclarativeDebugTrace::QDeclarativeDebugTrace() -: QDeclarativeDebugService(QLatin1String("CanvasFrameRate")) +: QDeclarativeDebugService(QLatin1String("CanvasFrameRate")), + m_enabled(false), m_deferredSend(true) { m_timer.start(); } @@ -78,45 +80,80 @@ void QDeclarativeDebugTrace::endRange(RangeType t) void QDeclarativeDebugTrace::addEventImpl(EventType event) { - if (status() != Enabled) + if (status() != Enabled || !m_enabled) return; QByteArray data; QDataStream ds(&data, QIODevice::WriteOnly); ds << m_timer.elapsed() << (int)Event << (int)event; - sendMessage(data); + processMessage(data); } void QDeclarativeDebugTrace::startRangeImpl(RangeType range) { - if (status() != Enabled) + if (status() != Enabled || !m_enabled) return; QByteArray data; QDataStream ds(&data, QIODevice::WriteOnly); ds << m_timer.elapsed() << (int)RangeStart << (int)range; - sendMessage(data); + processMessage(data); } void QDeclarativeDebugTrace::rangeDataImpl(RangeType range, const QUrl &u) { - if (status() != Enabled) + if (status() != Enabled || !m_enabled) return; QByteArray data; QDataStream ds(&data, QIODevice::WriteOnly); ds << m_timer.elapsed() << (int)RangeData << (int)range << (QString)u.toString(); - sendMessage(data); + processMessage(data); } void QDeclarativeDebugTrace::endRangeImpl(RangeType range) { - if (status() != Enabled) + if (status() != Enabled || !m_enabled) return; QByteArray data; QDataStream ds(&data, QIODevice::WriteOnly); ds << m_timer.elapsed() << (int)RangeEnd << (int)range; - sendMessage(data); + processMessage(data); } +/* + Either send the message directly, or queue up + a list of messages to send later (via sendMessages) +*/ +void QDeclarativeDebugTrace::processMessage(const QByteArray &message) +{ + if (m_deferredSend) + m_data.append(message); + else + sendMessage(message); +} + +/* + Send the messages queued up by processMessage +*/ +void QDeclarativeDebugTrace::sendMessages() +{ + if (m_deferredSend) { + //### this is a suboptimal way to send batched messages + for (int i = 0; i < m_data.count(); ++i) + sendMessage(m_data.at(i)); + m_data.clear(); + } +} + +void QDeclarativeDebugTrace::messageReceived(const QByteArray &message) +{ + QByteArray rwData = message; + QDataStream stream(&rwData, QIODevice::ReadOnly); + + stream >> m_enabled; + + if (!m_enabled) + sendMessages(); +} diff --git a/src/declarative/debugger/qdeclarativedebugtrace_p.h b/src/declarative/debugger/qdeclarativedebugtrace_p.h index d6fe0b0..c7c61bd 100644 --- a/src/declarative/debugger/qdeclarativedebugtrace_p.h +++ b/src/declarative/debugger/qdeclarativedebugtrace_p.h @@ -86,12 +86,19 @@ public: static void endRange(RangeType); QDeclarativeDebugTrace(); +protected: + virtual void messageReceived(const QByteArray &); private: void addEventImpl(EventType); void startRangeImpl(RangeType); void rangeDataImpl(RangeType, const QUrl &); void endRangeImpl(RangeType); + void processMessage(const QByteArray &); + void sendMessages(); QPerformanceTimer m_timer; + bool m_enabled; + bool m_deferredSend; + QList m_data; }; QT_END_NAMESPACE -- cgit v0.12 From 530b052bed6fd74699fead438035dc4684d83335 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Wed, 3 Nov 2010 15:12:16 +1000 Subject: Add additional tracing. Tracing for compile time, signal handlers, and deferred creation. --- src/declarative/debugger/qdeclarativedebugtrace_p.h | 3 ++- src/declarative/qml/qdeclarativeboundsignal.cpp | 3 +++ src/declarative/qml/qdeclarativeengine.cpp | 4 +++- src/declarative/qml/qdeclarativetypeloader.cpp | 3 +++ 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/declarative/debugger/qdeclarativedebugtrace_p.h b/src/declarative/debugger/qdeclarativedebugtrace_p.h index c7c61bd..d0e776e 100644 --- a/src/declarative/debugger/qdeclarativedebugtrace_p.h +++ b/src/declarative/debugger/qdeclarativedebugtrace_p.h @@ -74,7 +74,8 @@ public: Painting, Compiling, Creating, - Binding, + Binding, //running a binding + HandlingSignal, //running a signal handler MaximumRangeType }; diff --git a/src/declarative/qml/qdeclarativeboundsignal.cpp b/src/declarative/qml/qdeclarativeboundsignal.cpp index 6af3e05..1bb92dd 100644 --- a/src/declarative/qml/qdeclarativeboundsignal.cpp +++ b/src/declarative/qml/qdeclarativeboundsignal.cpp @@ -49,6 +49,7 @@ #include "qdeclarative.h" #include "qdeclarativecontext.h" #include "private/qdeclarativeglobal_p.h" +#include "private/qdeclarativedebugtrace_p.h" #include @@ -165,6 +166,7 @@ QDeclarativeBoundSignal *QDeclarativeBoundSignal::cast(QObject *o) int QDeclarativeBoundSignal::qt_metacall(QMetaObject::Call c, int id, void **a) { if (c == QMetaObject::InvokeMetaMethod && id == evaluateIdx) { + QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::HandlingSignal); m_isEvaluating = true; if (!m_paramsValid) { if (!m_signal.parameterTypes().isEmpty()) @@ -180,6 +182,7 @@ int QDeclarativeBoundSignal::qt_metacall(QMetaObject::Call c, int id, void **a) } if (m_params) m_params->clearValues(); m_isEvaluating = false; + QDeclarativeDebugTrace::endRange(QDeclarativeDebugTrace::HandlingSignal); return -1; } else { return QObject::qt_metacall(c, id, a); diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp index 808ba68..dac40b0 100644 --- a/src/declarative/qml/qdeclarativeengine.cpp +++ b/src/declarative/qml/qdeclarativeengine.cpp @@ -69,6 +69,7 @@ #include "private/qdeclarativetypenamecache_p.h" #include "private/qdeclarativeinclude_p.h" #include "private/qdeclarativenotifier_p.h" +#include "private/qdeclarativedebugtrace_p.h" #include #include @@ -927,7 +928,7 @@ Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object) QDeclarativeData *data = QDeclarativeData::get(object); if (data && data->deferredComponent) { - + QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Creating); QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(data->context->engine); QDeclarativeComponentPrivate::ConstructionState state; @@ -937,6 +938,7 @@ Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object) data->deferredComponent = 0; QDeclarativeComponentPrivate::complete(ep, &state); + QDeclarativeDebugTrace::endRange(QDeclarativeDebugTrace::Creating); } } diff --git a/src/declarative/qml/qdeclarativetypeloader.cpp b/src/declarative/qml/qdeclarativetypeloader.cpp index c015519..d9b4c54 100644 --- a/src/declarative/qml/qdeclarativetypeloader.cpp +++ b/src/declarative/qml/qdeclarativetypeloader.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -895,6 +896,7 @@ void QDeclarativeTypeData::downloadProgressChanged(qreal p) void QDeclarativeTypeData::compile() { Q_ASSERT(m_compiledData == 0); + QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Compiling); m_compiledData = new QDeclarativeCompiledData(typeLoader()->engine()); m_compiledData->url = m_imports.baseUrl(); @@ -906,6 +908,7 @@ void QDeclarativeTypeData::compile() m_compiledData->release(); m_compiledData = 0; } + QDeclarativeDebugTrace::endRange(QDeclarativeDebugTrace::Compiling); } void QDeclarativeTypeData::resolveTypes() -- cgit v0.12 From 3c05109ce609574f1525c465f68817d3af39397e Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Thu, 4 Nov 2010 15:34:17 +1000 Subject: Support directly setting string range data. --- src/declarative/debugger/qdeclarativedebugtrace.cpp | 8 ++++---- src/declarative/debugger/qdeclarativedebugtrace_p.h | 4 ++-- src/declarative/qml/qdeclarativebinding.cpp | 5 +++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/declarative/debugger/qdeclarativedebugtrace.cpp b/src/declarative/debugger/qdeclarativedebugtrace.cpp index 5edc3b6..cd4306b 100644 --- a/src/declarative/debugger/qdeclarativedebugtrace.cpp +++ b/src/declarative/debugger/qdeclarativedebugtrace.cpp @@ -66,10 +66,10 @@ void QDeclarativeDebugTrace::startRange(RangeType t) traceInstance()->startRangeImpl(t); } -void QDeclarativeDebugTrace::rangeData(RangeType t, const QUrl &url) +void QDeclarativeDebugTrace::rangeData(RangeType t, const QString &data) { if (QDeclarativeDebugService::isDebuggingEnabled()) - traceInstance()->rangeDataImpl(t, url); + traceInstance()->rangeDataImpl(t, data); } void QDeclarativeDebugTrace::endRange(RangeType t) @@ -100,14 +100,14 @@ void QDeclarativeDebugTrace::startRangeImpl(RangeType range) processMessage(data); } -void QDeclarativeDebugTrace::rangeDataImpl(RangeType range, const QUrl &u) +void QDeclarativeDebugTrace::rangeDataImpl(RangeType range, const QString &rData) { if (status() != Enabled || !m_enabled) return; QByteArray data; QDataStream ds(&data, QIODevice::WriteOnly); - ds << m_timer.elapsed() << (int)RangeData << (int)range << (QString)u.toString(); + ds << m_timer.elapsed() << (int)RangeData << (int)range << rData; processMessage(data); } diff --git a/src/declarative/debugger/qdeclarativedebugtrace_p.h b/src/declarative/debugger/qdeclarativedebugtrace_p.h index d0e776e..b935fbe 100644 --- a/src/declarative/debugger/qdeclarativedebugtrace_p.h +++ b/src/declarative/debugger/qdeclarativedebugtrace_p.h @@ -83,7 +83,7 @@ public: static void addEvent(EventType); static void startRange(RangeType); - static void rangeData(RangeType, const QUrl &); + static void rangeData(RangeType, const QString &); static void endRange(RangeType); QDeclarativeDebugTrace(); @@ -92,7 +92,7 @@ protected: private: void addEventImpl(EventType); void startRangeImpl(RangeType); - void rangeDataImpl(RangeType, const QUrl &); + void rangeDataImpl(RangeType, const QString &); void endRangeImpl(RangeType); void processMessage(const QByteArray &); void sendMessages(); diff --git a/src/declarative/qml/qdeclarativebinding.cpp b/src/declarative/qml/qdeclarativebinding.cpp index 2a1abd0..055d009 100644 --- a/src/declarative/qml/qdeclarativebinding.cpp +++ b/src/declarative/qml/qdeclarativebinding.cpp @@ -117,9 +117,10 @@ QDeclarativeProperty QDeclarativeBinding::property() const class QDeclarativeBindingProfiler { public: - QDeclarativeBindingProfiler() + QDeclarativeBindingProfiler(QDeclarativeBinding *bind) { QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Binding); + //QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::Binding, bind->expression()); } ~QDeclarativeBindingProfiler() @@ -136,7 +137,7 @@ void QDeclarativeBinding::update(QDeclarativePropertyPrivate::WriteFlags flags) return; if (!d->updating) { - QDeclarativeBindingProfiler prof; + QDeclarativeBindingProfiler prof(this); d->updating = true; bool wasDeleted = false; d->deleted = &wasDeleted; -- cgit v0.12 From 7aebf28291288ea6e8c1d9d28f4ed752b00dca97 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Fri, 5 Nov 2010 13:27:30 +1000 Subject: Make deferred tracing less expensive (real-time cost is the same) --- .../debugger/qdeclarativedebugtrace.cpp | 44 ++++++++++++---------- .../debugger/qdeclarativedebugtrace_p.h | 32 +++++++++++----- src/declarative/qml/qdeclarativebinding.cpp | 2 +- .../qperformancetimer/tst_qperformancetimer.cpp | 11 ++++++ 4 files changed, 59 insertions(+), 30 deletions(-) diff --git a/src/declarative/debugger/qdeclarativedebugtrace.cpp b/src/declarative/debugger/qdeclarativedebugtrace.cpp index cd4306b..7f970bf 100644 --- a/src/declarative/debugger/qdeclarativedebugtrace.cpp +++ b/src/declarative/debugger/qdeclarativedebugtrace.cpp @@ -47,6 +47,20 @@ Q_GLOBAL_STATIC(QDeclarativeDebugTrace, traceInstance); +// convert to a QByteArray that can be sent to the debug client +// use of QDataStream can skew results if m_deferredSend == false +// (see tst_qperformancetimer::trace() benchmark) +QByteArray QDeclarativeDebugData::toByteArray() const +{ + QByteArray data; + //### using QDataStream is relatively expensive + QDataStream ds(&data, QIODevice::WriteOnly); + ds << time << messageType << detailType; + if (messageType == (int)QDeclarativeDebugTrace::RangeData) + ds << detailData; + return data; +} + QDeclarativeDebugTrace::QDeclarativeDebugTrace() : QDeclarativeDebugService(QLatin1String("CanvasFrameRate")), m_enabled(false), m_deferredSend(true) @@ -83,10 +97,8 @@ void QDeclarativeDebugTrace::addEventImpl(EventType event) if (status() != Enabled || !m_enabled) return; - QByteArray data; - QDataStream ds(&data, QIODevice::WriteOnly); - ds << m_timer.elapsed() << (int)Event << (int)event; - processMessage(data); + QDeclarativeDebugData ed = {m_timer.elapsed(), (int)Event, (int)event, QString()}; + processMessage(ed); } void QDeclarativeDebugTrace::startRangeImpl(RangeType range) @@ -94,10 +106,8 @@ void QDeclarativeDebugTrace::startRangeImpl(RangeType range) if (status() != Enabled || !m_enabled) return; - QByteArray data; - QDataStream ds(&data, QIODevice::WriteOnly); - ds << m_timer.elapsed() << (int)RangeStart << (int)range; - processMessage(data); + QDeclarativeDebugData rd = {m_timer.elapsed(), (int)RangeStart, (int)range, QString()}; + processMessage(rd); } void QDeclarativeDebugTrace::rangeDataImpl(RangeType range, const QString &rData) @@ -105,10 +115,8 @@ void QDeclarativeDebugTrace::rangeDataImpl(RangeType range, const QString &rData if (status() != Enabled || !m_enabled) return; - QByteArray data; - QDataStream ds(&data, QIODevice::WriteOnly); - ds << m_timer.elapsed() << (int)RangeData << (int)range << rData; - processMessage(data); + QDeclarativeDebugData rd = {m_timer.elapsed(), (int)RangeData, (int)range, rData}; + processMessage(rd); } void QDeclarativeDebugTrace::endRangeImpl(RangeType range) @@ -116,22 +124,20 @@ void QDeclarativeDebugTrace::endRangeImpl(RangeType range) if (status() != Enabled || !m_enabled) return; - QByteArray data; - QDataStream ds(&data, QIODevice::WriteOnly); - ds << m_timer.elapsed() << (int)RangeEnd << (int)range; - processMessage(data); + QDeclarativeDebugData rd = {m_timer.elapsed(), (int)RangeEnd, (int)range, QString()}; + processMessage(rd); } /* Either send the message directly, or queue up a list of messages to send later (via sendMessages) */ -void QDeclarativeDebugTrace::processMessage(const QByteArray &message) +void QDeclarativeDebugTrace::processMessage(const QDeclarativeDebugData &message) { if (m_deferredSend) m_data.append(message); else - sendMessage(message); + sendMessage(message.toByteArray()); } /* @@ -142,7 +148,7 @@ void QDeclarativeDebugTrace::sendMessages() if (m_deferredSend) { //### this is a suboptimal way to send batched messages for (int i = 0; i < m_data.count(); ++i) - sendMessage(m_data.at(i)); + sendMessage(m_data.at(i).toByteArray()); m_data.clear(); } } diff --git a/src/declarative/debugger/qdeclarativedebugtrace_p.h b/src/declarative/debugger/qdeclarativedebugtrace_p.h index b935fbe..86c0987 100644 --- a/src/declarative/debugger/qdeclarativedebugtrace_p.h +++ b/src/declarative/debugger/qdeclarativedebugtrace_p.h @@ -49,18 +49,22 @@ QT_BEGIN_HEADER QT_BEGIN_NAMESPACE +struct QDeclarativeDebugData +{ + qint64 time; + int messageType; + int detailType; + QString detailData; + + QByteArray toByteArray() const; +}; + +Q_DECLARE_TYPEINFO(QDeclarativeDebugData,Q_PRIMITIVE_TYPE); + class QUrl; class Q_AUTOTEST_EXPORT QDeclarativeDebugTrace : public QDeclarativeDebugService { public: - enum EventType { - FramePaint, - Mouse, - Key, - - MaximumEventType - }; - enum Message { Event, RangeStart, @@ -70,6 +74,14 @@ public: MaximumMessage }; + enum EventType { + FramePaint, + Mouse, + Key, + + MaximumEventType + }; + enum RangeType { Painting, Compiling, @@ -94,12 +106,12 @@ private: void startRangeImpl(RangeType); void rangeDataImpl(RangeType, const QString &); void endRangeImpl(RangeType); - void processMessage(const QByteArray &); + void processMessage(const QDeclarativeDebugData &); void sendMessages(); QPerformanceTimer m_timer; bool m_enabled; bool m_deferredSend; - QList m_data; + QList m_data; }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativebinding.cpp b/src/declarative/qml/qdeclarativebinding.cpp index 055d009..c8b4c7d 100644 --- a/src/declarative/qml/qdeclarativebinding.cpp +++ b/src/declarative/qml/qdeclarativebinding.cpp @@ -120,7 +120,7 @@ public: QDeclarativeBindingProfiler(QDeclarativeBinding *bind) { QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Binding); - //QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::Binding, bind->expression()); + QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::Binding, bind->expression()); } ~QDeclarativeBindingProfiler() diff --git a/tests/benchmarks/declarative/qperformancetimer/tst_qperformancetimer.cpp b/tests/benchmarks/declarative/qperformancetimer/tst_qperformancetimer.cpp index 04737e7..497a556 100644 --- a/tests/benchmarks/declarative/qperformancetimer/tst_qperformancetimer.cpp +++ b/tests/benchmarks/declarative/qperformancetimer/tst_qperformancetimer.cpp @@ -54,6 +54,7 @@ private slots: void all(); void startElapsed(); void doubleElapsed(); + void trace(); }; void tst_qperformancetimer::all() @@ -84,6 +85,16 @@ void tst_qperformancetimer::doubleElapsed() } } +void tst_qperformancetimer::trace() +{ + QString s("A decent sized string of text here."); + QBENCHMARK { + QByteArray data; + QDataStream ds(&data, QIODevice::WriteOnly); + ds << (qint64)100 << (int)5 << (int)5 << s; + } +} + QTEST_MAIN(tst_qperformancetimer) #include "tst_qperformancetimer.moc" -- cgit v0.12 From 280f67d16430ce0dcfcc31a0c88ce7156126066c Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Fri, 5 Nov 2010 15:05:53 +1000 Subject: Add additional trace range data. --- src/declarative/debugger/qdeclarativedebugtrace.cpp | 15 +++++++++++++++ src/declarative/debugger/qdeclarativedebugtrace_p.h | 2 ++ src/declarative/qml/qdeclarativeboundsignal.cpp | 1 + src/declarative/qml/qdeclarativecomponent.cpp | 4 +++- src/declarative/qml/qdeclarativeengine.cpp | 1 + src/declarative/qml/qdeclarativetypeloader.cpp | 1 + 6 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/declarative/debugger/qdeclarativedebugtrace.cpp b/src/declarative/debugger/qdeclarativedebugtrace.cpp index 7f970bf..314db70 100644 --- a/src/declarative/debugger/qdeclarativedebugtrace.cpp +++ b/src/declarative/debugger/qdeclarativedebugtrace.cpp @@ -86,6 +86,12 @@ void QDeclarativeDebugTrace::rangeData(RangeType t, const QString &data) traceInstance()->rangeDataImpl(t, data); } +void QDeclarativeDebugTrace::rangeData(RangeType t, const QUrl &data) +{ + if (QDeclarativeDebugService::isDebuggingEnabled()) + traceInstance()->rangeDataImpl(t, data); +} + void QDeclarativeDebugTrace::endRange(RangeType t) { if (QDeclarativeDebugService::isDebuggingEnabled()) @@ -119,6 +125,15 @@ void QDeclarativeDebugTrace::rangeDataImpl(RangeType range, const QString &rData processMessage(rd); } +void QDeclarativeDebugTrace::rangeDataImpl(RangeType range, const QUrl &rData) +{ + if (status() != Enabled || !m_enabled) + return; + + QDeclarativeDebugData rd = {m_timer.elapsed(), (int)RangeData, (int)range, rData.toEncoded(QUrl::FormattingOption(0x100))}; + processMessage(rd); +} + void QDeclarativeDebugTrace::endRangeImpl(RangeType range) { if (status() != Enabled || !m_enabled) diff --git a/src/declarative/debugger/qdeclarativedebugtrace_p.h b/src/declarative/debugger/qdeclarativedebugtrace_p.h index 86c0987..3f9b904 100644 --- a/src/declarative/debugger/qdeclarativedebugtrace_p.h +++ b/src/declarative/debugger/qdeclarativedebugtrace_p.h @@ -96,6 +96,7 @@ public: static void startRange(RangeType); static void rangeData(RangeType, const QString &); + static void rangeData(RangeType, const QUrl &); static void endRange(RangeType); QDeclarativeDebugTrace(); @@ -105,6 +106,7 @@ private: void addEventImpl(EventType); void startRangeImpl(RangeType); void rangeDataImpl(RangeType, const QString &); + void rangeDataImpl(RangeType, const QUrl &); void endRangeImpl(RangeType); void processMessage(const QDeclarativeDebugData &); void sendMessages(); diff --git a/src/declarative/qml/qdeclarativeboundsignal.cpp b/src/declarative/qml/qdeclarativeboundsignal.cpp index 1bb92dd..030fb2c 100644 --- a/src/declarative/qml/qdeclarativeboundsignal.cpp +++ b/src/declarative/qml/qdeclarativeboundsignal.cpp @@ -167,6 +167,7 @@ int QDeclarativeBoundSignal::qt_metacall(QMetaObject::Call c, int id, void **a) { if (c == QMetaObject::InvokeMetaMethod && id == evaluateIdx) { QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::HandlingSignal); + QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::HandlingSignal, QLatin1String(m_signal.signature()) + QLatin1String(": ") + (m_expression ? m_expression->expression() : "")); m_isEvaluating = true; if (!m_paramsValid) { if (!m_signal.parameterTypes().isEmpty()) diff --git a/src/declarative/qml/qdeclarativecomponent.cpp b/src/declarative/qml/qdeclarativecomponent.cpp index 2686ce3..5be41ab 100644 --- a/src/declarative/qml/qdeclarativecomponent.cpp +++ b/src/declarative/qml/qdeclarativecomponent.cpp @@ -785,8 +785,10 @@ QObject * QDeclarativeComponentPrivate::begin(QDeclarativeContextData *parentCon Q_ASSERT(!isRoot || state); // Either this isn't a root component, or a state data must be provided Q_ASSERT((state != 0) ^ (errors != 0)); // One of state or errors (but not both) must be provided - if (isRoot) + if (isRoot) { QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Creating); + QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::Creating, component->url); + } QDeclarativeContextData *ctxt = new QDeclarativeContextData; ctxt->isInternal = true; diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp index dac40b0..5122bdf 100644 --- a/src/declarative/qml/qdeclarativeengine.cpp +++ b/src/declarative/qml/qdeclarativeengine.cpp @@ -929,6 +929,7 @@ Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object) if (data && data->deferredComponent) { QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Creating); + QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::Creating, QLatin1String("Deferred Creation:") + object->metaObject()->className()); QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(data->context->engine); QDeclarativeComponentPrivate::ConstructionState state; diff --git a/src/declarative/qml/qdeclarativetypeloader.cpp b/src/declarative/qml/qdeclarativetypeloader.cpp index d9b4c54..f42e8a7 100644 --- a/src/declarative/qml/qdeclarativetypeloader.cpp +++ b/src/declarative/qml/qdeclarativetypeloader.cpp @@ -901,6 +901,7 @@ void QDeclarativeTypeData::compile() m_compiledData = new QDeclarativeCompiledData(typeLoader()->engine()); m_compiledData->url = m_imports.baseUrl(); m_compiledData->name = m_compiledData->url.toString(); + QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::Compiling, m_compiledData->name); QDeclarativeCompiler compiler; if (!compiler.compile(typeLoader()->engine(), this, m_compiledData)) { -- cgit v0.12 From e64535b227599b5adb8847dfda0b2516ae7e5625 Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Wed, 10 Nov 2010 14:43:11 +1000 Subject: Fix ListModel::set() to update the model cache when setting a list value Task-number: QTBUG-15190 --- src/declarative/util/qdeclarativelistmodel.cpp | 2 ++ .../qdeclarativelistmodel/data/setmodelcachelist.qml | 20 ++++++++++++++++++++ .../tst_qdeclarativelistmodel.cpp | 12 ++++++++++++ 3 files changed, 34 insertions(+) create mode 100644 tests/auto/declarative/qdeclarativelistmodel/data/setmodelcachelist.qml diff --git a/src/declarative/util/qdeclarativelistmodel.cpp b/src/declarative/util/qdeclarativelistmodel.cpp index 398480e..538e8af 100644 --- a/src/declarative/util/qdeclarativelistmodel.cpp +++ b/src/declarative/util/qdeclarativelistmodel.cpp @@ -1450,6 +1450,8 @@ void ModelNode::setObjectValue(const QScriptValue& valuemap, bool writeToCache) if (v.isArray()) { value->isArray = true; value->setListValue(v); + if (writeToCache && objectCache) + objectCache->setValue(it.name().toUtf8(), QVariant::fromValue(value->model(m_model))); } else { value->values << v.toVariant(); if (writeToCache && objectCache) diff --git a/tests/auto/declarative/qdeclarativelistmodel/data/setmodelcachelist.qml b/tests/auto/declarative/qdeclarativelistmodel/data/setmodelcachelist.qml new file mode 100644 index 0000000..ffe417a --- /dev/null +++ b/tests/auto/declarative/qdeclarativelistmodel/data/setmodelcachelist.qml @@ -0,0 +1,20 @@ +import QtQuick 1.0 + +ListModel { + id: model + property bool ok : false + + Component.onCompleted: { + model.append({"attrs": []}) + model.get(0) + model.set(0, {"attrs": [{'abc': 123, 'def': 456}] } ) + ok = ( model.get(0).attrs.get(0).abc == 123 + && model.get(0).attrs.get(0).def == 456 ) + + model.set(0, {"attrs": [{'abc': 789, 'def': 101}] } ) + ok = ( model.get(0).attrs.get(0).abc == 789 + && model.get(0).attrs.get(0).def == 101 ) + + } +} + diff --git a/tests/auto/declarative/qdeclarativelistmodel/tst_qdeclarativelistmodel.cpp b/tests/auto/declarative/qdeclarativelistmodel/tst_qdeclarativelistmodel.cpp index 4b8d772..55f7421 100644 --- a/tests/auto/declarative/qdeclarativelistmodel/tst_qdeclarativelistmodel.cpp +++ b/tests/auto/declarative/qdeclarativelistmodel/tst_qdeclarativelistmodel.cpp @@ -100,6 +100,7 @@ private slots: void get_nested(); void get_nested_data(); void crash_model_with_multiple_roles(); + void set_model_cache(); }; int tst_qdeclarativelistmodel::roleFromName(const QDeclarativeListModel *model, const QString &roleName) { @@ -928,6 +929,17 @@ void tst_qdeclarativelistmodel::crash_model_with_multiple_roles() model->setProperty(0, "black", true); } +//QTBUG-15190 +void tst_qdeclarativelistmodel::set_model_cache() +{ + QDeclarativeEngine eng; + QDeclarativeComponent component(&eng, QUrl::fromLocalFile(SRCDIR "/data/setmodelcachelist.qml")); + QObject *model = component.create(); + QVERIFY2(component.errorString().isEmpty(), QTest::toString(component.errorString())); + QVERIFY(model != 0); + QVERIFY(model->property("ok").toBool()); +} + QTEST_MAIN(tst_qdeclarativelistmodel) #include "tst_qdeclarativelistmodel.moc" -- cgit v0.12 From 940856ee20287ce0a61cfaf46012dd5509f857b5 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Mon, 29 Nov 2010 09:10:08 +1000 Subject: Add PinchArea. Provides two finger gestures: zoom, rotate, pan. Task-number: QTBUG-15491 Reviewed-by: Aaron Kennedy --- src/declarative/graphicsitems/graphicsitems.pri | 7 +- .../graphicsitems/qdeclarativeitemsmodule.cpp | 4 + .../graphicsitems/qdeclarativepincharea.cpp | 579 +++++++++++++++++++++ .../graphicsitems/qdeclarativepincharea_p.h | 308 +++++++++++ .../graphicsitems/qdeclarativepincharea_p_p.h | 109 ++++ .../qdeclarativepincharea/data/pinchproperties.qml | 46 ++ .../qdeclarativepincharea.pro | 16 + .../tst_qdeclarativepincharea.cpp | 315 +++++++++++ 8 files changed, 1382 insertions(+), 2 deletions(-) create mode 100644 src/declarative/graphicsitems/qdeclarativepincharea.cpp create mode 100644 src/declarative/graphicsitems/qdeclarativepincharea_p.h create mode 100644 src/declarative/graphicsitems/qdeclarativepincharea_p_p.h create mode 100644 tests/auto/declarative/qdeclarativepincharea/data/pinchproperties.qml create mode 100644 tests/auto/declarative/qdeclarativepincharea/qdeclarativepincharea.pro create mode 100644 tests/auto/declarative/qdeclarativepincharea/tst_qdeclarativepincharea.cpp diff --git a/src/declarative/graphicsitems/graphicsitems.pri b/src/declarative/graphicsitems/graphicsitems.pri index ffdeb29..2cd3323 100644 --- a/src/declarative/graphicsitems/graphicsitems.pri +++ b/src/declarative/graphicsitems/graphicsitems.pri @@ -50,7 +50,9 @@ HEADERS += \ $$PWD/qdeclarativelayoutitem_p.h \ $$PWD/qdeclarativeitemchangelistener_p.h \ $$PWD/qdeclarativegraphicswidget_p.h \ - $$PWD/qdeclarativetextlayout_p.h + $$PWD/qdeclarativetextlayout_p.h \ + $$PWD/qdeclarativepincharea_p.h \ + $$PWD/qdeclarativepincharea_p_p.h SOURCES += \ $$PWD/qdeclarativeitemsmodule.cpp \ @@ -83,5 +85,6 @@ SOURCES += \ $$PWD/qdeclarativelistview.cpp \ $$PWD/qdeclarativelayoutitem.cpp \ $$PWD/qdeclarativegraphicswidget.cpp \ - $$PWD/qdeclarativetextlayout.cpp + $$PWD/qdeclarativetextlayout.cpp \ + $$PWD/qdeclarativepincharea.cpp diff --git a/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp b/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp index 52703c2..a462763 100644 --- a/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp +++ b/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp @@ -78,6 +78,7 @@ #include "private/qdeclarativewebview_p_p.h" #endif #include "private/qdeclarativeanchors_p.h" +#include "private/qdeclarativepincharea_p.h" static QDeclarativePrivate::AutoParentResult qgraphicsobject_autoParent(QObject *obj, QObject *parent) { @@ -147,10 +148,13 @@ void QDeclarativeItemModule::defineModule() qmlRegisterType("QtQuick",1,0,"ViewSection"); qmlRegisterType("QtQuick",1,0,"VisualDataModel"); qmlRegisterType("QtQuick",1,0,"VisualItemModel"); + qmlRegisterType("QtQuick",1,1,"PinchArea"); + qmlRegisterType(); qmlRegisterType(); qmlRegisterType(); qmlRegisterType(); + qmlRegisterType(); qmlRegisterType(); qmlRegisterType("QtQuick",1,0,"QGraphicsWidget"); qmlRegisterExtendedType("QtQuick",1,0,"QGraphicsWidget"); diff --git a/src/declarative/graphicsitems/qdeclarativepincharea.cpp b/src/declarative/graphicsitems/qdeclarativepincharea.cpp new file mode 100644 index 0000000..998c30d --- /dev/null +++ b/src/declarative/graphicsitems/qdeclarativepincharea.cpp @@ -0,0 +1,579 @@ +/**************************************************************************** +** +** 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 "qdeclarativepincharea_p.h" +#include "qdeclarativepincharea_p_p.h" + +#include +#include + +#include +#include + +QT_BEGIN_NAMESPACE + + +/*! + \qmlclass PinchEvent QDeclarativePinchEvent + \ingroup qml-event-elements + \brief The PinchEvent object provides information about a pinch event. + + \bold {The PinchEvent element was added in QtQuick 1.1} + + The \c center, \c startCenter, \c lastCenter properties provide the center position between the two touch points. + + The \c scale and \c lastScale properties provide the scale factor. + + The \c angle, \c lastAngle and \c rotation properties provide the angle between the two points and the amount of rotation. + + The \c point1, \c point2, \c startPoint1, \c startPoint2 properties provide the positions of the touch points. + + The \c accepted property may be set to false in the \c onPinchStarted handler if the gesture should not + be handled. + + \sa PinchArea +*/ + +/*! + \qmlproperty QPointF PinchEvent::center + \qmlproperty QPointF PinchEvent::startCenter + \qmlproperty QPointF PinchEvent::lastCenter + + These properties hold the position of the center point between the two touch points. + + \list + \o \c center is the current center point + \o \c lastCenter is the center point of the previous event. + \o \c startCenter is the center point when the gesture began + \endlist +*/ + +/*! + \qmlproperty real PinchEvent::scale + \qmlproperty real PinchEvent::lastScale + + These properties hold the scale factor determined by the change in distance between the two touch points. + + \list + \o \c scale is the current scale factor. + \o \c lastScale is the scale factor of the previous event. + \endlist + + When a pinch gesture is started, the scale is 1.0. +*/ + +/*! + \qmlproperty real PinchEvent::angle + \qmlproperty real PinchEvent::lastAngle + \qmlproperty real PinchEvent::rotation + + These properties hold the angle between the two touch points. + + \list + \o \c angle is the current angle between the two points in the range -180 to 180. + \o \c lastAngle is the angle of the previous event. + \o \c rotation is the total rotation since the pinch gesture started. + \endlist + + When a pinch gesture is started, the rotation is 0.0. +*/ + +/*! + \qmlproperty QPointF PinchEvent::point1 + \qmlproperty QPointF PinchEvent::startPoint1 + \qmlproperty QPointF PinchEvent::point2 + \qmlproperty QPointF PinchEvent::startPoint2 + + These properties provide the actual touch points generating the pinch. + + \list + \o \c point1 and \c point2 hold the current positions of the points. + \o \c startPoint1 and \c startPoint2 hold the positions of the points when the second point was touched. + \endlist +*/ + +/*! + \qmlproperty bool PinchEvent::accepted + + Setting this property to false in the \c PinchArea::onPinchStarted handler + will result in no further pinch events being generated, and the gesture + ignored. +*/ + +QDeclarativePinch::QDeclarativePinch() + : m_target(0), m_minScale(1.0), m_maxScale(1.0) + , m_minRotation(0.0), m_maxRotation(0.0) + , m_axis(NoDrag), m_xmin(-FLT_MAX), m_xmax(FLT_MAX) + , m_ymin(-FLT_MAX), m_ymax(FLT_MAX), m_active(false) +{ +} + +QDeclarativePinchAreaPrivate::~QDeclarativePinchAreaPrivate() +{ + delete pinch; +} + +/*! + \qmlclass PinchArea QDeclarativePinchArea + \brief The PinchArea item enables simple pinch gesture handling. + \inherits Item + + \bold {The PinchArea element was added in QtQuick 1.1} + + A PinchArea is an invisible item that is typically used in conjunction with + a visible item in order to provide pinch gesture handling for that item. + + The \l enabled property is used to enable and disable pinch handling for + the proxied item. When disabled, the pinch area becomes transparent to + mouse/touch events. + + PinchArea can be used in two ways: + + \list + \o setting a \c pinch.target to provide automatic interaction with an element + \o using the onPinchStarted, onPinchChanged and onPinchFinished handlers + \endlist + + \sa PinchEvent +*/ + +/*! + \qmlsignal PinchArea::onPinchStarted() + + This handler is called when the pinch area detects that a pinch gesture has started. + + The \l {PinchEvent}{pinch} parameter provides information about the pinch gesture, + including the scale, center and angle of the pinch. + + To ignore this gesture set the \c pinch.accepted property to false. The gesture + will be cancelled and no further events will be sent. +*/ + +/*! + \qmlsignal PinchArea::onPinchChanged() + + This handler is called when the pinch area detects that a pinch gesture has changed. + + The \l {PinchEvent}{pinch} parameter provides information about the pinch gesture, + including the scale, center and angle of the pinch. +*/ + +/*! + \qmlsignal PinchArea::onPinchFinished() + + This handler is called when the pinch area detects that a pinch gesture has finished. + + The \l {PinchEvent}{pinch} parameter provides information about the pinch gesture, + including the scale, center and angle of the pinch. +*/ + + +/*! + \qmlproperty Item PinchArea::pinch.target + \qmlproperty bool PinchArea::pinch.active + \qmlproperty real PinchArea::pinch.minimumScale + \qmlproperty real PinchArea::pinch.maximumScale + \qmlproperty real PinchArea::pinch.minimumRotation + \qmlproperty real PinchArea::pinch.maximumRotation + \qmlproperty enumeration PinchArea::pinch.dragAxis + \qmlproperty real PinchArea::pinch.minimumX + \qmlproperty real PinchArea::pinch.maximumX + \qmlproperty real PinchArea::pinch.minimumY + \qmlproperty real PinchArea::pinch.maximumY + + \c pinch provides a convenient way to make an item react to pinch gestures. + + \list + \i \c pinch.target specifies the id of the item to drag. + \i \c pinch.active specifies if the target item is currently being dragged. + \i \c pinch.minimumScale and \c pinch.maximumScale limit the range of the Item::scale property. + \i \c pinch.minimumRotation and \c pinch.maximumRotation limit the range of the Item::rotation property. + \i \c pinch.dragAxis specifies whether dragging in not allowed (\c Pinch.NoDrag), can be done horizontally (\c Pinch.XAxis), vertically (\c Pinch.YAxis), or both (\c Pinch.XandYAxis) + \i \c pinch.minimum and \c pinch.maximum limit how far the target can be dragged along the corresponding axes. + \endlist +*/ + +QDeclarativePinchArea::QDeclarativePinchArea(QDeclarativeItem *parent) + : QDeclarativeItem(*(new QDeclarativePinchAreaPrivate), parent) +{ + Q_D(QDeclarativePinchArea); + d->init(); +} + +QDeclarativePinchArea::~QDeclarativePinchArea() +{ +} + +/*! + \qmlproperty bool PinchArea::enabled + This property holds whether the item accepts pinch gestures. + + This property defaults to true. +*/ +bool QDeclarativePinchArea::isEnabled() const +{ + Q_D(const QDeclarativePinchArea); + return d->absorb; +} + +void QDeclarativePinchArea::setEnabled(bool a) +{ + Q_D(QDeclarativePinchArea); + if (a != d->absorb) { + d->absorb = a; + emit enabledChanged(); + } +} + +bool QDeclarativePinchArea::event(QEvent *event) +{ + Q_D(QDeclarativePinchArea); + if (!d->absorb || !isVisible()) + return QDeclarativeItem::event(event); + switch (event->type()) { + case QEvent::TouchBegin: + case QEvent::TouchUpdate: { + QTouchEvent *touch = static_cast(event); + d->touchPoints.clear(); + for (int i = 0; i < touch->touchPoints().count(); ++i) { + if (!(touch->touchPoints().at(i).state() & Qt::TouchPointReleased)) { + d->touchPoints << touch->touchPoints().at(i); + } + } + updatePinch(); + } + return true; + case QEvent::TouchEnd: + d->touchPoints.clear(); + updatePinch(); + break; + default: + return QDeclarativeItem::event(event); + } + + return QDeclarativeItem::event(event); +} + +void QDeclarativePinchArea::updatePinch() +{ + Q_D(QDeclarativePinchArea); + if (d->touchPoints.count() != 2) { + if (d->inPinch) { + d->stealMouse = false; + setKeepMouseGrab(false); + d->inPinch = false; + const qreal rotationAngle = d->pinchStartAngle - d->pinchLastAngle; + QPointF pinchCenter = mapFromScene(d->sceneLastCenter); + QDeclarativePinchEvent pe(pinchCenter, d->pinchLastScale, d->pinchLastAngle, rotationAngle); + pe.setStartCenter(d->pinchStartCenter); + pe.setLastCenter(pinchCenter); + pe.setLastAngle(d->pinchLastAngle); + pe.setLastScale(d->pinchLastScale); + pe.setStartPoint1(mapFromScene(d->sceneStartPoint1)); + pe.setStartPoint2(mapFromScene(d->sceneStartPoint2)); + pe.setPoint1(d->lastPoint1); + pe.setPoint2(d->lastPoint2); + emit pinchFinished(&pe); + if (d->pinch && d->pinch->target()) + d->pinch->setActive(false); + } + return; + } + if (d->touchPoints.at(0).state() & Qt::TouchPointPressed + || d->touchPoints.at(1).state() & Qt::TouchPointPressed) { + d->sceneStartPoint1 = d->touchPoints.at(0).scenePos(); + d->sceneStartPoint2 = d->touchPoints.at(1).scenePos(); + d->inPinch = false; + d->pinchRejected = false; + } else if (!d->pinchRejected){ + QDeclarativeItem *grabber = scene() ? qobject_cast(scene()->mouseGrabberItem()) : 0; + if (grabber == this || !grabber || !grabber->keepMouseGrab()) { + const int dragThreshold = QApplication::startDragDistance(); + QPointF p1 = d->touchPoints.at(0).scenePos(); + QPointF p2 = d->touchPoints.at(1).scenePos(); + qreal dx = p1.x() - p2.x(); + qreal dy = p1.y() - p2.y(); + qreal dist = sqrt(dx*dx + dy*dy); + QPointF sceneCenter = (p1 + p2)/2; + qreal angle = QLineF(p1, p2).angle(); + if (angle > 180) + angle -= 360; + if (!d->inPinch) { + if (qAbs(p1.x()-d->sceneStartPoint1.x()) > dragThreshold + || qAbs(p1.y()-d->sceneStartPoint1.y()) > dragThreshold + || qAbs(p2.x()-d->sceneStartPoint2.x()) > dragThreshold + || qAbs(p2.y()-d->sceneStartPoint2.y()) > dragThreshold) { + d->sceneStartCenter = sceneCenter; + d->sceneLastCenter = sceneCenter; + d->pinchStartCenter = mapFromScene(sceneCenter); + d->pinchStartDist = dist; + d->pinchStartAngle = angle; + d->pinchLastScale = 1.0; + d->pinchLastAngle = angle; + d->lastPoint1 = d->touchPoints.at(0).pos(); + d->lastPoint2 = d->touchPoints.at(1).pos(); + QDeclarativePinchEvent pe(d->pinchStartCenter, 1.0, angle, 0.0); + pe.setStartCenter(d->pinchStartCenter); + pe.setLastCenter(d->pinchStartCenter); + pe.setLastAngle(d->pinchLastAngle); + pe.setLastScale(d->pinchLastScale); + pe.setStartPoint1(mapFromScene(d->sceneStartPoint1)); + pe.setStartPoint2(mapFromScene(d->sceneStartPoint2)); + pe.setPoint1(d->lastPoint1); + pe.setPoint2(d->lastPoint2); + emit pinchStarted(&pe); + if (pe.accepted()) { + d->inPinch = true; + d->stealMouse = true; + grabMouse(); + setKeepMouseGrab(true); + if (d->pinch && d->pinch->target()) { + d->pinchStartPos = pinch()->target()->pos(); + d->pinchStartScale = d->pinch->target()->scale(); + d->pinchStartRotation = d->pinch->target()->rotation(); + d->pinch->setActive(true); + } + } else { + d->pinchRejected = true; + } + } + } else if (d->pinchStartDist > 0) { + qreal scale = dist / d->pinchStartDist; + qreal rotationAngle = d->pinchStartAngle - angle; + if (rotationAngle > 180) + rotationAngle -= 360; + QPointF pinchCenter = mapFromScene(sceneCenter); + QDeclarativePinchEvent pe(pinchCenter, scale, angle, rotationAngle); + pe.setStartCenter(d->pinchStartCenter); + pe.setLastCenter(mapFromScene(d->sceneLastCenter)); + pe.setLastAngle(d->pinchLastAngle); + pe.setLastScale(d->pinchLastScale); + pe.setStartPoint1(mapFromScene(d->sceneStartPoint1)); + pe.setStartPoint2(mapFromScene(d->sceneStartPoint2)); + pe.setPoint1(d->touchPoints.at(0).pos()); + pe.setPoint2(d->touchPoints.at(1).pos()); + d->pinchLastScale = scale; + d->sceneLastCenter = sceneCenter; + d->pinchLastAngle = angle; + d->lastPoint1 = d->touchPoints.at(0).pos(); + d->lastPoint2 = d->touchPoints.at(1).pos(); + emit pinchChanged(&pe); + if (d->pinch && d->pinch->target()) { + qreal s = d->pinchStartScale * scale; + s = qMin(qMax(pinch()->minimumScale(),s), pinch()->maximumScale()); + pinch()->target()->setScale(s); + QPointF pos = sceneCenter - d->sceneStartCenter + d->pinchStartPos; + if (pinch()->axis() & QDeclarativePinch::XAxis) { + qreal x = pos.x(); + if (x < pinch()->xmin()) + x = pinch()->xmin(); + else if (x > pinch()->xmax()) + x = pinch()->xmax(); + pinch()->target()->setX(x); + } + if (pinch()->axis() & QDeclarativePinch::YAxis) { + qreal y = pos.y(); + if (y < pinch()->ymin()) + y = pinch()->ymin(); + else if (y > pinch()->ymax()) + y = pinch()->ymax(); + pinch()->target()->setY(y); + } + if (d->pinchStartRotation >= pinch()->minimumRotation() + && d->pinchStartRotation <= pinch()->maximumRotation()) { + qreal r = rotationAngle + d->pinchStartRotation; + r = qMin(qMax(pinch()->minimumRotation(),r), pinch()->maximumRotation()); + pinch()->target()->setRotation(r); + } + } + } + } + } +} + +void QDeclarativePinchArea::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + Q_D(QDeclarativePinchArea); + d->stealMouse = false; + if (!d->absorb) + QDeclarativeItem::mousePressEvent(event); + else { + setKeepMouseGrab(false); + event->setAccepted(true); + } +} + +void QDeclarativePinchArea::mouseMoveEvent(QGraphicsSceneMouseEvent *event) +{ + Q_D(QDeclarativePinchArea); + if (!d->absorb) { + QDeclarativeItem::mouseMoveEvent(event); + return; + } +} + +void QDeclarativePinchArea::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +{ + Q_D(QDeclarativePinchArea); + d->stealMouse = false; + if (!d->absorb) { + QDeclarativeItem::mouseReleaseEvent(event); + } else { + QGraphicsScene *s = scene(); + if (s && s->mouseGrabberItem() == this) + ungrabMouse(); + setKeepMouseGrab(false); + } +} + +bool QDeclarativePinchArea::sceneEvent(QEvent *event) +{ + bool rv = QDeclarativeItem::sceneEvent(event); + if (event->type() == QEvent::UngrabMouse) { + setKeepMouseGrab(false); + } + return rv; +} + +bool QDeclarativePinchArea::sendMouseEvent(QGraphicsSceneMouseEvent *event) +{ + Q_D(QDeclarativePinchArea); + QGraphicsSceneMouseEvent mouseEvent(event->type()); + QRectF myRect = mapToScene(QRectF(0, 0, width(), height())).boundingRect(); + + QGraphicsScene *s = scene(); + QDeclarativeItem *grabber = s ? qobject_cast(s->mouseGrabberItem()) : 0; + bool stealThisEvent = d->stealMouse; + if ((stealThisEvent || myRect.contains(event->scenePos().toPoint())) && (!grabber || !grabber->keepMouseGrab())) { + mouseEvent.setAccepted(false); + for (int i = 0x1; i <= 0x10; i <<= 1) { + if (event->buttons() & i) { + Qt::MouseButton button = Qt::MouseButton(i); + mouseEvent.setButtonDownPos(button, mapFromScene(event->buttonDownPos(button))); + } + } + mouseEvent.setScenePos(event->scenePos()); + mouseEvent.setLastScenePos(event->lastScenePos()); + mouseEvent.setPos(mapFromScene(event->scenePos())); + mouseEvent.setLastPos(mapFromScene(event->lastScenePos())); + + switch(mouseEvent.type()) { + case QEvent::GraphicsSceneMouseMove: + mouseMoveEvent(&mouseEvent); + break; + case QEvent::GraphicsSceneMousePress: + mousePressEvent(&mouseEvent); + break; + case QEvent::GraphicsSceneMouseRelease: + mouseReleaseEvent(&mouseEvent); + break; + default: + break; + } + grabber = qobject_cast(s->mouseGrabberItem()); + if (grabber && stealThisEvent && !grabber->keepMouseGrab() && grabber != this) + grabMouse(); + + return stealThisEvent; + } + if (mouseEvent.type() == QEvent::GraphicsSceneMouseRelease) { + d->stealMouse = false; + if (s && s->mouseGrabberItem() == this) + ungrabMouse(); + setKeepMouseGrab(false); + } + return false; +} + +bool QDeclarativePinchArea::sceneEventFilter(QGraphicsItem *i, QEvent *e) +{ + Q_D(QDeclarativePinchArea); + if (!d->absorb || !isVisible()) + return QDeclarativeItem::sceneEventFilter(i, e); + switch (e->type()) { + case QEvent::GraphicsSceneMousePress: + case QEvent::GraphicsSceneMouseMove: + case QEvent::GraphicsSceneMouseRelease: + return sendMouseEvent(static_cast(e)); + break; + case QEvent::TouchBegin: + case QEvent::TouchUpdate: { + QTouchEvent *touch = static_cast(e); + d->touchPoints.clear(); + for (int i = 0; i < touch->touchPoints().count(); ++i) + if (!(touch->touchPoints().at(i).state() & Qt::TouchPointReleased)) + d->touchPoints << touch->touchPoints().at(i); + updatePinch(); + } + return d->inPinch; + case QEvent::TouchEnd: + d->touchPoints.clear(); + updatePinch(); + break; + default: + break; + } + + return QDeclarativeItem::sceneEventFilter(i, e); +} + +void QDeclarativePinchArea::geometryChanged(const QRectF &newGeometry, + const QRectF &oldGeometry) +{ + QDeclarativeItem::geometryChanged(newGeometry, oldGeometry); +} + +QVariant QDeclarativePinchArea::itemChange(GraphicsItemChange change, + const QVariant &value) +{ + return QDeclarativeItem::itemChange(change, value); +} + +QDeclarativePinch *QDeclarativePinchArea::pinch() +{ + Q_D(QDeclarativePinchArea); + if (!d->pinch) + d->pinch = new QDeclarativePinch; + return d->pinch; +} + + +QT_END_NAMESPACE diff --git a/src/declarative/graphicsitems/qdeclarativepincharea_p.h b/src/declarative/graphicsitems/qdeclarativepincharea_p.h new file mode 100644 index 0000000..9a73a17 --- /dev/null +++ b/src/declarative/graphicsitems/qdeclarativepincharea_p.h @@ -0,0 +1,308 @@ +/**************************************************************************** +** +** 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 QDECLARATIVEPINCHAREA_H +#define QDECLARATIVEPINCHAREA_H + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class Q_AUTOTEST_EXPORT QDeclarativePinch : public QObject +{ + Q_OBJECT + + Q_ENUMS(Axis) + Q_PROPERTY(QGraphicsObject *target READ target WRITE setTarget RESET resetTarget) + Q_PROPERTY(qreal minimumScale READ minimumScale WRITE setMinimumScale NOTIFY minimumScaleChanged) + Q_PROPERTY(qreal maximumScale READ maximumScale WRITE setMaximumScale NOTIFY maximumScaleChanged) + Q_PROPERTY(qreal minimumRotation READ minimumRotation WRITE setMinimumRotation NOTIFY minimumRotationChanged) + Q_PROPERTY(qreal maximumRotation READ maximumRotation WRITE setMaximumRotation NOTIFY maximumRotationChanged) + Q_PROPERTY(Axis dragAxis READ axis WRITE setAxis NOTIFY dragAxisChanged) + Q_PROPERTY(qreal minimumX READ xmin WRITE setXmin NOTIFY minimumXChanged) + Q_PROPERTY(qreal maximumX READ xmax WRITE setXmax NOTIFY maximumXChanged) + Q_PROPERTY(qreal minimumY READ ymin WRITE setYmin NOTIFY minimumYChanged) + Q_PROPERTY(qreal maximumY READ ymax WRITE setYmax NOTIFY maximumYChanged) + Q_PROPERTY(bool active READ active NOTIFY activeChanged) + +public: + QDeclarativePinch(); + + QGraphicsObject *target() const { return m_target; } + void setTarget(QGraphicsObject *target) { + if (target == m_target) + return; + m_target = target; + emit targetChanged(); + } + void resetTarget() { + if (!m_target) + return; + m_target = 0; + emit targetChanged(); + } + + qreal minimumScale() const { return m_minScale; } + void setMinimumScale(qreal s) { + if (s == m_minScale) + return; + m_minScale = s; + emit minimumScaleChanged(); + } + qreal maximumScale() const { return m_maxScale; } + void setMaximumScale(qreal s) { + if (s == m_maxScale) + return; + m_maxScale = s; + emit maximumScaleChanged(); + } + + qreal minimumRotation() const { return m_minRotation; } + void setMinimumRotation(qreal r) { + if (r == m_minRotation) + return; + m_minRotation = r; + emit minimumRotationChanged(); + } + qreal maximumRotation() const { return m_maxRotation; } + void setMaximumRotation(qreal r) { + if (r == m_maxRotation) + return; + m_maxRotation = r; + emit maximumRotationChanged(); + } + + enum Axis { NoDrag=0x00, XAxis=0x01, YAxis=0x02, XandYAxis=0x03 }; + Axis axis() const { return m_axis; } + void setAxis(Axis a) { + if (a == m_axis) + return; + m_axis = a; + emit dragAxisChanged(); + } + + qreal xmin() const { return m_xmin; } + void setXmin(qreal x) { + if (x == m_xmin) + return; + m_xmin = x; + emit minimumXChanged(); + } + qreal xmax() const { return m_xmax; } + void setXmax(qreal x) { + if (x == m_xmax) + return; + m_xmax = x; + emit maximumXChanged(); + } + qreal ymin() const { return m_ymin; } + void setYmin(qreal y) { + if (y == m_ymin) + return; + m_ymin = y; + emit minimumYChanged(); + } + qreal ymax() const { return m_ymax; } + void setYmax(qreal y) { + if (y == m_ymax) + return; + m_ymax = y; + emit maximumYChanged(); + } + + bool active() const { return m_active; } + void setActive(bool a) { + if (a == m_active) + return; + m_active = a; + emit activeChanged(); + } + +signals: + void targetChanged(); + void minimumScaleChanged(); + void maximumScaleChanged(); + void minimumRotationChanged(); + void maximumRotationChanged(); + void dragAxisChanged(); + void minimumXChanged(); + void maximumXChanged(); + void minimumYChanged(); + void maximumYChanged(); + void activeChanged(); + +private: + QGraphicsObject *m_target; + qreal m_minScale; + qreal m_maxScale; + qreal m_minRotation; + qreal m_maxRotation; + Axis m_axis; + qreal m_xmin; + qreal m_xmax; + qreal m_ymin; + qreal m_ymax; + bool m_active; +}; + +class Q_AUTOTEST_EXPORT QDeclarativePinchEvent : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QPointF center READ center) + Q_PROPERTY(QPointF startCenter READ startCenter) + Q_PROPERTY(QPointF lastCenter READ lastCenter) + Q_PROPERTY(qreal scale READ scale) + Q_PROPERTY(qreal lastScale READ lastScale) + Q_PROPERTY(qreal angle READ angle) + Q_PROPERTY(qreal lastAngle READ lastAngle) + Q_PROPERTY(qreal rotation READ rotation) + Q_PROPERTY(QPointF point1 READ point1) + Q_PROPERTY(QPointF startPoint1 READ startPoint1) + Q_PROPERTY(QPointF point2 READ point2) + Q_PROPERTY(QPointF startPoint2 READ startPoint2) + Q_PROPERTY(bool accepted READ accepted WRITE setAccepted) + +public: + QDeclarativePinchEvent(QPointF c, qreal s, qreal a, qreal r) + : QObject(), m_center(c), m_scale(s), m_angle(a), m_rotation(r) {} + + QPointF center() const { return m_center; } + QPointF startCenter() const { return m_startCenter; } + void setStartCenter(QPointF c) { m_startCenter = c; } + QPointF lastCenter() const { return m_lastCenter; } + void setLastCenter(QPointF c) { m_lastCenter = c; } + qreal scale() const { return m_scale; } + qreal lastScale() const { return m_lastScale; } + void setLastScale(qreal s) { m_lastScale = s; } + qreal angle() const { return m_angle; } + qreal lastAngle() const { return m_lastAngle; } + void setLastAngle(qreal a) { m_lastAngle = a; } + qreal rotation() const { return m_rotation; } + QPointF point1() const { return m_point1; } + void setPoint1(QPointF p) { m_point1 = p; } + QPointF startPoint1() const { return m_startPoint1; } + void setStartPoint1(QPointF p) { m_startPoint1 = p; } + QPointF point2() const { return m_point2; } + void setPoint2(QPointF p) { m_point2 = p; } + QPointF startPoint2() const { return m_startPoint2; } + void setStartPoint2(QPointF p) { m_startPoint2 = p; } + + bool accepted() const { return m_accepted; } + void setAccepted(bool a) { m_accepted = a; } + +private: + QPointF m_center; + QPointF m_startCenter; + QPointF m_lastCenter; + qreal m_scale; + qreal m_lastScale; + qreal m_angle; + qreal m_lastAngle; + qreal m_rotation; + QPointF m_point1; + QPointF m_point2; + QPointF m_startPoint1; + QPointF m_startPoint2; + bool m_accepted; +}; + + +class QDeclarativeMouseEvent; +class QDeclarativePinchAreaPrivate; +class Q_AUTOTEST_EXPORT QDeclarativePinchArea : public QDeclarativeItem +{ + Q_OBJECT + + Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged) + Q_PROPERTY(QDeclarativePinch *pinch READ pinch CONSTANT) + +public: + QDeclarativePinchArea(QDeclarativeItem *parent=0); + ~QDeclarativePinchArea(); + + bool isEnabled() const; + void setEnabled(bool); + + QDeclarativePinch *pinch(); + +Q_SIGNALS: + void enabledChanged(); + void pinchStarted(QDeclarativePinchEvent *pinch); + void pinchChanged(QDeclarativePinchEvent *pinch); + void pinchFinished(QDeclarativePinchEvent *pinch); + +protected: + void mousePressEvent(QGraphicsSceneMouseEvent *event); + void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); + void mouseMoveEvent(QGraphicsSceneMouseEvent *event); + bool sceneEvent(QEvent *); + bool sendMouseEvent(QGraphicsSceneMouseEvent *event); + bool sceneEventFilter(QGraphicsItem *i, QEvent *e); + bool event(QEvent *); + + virtual void geometryChanged(const QRectF &newGeometry, + const QRectF &oldGeometry); + virtual QVariant itemChange(GraphicsItemChange change, const QVariant& value); + +private: + void updatePinch(); + void handlePress(); + void handleRelease(); + +private: + Q_DISABLE_COPY(QDeclarativePinchArea) + Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarativePinchArea) +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QDeclarativePinch) +QML_DECLARE_TYPE(QDeclarativePinchEvent) +QML_DECLARE_TYPE(QDeclarativePinchArea) + +QT_END_HEADER + +#endif // QDECLARATIVEPINCHAREA_H diff --git a/src/declarative/graphicsitems/qdeclarativepincharea_p_p.h b/src/declarative/graphicsitems/qdeclarativepincharea_p_p.h new file mode 100644 index 0000000..b1cdf68 --- /dev/null +++ b/src/declarative/graphicsitems/qdeclarativepincharea_p_p.h @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** 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 QDECLARATIVEPINCHAREA_P_H +#define QDECLARATIVEPINCHAREA_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 +#include +#include +#include +#include "qdeclarativeitem_p.h" + +QT_BEGIN_NAMESPACE + +class QDeclarativePinch; +class QDeclarativePinchAreaPrivate : public QDeclarativeItemPrivate +{ + Q_DECLARE_PUBLIC(QDeclarativePinchArea) +public: + QDeclarativePinchAreaPrivate() + : absorb(true), stealMouse(false), inPinch(false) + , pinchRejected(false), pinch(0) + { + } + + ~QDeclarativePinchAreaPrivate(); + + void init() + { + Q_Q(QDeclarativePinchArea); + q->setAcceptedMouseButtons(Qt::LeftButton); + q->setAcceptTouchEvents(true); + q->setFiltersChildEvents(true); + } + + bool absorb : 1; + bool stealMouse : 1; + bool inPinch : 1; + bool pinchRejected : 1; + QDeclarativePinch *pinch; + QPointF sceneStartPoint1; + QPointF sceneStartPoint2; + QPointF lastPoint1; + QPointF lastPoint2; + qreal pinchStartDist; + qreal pinchStartScale; + qreal pinchLastScale; + qreal pinchStartRotation; + qreal pinchStartAngle; + qreal pinchLastAngle; + QPointF sceneStartCenter; + QPointF pinchStartCenter; + QPointF sceneLastCenter; + QPointF pinchStartPos; + QList touchPoints; +}; + +QT_END_NAMESPACE + +#endif // QDECLARATIVEPINCHAREA_P_H diff --git a/tests/auto/declarative/qdeclarativepincharea/data/pinchproperties.qml b/tests/auto/declarative/qdeclarativepincharea/data/pinchproperties.qml new file mode 100644 index 0000000..f39ea06 --- /dev/null +++ b/tests/auto/declarative/qdeclarativepincharea/data/pinchproperties.qml @@ -0,0 +1,46 @@ +import QtQuick 1.1 +Rectangle { + id: whiteRect + property variant center + property real scale + width: 240; height: 320 + color: "white" + Rectangle { + id: blackRect + objectName: "blackrect" + color: "black" + y: 50 + x: 50 + width: 100 + height: 100 + opacity: (whiteRect.width-blackRect.x+whiteRect.height-blackRect.y-199)/200 + Text { text: blackRect.opacity} + PinchArea { + id: pincharea + objectName: "pincharea" + anchors.fill: parent + pinch.target: blackRect + pinch.dragAxis: Drag.XandYAxis + pinch.minimumX: 0 + pinch.maximumX: whiteRect.width-blackRect.width + pinch.minimumY: 0 + pinch.maximumY: whiteRect.height-blackRect.height + pinch.minimumScale: 1.0 + pinch.maximumScale: 2.0 + pinch.minimumRotation: 0.0 + pinch.maximumRotation: 90.0 + onPinchStarted: { + whiteRect.center = pinch.center + whiteRect.scale = pinch.scale + } + onPinchChanged: { + whiteRect.center = pinch.center + whiteRect.scale = pinch.scale + } + onPinchFinished: { + whiteRect.center = pinch.center + whiteRect.scale = pinch.scale + } + } + } + } diff --git a/tests/auto/declarative/qdeclarativepincharea/qdeclarativepincharea.pro b/tests/auto/declarative/qdeclarativepincharea/qdeclarativepincharea.pro new file mode 100644 index 0000000..2c13644 --- /dev/null +++ b/tests/auto/declarative/qdeclarativepincharea/qdeclarativepincharea.pro @@ -0,0 +1,16 @@ +load(qttest_p4) +contains(QT_CONFIG,declarative): QT += declarative gui +macx:CONFIG -= app_bundle + +SOURCES += tst_qdeclarativepincharea.cpp + +symbian: { + importFiles.sources = data + importFiles.path = . + DEPLOYMENT = importFiles +} else { + DEFINES += SRCDIR=\\\"$$PWD\\\" +} + +CONFIG += parallel_test + diff --git a/tests/auto/declarative/qdeclarativepincharea/tst_qdeclarativepincharea.cpp b/tests/auto/declarative/qdeclarativepincharea/tst_qdeclarativepincharea.cpp new file mode 100644 index 0000000..d1015fc --- /dev/null +++ b/tests/auto/declarative/qdeclarativepincharea/tst_qdeclarativepincharea.cpp @@ -0,0 +1,315 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite 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 +#include +#include +#include +#include +#include + +#ifdef Q_OS_SYMBIAN +// In Symbian OS test data is located in applications private dir +#define SRCDIR "." +#endif + +class tst_QDeclarativePinchArea: public QObject +{ + Q_OBJECT +private slots: + void pinchProperties(); + void scale(); + void pan(); + +private: + QDeclarativeView *createView(); +}; + +void tst_QDeclarativePinchArea::pinchProperties() +{ + QDeclarativeView *canvas = createView(); + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/pinchproperties.qml")); + canvas->show(); + canvas->setFocus(); + QVERIFY(canvas->rootObject() != 0); + + QDeclarativePinchArea *pinchArea = canvas->rootObject()->findChild("pincharea"); + QDeclarativePinch *pinch = pinchArea->pinch(); + QVERIFY(pinchArea != 0); + QVERIFY(pinch != 0); + + // target + QDeclarativeItem *blackRect = canvas->rootObject()->findChild("blackrect"); + QVERIFY(blackRect != 0); + QVERIFY(blackRect == pinch->target()); + QDeclarativeItem *rootItem = qobject_cast(canvas->rootObject()); + QVERIFY(rootItem != 0); + QSignalSpy targetSpy(pinch, SIGNAL(targetChanged())); + pinch->setTarget(rootItem); + QCOMPARE(targetSpy.count(),1); + pinch->setTarget(rootItem); + QCOMPARE(targetSpy.count(),1); + + // axis + QCOMPARE(pinch->axis(), QDeclarativePinch::XandYAxis); + QSignalSpy axisSpy(pinch, SIGNAL(dragAxisChanged())); + pinch->setAxis(QDeclarativePinch::XAxis); + QCOMPARE(pinch->axis(), QDeclarativePinch::XAxis); + QCOMPARE(axisSpy.count(),1); + pinch->setAxis(QDeclarativePinch::XAxis); + QCOMPARE(axisSpy.count(),1); + + // minimum and maximum drag properties + QSignalSpy xminSpy(pinch, SIGNAL(minimumXChanged())); + QSignalSpy xmaxSpy(pinch, SIGNAL(maximumXChanged())); + QSignalSpy yminSpy(pinch, SIGNAL(minimumYChanged())); + QSignalSpy ymaxSpy(pinch, SIGNAL(maximumYChanged())); + + QCOMPARE(pinch->xmin(), 0.0); + QCOMPARE(pinch->xmax(), rootItem->width()-blackRect->width()); + QCOMPARE(pinch->ymin(), 0.0); + QCOMPARE(pinch->ymax(), rootItem->height()-blackRect->height()); + + pinch->setXmin(10); + pinch->setXmax(10); + pinch->setYmin(10); + pinch->setYmax(10); + + QCOMPARE(pinch->xmin(), 10.0); + QCOMPARE(pinch->xmax(), 10.0); + QCOMPARE(pinch->ymin(), 10.0); + QCOMPARE(pinch->ymax(), 10.0); + + QCOMPARE(xminSpy.count(),1); + QCOMPARE(xmaxSpy.count(),1); + QCOMPARE(yminSpy.count(),1); + QCOMPARE(ymaxSpy.count(),1); + + pinch->setXmin(10); + pinch->setXmax(10); + pinch->setYmin(10); + pinch->setYmax(10); + + QCOMPARE(xminSpy.count(),1); + QCOMPARE(xmaxSpy.count(),1); + QCOMPARE(yminSpy.count(),1); + QCOMPARE(ymaxSpy.count(),1); + + // minimum and maximum scale properties + QSignalSpy scaleMinSpy(pinch, SIGNAL(minimumScaleChanged())); + QSignalSpy scaleMaxSpy(pinch, SIGNAL(maximumScaleChanged())); + + QCOMPARE(pinch->minimumScale(), 1.0); + QCOMPARE(pinch->maximumScale(), 2.0); + + pinch->setMinimumScale(0.5); + pinch->setMaximumScale(1.5); + + QCOMPARE(pinch->minimumScale(), 0.5); + QCOMPARE(pinch->maximumScale(), 1.5); + + QCOMPARE(scaleMinSpy.count(),1); + QCOMPARE(scaleMaxSpy.count(),1); + + pinch->setMinimumScale(0.5); + pinch->setMaximumScale(1.5); + + QCOMPARE(scaleMinSpy.count(),1); + QCOMPARE(scaleMaxSpy.count(),1); + + // minimum and maximum rotation properties + QSignalSpy rotMinSpy(pinch, SIGNAL(minimumRotationChanged())); + QSignalSpy rotMaxSpy(pinch, SIGNAL(maximumRotationChanged())); + + QCOMPARE(pinch->minimumRotation(), 0.0); + QCOMPARE(pinch->maximumRotation(), 90.0); + + pinch->setMinimumRotation(-90.0); + pinch->setMaximumRotation(45.0); + + QCOMPARE(pinch->minimumRotation(), -90.0); + QCOMPARE(pinch->maximumRotation(), 45.0); + + QCOMPARE(rotMinSpy.count(),1); + QCOMPARE(rotMaxSpy.count(),1); + + pinch->setMinimumRotation(-90.0); + pinch->setMaximumRotation(45.0); + + QCOMPARE(rotMinSpy.count(),1); + QCOMPARE(rotMaxSpy.count(),1); + + delete canvas; +} + +QTouchEvent::TouchPoint makeTouchPoint(int id, QPoint p, QGraphicsView *v, QGraphicsItem *i) +{ + QTouchEvent::TouchPoint touchPoint(id); + touchPoint.setPos(i->mapFromScene(p)); + touchPoint.setScreenPos(v->mapToGlobal(p)); + touchPoint.setScenePos(p); + return touchPoint; +} + +void tst_QDeclarativePinchArea::scale() +{ + QDeclarativeView *canvas = createView(); + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/pinchproperties.qml")); + canvas->show(); + canvas->setFocus(); + QTest::qWaitForWindowShown(canvas); + QVERIFY(canvas->rootObject() != 0); + qApp->processEvents(); + + QDeclarativePinchArea *pinchArea = canvas->rootObject()->findChild("pincharea"); + QDeclarativePinch *pinch = pinchArea->pinch(); + QVERIFY(pinchArea != 0); + QVERIFY(pinch != 0); + + QDeclarativeItem *root = qobject_cast(canvas->rootObject()); + QVERIFY(root != 0); + + // target + QDeclarativeItem *blackRect = canvas->rootObject()->findChild("blackrect"); + QVERIFY(blackRect != 0); + + QWidget *vp = canvas->viewport(); + + QPoint p1(80, 80); + QPoint p2(100, 100); + + QTest::touchEvent(vp).press(0, p1); + QTest::touchEvent(vp).stationary(0).press(1, p2); + p1 -= QPoint(10,10); + p2 += QPoint(10,10); + QTest::touchEvent(vp).move(0, p1).move(1, p2); + + QCOMPARE(root->property("scale").toReal(), 1.0); + + p1 -= QPoint(10,10); + p2 += QPoint(10,10); + QTest::touchEvent(vp).move(0, p1).move(1, p2); + + QCOMPARE(root->property("scale").toReal(), 1.5); + QCOMPARE(root->property("center").toPointF(), QPointF(90, 90)); + QCOMPARE(blackRect->scale(), 1.5); + + // scale beyond bound + p1 -= QPoint(50,50); + p2 += QPoint(50,50); + QTest::touchEvent(vp).move(0, p1).move(1, p2); + + QCOMPARE(blackRect->scale(), 2.0); + + QTest::touchEvent(vp).release(0, p1).release(1, p2); + + delete canvas; +} + +void tst_QDeclarativePinchArea::pan() +{ + QDeclarativeView *canvas = createView(); + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/pinchproperties.qml")); + canvas->show(); + canvas->setFocus(); + QTest::qWaitForWindowShown(canvas); + QVERIFY(canvas->rootObject() != 0); + qApp->processEvents(); + + QDeclarativePinchArea *pinchArea = canvas->rootObject()->findChild("pincharea"); + QDeclarativePinch *pinch = pinchArea->pinch(); + QVERIFY(pinchArea != 0); + QVERIFY(pinch != 0); + + QDeclarativeItem *root = qobject_cast(canvas->rootObject()); + QVERIFY(root != 0); + + // target + QDeclarativeItem *blackRect = canvas->rootObject()->findChild("blackrect"); + QVERIFY(blackRect != 0); + + QWidget *vp = canvas->viewport(); + + QPoint p1(80, 80); + QPoint p2(100, 100); + + QTest::touchEvent(vp).press(0, p1); + QTest::touchEvent(vp).stationary(0).press(1, p2); + p1 += QPoint(10,10); + p2 += QPoint(10,10); + QTest::touchEvent(vp).move(0, p1).move(1, p2); + + QCOMPARE(root->property("scale").toReal(), 1.0); + + p1 += QPoint(10,10); + p2 += QPoint(10,10); + QTest::touchEvent(vp).move(0, p1).move(1, p2); + + QCOMPARE(root->property("center").toPointF(), QPointF(110, 110)); + + QCOMPARE(blackRect->x(), 60.0); + QCOMPARE(blackRect->y(), 60.0); + + // pan x beyond bound + p1 += QPoint(100,100); + p2 += QPoint(100,100); + QTest::touchEvent(vp).move(0, p1).move(1, p2); + + QCOMPARE(blackRect->x(), 140.0); + QCOMPARE(blackRect->y(), 160.0); + + QTest::touchEvent(vp).release(0, p1).release(1, p2); + + delete canvas; +} + +QDeclarativeView *tst_QDeclarativePinchArea::createView() +{ + QDeclarativeView *canvas = new QDeclarativeView(0); + canvas->viewport()->setAttribute(Qt::WA_AcceptTouchEvents); + canvas->setFixedSize(240,320); + + return canvas; +} + +QTEST_MAIN(tst_QDeclarativePinchArea) + +#include "tst_qdeclarativepincharea.moc" -- cgit v0.12 From 031ab2136c632d582a324941798be9e37825d287 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Mon, 29 Nov 2010 11:01:46 +1000 Subject: Allow resizing Flickable content about a center point. Useful for zooming via pinch, for example. Task-number: QTBUG-15148 Reviewed-by: Aaron Kennedy --- .../graphicsitems/qdeclarativeflickable.cpp | 54 ++++++++++++++++++++++ .../graphicsitems/qdeclarativeflickable_p.h | 4 ++ .../qdeclarativeflickable/data/resize.qml | 27 +++++++++++ .../tst_qdeclarativeflickable.cpp | 54 ++++++++++++++++++++++ 4 files changed, 139 insertions(+) create mode 100644 tests/auto/declarative/qdeclarativeflickable/data/resize.qml diff --git a/src/declarative/graphicsitems/qdeclarativeflickable.cpp b/src/declarative/graphicsitems/qdeclarativeflickable.cpp index 377f3b5..b13d82b 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable.cpp +++ b/src/declarative/graphicsitems/qdeclarativeflickable.cpp @@ -1269,6 +1269,60 @@ void QDeclarativeFlickable::setContentHeight(qreal h) d->updateBeginningEnd(); } +/*! + \qmlmethod Flickable::resizeContent(real width, real height, QPointF center) + \preliminary + + Resizes the content to \a width x \a height about \a center. + + \bold {This method was added in QtQuick 1.1.} + + This does not scale the contents of the Flickable - it only resizes the \l contentWidth + and \l contentHeight. + + Resizing the content may result in the content being positioned outside + the bounds of the Flickable. Calling \l returnToBounds() will + move the content back within legal bounds. +*/ +void QDeclarativeFlickable::resizeContent(qreal w, qreal h, QPointF center) +{ + Q_D(QDeclarativeFlickable); + if (w != d->hData.viewSize) { + qreal oldSize = d->hData.viewSize; + setContentWidth(w); + if (center.x() != 0) { + qreal pos = center.x() * w / oldSize; + setContentX(contentX() + pos - center.x()); + } + } + if (h != d->vData.viewSize) { + qreal oldSize = d->vData.viewSize; + setContentHeight(h); + if (center.y() != 0) { + qreal pos = center.y() * h / oldSize; + setContentY(contentY() + pos - center.y()); + } + } +} + +/*! + \qmlmethod Flickable::returnToBounds() + \preliminary + + Ensures the content is within legal bounds. + + \bold {This method was added in QtQuick 1.1.} + + This may be called to ensure that the content is within legal bounds + after manually positioning the content. +*/ +void QDeclarativeFlickable::returnToBounds() +{ + Q_D(QDeclarativeFlickable); + d->fixupX(); + d->fixupY(); +} + qreal QDeclarativeFlickable::vWidth() const { Q_D(const QDeclarativeFlickable); diff --git a/src/declarative/graphicsitems/qdeclarativeflickable_p.h b/src/declarative/graphicsitems/qdeclarativeflickable_p.h index 6e4d8ed..ece2db7 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable_p.h +++ b/src/declarative/graphicsitems/qdeclarativeflickable_p.h @@ -149,6 +149,10 @@ public: FlickableDirection flickableDirection() const; void setFlickableDirection(FlickableDirection); + //XXX Added in QtQuick 1.1 + Q_INVOKABLE void resizeContent(qreal w, qreal h, QPointF center); + Q_INVOKABLE void returnToBounds(); + Q_SIGNALS: void contentWidthChanged(); void contentHeightChanged(); diff --git a/tests/auto/declarative/qdeclarativeflickable/data/resize.qml b/tests/auto/declarative/qdeclarativeflickable/data/resize.qml new file mode 100644 index 0000000..e2abb99 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeflickable/data/resize.qml @@ -0,0 +1,27 @@ +import QtQuick 1.1 + +Rectangle { + function resizeContent() { + flick.resizeContent(600, 600, Qt.point(100, 100)) + } + function returnToBounds() { + flick.returnToBounds() + } + width: 400 + height: 360 + color: "gray" + + Flickable { + id: flick + objectName: "flick" + anchors.fill: parent + contentWidth: 300 + contentHeight: 300 + + Rectangle { + width: flick.contentWidth + height: flick.contentHeight + color: "red" + } + } +} diff --git a/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp b/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp index 25edb36..c1564bc 100644 --- a/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp +++ b/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp @@ -46,6 +46,7 @@ #include #include #include +#include "../../../shared/util.h" #ifdef Q_OS_SYMBIAN // In Symbian OS test data is located in applications private dir @@ -69,6 +70,8 @@ private slots: void pressDelay(); void flickableDirection(); void qgraphicswidget(); + void resizeContent(); + void returnToBounds(); private: QDeclarativeEngine engine; @@ -277,6 +280,57 @@ void tst_qdeclarativeflickable::qgraphicswidget() QVERIFY(widget); } +// QtQuick 1.1 +void tst_qdeclarativeflickable::resizeContent() +{ + QDeclarativeEngine engine; + QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/resize.qml")); + QDeclarativeItem *root = qobject_cast(c.create()); + QDeclarativeFlickable *obj = findItem(root, "flick"); + + QVERIFY(obj != 0); + QCOMPARE(obj->contentX(), 0.); + QCOMPARE(obj->contentY(), 0.); + QCOMPARE(obj->contentWidth(), 300.); + QCOMPARE(obj->contentHeight(), 300.); + + QMetaObject::invokeMethod(root, "resizeContent"); + + QCOMPARE(obj->contentX(), 100.); + QCOMPARE(obj->contentY(), 100.); + QCOMPARE(obj->contentWidth(), 600.); + QCOMPARE(obj->contentHeight(), 600.); + + delete root; +} + +// QtQuick 1.1 +void tst_qdeclarativeflickable::returnToBounds() +{ + QDeclarativeEngine engine; + QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/resize.qml")); + QDeclarativeItem *root = qobject_cast(c.create()); + QDeclarativeFlickable *obj = findItem(root, "flick"); + + QVERIFY(obj != 0); + QCOMPARE(obj->contentX(), 0.); + QCOMPARE(obj->contentY(), 0.); + QCOMPARE(obj->contentWidth(), 300.); + QCOMPARE(obj->contentHeight(), 300.); + + obj->setContentX(100); + obj->setContentY(400); + QTRY_COMPARE(obj->contentX(), 100.); + QTRY_COMPARE(obj->contentY(), 400.); + + QMetaObject::invokeMethod(root, "returnToBounds"); + + QTRY_COMPARE(obj->contentX(), 0.); + QTRY_COMPARE(obj->contentY(), 0.); + + delete root; +} + template T *tst_qdeclarativeflickable::findItem(QGraphicsObject *parent, const QString &objectName) { -- cgit v0.12 From 6258fc281f5b66b2634b81a2633b117165cea7ef Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Mon, 29 Nov 2010 11:03:31 +1000 Subject: Add an example of using PinchArea. Task-number: QTBUG-15491 --- .../touchinteraction/pincharea/flickresize.qml | 50 +++++++++++++++++++++ .../touchinteraction/pincharea/qt-logo.jpg | Bin 0 -> 40886 bytes 2 files changed, 50 insertions(+) create mode 100644 examples/declarative/touchinteraction/pincharea/flickresize.qml create mode 100644 examples/declarative/touchinteraction/pincharea/qt-logo.jpg diff --git a/examples/declarative/touchinteraction/pincharea/flickresize.qml b/examples/declarative/touchinteraction/pincharea/flickresize.qml new file mode 100644 index 0000000..8034e29 --- /dev/null +++ b/examples/declarative/touchinteraction/pincharea/flickresize.qml @@ -0,0 +1,50 @@ +import QtQuick 1.1 + +Rectangle { + width: 640 + height: 360 + color: "gray" + + Flickable { + id: flick + anchors.fill: parent + contentWidth: 500 + contentHeight: 500 + + PinchArea { + width: Math.max(flick.contentWidth, flick.width) + height: Math.max(flick.contentHeight, flick.height) + onPinchChanged: { + // adjust content pos due to drag + flick.contentX += pinch.lastCenter.x - pinch.center.x + flick.contentY += pinch.lastCenter.y - pinch.center.y + + // resize content + var scale = 1.0 + pinch.scale - pinch.lastScale + flick.resizeContent(flick.contentWidth * scale, flick.contentHeight * scale, pinch.center) + } + + onPinchFinished: { + // Move its content within bounds. + flick.returnToBounds() + } + + Rectangle { + width: flick.contentWidth + height: flick.contentHeight + color: "white" + Image { + anchors.fill: parent + source: "qt-logo.jpg" + MouseArea { + anchors.fill: parent + onDoubleClicked: { + flick.contentWidth = 500 + flick.contentHeight = 500 + } + } + } + } + } + } +} diff --git a/examples/declarative/touchinteraction/pincharea/qt-logo.jpg b/examples/declarative/touchinteraction/pincharea/qt-logo.jpg new file mode 100644 index 0000000..4014b46 Binary files /dev/null and b/examples/declarative/touchinteraction/pincharea/qt-logo.jpg differ -- cgit v0.12 From b02cf26c0c236679439826cb8093f6dd6d3b2fec Mon Sep 17 00:00:00 2001 From: Christopher Ham Date: Fri, 3 Dec 2010 16:20:58 +1000 Subject: borderImage should not support setting sourceSize SIGNAL sourceSizeChanged is properly called. Setting the sourceSize for borderImage in QML returns a warning. Auto tests were added to check that sourceSize remains consistent. Reviewed-by: Joona Petrell --- src/declarative/graphicsitems/qdeclarativeborderimage.cpp | 10 ++++++++++ src/declarative/graphicsitems/qdeclarativeborderimage_p.h | 2 ++ .../qdeclarativeborderimage/tst_qdeclarativeborderimage.cpp | 4 ++++ 3 files changed, 16 insertions(+) diff --git a/src/declarative/graphicsitems/qdeclarativeborderimage.cpp b/src/declarative/graphicsitems/qdeclarativeborderimage.cpp index c770a85..0bf09ad 100644 --- a/src/declarative/graphicsitems/qdeclarativeborderimage.cpp +++ b/src/declarative/graphicsitems/qdeclarativeborderimage.cpp @@ -246,6 +246,12 @@ void QDeclarativeBorderImage::setSource(const QUrl &url) load(); } +void QDeclarativeBorderImage::setSourceSize(const QSize& size) +{ + Q_UNUSED(size); + qmlInfo(this) << "Setting sourceSize for borderImage not supported"; +} + void QDeclarativeBorderImage::load() { Q_D(QDeclarativeBorderImage); @@ -315,6 +321,7 @@ void QDeclarativeBorderImage::load() d->progress = 1.0; emit statusChanged(d->status); emit progressChanged(d->progress); + requestFinished(); update(); } } @@ -475,6 +482,9 @@ void QDeclarativeBorderImage::requestFinished() setImplicitWidth(impsize.width()); setImplicitHeight(impsize.height()); + if (d->sourcesize.width() != d->pix.width() || d->sourcesize.height() != d->pix.height()) + emit sourceSizeChanged(); + d->progress = 1.0; emit statusChanged(d->status); emit progressChanged(1.0); diff --git a/src/declarative/graphicsitems/qdeclarativeborderimage_p.h b/src/declarative/graphicsitems/qdeclarativeborderimage_p.h index 9944cbe..7cf24f2 100644 --- a/src/declarative/graphicsitems/qdeclarativeborderimage_p.h +++ b/src/declarative/graphicsitems/qdeclarativeborderimage_p.h @@ -80,6 +80,8 @@ public: void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *); void setSource(const QUrl &url); + void setSourceSize(const QSize&); + Q_SIGNALS: void horizontalTileModeChanged(); void verticalTileModeChanged(); diff --git a/tests/auto/declarative/qdeclarativeborderimage/tst_qdeclarativeborderimage.cpp b/tests/auto/declarative/qdeclarativeborderimage/tst_qdeclarativeborderimage.cpp index 2f00f60..5478145 100644 --- a/tests/auto/declarative/qdeclarativeborderimage/tst_qdeclarativeborderimage.cpp +++ b/tests/auto/declarative/qdeclarativeborderimage/tst_qdeclarativeborderimage.cpp @@ -153,6 +153,8 @@ void tst_qdeclarativeborderimage::imageSource() QTRY_VERIFY(obj->status() == QDeclarativeBorderImage::Ready); QCOMPARE(obj->width(), 120.); QCOMPARE(obj->height(), 120.); + QCOMPARE(obj->sourceSize().width(), 120); + QCOMPARE(obj->sourceSize().height(), 120); QCOMPARE(obj->horizontalTileMode(), QDeclarativeBorderImage::Stretch); QCOMPARE(obj->verticalTileMode(), QDeclarativeBorderImage::Stretch); } else { @@ -192,6 +194,8 @@ void tst_qdeclarativeborderimage::resized() QVERIFY(obj != 0); QCOMPARE(obj->width(), 300.); QCOMPARE(obj->height(), 300.); + QCOMPARE(obj->sourceSize().width(), 120); + QCOMPARE(obj->sourceSize().height(), 120); QCOMPARE(obj->horizontalTileMode(), QDeclarativeBorderImage::Stretch); QCOMPARE(obj->verticalTileMode(), QDeclarativeBorderImage::Stretch); -- cgit v0.12 From 61a5cc5fcde2de0c3639e20104ff58ca91cf793b Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Thu, 9 Dec 2010 14:31:10 +0100 Subject: QmlDebugger: avoid deferring properties when compiling in a debug environment Reviewed-by: Kai Koehne --- src/declarative/qml/qdeclarativecompiler.cpp | 6 +- .../qdeclarativedebug/tst_qdeclarativedebug.cpp | 97 +++++++++++++++++++++- 2 files changed, 100 insertions(+), 3 deletions(-) diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp index 4749bf8..b375b27 100644 --- a/src/declarative/qml/qdeclarativecompiler.cpp +++ b/src/declarative/qml/qdeclarativecompiler.cpp @@ -65,6 +65,7 @@ #include "private/qdeclarativebinding_p.h" #include "private/qdeclarativecompiledbindings_p.h" #include "private/qdeclarativeglobalscriptclass_p.h" +#include "private/qdeclarativedebugservice_p.h" #include #include @@ -754,7 +755,10 @@ bool QDeclarativeCompiler::buildObject(Object *obj, const BindingContext &ctxt) QList customProps; // Fetch the list of deferred properties - QStringList deferredList = deferredProperties(obj); + QStringList deferredList; + if (!QDeclarativeDebugService::isDebuggingEnabled()) { + deferredList = deferredProperties(obj); + } // Must do id property first. This is to ensure that the id given to any // id reference created matches the order in which the objects are diff --git a/tests/auto/declarative/qdeclarativedebug/tst_qdeclarativedebug.cpp b/tests/auto/declarative/qdeclarativedebug/tst_qdeclarativedebug.cpp index 53471bf..20a3fa6 100644 --- a/tests/auto/declarative/qdeclarativedebug/tst_qdeclarativedebug.cpp +++ b/tests/auto/declarative/qdeclarativedebug/tst_qdeclarativedebug.cpp @@ -114,6 +114,7 @@ private slots: void tst_QDeclarativeDebugPropertyReference(); void setMethodBody(); + void queryObjectTree(); }; QDeclarativeDebugObjectReference tst_QDeclarativeDebug::findRootObject(int context) @@ -308,6 +309,34 @@ void tst_QDeclarativeDebug::initTestCase() "function myMethodIndirect() { myMethod(3); }\n" "}"; + // and a fourth to test states + qml << "import QtQuick 1.0\n" + "Rectangle {\n" + "id:rootRect\n" + "width:100\n" + "states: [\n" + "State {\n" + "name:\"state1\"\n" + "PropertyChanges {\n" + "target:rootRect\n" + "width:200\n" + "}\n" + "}\n" + "]\n" + "transitions: [\n" + "Transition {\n" + "from:\"*\"\n" + "to:\"state1\"\n" + "PropertyAnimation {\n" + "target:rootRect\n" + "property:\"width\"\n" + "duration:100\n" + "}\n" + "}\n" + "]\n" + "}\n" + ; + for (int i=0; iobjectName()); - QCOMPARE(context.objects().count(), 3); // 3 qml component objects created for context in main() + QCOMPARE(context.objects().count(), 4); // 4 qml component objects created for context in main() // root context query sends only root object data - it doesn't fill in // the children or property info QCOMPARE(context.objects()[0].properties().count(), 0); QCOMPARE(context.objects()[0].children().count(), 0); - QCOMPARE(context.contexts().count(), 4); + QCOMPARE(context.contexts().count(), 5); QVERIFY(context.contexts()[0].debugId() >= 0); QCOMPARE(context.contexts()[0].name(), QString("tst_QDeclarativeDebug_childContext")); @@ -897,6 +926,70 @@ void tst_QDeclarativeDebug::tst_QDeclarativeDebugPropertyReference() compareProperties(r, ref); } +void tst_QDeclarativeDebug::queryObjectTree() +{ + const int sourceIndex = 3; + + // Check if states/transitions are initialized when fetching root item + QDeclarativeDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this); + waitForQuery(q_engines); + + QDeclarativeDebugRootContextQuery *q_context = m_dbg->queryRootContexts(q_engines->engines()[0].debugId(), this); + waitForQuery(q_context); + + QVERIFY(q_context->rootContext().objects().count() > sourceIndex); + QDeclarativeDebugObjectReference rootObject = q_context->rootContext().objects()[sourceIndex]; + + QDeclarativeDebugObjectQuery *q_obj = m_dbg->queryObjectRecursive(rootObject, this); + waitForQuery(q_obj); + + QDeclarativeDebugObjectReference obj = q_obj->object(); + + delete q_engines; + delete q_context; + delete q_obj; + + QVERIFY(obj.debugId() != -1); + QVERIFY(obj.children().count() >= 2); + + + + // check state + QDeclarativeDebugObjectReference state = obj.children()[0]; + QCOMPARE(state.className(), QString("State")); + QVERIFY(state.children().count() > 0); + + QDeclarativeDebugObjectReference propertyChange = state.children()[0]; + QVERIFY(propertyChange.debugId() != -1); + + QDeclarativeDebugPropertyReference propertyChangeTarget = findProperty(propertyChange.properties(),"target"); + QCOMPARE(propertyChangeTarget.objectDebugId(), propertyChange.debugId()); + + QDeclarativeDebugObjectReference targetReference = qvariant_cast(propertyChangeTarget.value()); + QVERIFY(targetReference.debugId() != -1); + + + + // check transition + QDeclarativeDebugObjectReference transition = obj.children()[1]; + QCOMPARE(transition.className(), QString("Transition")); + QCOMPARE(findProperty(transition.properties(),"from").value().toString(), QString("*")); + QCOMPARE(findProperty(transition.properties(),"to").value(), findProperty(state.properties(),"name").value()); + QVERIFY(transition.children().count() > 0); + + QDeclarativeDebugObjectReference animation = transition.children()[0]; + QVERIFY(animation.debugId() != -1); + + QDeclarativeDebugPropertyReference animationTarget = findProperty(animation.properties(),"target"); + QCOMPARE(animationTarget.objectDebugId(), animation.debugId()); + + targetReference = qvariant_cast(animationTarget.value()); + QVERIFY(targetReference.debugId() != -1); + + QCOMPARE(findProperty(animation.properties(),"property").value().toString(), QString("width")); + QCOMPARE(findProperty(animation.properties(),"duration").value().toInt(), 100); +} + int main(int argc, char *argv[]) { int _argc = argc + 1; -- cgit v0.12 From f2eca0c0380a0e06ccc7f98c8d112549ac9fa085 Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Fri, 10 Dec 2010 11:24:49 +1000 Subject: Add 'mirror' property to Image element. Setting mirror to true will horizontally invert an image. This feature is part of the task to support RTL in QML (see QTBUG-11042). Task-number: QTBUG-15878 Reviewed-by: Joona Petrell --- .../graphicsitems/qdeclarativeanimatedimage.cpp | 12 ++- .../graphicsitems/qdeclarativeborderimage.cpp | 19 ++++ .../graphicsitems/qdeclarativeimage.cpp | 103 +++++++++++---------- .../graphicsitems/qdeclarativeimagebase.cpp | 20 ++++ .../graphicsitems/qdeclarativeimagebase_p.h | 5 + .../graphicsitems/qdeclarativeimagebase_p_p.h | 4 +- .../qdeclarativeanimatedimage/data/hearts.gif | Bin 0 -> 6524 bytes .../qdeclarativeanimatedimage/data/hearts.qml | 6 ++ .../tst_qdeclarativeanimatedimage.cpp | 103 +++++++++++++++++++++ .../qdeclarativeborderimage/data/heart200.png | Bin 0 -> 7943 bytes .../tst_qdeclarativeborderimage.cpp | 34 +++++++ .../qdeclarativeimage/tst_qdeclarativeimage.cpp | 86 +++++++++++++++++ 12 files changed, 343 insertions(+), 49 deletions(-) create mode 100644 tests/auto/declarative/qdeclarativeanimatedimage/data/hearts.gif create mode 100644 tests/auto/declarative/qdeclarativeanimatedimage/data/hearts.qml create mode 100644 tests/auto/declarative/qdeclarativeborderimage/data/heart200.png diff --git a/src/declarative/graphicsitems/qdeclarativeanimatedimage.cpp b/src/declarative/graphicsitems/qdeclarativeanimatedimage.cpp index 12a820f..abdfdfa 100644 --- a/src/declarative/graphicsitems/qdeclarativeanimatedimage.cpp +++ b/src/declarative/graphicsitems/qdeclarativeanimatedimage.cpp @@ -86,6 +86,16 @@ QT_BEGIN_NAMESPACE \sa BorderImage, Image */ +/*! + \qmlproperty bool AnimatedImage::mirror + \since Quick 1.1 + + This property holds whether the image should be horizontally inverted + (effectively displaying a mirrored image). + + The default value is false. +*/ + QDeclarativeAnimatedImage::QDeclarativeAnimatedImage(QDeclarativeItem *parent) : QDeclarativeImage(*(new QDeclarativeAnimatedImagePrivate), parent) { @@ -126,7 +136,7 @@ void QDeclarativeAnimatedImage::setPaused(bool pause) \qmlproperty bool AnimatedImage::playing This property holds whether the animated image is playing. - By defaults, this property is true, meaning that the animation + By default, this property is true, meaning that the animation will start playing immediately. */ bool QDeclarativeAnimatedImage::isPlaying() const diff --git a/src/declarative/graphicsitems/qdeclarativeborderimage.cpp b/src/declarative/graphicsitems/qdeclarativeborderimage.cpp index 0bf09ad..a25074a 100644 --- a/src/declarative/graphicsitems/qdeclarativeborderimage.cpp +++ b/src/declarative/graphicsitems/qdeclarativeborderimage.cpp @@ -200,6 +200,16 @@ QDeclarativeBorderImage::~QDeclarativeBorderImage() */ /*! + \qmlproperty bool BorderImage::mirror + \since Quick 1.1 + + This property holds whether the image should be horizontally inverted + (effectively displaying a mirrored image). + + The default value is false. +*/ + +/*! \qmlproperty url BorderImage::source This property holds the URL that refers to the source image. @@ -534,8 +544,15 @@ void QDeclarativeBorderImage::paint(QPainter *p, const QStyleOptionGraphicsItem bool oldAA = p->testRenderHint(QPainter::Antialiasing); bool oldSmooth = p->testRenderHint(QPainter::SmoothPixmapTransform); + QTransform oldTransform; if (d->smooth) p->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, d->smooth); + if (d->mirror) { + oldTransform = p->transform(); + QTransform mirror; + mirror.translate(d->width(), 0).scale(-1, 1.0); + p->setWorldTransform(mirror * oldTransform); + } const QDeclarativeScaleGrid *border = d->getScaleGrid(); int left = border->left(); @@ -561,6 +578,8 @@ void QDeclarativeBorderImage::paint(QPainter *p, const QStyleOptionGraphicsItem p->setRenderHint(QPainter::Antialiasing, oldAA); p->setRenderHint(QPainter::SmoothPixmapTransform, oldSmooth); } + if (d->mirror) + p->setWorldTransform(oldTransform); } QT_END_NAMESPACE diff --git a/src/declarative/graphicsitems/qdeclarativeimage.cpp b/src/declarative/graphicsitems/qdeclarativeimage.cpp index e07292b..68a1ecb 100644 --- a/src/declarative/graphicsitems/qdeclarativeimage.cpp +++ b/src/declarative/graphicsitems/qdeclarativeimage.cpp @@ -467,84 +467,93 @@ QRectF QDeclarativeImage::boundingRect() const to make sure that they aren't cached at the expense of small 'ui element' images. */ +/*! + \qmlproperty bool Image::mirror + \since Quick 1.1 + + This property holds whether the image should be horizontally inverted + (effectively displaying a mirrored image). + + The default value is false. +*/ + + void QDeclarativeImage::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *) { Q_D(QDeclarativeImage); if (d->pix.pixmap().isNull() ) return; - bool oldAA = p->testRenderHint(QPainter::Antialiasing); - bool oldSmooth = p->testRenderHint(QPainter::SmoothPixmapTransform); - if (d->smooth) - p->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, d->smooth); + int drawWidth = width(); + int drawHeight = height(); + bool doClip = false; + QTransform transform; + qreal widthScale = width() / qreal(d->pix.width()); + qreal heightScale = height() / qreal(d->pix.height()); if (width() != d->pix.width() || height() != d->pix.height()) { if (d->fillMode >= Tile) { - if (d->fillMode == Tile) { - p->drawTiledPixmap(QRectF(0,0,width(),height()), d->pix); - } else { - qreal widthScale = width() / qreal(d->pix.width()); - qreal heightScale = height() / qreal(d->pix.height()); - - QTransform scale; - if (d->fillMode == TileVertically) { - scale.scale(widthScale, 1.0); - QTransform old = p->transform(); - p->setWorldTransform(scale * old); - p->drawTiledPixmap(QRectF(0,0,d->pix.width(),height()), d->pix); - p->setWorldTransform(old); - } else { - scale.scale(1.0, heightScale); - QTransform old = p->transform(); - p->setWorldTransform(scale * old); - p->drawTiledPixmap(QRectF(0,0,width(),d->pix.height()), d->pix); - p->setWorldTransform(old); - } + if (d->fillMode == TileVertically) { + transform.scale(widthScale, 1.0); + drawWidth = d->pix.width(); + } else if (d->fillMode == TileHorizontally) { + transform.scale(1.0, heightScale); + drawHeight = d->pix.height(); } } else { - qreal widthScale = width() / qreal(d->pix.width()); - qreal heightScale = height() / qreal(d->pix.height()); - - QTransform scale; - if (d->fillMode == PreserveAspectFit) { if (widthScale <= heightScale) { heightScale = widthScale; - scale.translate(0, (height() - heightScale * d->pix.height()) / 2); + transform.translate(0, (height() - heightScale * d->pix.height()) / 2); } else if(heightScale < widthScale) { widthScale = heightScale; - scale.translate((width() - widthScale * d->pix.width()) / 2, 0); + transform.translate((width() - widthScale * d->pix.width()) / 2, 0); } } else if (d->fillMode == PreserveAspectCrop) { if (widthScale < heightScale) { widthScale = heightScale; - scale.translate((width() - widthScale * d->pix.width()) / 2, 0); + transform.translate((width() - widthScale * d->pix.width()) / 2, 0); } else if(heightScale < widthScale) { heightScale = widthScale; - scale.translate(0, (height() - heightScale * d->pix.height()) / 2); + transform.translate(0, (height() - heightScale * d->pix.height()) / 2); } } - if (clip()) { - p->save(); - p->setClipRect(QRectF(0, 0, d->mWidth, d->mHeight), Qt::IntersectClip); - } - scale.scale(widthScale, heightScale); - QTransform old = p->transform(); - p->setWorldTransform(scale * old); - p->drawPixmap(0, 0, d->pix); - p->setWorldTransform(old); - if (clip()) { - p->restore(); - } + transform.scale(widthScale, heightScale); + drawWidth = d->pix.width(); + drawHeight = d->pix.height(); + doClip = clip(); } - } else { - p->drawPixmap(0, 0, d->pix); } + QTransform oldTransform; + bool oldAA = p->testRenderHint(QPainter::Antialiasing); + bool oldSmooth = p->testRenderHint(QPainter::SmoothPixmapTransform); + if (d->smooth) + p->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, d->smooth); + if (doClip) { + p->save(); + p->setClipRect(QRectF(0, 0, d->mWidth, d->mHeight), Qt::IntersectClip); + } + if (d->mirror) + transform.translate(drawWidth, 0).scale(-1.0, 1.0); + if (!transform.isIdentity()) { + oldTransform = p->transform(); + p->setWorldTransform(transform * oldTransform); + } + + if (d->fillMode >= Tile) + p->drawTiledPixmap(QRectF(0, 0, drawWidth, drawHeight), d->pix); + else + p->drawPixmap(QRectF(0, 0, drawWidth, drawHeight), d->pix, QRectF(0, 0, drawWidth, drawHeight)); + if (d->smooth) { p->setRenderHint(QPainter::Antialiasing, oldAA); p->setRenderHint(QPainter::SmoothPixmapTransform, oldSmooth); } + if (doClip) + p->restore(); + if (!transform.isIdentity()) + p->setWorldTransform(oldTransform); } void QDeclarativeImage::pixmapChange() diff --git a/src/declarative/graphicsitems/qdeclarativeimagebase.cpp b/src/declarative/graphicsitems/qdeclarativeimagebase.cpp index 37b0734..c745635 100644 --- a/src/declarative/graphicsitems/qdeclarativeimagebase.cpp +++ b/src/declarative/graphicsitems/qdeclarativeimagebase.cpp @@ -146,6 +146,26 @@ void QDeclarativeImageBase::setCached(bool cached) load(); } +void QDeclarativeImageBase::setMirror(bool mirror) +{ + Q_D(QDeclarativeImageBase); + if (mirror == d->mirror) + return; + + d->mirror = mirror; + + if (isComponentComplete()) + update(); + + emit mirrorChanged(); +} + +bool QDeclarativeImageBase::mirror() const +{ + Q_D(const QDeclarativeImageBase); + return d->mirror; +} + void QDeclarativeImageBase::load() { Q_D(QDeclarativeImageBase); diff --git a/src/declarative/graphicsitems/qdeclarativeimagebase_p.h b/src/declarative/graphicsitems/qdeclarativeimagebase_p.h index d25f7c3..b6e55ec 100644 --- a/src/declarative/graphicsitems/qdeclarativeimagebase_p.h +++ b/src/declarative/graphicsitems/qdeclarativeimagebase_p.h @@ -60,6 +60,7 @@ class Q_AUTOTEST_EXPORT QDeclarativeImageBase : public QDeclarativeItem Q_PROPERTY(bool asynchronous READ asynchronous WRITE setAsynchronous NOTIFY asynchronousChanged) Q_PROPERTY(bool cached READ cached WRITE setCached NOTIFY cachedChanged) // ### VERSIONING: Only in QtQuick 1.1 Q_PROPERTY(QSize sourceSize READ sourceSize WRITE setSourceSize NOTIFY sourceSizeChanged) + Q_PROPERTY(bool mirror READ mirror WRITE setMirror NOTIFY mirrorChanged) // ### VERSIONING: Only in QtQuick 1.1 public: ~QDeclarativeImageBase(); @@ -79,6 +80,9 @@ public: virtual void setSourceSize(const QSize&); QSize sourceSize() const; + virtual void setMirror(bool mirror); + bool mirror() const; + Q_SIGNALS: void sourceChanged(const QUrl &); void sourceSizeChanged(); @@ -86,6 +90,7 @@ Q_SIGNALS: void progressChanged(qreal progress); void asynchronousChanged(); void cachedChanged(); + void mirrorChanged(); protected: virtual void load(); diff --git a/src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h b/src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h index a539649..950914f 100644 --- a/src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h @@ -71,7 +71,8 @@ public: progress(0.0), explicitSourceSize(false), async(false), - cached(true) + cached(true), + mirror(false) { QGraphicsItemPrivate::flags = QGraphicsItemPrivate::flags & ~QGraphicsItem::ItemHasNoContents; } @@ -84,6 +85,7 @@ public: bool explicitSourceSize : 1; bool async : 1; bool cached : 1; + bool mirror: 1; }; QT_END_NAMESPACE diff --git a/tests/auto/declarative/qdeclarativeanimatedimage/data/hearts.gif b/tests/auto/declarative/qdeclarativeanimatedimage/data/hearts.gif new file mode 100644 index 0000000..cfb55f2 Binary files /dev/null and b/tests/auto/declarative/qdeclarativeanimatedimage/data/hearts.gif differ diff --git a/tests/auto/declarative/qdeclarativeanimatedimage/data/hearts.qml b/tests/auto/declarative/qdeclarativeanimatedimage/data/hearts.qml new file mode 100644 index 0000000..8729dd2 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeanimatedimage/data/hearts.qml @@ -0,0 +1,6 @@ +import QtQuick 1.0 + +AnimatedImage { + source: "hearts.gif" + playing: false +} diff --git a/tests/auto/declarative/qdeclarativeanimatedimage/tst_qdeclarativeanimatedimage.cpp b/tests/auto/declarative/qdeclarativeanimatedimage/tst_qdeclarativeanimatedimage.cpp index 8cbe813..bd701e7 100644 --- a/tests/auto/declarative/qdeclarativeanimatedimage/tst_qdeclarativeanimatedimage.cpp +++ b/tests/auto/declarative/qdeclarativeanimatedimage/tst_qdeclarativeanimatedimage.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include "../shared/testhttpserver.h" #include "../../../shared/util.h" @@ -66,13 +67,28 @@ private slots: void stopped(); void setFrame(); void frameCount(); + void mirror_running(); + void mirror_notRunning(); + void mirror_notRunning_data(); void remote(); void remote_data(); void sourceSize(); void sourceSizeReadOnly(); void invalidSource(); + +private: + QPixmap grabScene(QGraphicsScene *scene, int width, int height); }; +QPixmap tst_qdeclarativeanimatedimage::grabScene(QGraphicsScene *scene, int width, int height) +{ + QPixmap screenshot(width, height); + screenshot.fill(); + QPainter p_screenshot(&screenshot); + scene->render(&p_screenshot, QRect(0, 0, width, height), QRect(0, 0, width, height)); + return screenshot; +} + void tst_qdeclarativeanimatedimage::play() { QDeclarativeEngine engine; @@ -132,6 +148,93 @@ void tst_qdeclarativeanimatedimage::frameCount() delete anim; } +void tst_qdeclarativeanimatedimage::mirror_running() +{ + // test where mirror is set to true after animation has started + + QDeclarativeEngine engine; + QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/hearts.qml")); + QDeclarativeAnimatedImage *anim = qobject_cast(component.create()); + QVERIFY(anim); + + QGraphicsScene scene; + int width = anim->property("width").toInt(); + int height = anim->property("height").toInt(); + scene.addItem(qobject_cast(anim)); + + QCOMPARE(anim->currentFrame(), 0); + QPixmap frame0 = grabScene(&scene, width, height); + anim->setCurrentFrame(1); + QPixmap frame1 = grabScene(&scene, width, height); + + anim->setCurrentFrame(0); + + QSignalSpy spy(anim, SIGNAL(frameChanged())); + anim->setPlaying(true); + + QTRY_VERIFY(spy.count() == 1); spy.clear(); + anim->setProperty("mirror", true); + + QCOMPARE(anim->currentFrame(), 1); + QPixmap frame1_flipped = grabScene(&scene, width, height); + + QTRY_VERIFY(spy.count() == 1); spy.clear(); + QCOMPARE(anim->currentFrame(), 0); // animation only has 2 frames, should cycle back to first + QPixmap frame0_flipped = grabScene(&scene, width, height); + + QTransform transform; + transform.translate(width, 0).scale(-1, 1.0); + QPixmap frame0_expected = frame0.transformed(transform); + QPixmap frame1_expected = frame1.transformed(transform); + + QCOMPARE(frame0_flipped, frame0_expected); + QCOMPARE(frame1_flipped, frame1_expected); +} + +void tst_qdeclarativeanimatedimage::mirror_notRunning() +{ + QFETCH(QUrl, fileUrl); + + QDeclarativeEngine engine; + QDeclarativeComponent component(&engine, fileUrl); + QDeclarativeAnimatedImage *anim = qobject_cast(component.create()); + QVERIFY(anim); + + QGraphicsScene scene; + int width = anim->property("width").toInt(); + int height = anim->property("height").toInt(); + scene.addItem(qobject_cast(anim)); + QPixmap screenshot = grabScene(&scene, width, height); + + QTransform transform; + transform.translate(width, 0).scale(-1, 1.0); + QPixmap expected = screenshot.transformed(transform); + + int frame = anim->currentFrame(); + bool playing = anim->isPlaying(); + bool paused = anim->isPlaying(); + + anim->setProperty("mirror", true); + screenshot = grabScene(&scene, width, height); + + QCOMPARE(screenshot, expected); + + // mirroring should not change the current frame or playing status + QCOMPARE(anim->currentFrame(), frame); + QCOMPARE(anim->isPlaying(), playing); + QCOMPARE(anim->isPaused(), paused); + + delete anim; +} + +void tst_qdeclarativeanimatedimage::mirror_notRunning_data() +{ + QTest::addColumn("fileUrl"); + + QTest::newRow("paused") << QUrl::fromLocalFile(SRCDIR "/data/stickmanpause.qml"); + QTest::newRow("stopped") << QUrl::fromLocalFile(SRCDIR "/data/stickmanstopped.qml"); +} + void tst_qdeclarativeanimatedimage::remote() { QFETCH(QString, fileName); diff --git a/tests/auto/declarative/qdeclarativeborderimage/data/heart200.png b/tests/auto/declarative/qdeclarativeborderimage/data/heart200.png new file mode 100644 index 0000000..5a31ae8 Binary files /dev/null and b/tests/auto/declarative/qdeclarativeborderimage/data/heart200.png differ diff --git a/tests/auto/declarative/qdeclarativeborderimage/tst_qdeclarativeborderimage.cpp b/tests/auto/declarative/qdeclarativeborderimage/tst_qdeclarativeborderimage.cpp index 5478145..c22cde2 100644 --- a/tests/auto/declarative/qdeclarativeborderimage/tst_qdeclarativeborderimage.cpp +++ b/tests/auto/declarative/qdeclarativeborderimage/tst_qdeclarativeborderimage.cpp @@ -43,6 +43,8 @@ #include #include #include +#include +#include #include #include @@ -77,6 +79,7 @@ private slots: void clearSource(); void resized(); void smooth(); + void mirror(); void tileModes(); void sciSource(); void sciSource_data(); @@ -218,6 +221,37 @@ void tst_qdeclarativeborderimage::smooth() delete obj; } +void tst_qdeclarativeborderimage::mirror() +{ + QString componentStr = "import QtQuick 1.0\nBorderImage { source: \"" SRCDIR "/data/heart200.png\"; smooth: true; width: 300; height: 300; border { top: 50; right: 50; bottom: 50; left: 50 } }"; + QDeclarativeComponent component(&engine); + component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QDeclarativeBorderImage *obj = qobject_cast(component.create()); + QVERIFY(obj != 0); + + int width = obj->property("width").toInt(); + int height = obj->property("height").toInt(); + + QGraphicsScene scene; + scene.addItem(qobject_cast(obj)); + QPixmap screenshot(width, height); + screenshot.fill(); + QPainter p_screenshot(&screenshot); + scene.render(&p_screenshot, QRect(0, 0, width, height), QRect(0, 0, width, height)); + + QTransform transform; + transform.translate(width, 0).scale(-1, 1.0); + QPixmap expected = screenshot.transformed(transform); + + obj->setProperty("mirror", true); + p_screenshot.fillRect(QRect(0, 0, width, height), Qt::white); + scene.render(&p_screenshot, QRect(0, 0, width, height), QRect(0, 0, width, height)); + + QCOMPARE(screenshot, expected); + + delete obj; +} + void tst_qdeclarativeborderimage::tileModes() { { diff --git a/tests/auto/declarative/qdeclarativeimage/tst_qdeclarativeimage.cpp b/tests/auto/declarative/qdeclarativeimage/tst_qdeclarativeimage.cpp index c811f62..27c7964 100644 --- a/tests/auto/declarative/qdeclarativeimage/tst_qdeclarativeimage.cpp +++ b/tests/auto/declarative/qdeclarativeimage/tst_qdeclarativeimage.cpp @@ -79,6 +79,8 @@ private slots: void resized(); void preserveAspectRatio(); void smooth(); + void mirror(); + void mirror_data(); void svg(); void geometry(); void geometry_data(); @@ -270,6 +272,90 @@ void tst_qdeclarativeimage::smooth() delete obj; } +void tst_qdeclarativeimage::mirror() +{ + QFETCH(int, fillMode); + + qreal width = 300; + qreal height = 250; + + QString src = QUrl::fromLocalFile(SRCDIR "/data/heart200.png").toString(); + QString componentStr = "import QtQuick 1.0\nImage { source: \"" + src + "\"; }"; + + QDeclarativeComponent component(&engine); + component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QDeclarativeImage *obj = qobject_cast(component.create()); + QVERIFY(obj != 0); + + obj->setProperty("width", width); + obj->setProperty("height", height); + obj->setFillMode((QDeclarativeImage::FillMode)fillMode); + obj->setProperty("mirror", true); + + QGraphicsScene scene; + scene.addItem(qobject_cast(obj)); + QPixmap screenshot(width, height); + screenshot.fill(); + QPainter p_screenshot(&screenshot); + scene.render(&p_screenshot, QRect(0, 0, width, height), QRect(0, 0, width, height)); + + QPixmap srcPixmap; + QVERIFY(srcPixmap.load(SRCDIR "/data/heart200.png")); + + QPixmap expected(width, height); + expected.fill(); + QPainter p_e(&expected); + QTransform transform; + transform.translate(width, 0).scale(-1, 1.0); + p_e.setTransform(transform); + + switch (fillMode) { + case QDeclarativeImage::Stretch: + p_e.drawPixmap(QRect(0, 0, width, height), srcPixmap, QRect(0, 0, srcPixmap.width(), srcPixmap.height())); + break; + case QDeclarativeImage::PreserveAspectFit: + p_e.drawPixmap(QRect(25, 0, width / (width/height), height), srcPixmap, QRect(0, 0, srcPixmap.width(), srcPixmap.height())); + break; + case QDeclarativeImage::PreserveAspectCrop: + { + qreal ratio = width/srcPixmap.width(); // width is the longer side + QRect rect(0, 0, srcPixmap.width()*ratio, srcPixmap.height()*ratio); + rect.moveCenter(QRect(0, 0, width, height).center()); + p_e.drawPixmap(rect, srcPixmap, QRect(0, 0, srcPixmap.width(), srcPixmap.height())); + break; + } + case QDeclarativeImage::Tile: + p_e.drawTiledPixmap(QRect(0, 0, width, height), srcPixmap); + break; + case QDeclarativeImage::TileVertically: + transform.scale(width / srcPixmap.width(), 1.0); + p_e.setTransform(transform); + p_e.drawTiledPixmap(QRect(0, 0, width, height), srcPixmap); + break; + case QDeclarativeImage::TileHorizontally: + transform.scale(1.0, height / srcPixmap.height()); + p_e.setTransform(transform); + p_e.drawTiledPixmap(QRect(0, 0, width, height), srcPixmap); + break; + } + + QCOMPARE(screenshot, expected); + + delete obj; +} + +void tst_qdeclarativeimage::mirror_data() +{ + QTest::addColumn("fillMode"); + + QTest::newRow("Stretch") << int(QDeclarativeImage::Stretch); + QTest::newRow("PreserveAspectFit") << int(QDeclarativeImage::PreserveAspectFit); + QTest::newRow("PreserveAspectCrop") << int(QDeclarativeImage::PreserveAspectCrop); + QTest::newRow("Tile") << int(QDeclarativeImage::Tile); + QTest::newRow("TileVertically") << int(QDeclarativeImage::TileVertically); + QTest::newRow("TileHorizontally") << int(QDeclarativeImage::TileHorizontally); +} + void tst_qdeclarativeimage::svg() { QString src = QUrl::fromLocalFile(SRCDIR "/data/heart.svg").toString(); -- cgit v0.12 From a32728ce8cf4fa1d1dc1001b1fadc66e9c86e025 Mon Sep 17 00:00:00 2001 From: Christopher Ham Date: Fri, 10 Dec 2010 13:03:59 +1000 Subject: The sourceSize property for borderImage should be read only Trying the sourceSize property from QML should emit a read-only warning. Task-number: QTBUG-15703 Reviewed-by: Bea Lam --- src/declarative/graphicsitems/qdeclarativeborderimage.cpp | 6 ------ src/declarative/graphicsitems/qdeclarativeborderimage_p.h | 6 ++++-- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativeborderimage.cpp b/src/declarative/graphicsitems/qdeclarativeborderimage.cpp index a25074a..d9ba2bd 100644 --- a/src/declarative/graphicsitems/qdeclarativeborderimage.cpp +++ b/src/declarative/graphicsitems/qdeclarativeborderimage.cpp @@ -256,12 +256,6 @@ void QDeclarativeBorderImage::setSource(const QUrl &url) load(); } -void QDeclarativeBorderImage::setSourceSize(const QSize& size) -{ - Q_UNUSED(size); - qmlInfo(this) << "Setting sourceSize for borderImage not supported"; -} - void QDeclarativeBorderImage::load() { Q_D(QDeclarativeBorderImage); diff --git a/src/declarative/graphicsitems/qdeclarativeborderimage_p.h b/src/declarative/graphicsitems/qdeclarativeborderimage_p.h index 7cf24f2..d9db0ac 100644 --- a/src/declarative/graphicsitems/qdeclarativeborderimage_p.h +++ b/src/declarative/graphicsitems/qdeclarativeborderimage_p.h @@ -63,6 +63,9 @@ class Q_AUTOTEST_EXPORT QDeclarativeBorderImage : public QDeclarativeImageBase Q_PROPERTY(TileMode horizontalTileMode READ horizontalTileMode WRITE setHorizontalTileMode NOTIFY horizontalTileModeChanged) Q_PROPERTY(TileMode verticalTileMode READ verticalTileMode WRITE setVerticalTileMode NOTIFY verticalTileModeChanged) + // read-only for BorderImage + Q_PROPERTY(QSize sourceSize READ sourceSize NOTIFY sourceSizeChanged) + public: QDeclarativeBorderImage(QDeclarativeItem *parent=0); ~QDeclarativeBorderImage(); @@ -80,11 +83,10 @@ public: void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *); void setSource(const QUrl &url); - void setSourceSize(const QSize&); - Q_SIGNALS: void horizontalTileModeChanged(); void verticalTileModeChanged(); + void sourceSizeChanged(); protected: virtual void load(); -- cgit v0.12 From 5710cc981ae39a018d4c30b2c77f6623713a5bf1 Mon Sep 17 00:00:00 2001 From: Christopher Ham Date: Fri, 10 Dec 2010 13:19:03 +1000 Subject: KeyNavigation skips disabled or invisible items When using KeyNavigation, if the "visible" or "enabled" property of the item set in the KeyNavigation handler is false, an attempt will be made to skip this item and setFocus to the following item. Task-number: QTBUG-15862 Reviewed-by: Martin Jones --- src/declarative/graphicsitems/qdeclarativeitem.cpp | 46 ++++++++++--- src/declarative/graphicsitems/qdeclarativeitem_p.h | 1 + .../qdeclarativeitem/tst_qdeclarativeitem.cpp | 79 ++++++++++++++++++++++ 3 files changed, 118 insertions(+), 8 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativeitem.cpp b/src/declarative/graphicsitems/qdeclarativeitem.cpp index 9d6fe12..cf12688 100644 --- a/src/declarative/graphicsitems/qdeclarativeitem.cpp +++ b/src/declarative/graphicsitems/qdeclarativeitem.cpp @@ -444,6 +444,11 @@ void QDeclarativeItemKeyFilter::componentComplete() \c KeyNavigation.BeforeItem allows the event to be used for key navigation before the item, rather than after. + If item to which the focus is switching is not enabled or visible, an attempt will + be made to skip this item and focus on the next. This is possible if there are + a chain of items with the same KeyNavigation handler. If multiple items in a row are not enabled + or visible, they will also be skipped. + \sa {Keys}{Keys attached property} */ @@ -452,10 +457,12 @@ void QDeclarativeItemKeyFilter::componentComplete() \qmlproperty Item KeyNavigation::right \qmlproperty Item KeyNavigation::up \qmlproperty Item KeyNavigation::down + \qmlproperty Item KeyNavigation::tab + \qmlproperty Item KeyNavigation::backtab These properties hold the item to assign focus to - when Key_Left, Key_Right, Key_Up or Key_Down are - pressed. + when Key_Left, Key_Right, Key_Up, Key_Down, Key_Tab or Key_BackTab + are pressed. */ QDeclarativeKeyNavigationAttached::QDeclarativeKeyNavigationAttached(QObject *parent) @@ -603,37 +610,37 @@ void QDeclarativeKeyNavigationAttached::keyPressed(QKeyEvent *event, bool post) switch(event->key()) { case Qt::Key_Left: if (d->left) { - d->left->setFocus(true); + setFocusNavigation(d->left, "left"); event->accept(); } break; case Qt::Key_Right: if (d->right) { - d->right->setFocus(true); + setFocusNavigation(d->right, "right"); event->accept(); } break; case Qt::Key_Up: if (d->up) { - d->up->setFocus(true); + setFocusNavigation(d->up, "up"); event->accept(); } break; case Qt::Key_Down: if (d->down) { - d->down->setFocus(true); + setFocusNavigation(d->down, "down"); event->accept(); } break; case Qt::Key_Tab: if (d->tab) { - d->tab->setFocus(true); + setFocusNavigation(d->tab, "tab"); event->accept(); } break; case Qt::Key_Backtab: if (d->backtab) { - d->backtab->setFocus(true); + setFocusNavigation(d->backtab, "backtab"); event->accept(); } break; @@ -692,6 +699,29 @@ void QDeclarativeKeyNavigationAttached::keyReleased(QKeyEvent *event, bool post) if (!event->isAccepted()) QDeclarativeItemKeyFilter::keyReleased(event, post); } +void QDeclarativeKeyNavigationAttached::setFocusNavigation(QDeclarativeItem *currentItem, const char *dir) +{ + QDeclarativeItem *initialItem = currentItem; + bool isNextItem = false; + do { + isNextItem = false; + if (currentItem->isVisible() && currentItem->isEnabled()) { + currentItem->setFocus(true); + } else { + QObject *attached = + qmlAttachedPropertiesObject(currentItem, false); + if (attached) { + QDeclarativeItem *tempItem = qvariant_cast(attached->property(dir)); + if (tempItem) { + currentItem = tempItem; + isNextItem = true; + } + } + } + } + while (currentItem != initialItem && isNextItem); +} + /*! \qmlclass Keys QDeclarativeKeysAttached \ingroup qml-basic-interaction-elements diff --git a/src/declarative/graphicsitems/qdeclarativeitem_p.h b/src/declarative/graphicsitems/qdeclarativeitem_p.h index d8635b9..402554b 100644 --- a/src/declarative/graphicsitems/qdeclarativeitem_p.h +++ b/src/declarative/graphicsitems/qdeclarativeitem_p.h @@ -411,6 +411,7 @@ Q_SIGNALS: private: virtual void keyPressed(QKeyEvent *event, bool post); virtual void keyReleased(QKeyEvent *event, bool post); + void setFocusNavigation(QDeclarativeItem *currentItem, const char *dir); }; class QDeclarativeKeysAttachedPrivate : public QObjectPrivate diff --git a/tests/auto/declarative/qdeclarativeitem/tst_qdeclarativeitem.cpp b/tests/auto/declarative/qdeclarativeitem/tst_qdeclarativeitem.cpp index 711bf00..9587254 100644 --- a/tests/auto/declarative/qdeclarativeitem/tst_qdeclarativeitem.cpp +++ b/tests/auto/declarative/qdeclarativeitem/tst_qdeclarativeitem.cpp @@ -65,6 +65,7 @@ private slots: void keys(); void keysProcessingOrder(); void keyNavigation(); + void keyNavigation_skipNotVisible(); void smooth(); void clip(); void mapCoordinates(); @@ -450,6 +451,84 @@ void tst_QDeclarativeItem::keyNavigation() delete canvas; } +void tst_QDeclarativeItem::keyNavigation_skipNotVisible() +{ + QDeclarativeView *canvas = new QDeclarativeView(0); + canvas->setFixedSize(240,320); + + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/keynavigationtest.qml")); + canvas->show(); + qApp->processEvents(); + + QEvent wa(QEvent::WindowActivate); + QApplication::sendEvent(canvas, &wa); + QFocusEvent fe(QEvent::FocusIn); + QApplication::sendEvent(canvas, &fe); + + QDeclarativeItem *item = findItem(canvas->rootObject(), "item1"); + QVERIFY(item); + QVERIFY(item->hasActiveFocus()); + + // Set item 2 to not visible + item = findItem(canvas->rootObject(), "item2"); + QVERIFY(item); + item->setVisible(false); + QVERIFY(!item->isVisible()); + + // right + QKeyEvent key(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier, "", false, 1); + QApplication::sendEvent(canvas, &key); + QVERIFY(key.isAccepted()); + + item = findItem(canvas->rootObject(), "item1"); + QVERIFY(item); + QVERIFY(item->hasActiveFocus()); + + // tab + key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier, "", false, 1); + QApplication::sendEvent(canvas, &key); + QVERIFY(key.isAccepted()); + + item = findItem(canvas->rootObject(), "item3"); + QVERIFY(item); + QVERIFY(item->hasActiveFocus()); + + // backtab + key = QKeyEvent(QEvent::KeyPress, Qt::Key_Backtab, Qt::NoModifier, "", false, 1); + QApplication::sendEvent(canvas, &key); + QVERIFY(key.isAccepted()); + + item = findItem(canvas->rootObject(), "item1"); + QVERIFY(item); + QVERIFY(item->hasActiveFocus()); + + //Set item 3 to not visible + item = findItem(canvas->rootObject(), "item3"); + QVERIFY(item); + item->setVisible(false); + QVERIFY(!item->isVisible()); + + // tab + key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier, "", false, 1); + QApplication::sendEvent(canvas, &key); + QVERIFY(key.isAccepted()); + + item = findItem(canvas->rootObject(), "item4"); + QVERIFY(item); + QVERIFY(item->hasActiveFocus()); + + // backtab + key = QKeyEvent(QEvent::KeyPress, Qt::Key_Backtab, Qt::NoModifier, "", false, 1); + QApplication::sendEvent(canvas, &key); + QVERIFY(key.isAccepted()); + + item = findItem(canvas->rootObject(), "item1"); + QVERIFY(item); + QVERIFY(item->hasActiveFocus()); + + delete canvas; +} + void tst_QDeclarativeItem::smooth() { QDeclarativeComponent component(&engine); -- cgit v0.12 From 6541562252cecd102788257022d3cf159954cae8 Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Fri, 10 Dec 2010 11:47:43 +0100 Subject: QmlDebugger: Instantiation of deferred objects moved to the debugger engine Reviewed-by: Kai Koehne --- src/declarative/qml/qdeclarativecompiler.cpp | 6 +----- src/declarative/qml/qdeclarativeenginedebug.cpp | 22 ++++++++++++++++------ src/declarative/qml/qdeclarativeenginedebug_p.h | 1 + 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp index b375b27..4749bf8 100644 --- a/src/declarative/qml/qdeclarativecompiler.cpp +++ b/src/declarative/qml/qdeclarativecompiler.cpp @@ -65,7 +65,6 @@ #include "private/qdeclarativebinding_p.h" #include "private/qdeclarativecompiledbindings_p.h" #include "private/qdeclarativeglobalscriptclass_p.h" -#include "private/qdeclarativedebugservice_p.h" #include #include @@ -755,10 +754,7 @@ bool QDeclarativeCompiler::buildObject(Object *obj, const BindingContext &ctxt) QList customProps; // Fetch the list of deferred properties - QStringList deferredList; - if (!QDeclarativeDebugService::isDebuggingEnabled()) { - deferredList = deferredProperties(obj); - } + QStringList deferredList = deferredProperties(obj); // Must do id property first. This is to ensure that the id given to any // id reference created matches the order in which the objects are diff --git a/src/declarative/qml/qdeclarativeenginedebug.cpp b/src/declarative/qml/qdeclarativeenginedebug.cpp index bffe681..5f338db 100644 --- a/src/declarative/qml/qdeclarativeenginedebug.cpp +++ b/src/declarative/qml/qdeclarativeenginedebug.cpp @@ -192,11 +192,6 @@ void QDeclarativeEngineDebugServer::buildObjectDump(QDataStream &message, { message << objectData(object); - // Some children aren't added to an object until particular properties are read - // - e.g. child state objects aren't added until the 'states' property is read - - // but this should only affect internal objects that aren't shown by the - // debugger anyway. - QObjectList children = object->children(); int childrenCount = children.count(); @@ -257,6 +252,18 @@ void QDeclarativeEngineDebugServer::buildObjectDump(QDataStream &message, message << fakeProperties[ii]; } +void QDeclarativeEngineDebugServer::prepareDeferredObjects(QObject *obj) +{ + qmlExecuteDeferred(obj); + + QObjectList children = obj->children(); + for (int ii = 0; ii < children.count(); ++ii) { + QObject *child = children.at(ii); + prepareDeferredObjects(child); + } + +} + void QDeclarativeEngineDebugServer::buildObjectList(QDataStream &message, QDeclarativeContext *ctxt) { QDeclarativeContextData *p = QDeclarativeContextData::get(ctxt); @@ -393,8 +400,11 @@ void QDeclarativeEngineDebugServer::messageReceived(const QByteArray &message) QDataStream rs(&reply, QIODevice::WriteOnly); rs << QByteArray("FETCH_OBJECT_R") << queryId; - if (object) + if (object) { + if (recurse) + prepareDeferredObjects(object); buildObjectDump(rs, object, recurse, dumpProperties); + } sendMessage(reply); } else if (type == "WATCH_OBJECT") { diff --git a/src/declarative/qml/qdeclarativeenginedebug_p.h b/src/declarative/qml/qdeclarativeenginedebug_p.h index 97b8121..dc8bc85 100644 --- a/src/declarative/qml/qdeclarativeenginedebug_p.h +++ b/src/declarative/qml/qdeclarativeenginedebug_p.h @@ -105,6 +105,7 @@ private Q_SLOTS: void propertyChanged(int id, int objectId, const QMetaProperty &property, const QVariant &value); private: + void prepareDeferredObjects(QObject *); void buildObjectList(QDataStream &, QDeclarativeContext *); void buildObjectDump(QDataStream &, QObject *, bool, bool); QDeclarativeObjectData objectData(QObject *); -- cgit v0.12 From 3006bdd1eab665d3a0e666975246d2fb20b578af Mon Sep 17 00:00:00 2001 From: Christopher Ham Date: Mon, 13 Dec 2010 09:34:04 +1000 Subject: Adding documentation for borderImage Documentation describing the read-only behaviour of property sourceSize Task-number: QTBUG-15703 Reviewed-by: Martin Jones --- src/declarative/graphicsitems/qdeclarativeborderimage.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/declarative/graphicsitems/qdeclarativeborderimage.cpp b/src/declarative/graphicsitems/qdeclarativeborderimage.cpp index d9ba2bd..63b2b9a 100644 --- a/src/declarative/graphicsitems/qdeclarativeborderimage.cpp +++ b/src/declarative/graphicsitems/qdeclarativeborderimage.cpp @@ -236,6 +236,16 @@ QDeclarativeBorderImage::~QDeclarativeBorderImage() \sa QDeclarativeImageProvider */ + +/*! + \qmlproperty QSize BorderImage::sourceSize + + This property holds the actual width and height of the loaded image. + + In BorderImage, this property is read-only. + + \sa Image::sourceSize +*/ void QDeclarativeBorderImage::setSource(const QUrl &url) { Q_D(QDeclarativeBorderImage); -- cgit v0.12 From 409f60f0f6fd2c2bad6125d0463c812ba1b1180a Mon Sep 17 00:00:00 2001 From: Joona Petrell Date: Mon, 13 Dec 2010 15:34:23 +1000 Subject: Document TextInput property maximumLength Task-number: Reviewed-by: Martin Jones --- src/declarative/graphicsitems/qdeclarativetextinput.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/declarative/graphicsitems/qdeclarativetextinput.cpp b/src/declarative/graphicsitems/qdeclarativetextinput.cpp index 0deacf8..2fb7ace 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextinput.cpp @@ -361,6 +361,14 @@ void QDeclarativeTextInput::setReadOnly(bool ro) emit readOnlyChanged(ro); } +/*! + \qmlproperty int TextInput::maximumLength + The maximum permitted length of the text in the TextInput. + + If the text is too long, it is truncated at the limit. + + By default, this property contains a value of 32767. +*/ int QDeclarativeTextInput::maxLength() const { Q_D(const QDeclarativeTextInput); -- cgit v0.12 From b3666a5ac8ee295adc86d8d20f5452eaad3063aa Mon Sep 17 00:00:00 2001 From: Joona Petrell Date: Mon, 13 Dec 2010 17:05:45 +1000 Subject: Revert "Add mirroring-positioners.qml example" that was accidentally pushed This reverts commit 18b940539d0633f30ae055feedb48aeb15969814. --- .../positioners/mirroring-positioners.qml | 70 ---------------------- 1 file changed, 70 deletions(-) delete mode 100644 examples/declarative/positioners/mirroring-positioners.qml diff --git a/examples/declarative/positioners/mirroring-positioners.qml b/examples/declarative/positioners/mirroring-positioners.qml deleted file mode 100644 index 0db95dd..0000000 --- a/examples/declarative/positioners/mirroring-positioners.qml +++ /dev/null @@ -1,70 +0,0 @@ -import QtQuick 1.0 - -Rectangle { - width: column.width+10 - height: column.height+10 - property bool arabic: false - Column { - id: column - spacing: 10 - anchors.centerIn: parent - Text { - text: "Row" - anchors.horizontalCenter: parent.horizontalCenter - } - Row { - flow: arabic ? Row.RightToLeft : Row.LeftToRight - spacing: 10 - Repeater { - model: 4 - Loader { - property int value: index - sourceComponent: delegate - } - } - } - Text { - text: "Grid" - anchors.horizontalCenter: parent.horizontalCenter - } - Grid { - flow: arabic ? Grid.RightToLeft : Grid.LeftToRight - spacing: 10; columns: 4 - Repeater { - model: 11 - Loader { - property int value: index - sourceComponent: delegate - } - } - } - Rectangle { - height: 50; width: parent.width - color: mouseArea.pressed ? "black" : "gray" - Text { - text: arabic ? "RTL" : "LTR" - color: "white" - font.pixelSize: 20 - anchors.centerIn: parent - } - MouseArea { - id: mouseArea - onClicked: arabic = !arabic - anchors.fill: parent - } - } - } - Component { - id: delegate - Rectangle { - width: 50; height: 50 - color: Qt.rgba(0.8/(parent.value+1),0.8/(parent.value+1),0.8/(parent.value+1),1.0) - Text { - text: parent.parent.value+1 - color: "white" - font.pixelSize: 20 - anchors.centerIn: parent - } - } - } -} -- cgit v0.12 From 7618adbd60f0aaeac63a1ac65e733fc8962a1cd9 Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Mon, 13 Dec 2010 13:26:56 +0100 Subject: QmlDebugger: setting bindings in states Reviewied-by: Kai Koehne --- src/declarative/qml/qdeclarativeenginedebug.cpp | 110 +++++++++++++++++---- src/declarative/qml/qdeclarativeenginedebug_p.h | 5 + .../qdeclarativedebug/tst_qdeclarativedebug.cpp | 101 ++++++++++++++++++- 3 files changed, 196 insertions(+), 20 deletions(-) diff --git a/src/declarative/qml/qdeclarativeenginedebug.cpp b/src/declarative/qml/qdeclarativeenginedebug.cpp index 5f338db..4d6e50c 100644 --- a/src/declarative/qml/qdeclarativeenginedebug.cpp +++ b/src/declarative/qml/qdeclarativeenginedebug.cpp @@ -52,6 +52,7 @@ #include "private/qdeclarativevaluetype_p.h" #include "private/qdeclarativevmemetaobject_p.h" #include "private/qdeclarativeexpression_p.h" +#include "private/qdeclarativepropertychanges_p.h" #include #include @@ -304,6 +305,35 @@ void QDeclarativeEngineDebugServer::buildObjectList(QDataStream &message, QDecla } } +void QDeclarativeEngineDebugServer::buildStatesList(QDeclarativeContext *ctxt, bool cleanList=false) +{ + if (cleanList) + m_allStates.clear(); + + QDeclarativeContextPrivate *ctxtPriv = QDeclarativeContextPrivate::get(ctxt); + for (int ii = 0; ii < ctxtPriv->instances.count(); ++ii) { + buildStatesList(ctxtPriv->instances.at(ii)); + } + + QDeclarativeContextData *child = QDeclarativeContextData::get(ctxt)->childContexts; + while (child) { + buildStatesList(child->asQDeclarativeContext()); + child = child->nextChild; + } +} + +void QDeclarativeEngineDebugServer::buildStatesList(QObject *obj) +{ + if (QDeclarativeState *state = dynamic_cast(obj)) { + m_allStates.append(state); + } + + QObjectList children = obj->children(); + for (int ii = 0; ii < children.count(); ++ii) { + buildStatesList(children.at(ii)); + } +} + QDeclarativeEngineDebugServer::QDeclarativeObjectData QDeclarativeEngineDebugServer::objectData(QObject *object) { @@ -382,8 +412,10 @@ void QDeclarativeEngineDebugServer::messageReceived(const QByteArray &message) QDataStream rs(&reply, QIODevice::WriteOnly); rs << QByteArray("LIST_OBJECTS_R") << queryId; - if (engine) + if (engine) { buildObjectList(rs, engine->rootContext()); + buildStatesList(engine->rootContext(), true); + } sendMessage(reply); } else if (type == "FETCH_OBJECT") { @@ -504,26 +536,66 @@ void QDeclarativeEngineDebugServer::setBinding(int objectId, { QObject *object = objectForId(objectId); QDeclarativeContext *context = qmlContext(object); + QByteArray propertyNameArray = propertyName.toUtf8(); if (object && context) { - QDeclarativeProperty property(object, propertyName, context); - if (isLiteralValue) { - property.write(expression); - } else if (hasValidSignal(object, propertyName)) { - QDeclarativeExpression *declarativeExpression = new QDeclarativeExpression(context, object, expression.toString()); - QDeclarativeExpression *oldExpression = QDeclarativePropertyPrivate::setSignalExpression(property, declarativeExpression); - declarativeExpression->setSourceLocation(oldExpression->sourceFile(), oldExpression->lineNumber()); - } else if (property.isProperty()) { - QDeclarativeBinding *binding = new QDeclarativeBinding(expression.toString(), object, context); - binding->setTarget(property); - binding->setNotifyOnValueChanged(true); - QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::setBinding(property, binding); - if (oldBinding) - oldBinding->destroy(); - binding->update(); + if (property.isValid()) { + + bool inBaseState = true; + + foreach(QWeakPointer statePointer, m_allStates) { + if (QDeclarativeState *state = statePointer.data()) { + // here we assume that the revert list on itself defines the base state + if ( state->isStateActive() && state->containsPropertyInRevertList(object, propertyNameArray) ) { + inBaseState = false; + + QDeclarativeBinding *newBinding = 0; + if (!isLiteralValue) { + newBinding = new QDeclarativeBinding(expression.toString(), object, context); + newBinding->setTarget(property); + newBinding->setNotifyOnValueChanged(true); + } + + state->changeBindingInRevertList(object,propertyNameArray, newBinding); + + if (isLiteralValue) + state->changeValueInRevertList(object, propertyNameArray, expression); + } + } + } + + if (inBaseState) { + if (isLiteralValue) { + property.write(expression); + } else if (hasValidSignal(object, propertyName)) { + QDeclarativeExpression *declarativeExpression = new QDeclarativeExpression(context, object, expression.toString()); + QDeclarativeExpression *oldExpression = QDeclarativePropertyPrivate::setSignalExpression(property, declarativeExpression); + declarativeExpression->setSourceLocation(oldExpression->sourceFile(), oldExpression->lineNumber()); + } else if (property.isProperty()) { + QDeclarativeBinding *binding = new QDeclarativeBinding(expression.toString(), object, context); + binding->setTarget(property); + binding->setNotifyOnValueChanged(true); + QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::setBinding(property, binding); + if (oldBinding) + oldBinding->destroy(); + binding->update(); + } else { + qWarning() << "QDeclarativeEngineDebugServer::setBinding: unable to set property" << propertyName << "on object" << object; + } + } + } else { - qWarning() << "QDeclarativeEngineDebugServer::setBinding: unable to set property" << propertyName << "on object" << object; + // not a valid property + if (QDeclarativePropertyChanges *propertyChanges = dynamic_cast(object)) { + if (isLiteralValue) { + propertyChanges->changeValue(propertyName.toUtf8(),expression); + } else { + propertyChanges->changeExpression(propertyName.toUtf8(),expression.toString()); + } + } else { + qWarning() << "QDeclarativeEngineDebugServer::setBinding: unable to set property" << propertyName << "on object" << object; + } } } } @@ -546,6 +618,10 @@ void QDeclarativeEngineDebugServer::resetBinding(int objectId, const QString &pr property.reset(); } } + } else { + if (QDeclarativePropertyChanges *propertyChanges = dynamic_cast(object)) { + propertyChanges->removeProperty(propertyName.toUtf8()); + } } } } diff --git a/src/declarative/qml/qdeclarativeenginedebug_p.h b/src/declarative/qml/qdeclarativeenginedebug_p.h index dc8bc85..65eb1ff 100644 --- a/src/declarative/qml/qdeclarativeenginedebug_p.h +++ b/src/declarative/qml/qdeclarativeenginedebug_p.h @@ -57,6 +57,7 @@ #include #include +#include QT_BEGIN_NAMESPACE @@ -64,6 +65,7 @@ class QDeclarativeEngine; class QDeclarativeContext; class QDeclarativeWatcher; class QDataStream; +class QDeclarativeState; class QDeclarativeEngineDebugServer : public QDeclarativeDebugService { @@ -108,6 +110,8 @@ private: void prepareDeferredObjects(QObject *); void buildObjectList(QDataStream &, QDeclarativeContext *); void buildObjectDump(QDataStream &, QObject *, bool, bool); + void buildStatesList(QDeclarativeContext *, bool); + void buildStatesList(QObject *obj); QDeclarativeObjectData objectData(QObject *); QDeclarativeObjectProperty propertyData(QObject *, int); QVariant valueContents(const QVariant &defaultValue) const; @@ -117,6 +121,7 @@ private: QList m_engines; QDeclarativeWatcher *m_watch; + QList > m_allStates; }; Q_DECLARATIVE_PRIVATE_EXPORT QDataStream &operator<<(QDataStream &, const QDeclarativeEngineDebugServer::QDeclarativeObjectData &); Q_DECLARATIVE_PRIVATE_EXPORT QDataStream &operator>>(QDataStream &, QDeclarativeEngineDebugServer::QDeclarativeObjectData &); diff --git a/tests/auto/declarative/qdeclarativedebug/tst_qdeclarativedebug.cpp b/tests/auto/declarative/qdeclarativedebug/tst_qdeclarativedebug.cpp index 20a3fa6..fac32d7 100644 --- a/tests/auto/declarative/qdeclarativedebug/tst_qdeclarativedebug.cpp +++ b/tests/auto/declarative/qdeclarativedebug/tst_qdeclarativedebug.cpp @@ -72,7 +72,7 @@ class tst_QDeclarativeDebug : public QObject Q_OBJECT private: - QDeclarativeDebugObjectReference findRootObject(int context = 0); + QDeclarativeDebugObjectReference findRootObject(int context = 0, bool recursive = false); QDeclarativeDebugPropertyReference findProperty(const QList &props, const QString &name) const; void waitForQuery(QDeclarativeDebugQuery *query); @@ -115,9 +115,10 @@ private slots: void setMethodBody(); void queryObjectTree(); + void setBindingInStates(); }; -QDeclarativeDebugObjectReference tst_QDeclarativeDebug::findRootObject(int context) +QDeclarativeDebugObjectReference tst_QDeclarativeDebug::findRootObject(int context, bool recursive) { QDeclarativeDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this); waitForQuery(q_engines); @@ -129,7 +130,9 @@ QDeclarativeDebugObjectReference tst_QDeclarativeDebug::findRootObject(int conte if (q_context->rootContext().objects().count() == 0) return QDeclarativeDebugObjectReference(); - QDeclarativeDebugObjectQuery *q_obj = m_dbg->queryObject(q_context->rootContext().objects()[context], this); + QDeclarativeDebugObjectQuery *q_obj = recursive ? + m_dbg->queryObjectRecursive(q_context->rootContext().objects()[context], this) : + m_dbg->queryObject(q_context->rootContext().objects()[context], this); waitForQuery(q_obj); QDeclarativeDebugObjectReference result = q_obj->object(); @@ -926,6 +929,98 @@ void tst_QDeclarativeDebug::tst_QDeclarativeDebugPropertyReference() compareProperties(r, ref); } +void tst_QDeclarativeDebug::setBindingInStates() +{ + // Check if changing bindings of propertychanges works + + const int sourceIndex = 3; + + QDeclarativeDebugObjectReference obj = findRootObject(sourceIndex); + + QVERIFY(obj.debugId() != -1); + QVERIFY(obj.children().count() >= 2); + + // We are going to switch state a couple of times, we need to get rid of the transition before + QDeclarativeDebugExpressionQuery *q_deleteTransition = m_dbg->queryExpressionResult(obj.debugId(),QString("transitions = []"),this); + waitForQuery(q_deleteTransition); + delete q_deleteTransition; + + + // check initial value of the property that is changing + QDeclarativeDebugExpressionQuery *q_setState; + q_setState = m_dbg->queryExpressionResult(obj.debugId(),QString("state=\"state1\""),this); + waitForQuery(q_setState); + delete q_setState; + + obj = findRootObject(sourceIndex); + QCOMPARE(findProperty(obj.properties(),"width").value().toInt(),200); + + + q_setState = m_dbg->queryExpressionResult(obj.debugId(),QString("state=\"\""),this); + waitForQuery(q_setState); + delete q_setState; + + + obj = findRootObject(sourceIndex, true); + QCOMPARE(findProperty(obj.properties(),"width").value().toInt(),100); + + + // change the binding + QDeclarativeDebugObjectReference state = obj.children()[0]; + QCOMPARE(state.className(), QString("State")); + QVERIFY(state.children().count() > 0); + + QDeclarativeDebugObjectReference propertyChange = state.children()[0]; + QVERIFY(propertyChange.debugId() != -1); + + QVERIFY( m_dbg->setBindingForObject(propertyChange.debugId(), "width",QVariant(300),true) ); + + // check properties changed in state + obj = findRootObject(sourceIndex); + QCOMPARE(findProperty(obj.properties(),"width").value().toInt(),100); + + + q_setState = m_dbg->queryExpressionResult(obj.debugId(),QString("state=\"state1\""),this); + waitForQuery(q_setState); + delete q_setState; + + obj = findRootObject(sourceIndex); + QCOMPARE(findProperty(obj.properties(),"width").value().toInt(),300); + + // check changing properties of base state from within a state + QVERIFY(m_dbg->setBindingForObject(obj.debugId(),"width","height*2",false)); + QVERIFY(m_dbg->setBindingForObject(obj.debugId(),"height","200",true)); + + obj = findRootObject(sourceIndex); + QCOMPARE(findProperty(obj.properties(),"width").value().toInt(),300); + + q_setState = m_dbg->queryExpressionResult(obj.debugId(),QString("state=\"\""),this); + waitForQuery(q_setState); + delete q_setState; + + obj = findRootObject(sourceIndex); + QCOMPARE(findProperty(obj.properties(),"width").value().toInt(), 400); + + // reset binding while in a state + q_setState = m_dbg->queryExpressionResult(obj.debugId(),QString("state=\"state1\""),this); + waitForQuery(q_setState); + delete q_setState; + + obj = findRootObject(sourceIndex); + QCOMPARE(findProperty(obj.properties(),"width").value().toInt(), 300); + + m_dbg->resetBindingForObject(propertyChange.debugId(), "width"); + + obj = findRootObject(sourceIndex); + QCOMPARE(findProperty(obj.properties(),"width").value().toInt(), 400); + + // re-add binding + m_dbg->setBindingForObject(propertyChange.debugId(), "width", "300", true); + + obj = findRootObject(sourceIndex); + QCOMPARE(findProperty(obj.properties(),"width").value().toInt(), 300); +} + void tst_QDeclarativeDebug::queryObjectTree() { const int sourceIndex = 3; -- cgit v0.12 From d1139664012718f9bbf54e283ef7c370d98c48a8 Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Thu, 16 Dec 2010 12:33:21 +0100 Subject: QmlDebugger: reset properties to default value Reviewed-by: Kai Koehne --- src/declarative/qml/qdeclarativeenginedebug.cpp | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/declarative/qml/qdeclarativeenginedebug.cpp b/src/declarative/qml/qdeclarativeenginedebug.cpp index 4d6e50c..6c013de 100644 --- a/src/declarative/qml/qdeclarativeenginedebug.cpp +++ b/src/declarative/qml/qdeclarativeenginedebug.cpp @@ -613,9 +613,25 @@ void QDeclarativeEngineDebugServer::resetBinding(int objectId, const QString &pr QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::setBinding(property, 0); if (oldBinding) oldBinding->destroy(); + } + if (property.isResettable()) { + // Note: this will reset the property in any case, without regard to states + // Right now almost no QDeclarativeItem has reset methods for its properties (with the + // notable exception of QDeclarativeAnchors), so this is not a big issue + // later on, setBinding does take states into account + property.reset(); } else { - if (property.isResettable()) { - property.reset(); + // overwrite with default value + if (QDeclarativeType *objType = QDeclarativeMetaType::qmlType(object->metaObject())) { + if (QObject *emptyObject = objType->create()) { + if (emptyObject->property(propertyName.toLatin1()).isValid()) { + QVariant defaultValue = QDeclarativeProperty(emptyObject, propertyName).read(); + if (defaultValue.isValid()) { + setBinding(objectId, propertyName, defaultValue, true); + } + } + delete emptyObject; + } } } } else { -- cgit v0.12 From c54443507edf98832c67d727746ae4a130a14571 Mon Sep 17 00:00:00 2001 From: Yann Bodson Date: Fri, 17 Dec 2010 15:55:50 +1000 Subject: Support for justification in Text and TextEdit elements. Task-number: QTBUG-13242 Reviewed-by: Michael Brasser --- src/declarative/graphicsitems/qdeclarativetext.cpp | 11 +++++++---- src/declarative/graphicsitems/qdeclarativetext_p.h | 3 ++- .../graphicsitems/qdeclarativetextedit.cpp | 1 + .../graphicsitems/qdeclarativetextedit_p.h | 3 ++- .../qdeclarativetext/align/data-MAC/justify.0.png | Bin 0 -> 7233 bytes .../qdeclarativetext/align/data-MAC/justify.qml | 11 +++++++++++ .../qmlvisual/qdeclarativetext/align/justify.qml | 22 +++++++++++++++++++++ .../qdeclarativetextedit/data-MAC/justify.0.png | Bin 0 -> 7233 bytes .../qdeclarativetextedit/data-MAC/justify.qml | 11 +++++++++++ .../qmlvisual/qdeclarativetextedit/justify.qml | 22 +++++++++++++++++++++ 10 files changed, 78 insertions(+), 6 deletions(-) create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetext/align/data-MAC/justify.0.png create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetext/align/data-MAC/justify.qml create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetext/align/justify.qml create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetextedit/data-MAC/justify.0.png create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetextedit/data-MAC/justify.qml create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetextedit/justify.qml diff --git a/src/declarative/graphicsitems/qdeclarativetext.cpp b/src/declarative/graphicsitems/qdeclarativetext.cpp index 303b21c..cf11be6 100644 --- a/src/declarative/graphicsitems/qdeclarativetext.cpp +++ b/src/declarative/graphicsitems/qdeclarativetext.cpp @@ -297,6 +297,8 @@ QSize QDeclarativeTextPrivate::setupTextLayout() lineWidth = q->width(); QTextOption textOption = layout.textOption(); + if (hAlign == QDeclarativeText::AlignJustify) + textOption.setAlignment(Qt::Alignment(hAlign)); textOption.setWrapMode(QTextOption::WrapMode(wrapMode)); layout.setTextOption(textOption); @@ -325,7 +327,7 @@ QSize QDeclarativeTextPrivate::setupTextLayout() height += line.height(); if (!cacheAllTextAsImage) { - if (hAlign == QDeclarativeText::AlignLeft) { + if ((hAlign == QDeclarativeText::AlignLeft) || (hAlign == QDeclarativeText::AlignJustify)) { x = 0; } else if (hAlign == QDeclarativeText::AlignRight) { x = layoutWidth - line.naturalTextWidth(); @@ -351,7 +353,7 @@ QPixmap QDeclarativeTextPrivate::textLayoutImage(bool drawStyle) qreal x = 0; for (int i = 0; i < layout.lineCount(); ++i) { QTextLine line = layout.lineAt(i); - if (hAlign == QDeclarativeText::AlignLeft) { + if ((hAlign == QDeclarativeText::AlignLeft) || (hAlign == QDeclarativeText::AlignJustify)) { x = 0; } else if (hAlign == QDeclarativeText::AlignRight) { x = size.width() - line.naturalTextWidth(); @@ -898,8 +900,8 @@ void QDeclarativeText::setStyleColor(const QColor &color) Sets the horizontal and vertical alignment of the text within the Text items width and height. By default, the text is top-left aligned. - The valid values for \c horizontalAlignment are \c Text.AlignLeft, \c Text.AlignRight and - \c Text.AlignHCenter. The valid values for \c verticalAlignment are \c Text.AlignTop, \c Text.AlignBottom + The valid values for \c horizontalAlignment are \c Text.AlignLeft, \c Text.AlignRight, \c Text.AlignHCenter and + \c Text.AlignJustify. The valid values for \c verticalAlignment are \c Text.AlignTop, \c Text.AlignBottom and \c Text.AlignVCenter. Note that for a single line of text, the size of the text is the area of the text. In this common case, @@ -1117,6 +1119,7 @@ QRectF QDeclarativeText::boundingRect() const switch (d->hAlign) { case AlignLeft: + case AlignJustify: x = 0; break; case AlignRight: diff --git a/src/declarative/graphicsitems/qdeclarativetext_p.h b/src/declarative/graphicsitems/qdeclarativetext_p.h index 51434d5..49bff14 100644 --- a/src/declarative/graphicsitems/qdeclarativetext_p.h +++ b/src/declarative/graphicsitems/qdeclarativetext_p.h @@ -82,7 +82,8 @@ public: enum HAlignment { AlignLeft = Qt::AlignLeft, AlignRight = Qt::AlignRight, - AlignHCenter = Qt::AlignHCenter }; + AlignHCenter = Qt::AlignHCenter, + AlignJustify = Qt::AlignJustify }; // ### VERSIONING: Only in QtQuick 1.1 enum VAlignment { AlignTop = Qt::AlignTop, AlignBottom = Qt::AlignBottom, AlignVCenter = Qt::AlignVCenter }; diff --git a/src/declarative/graphicsitems/qdeclarativetextedit.cpp b/src/declarative/graphicsitems/qdeclarativetextedit.cpp index e05f4e4..f37fa62 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextedit.cpp @@ -442,6 +442,7 @@ void QDeclarativeTextEdit::setSelectedTextColor(const QColor &color) \o TextEdit.AlignLeft (default) \o TextEdit.AlignRight \o TextEdit.AlignHCenter + \o TextEdit.AlignJustify \endlist Valid values for \c verticalAlignment are: diff --git a/src/declarative/graphicsitems/qdeclarativetextedit_p.h b/src/declarative/graphicsitems/qdeclarativetextedit_p.h index 68fde3d..7f12c85 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextedit_p.h @@ -97,7 +97,8 @@ public: enum HAlignment { AlignLeft = Qt::AlignLeft, AlignRight = Qt::AlignRight, - AlignHCenter = Qt::AlignHCenter + AlignHCenter = Qt::AlignHCenter, + AlignJustify = Qt::AlignJustify // ### VERSIONING: Only in QtQuick 1.1 }; enum VAlignment { diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/align/data-MAC/justify.0.png b/tests/auto/declarative/qmlvisual/qdeclarativetext/align/data-MAC/justify.0.png new file mode 100644 index 0000000..74c6934 Binary files /dev/null and b/tests/auto/declarative/qmlvisual/qdeclarativetext/align/data-MAC/justify.0.png differ diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/align/data-MAC/justify.qml b/tests/auto/declarative/qmlvisual/qdeclarativetext/align/data-MAC/justify.qml new file mode 100644 index 0000000..e4dbeb1 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/align/data-MAC/justify.qml @@ -0,0 +1,11 @@ +import Qt.VisualTest 4.7 + +VisualTest { + Frame { + msec: 0 + } + Frame { + msec: 16 + image: "justify.0.png" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/align/justify.qml b/tests/auto/declarative/qmlvisual/qdeclarativetext/align/justify.qml new file mode 100644 index 0000000..c3a7aaa --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/align/justify.qml @@ -0,0 +1,22 @@ +import QtQuick 1.0 +import "../../shared" 1.0 + +Rectangle { + width: 450 + height: 250 + + TestText { + anchors.fill: parent + anchors { leftMargin: 10; rightMargin: 10; topMargin:10; bottomMargin: 10 } + wrapMode: Text.Wrap + horizontalAlignment: Text.AlignJustify + + text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin a aliquet massa. Integer id velit a nibh imperdiet sagittis. Cras fringilla enim non nulla porta bibendum. Integer risus urna, hendrerit non interdum ut, dapibus id velit. Nullam fermentum viverra pellentesque. In molestie scelerisque lorem molestie ultrices. Curabitur dolor arcu, tristique in sodales in, varius sed diam. Quisque magna velit, tincidunt sed ullamcorper sit amet, ornare adipiscing ligula. In hac habitasse platea dictumst. Ut tincidunt urna vel mauris fermentum ornare quis a ligula. Suspendisse cursus volutpat sapien eget cursus." + + Rectangle { + anchors.fill: parent + color: "transparent" + border.color: "red" + } + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data-MAC/justify.0.png b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data-MAC/justify.0.png new file mode 100644 index 0000000..74c6934 Binary files /dev/null and b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data-MAC/justify.0.png differ diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data-MAC/justify.qml b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data-MAC/justify.qml new file mode 100644 index 0000000..e4dbeb1 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data-MAC/justify.qml @@ -0,0 +1,11 @@ +import Qt.VisualTest 4.7 + +VisualTest { + Frame { + msec: 0 + } + Frame { + msec: 16 + image: "justify.0.png" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextedit/justify.qml b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/justify.qml new file mode 100644 index 0000000..4aeb58c --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/justify.qml @@ -0,0 +1,22 @@ +import QtQuick 1.0 +import "../shared" 1.0 + +Rectangle { + width: 450 + height: 250 + + TestTextEdit { + anchors.fill: parent + anchors { leftMargin: 10; rightMargin: 10; topMargin:10; bottomMargin: 10 } + wrapMode: Text.Wrap + horizontalAlignment: Text.AlignJustify + + text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin a aliquet massa. Integer id velit a nibh imperdiet sagittis. Cras fringilla enim non nulla porta bibendum. Integer risus urna, hendrerit non interdum ut, dapibus id velit. Nullam fermentum viverra pellentesque. In molestie scelerisque lorem molestie ultrices. Curabitur dolor arcu, tristique in sodales in, varius sed diam. Quisque magna velit, tincidunt sed ullamcorper sit amet, ornare adipiscing ligula. In hac habitasse platea dictumst. Ut tincidunt urna vel mauris fermentum ornare quis a ligula. Suspendisse cursus volutpat sapien eget cursus." + + Rectangle { + anchors.fill: parent + color: "transparent" + border.color: "red" + } + } +} -- cgit v0.12 From cdd9209590f9c970ea6f9e0c734f0729610ede2a Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Tue, 14 Dec 2010 08:54:25 +1000 Subject: Optimization for photoviewer demo. --- demos/declarative/photoviewer/PhotoViewerCore/PhotoDelegate.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demos/declarative/photoviewer/PhotoViewerCore/PhotoDelegate.qml b/demos/declarative/photoviewer/PhotoViewerCore/PhotoDelegate.qml index 856a2c7..6248745 100644 --- a/demos/declarative/photoviewer/PhotoViewerCore/PhotoDelegate.qml +++ b/demos/declarative/photoviewer/PhotoViewerCore/PhotoDelegate.qml @@ -61,7 +61,7 @@ Package { BorderImage { anchors { - fill: border.visible ? border : placeHolder + fill: originalImage.status == Image.Ready ? border : placeHolder leftMargin: -6; topMargin: -6; rightMargin: -8; bottomMargin: -8 } source: 'images/box-shadow.png'; smooth: true -- cgit v0.12 From 139ecc0e74af2795faa55cfd532aeb10c631049e Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Tue, 14 Dec 2010 10:20:57 +1000 Subject: Optimize construction of QDeclarativeProperty in state operations. Reviewed-by: Martin Jones --- src/declarative/util/qdeclarativestate.cpp | 2 +- .../util/qdeclarativestateoperations.cpp | 63 ++++++++++++---------- 2 files changed, 35 insertions(+), 30 deletions(-) diff --git a/src/declarative/util/qdeclarativestate.cpp b/src/declarative/util/qdeclarativestate.cpp index 3915485..6925e03 100644 --- a/src/declarative/util/qdeclarativestate.cpp +++ b/src/declarative/util/qdeclarativestate.cpp @@ -66,7 +66,7 @@ QDeclarativeAction::QDeclarativeAction() QDeclarativeAction::QDeclarativeAction(QObject *target, const QString &propertyName, const QVariant &value) : restore(true), actionDone(false), reverseEvent(false), deletableToBinding(false), - property(target, propertyName), toValue(value), + property(target, propertyName, qmlEngine(target)), toValue(value), fromBinding(0), event(0), specifiedObject(target), specifiedProperty(propertyName) { diff --git a/src/declarative/util/qdeclarativestateoperations.cpp b/src/declarative/util/qdeclarativestateoperations.cpp index d1d7822..82360b2 100644 --- a/src/declarative/util/qdeclarativestateoperations.cpp +++ b/src/declarative/util/qdeclarativestateoperations.cpp @@ -367,16 +367,18 @@ QDeclarativeStateOperation::ActionList QDeclarativeParentChange::actions() a.event = this; actions << a; + QDeclarativeContext *ctxt = qmlContext(this); + if (d->xString.isValid()) { bool ok = false; QString script = d->xString.value.script(); qreal x = script.toFloat(&ok); if (ok) { - QDeclarativeAction xa(d->target, QLatin1String("x"), x); + QDeclarativeAction xa(d->target, QLatin1String("x"), ctxt, x); actions << xa; } else { - QDeclarativeBinding *newBinding = new QDeclarativeBinding(script, d->target, qmlContext(this)); - newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("x"))); + QDeclarativeBinding *newBinding = new QDeclarativeBinding(script, d->target, ctxt); + newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("x"), ctxt)); QDeclarativeAction xa; xa.property = newBinding->property(); xa.toBinding = newBinding; @@ -391,11 +393,11 @@ QDeclarativeStateOperation::ActionList QDeclarativeParentChange::actions() QString script = d->yString.value.script(); qreal y = script.toFloat(&ok); if (ok) { - QDeclarativeAction ya(d->target, QLatin1String("y"), y); + QDeclarativeAction ya(d->target, QLatin1String("y"), ctxt, y); actions << ya; } else { - QDeclarativeBinding *newBinding = new QDeclarativeBinding(script, d->target, qmlContext(this)); - newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("y"))); + QDeclarativeBinding *newBinding = new QDeclarativeBinding(script, d->target, ctxt); + newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("y"), ctxt)); QDeclarativeAction ya; ya.property = newBinding->property(); ya.toBinding = newBinding; @@ -410,11 +412,11 @@ QDeclarativeStateOperation::ActionList QDeclarativeParentChange::actions() QString script = d->scaleString.value.script(); qreal scale = script.toFloat(&ok); if (ok) { - QDeclarativeAction sa(d->target, QLatin1String("scale"), scale); + QDeclarativeAction sa(d->target, QLatin1String("scale"), ctxt, scale); actions << sa; } else { - QDeclarativeBinding *newBinding = new QDeclarativeBinding(script, d->target, qmlContext(this)); - newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("scale"))); + QDeclarativeBinding *newBinding = new QDeclarativeBinding(script, d->target, ctxt); + newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("scale"), ctxt)); QDeclarativeAction sa; sa.property = newBinding->property(); sa.toBinding = newBinding; @@ -429,11 +431,11 @@ QDeclarativeStateOperation::ActionList QDeclarativeParentChange::actions() QString script = d->rotationString.value.script(); qreal rotation = script.toFloat(&ok); if (ok) { - QDeclarativeAction ra(d->target, QLatin1String("rotation"), rotation); + QDeclarativeAction ra(d->target, QLatin1String("rotation"), ctxt, rotation); actions << ra; } else { - QDeclarativeBinding *newBinding = new QDeclarativeBinding(script, d->target, qmlContext(this)); - newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("rotation"))); + QDeclarativeBinding *newBinding = new QDeclarativeBinding(script, d->target, ctxt); + newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("rotation"), ctxt)); QDeclarativeAction ra; ra.property = newBinding->property(); ra.toBinding = newBinding; @@ -448,11 +450,11 @@ QDeclarativeStateOperation::ActionList QDeclarativeParentChange::actions() QString script = d->widthString.value.script(); qreal width = script.toFloat(&ok); if (ok) { - QDeclarativeAction wa(d->target, QLatin1String("width"), width); + QDeclarativeAction wa(d->target, QLatin1String("width"), ctxt, width); actions << wa; } else { - QDeclarativeBinding *newBinding = new QDeclarativeBinding(script, d->target, qmlContext(this)); - newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("width"))); + QDeclarativeBinding *newBinding = new QDeclarativeBinding(script, d->target, ctxt); + newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("width"), ctxt)); QDeclarativeAction wa; wa.property = newBinding->property(); wa.toBinding = newBinding; @@ -467,11 +469,11 @@ QDeclarativeStateOperation::ActionList QDeclarativeParentChange::actions() QString script = d->heightString.value.script(); qreal height = script.toFloat(&ok); if (ok) { - QDeclarativeAction ha(d->target, QLatin1String("height"), height); + QDeclarativeAction ha(d->target, QLatin1String("height"), ctxt, height); actions << ha; } else { - QDeclarativeBinding *newBinding = new QDeclarativeBinding(script, d->target, qmlContext(this)); - newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("height"))); + QDeclarativeBinding *newBinding = new QDeclarativeBinding(script, d->target, ctxt); + newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("height"), ctxt)); QDeclarativeAction ha; ha.property = newBinding->property(); ha.toBinding = newBinding; @@ -1075,32 +1077,34 @@ QDeclarativeAnchorChanges::ActionList QDeclarativeAnchorChanges::actions() d->vCenterProp = QDeclarativeProperty(d->target, QLatin1String("anchors.verticalCenter")); d->baselineProp = QDeclarativeProperty(d->target, QLatin1String("anchors.baseline")); + QDeclarativeContext *ctxt = qmlContext(this); + if (d->anchorSet->d_func()->usedAnchors & QDeclarativeAnchors::LeftAnchor) { - d->leftBinding = new QDeclarativeBinding(d->anchorSet->d_func()->leftScript.script(), d->target, qmlContext(this)); + d->leftBinding = new QDeclarativeBinding(d->anchorSet->d_func()->leftScript.script(), d->target, ctxt); d->leftBinding->setTarget(d->leftProp); } if (d->anchorSet->d_func()->usedAnchors & QDeclarativeAnchors::RightAnchor) { - d->rightBinding = new QDeclarativeBinding(d->anchorSet->d_func()->rightScript.script(), d->target, qmlContext(this)); + d->rightBinding = new QDeclarativeBinding(d->anchorSet->d_func()->rightScript.script(), d->target, ctxt); d->rightBinding->setTarget(d->rightProp); } if (d->anchorSet->d_func()->usedAnchors & QDeclarativeAnchors::HCenterAnchor) { - d->hCenterBinding = new QDeclarativeBinding(d->anchorSet->d_func()->hCenterScript.script(), d->target, qmlContext(this)); + d->hCenterBinding = new QDeclarativeBinding(d->anchorSet->d_func()->hCenterScript.script(), d->target, ctxt); d->hCenterBinding->setTarget(d->hCenterProp); } if (d->anchorSet->d_func()->usedAnchors & QDeclarativeAnchors::TopAnchor) { - d->topBinding = new QDeclarativeBinding(d->anchorSet->d_func()->topScript.script(), d->target, qmlContext(this)); + d->topBinding = new QDeclarativeBinding(d->anchorSet->d_func()->topScript.script(), d->target, ctxt); d->topBinding->setTarget(d->topProp); } if (d->anchorSet->d_func()->usedAnchors & QDeclarativeAnchors::BottomAnchor) { - d->bottomBinding = new QDeclarativeBinding(d->anchorSet->d_func()->bottomScript.script(), d->target, qmlContext(this)); + d->bottomBinding = new QDeclarativeBinding(d->anchorSet->d_func()->bottomScript.script(), d->target, ctxt); d->bottomBinding->setTarget(d->bottomProp); } if (d->anchorSet->d_func()->usedAnchors & QDeclarativeAnchors::VCenterAnchor) { - d->vCenterBinding = new QDeclarativeBinding(d->anchorSet->d_func()->vCenterScript.script(), d->target, qmlContext(this)); + d->vCenterBinding = new QDeclarativeBinding(d->anchorSet->d_func()->vCenterScript.script(), d->target, ctxt); d->vCenterBinding->setTarget(d->vCenterProp); } if (d->anchorSet->d_func()->usedAnchors & QDeclarativeAnchors::BaselineAnchor) { - d->baselineBinding = new QDeclarativeBinding(d->anchorSet->d_func()->baselineScript.script(), d->target, qmlContext(this)); + d->baselineBinding = new QDeclarativeBinding(d->anchorSet->d_func()->baselineScript.script(), d->target, ctxt); d->baselineBinding->setTarget(d->baselineProp); } @@ -1380,24 +1384,25 @@ QList QDeclarativeAnchorChanges::additionalActions() bool vChange = combined & QDeclarativeAnchors::Vertical_Mask; if (d->target) { + QDeclarativeContext *ctxt = qmlContext(this); QDeclarativeAction a; if (hChange && d->fromX != d->toX) { - a.property = QDeclarativeProperty(d->target, QLatin1String("x")); + a.property = QDeclarativeProperty(d->target, QLatin1String("x"), ctxt); a.toValue = d->toX; extra << a; } if (vChange && d->fromY != d->toY) { - a.property = QDeclarativeProperty(d->target, QLatin1String("y")); + a.property = QDeclarativeProperty(d->target, QLatin1String("y"), ctxt); a.toValue = d->toY; extra << a; } if (hChange && d->fromWidth != d->toWidth) { - a.property = QDeclarativeProperty(d->target, QLatin1String("width")); + a.property = QDeclarativeProperty(d->target, QLatin1String("width"), ctxt); a.toValue = d->toWidth; extra << a; } if (vChange && d->fromHeight != d->toHeight) { - a.property = QDeclarativeProperty(d->target, QLatin1String("height")); + a.property = QDeclarativeProperty(d->target, QLatin1String("height"), ctxt); a.toValue = d->toHeight; extra << a; } -- cgit v0.12 From 488e616b50707e5b37162e6d0cfc71a1ffdf9bef Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Wed, 15 Dec 2010 12:08:13 +1000 Subject: Rewrite/cache bindings created by PropertyChanges. This provides a significant optimization for initial evaluation of bindings specified in a PropertyChanges. Reviewed-by: Aaron Kennedy --- src/declarative/qml/qdeclarativebinding.cpp | 14 +++++++++++ src/declarative/qml/qdeclarativebinding_p.h | 3 +++ src/declarative/qml/qdeclarativecompiler.cpp | 29 ++++++++++++++++++++++ src/declarative/qml/qdeclarativecompiler_p.h | 1 + src/declarative/qml/qdeclarativecontext_p.h | 1 - src/declarative/qml/qdeclarativecustomparser.cpp | 9 +++++++ src/declarative/qml/qdeclarativecustomparser_p.h | 3 +++ .../util/qdeclarativepropertychanges.cpp | 26 ++++++++++++++++--- 8 files changed, 82 insertions(+), 4 deletions(-) diff --git a/src/declarative/qml/qdeclarativebinding.cpp b/src/declarative/qml/qdeclarativebinding.cpp index 309d372..1ead6ce 100644 --- a/src/declarative/qml/qdeclarativebinding.cpp +++ b/src/declarative/qml/qdeclarativebinding.cpp @@ -46,6 +46,7 @@ #include "qdeclarativecontext.h" #include "qdeclarativeinfo.h" #include "private/qdeclarativecontext_p.h" +#include "private/qdeclarativecompiler_p.h" #include "private/qdeclarativedata_p.h" #include "private/qdeclarativestringconverters_p.h" #include "private/qdeclarativestate_p_p.h" @@ -233,6 +234,19 @@ QDeclarativeBinding::QDeclarativeBinding(void *data, QDeclarativeRefCount *rc, Q setNotifyOnValueChanged(true); } +QDeclarativeBinding * +QDeclarativeBinding::createBinding(Identifier id, QObject *obj, QDeclarativeContext *ctxt, + const QString &url, int lineNumber, QObject *parent) +{ + QDeclarativeContextData *ctxtdata = QDeclarativeContextData::get(ctxt); + + QDeclarativeEnginePrivate *engine = QDeclarativeEnginePrivate::get(qmlEngine(obj)); + QDeclarativeCompiledData *cdata = 0; + if (engine && ctxtdata && !ctxtdata->url.isEmpty()) + cdata = engine->typeLoader.get(ctxtdata->url)->compiledData(); + return cdata ? new QDeclarativeBinding((void*)cdata->datas.at(id).constData(), cdata, obj, ctxtdata, url, lineNumber, parent) : 0; +} + QDeclarativeBinding::QDeclarativeBinding(const QString &str, QObject *obj, QDeclarativeContext *ctxt, QObject *parent) : QDeclarativeExpression(QDeclarativeContextData::get(ctxt), obj, str, *new QDeclarativeBindingPrivate) diff --git a/src/declarative/qml/qdeclarativebinding_p.h b/src/declarative/qml/qdeclarativebinding_p.h index 7823a3d..787a3b9 100644 --- a/src/declarative/qml/qdeclarativebinding_p.h +++ b/src/declarative/qml/qdeclarativebinding_p.h @@ -162,6 +162,9 @@ public: virtual void update(QDeclarativePropertyPrivate::WriteFlags flags); virtual QString expression() const; + typedef int Identifier; + static QDeclarativeBinding *createBinding(Identifier, QObject *, QDeclarativeContext *, const QString &, int, QObject *parent=0); + public Q_SLOTS: void update() { update(QDeclarativePropertyPrivate::DontRemoveBinding); } diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp index 4749bf8..4f4ad3f 100644 --- a/src/declarative/qml/qdeclarativecompiler.cpp +++ b/src/declarative/qml/qdeclarativecompiler.cpp @@ -2262,6 +2262,35 @@ const QMetaObject *QDeclarativeCompiler::resolveType(const QByteArray& name) con return qmltype->metaObject(); } +// similar to logic of completeComponentBuild, but also sticks data +// into datas at the end +int QDeclarativeCompiler::rewriteBinding(const QString& expression, const QByteArray& name) +{ + QDeclarativeRewrite::RewriteBinding rewriteBinding; + rewriteBinding.setName('$' + name); + bool isSharable = false; + QString rewrite = rewriteBinding(expression, 0, &isSharable); + + quint32 length = rewrite.length(); + quint32 pc; + + if (isSharable) { + pc = output->cachedClosures.count(); + pc |= 0x80000000; + output->cachedClosures.append(0); + } else { + pc = output->cachedPrograms.length(); + output->cachedPrograms.append(0); + } + + QByteArray compiledData = + QByteArray((const char *)&pc, sizeof(quint32)) + + QByteArray((const char *)&length, sizeof(quint32)) + + QByteArray((const char *)rewrite.constData(), + rewrite.length() * sizeof(QChar)); + + return output->indexForByteArray(compiledData); +} // Ensures that the dynamic meta specification on obj is valid bool QDeclarativeCompiler::checkDynamicMeta(QDeclarativeParser::Object *obj) diff --git a/src/declarative/qml/qdeclarativecompiler_p.h b/src/declarative/qml/qdeclarativecompiler_p.h index 7d76ad9..bface8f 100644 --- a/src/declarative/qml/qdeclarativecompiler_p.h +++ b/src/declarative/qml/qdeclarativecompiler_p.h @@ -161,6 +161,7 @@ public: int evaluateEnum(const QByteArray& script) const; // for QDeclarativeCustomParser::evaluateEnum const QMetaObject *resolveType(const QByteArray& name) const; // for QDeclarativeCustomParser::resolveType + int rewriteBinding(const QString& expression, const QByteArray& name); // for QDeclarativeCustomParser::rewriteBinding private: static void reset(QDeclarativeCompiledData *); diff --git a/src/declarative/qml/qdeclarativecontext_p.h b/src/declarative/qml/qdeclarativecontext_p.h index 6c14feb..6b71381 100644 --- a/src/declarative/qml/qdeclarativecontext_p.h +++ b/src/declarative/qml/qdeclarativecontext_p.h @@ -77,7 +77,6 @@ class QDeclarativeEngine; class QDeclarativeExpression; class QDeclarativeExpressionPrivate; class QDeclarativeAbstractExpression; -class QDeclarativeBinding_Id; class QDeclarativeCompiledBindings; class QDeclarativeContextData; diff --git a/src/declarative/qml/qdeclarativecustomparser.cpp b/src/declarative/qml/qdeclarativecustomparser.cpp index 97a6a00..58ffc56 100644 --- a/src/declarative/qml/qdeclarativecustomparser.cpp +++ b/src/declarative/qml/qdeclarativecustomparser.cpp @@ -304,5 +304,14 @@ const QMetaObject *QDeclarativeCustomParser::resolveType(const QByteArray& name) return compiler->resolveType(name); } +/*! + Rewrites \a expression and returns an identifier that can be + used to construct the binding later. \a name + is used as the name of the rewritten function. +*/ +QDeclarativeBinding::Identifier QDeclarativeCustomParser::rewriteBinding(const QString& expression, const QByteArray& name) +{ + return compiler->rewriteBinding(expression, name); +} QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativecustomparser_p.h b/src/declarative/qml/qdeclarativecustomparser_p.h index c3f9dd2..9b419c2 100644 --- a/src/declarative/qml/qdeclarativecustomparser_p.h +++ b/src/declarative/qml/qdeclarativecustomparser_p.h @@ -56,6 +56,7 @@ #include "private/qdeclarativemetatype_p.h" #include "qdeclarativeerror.h" #include "private/qdeclarativeparser_p.h" +#include "private/qdeclarativebinding_p.h" #include #include @@ -140,6 +141,8 @@ protected: const QMetaObject *resolveType(const QByteArray&) const; + QDeclarativeBinding::Identifier rewriteBinding(const QString&, const QByteArray&); + private: QList exceptions; QDeclarativeCompiler *compiler; diff --git a/src/declarative/util/qdeclarativepropertychanges.cpp b/src/declarative/util/qdeclarativepropertychanges.cpp index 8d01b80..400803e 100644 --- a/src/declarative/util/qdeclarativepropertychanges.cpp +++ b/src/declarative/util/qdeclarativepropertychanges.cpp @@ -42,6 +42,9 @@ #include "private/qdeclarativepropertychanges_p.h" #include "private/qdeclarativeopenmetaobject_p.h" +#include "private/qdeclarativerewrite_p.h" +#include "private/qdeclarativeengine_p.h" +#include "private/qdeclarativecompiler_p.h" #include #include @@ -219,6 +222,7 @@ public: QList > properties; QList > expressions; + QList ids; QList signalReplacements; QDeclarativeProperty property(const QByteArray &); @@ -267,6 +271,7 @@ QDeclarativePropertyChangesParser::compile(const QList(data.at(ii).second); QVariant var; bool isScript = v.isScript(); + QDeclarativeBinding::Identifier id; switch(v.type()) { case QDeclarativeParser::Variant::Boolean: var = QVariant(v.asBoolean()); @@ -280,10 +285,17 @@ QDeclarativePropertyChangesParser::compile(const QList> name; ds >> isScript; ds >> data; + if (isScript) + ds >> id; QDeclarativeProperty prop = property(name); //### better way to check for signal property? if (prop.type() & QDeclarativeProperty::SignalProperty) { @@ -323,6 +338,7 @@ void QDeclarativePropertyChangesPrivate::decode() if (ddata && ddata->outerContext && !ddata->outerContext->url.isEmpty()) expression->setSourceLocation(ddata->outerContext->url.toString(), ddata->lineNumber); expressions << qMakePair(name, expression); + ids << id; } else { properties << qMakePair(name, data); } @@ -452,10 +468,14 @@ QDeclarativePropertyChanges::ActionList QDeclarativePropertyChanges::actions() a.toValue = d->expressions.at(ii).second->evaluate(); } else { QDeclarativeExpression *e = d->expressions.at(ii).second; - QDeclarativeBinding *newBinding = - new QDeclarativeBinding(e->expression(), object(), qmlContext(this)); + + QDeclarativeBinding::Identifier id = d->ids.at(ii); + QDeclarativeBinding *newBinding = QDeclarativeBinding::createBinding(id, object(), qmlContext(this), e->sourceFile(), e->lineNumber()); + if (!newBinding) { + newBinding = new QDeclarativeBinding(e->expression(), object(), qmlContext(this)); + newBinding->setSourceLocation(e->sourceFile(), e->lineNumber()); + } newBinding->setTarget(prop); - newBinding->setSourceLocation(e->sourceFile(), e->lineNumber()); a.toBinding = newBinding; a.deletableToBinding = true; } -- cgit v0.12 From 24b8dcee5bd51784c341acc708ce3985d85d430a Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Thu, 16 Dec 2010 14:54:28 +1000 Subject: ParentChange optimizations. The QDeclarativeScriptStrings used for the properties are unlikely to change, so we immediately attempt to convert to a real value, rather than converting every time actions() is called. Task-number: QTBUG-15331 Reviewed-by: Martin Jones --- .../util/qdeclarativestateoperations.cpp | 77 ++++++++++++---------- 1 file changed, 41 insertions(+), 36 deletions(-) diff --git a/src/declarative/util/qdeclarativestateoperations.cpp b/src/declarative/util/qdeclarativestateoperations.cpp index 82360b2..b606ff3 100644 --- a/src/declarative/util/qdeclarativestateoperations.cpp +++ b/src/declarative/util/qdeclarativestateoperations.cpp @@ -83,6 +83,13 @@ public: QDeclarativeNullableValue scaleString; QDeclarativeNullableValue rotationString; + QDeclarativeNullableValue x; + QDeclarativeNullableValue y; + QDeclarativeNullableValue width; + QDeclarativeNullableValue height; + QDeclarativeNullableValue scale; + QDeclarativeNullableValue rotation; + void doChange(QDeclarativeItem *targetParent, QDeclarativeItem *stackBefore = 0); }; @@ -213,10 +220,21 @@ QDeclarativeScriptString QDeclarativeParentChange::x() const return d->xString.value; } +void tryReal(QDeclarativeNullableValue &value, const QString &string) +{ + bool ok = false; + qreal realValue = string.toFloat(&ok); + if (ok) + value = realValue; + else + value.invalidate(); +} + void QDeclarativeParentChange::setX(QDeclarativeScriptString x) { Q_D(QDeclarativeParentChange); d->xString = x; + tryReal(d->x, x.script()); } bool QDeclarativeParentChange::xIsSet() const @@ -235,6 +253,7 @@ void QDeclarativeParentChange::setY(QDeclarativeScriptString y) { Q_D(QDeclarativeParentChange); d->yString = y; + tryReal(d->y, y.script()); } bool QDeclarativeParentChange::yIsSet() const @@ -253,6 +272,7 @@ void QDeclarativeParentChange::setWidth(QDeclarativeScriptString width) { Q_D(QDeclarativeParentChange); d->widthString = width; + tryReal(d->width, width.script()); } bool QDeclarativeParentChange::widthIsSet() const @@ -271,6 +291,7 @@ void QDeclarativeParentChange::setHeight(QDeclarativeScriptString height) { Q_D(QDeclarativeParentChange); d->heightString = height; + tryReal(d->height, height.script()); } bool QDeclarativeParentChange::heightIsSet() const @@ -289,6 +310,7 @@ void QDeclarativeParentChange::setScale(QDeclarativeScriptString scale) { Q_D(QDeclarativeParentChange); d->scaleString = scale; + tryReal(d->scale, scale.script()); } bool QDeclarativeParentChange::scaleIsSet() const @@ -307,6 +329,7 @@ void QDeclarativeParentChange::setRotation(QDeclarativeScriptString rotation) { Q_D(QDeclarativeParentChange); d->rotationString = rotation; + tryReal(d->rotation, rotation.script()); } bool QDeclarativeParentChange::rotationIsSet() const @@ -370,14 +393,11 @@ QDeclarativeStateOperation::ActionList QDeclarativeParentChange::actions() QDeclarativeContext *ctxt = qmlContext(this); if (d->xString.isValid()) { - bool ok = false; - QString script = d->xString.value.script(); - qreal x = script.toFloat(&ok); - if (ok) { - QDeclarativeAction xa(d->target, QLatin1String("x"), ctxt, x); + if (d->x.isValid()) { + QDeclarativeAction xa(d->target, QLatin1String("x"), ctxt, d->x.value); actions << xa; } else { - QDeclarativeBinding *newBinding = new QDeclarativeBinding(script, d->target, ctxt); + QDeclarativeBinding *newBinding = new QDeclarativeBinding(d->xString.value.script(), d->target, ctxt); newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("x"), ctxt)); QDeclarativeAction xa; xa.property = newBinding->property(); @@ -389,14 +409,11 @@ QDeclarativeStateOperation::ActionList QDeclarativeParentChange::actions() } if (d->yString.isValid()) { - bool ok = false; - QString script = d->yString.value.script(); - qreal y = script.toFloat(&ok); - if (ok) { - QDeclarativeAction ya(d->target, QLatin1String("y"), ctxt, y); + if (d->y.isValid()) { + QDeclarativeAction ya(d->target, QLatin1String("y"), ctxt, d->y.value); actions << ya; } else { - QDeclarativeBinding *newBinding = new QDeclarativeBinding(script, d->target, ctxt); + QDeclarativeBinding *newBinding = new QDeclarativeBinding(d->yString.value.script(), d->target, ctxt); newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("y"), ctxt)); QDeclarativeAction ya; ya.property = newBinding->property(); @@ -408,14 +425,11 @@ QDeclarativeStateOperation::ActionList QDeclarativeParentChange::actions() } if (d->scaleString.isValid()) { - bool ok = false; - QString script = d->scaleString.value.script(); - qreal scale = script.toFloat(&ok); - if (ok) { - QDeclarativeAction sa(d->target, QLatin1String("scale"), ctxt, scale); + if (d->scale.isValid()) { + QDeclarativeAction sa(d->target, QLatin1String("scale"), ctxt, d->scale.value); actions << sa; } else { - QDeclarativeBinding *newBinding = new QDeclarativeBinding(script, d->target, ctxt); + QDeclarativeBinding *newBinding = new QDeclarativeBinding(d->scaleString.value.script(), d->target, ctxt); newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("scale"), ctxt)); QDeclarativeAction sa; sa.property = newBinding->property(); @@ -427,14 +441,11 @@ QDeclarativeStateOperation::ActionList QDeclarativeParentChange::actions() } if (d->rotationString.isValid()) { - bool ok = false; - QString script = d->rotationString.value.script(); - qreal rotation = script.toFloat(&ok); - if (ok) { - QDeclarativeAction ra(d->target, QLatin1String("rotation"), ctxt, rotation); + if (d->rotation.isValid()) { + QDeclarativeAction ra(d->target, QLatin1String("rotation"), ctxt, d->rotation.value); actions << ra; } else { - QDeclarativeBinding *newBinding = new QDeclarativeBinding(script, d->target, ctxt); + QDeclarativeBinding *newBinding = new QDeclarativeBinding(d->rotationString.value.script(), d->target, ctxt); newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("rotation"), ctxt)); QDeclarativeAction ra; ra.property = newBinding->property(); @@ -446,14 +457,11 @@ QDeclarativeStateOperation::ActionList QDeclarativeParentChange::actions() } if (d->widthString.isValid()) { - bool ok = false; - QString script = d->widthString.value.script(); - qreal width = script.toFloat(&ok); - if (ok) { - QDeclarativeAction wa(d->target, QLatin1String("width"), ctxt, width); + if (d->width.isValid()) { + QDeclarativeAction wa(d->target, QLatin1String("width"), ctxt, d->width.value); actions << wa; } else { - QDeclarativeBinding *newBinding = new QDeclarativeBinding(script, d->target, ctxt); + QDeclarativeBinding *newBinding = new QDeclarativeBinding(d->widthString.value.script(), d->target, ctxt); newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("width"), ctxt)); QDeclarativeAction wa; wa.property = newBinding->property(); @@ -465,14 +473,11 @@ QDeclarativeStateOperation::ActionList QDeclarativeParentChange::actions() } if (d->heightString.isValid()) { - bool ok = false; - QString script = d->heightString.value.script(); - qreal height = script.toFloat(&ok); - if (ok) { - QDeclarativeAction ha(d->target, QLatin1String("height"), ctxt, height); + if (d->height.isValid()) { + QDeclarativeAction ha(d->target, QLatin1String("height"), ctxt, d->height.value); actions << ha; } else { - QDeclarativeBinding *newBinding = new QDeclarativeBinding(script, d->target, ctxt); + QDeclarativeBinding *newBinding = new QDeclarativeBinding(d->heightString.value.script(), d->target, ctxt); newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("height"), ctxt)); QDeclarativeAction ha; ha.property = newBinding->property(); -- cgit v0.12 From 9536b35d63716e88482baeed34d11509ed724606 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Fri, 17 Dec 2010 16:32:24 +1000 Subject: Fix PropertyChange's binding rewriting for 'dot' properties. For cases like PropertyChanges { font.pixelSize: myPixelSize } it was attempting to rewrite the function name as font.pixelSize, which is not syntactically correct. We now rewrite the function name as pixelSize. --- src/declarative/qml/qdeclarativecompiler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp index 4f4ad3f..b2b0990 100644 --- a/src/declarative/qml/qdeclarativecompiler.cpp +++ b/src/declarative/qml/qdeclarativecompiler.cpp @@ -2267,7 +2267,7 @@ const QMetaObject *QDeclarativeCompiler::resolveType(const QByteArray& name) con int QDeclarativeCompiler::rewriteBinding(const QString& expression, const QByteArray& name) { QDeclarativeRewrite::RewriteBinding rewriteBinding; - rewriteBinding.setName('$' + name); + rewriteBinding.setName('$' + name.mid(name.lastIndexOf('.') + 1)); bool isSharable = false; QString rewrite = rewriteBinding(expression, 0, &isSharable); -- cgit v0.12 From 84456ce081fa3c2e2f10b5162c70566f98124b0f Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Thu, 18 Nov 2010 10:32:36 +0100 Subject: QDeclarativeDebug: Rename member variable 'client' points to the QDeclarativeDebugConnection object, so better name it 'connection' then. Reviewed-by: Christiaan Janssen --- .../debugger/qdeclarativedebugclient.cpp | 36 +++++++++++----------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/declarative/debugger/qdeclarativedebugclient.cpp b/src/declarative/debugger/qdeclarativedebugclient.cpp index f5c5751..204ca4f 100644 --- a/src/declarative/debugger/qdeclarativedebugclient.cpp +++ b/src/declarative/debugger/qdeclarativedebugclient.cpp @@ -61,7 +61,7 @@ public: QDeclarativeDebugClientPrivate(); QString name; - QDeclarativeDebugConnection *client; + QDeclarativeDebugConnection *connection; }; class QDeclarativeDebugConnectionPrivate : public QObject @@ -202,7 +202,7 @@ QDeclarativeDebugConnection::~QDeclarativeDebugConnection() { QHash::iterator iter = d->plugins.begin(); for (; iter != d->plugins.end(); ++iter) { - iter.value()->d_func()->client = 0; + iter.value()->d_func()->connection = 0; iter.value()->statusChanged(QDeclarativeDebugClient::NotConnected); } } @@ -213,7 +213,7 @@ bool QDeclarativeDebugConnection::isConnected() const } QDeclarativeDebugClientPrivate::QDeclarativeDebugClientPrivate() -: client(0) +: connection(0) { } @@ -223,26 +223,26 @@ QDeclarativeDebugClient::QDeclarativeDebugClient(const QString &name, { Q_D(QDeclarativeDebugClient); d->name = name; - d->client = parent; + d->connection = parent; - if (!d->client) + if (!d->connection) return; - if (d->client->d->plugins.contains(name)) { + if (d->connection->d->plugins.contains(name)) { qWarning() << "QDeclarativeDebugClient: Conflicting plugin name" << name; - d->client = 0; + d->connection = 0; } else { - d->client->d->plugins.insert(name, this); - d->client->d->advertisePlugins(); + d->connection->d->plugins.insert(name, this); + d->connection->d->advertisePlugins(); } } QDeclarativeDebugClient::~QDeclarativeDebugClient() { Q_D(const QDeclarativeDebugClient); - if (d->client && d->client->d) { - d->client->d->plugins.remove(d->name); - d->client->d->advertisePlugins(); + if (d->connection && d->connection->d) { + d->connection->d->plugins.remove(d->name); + d->connection->d->advertisePlugins(); } } @@ -255,12 +255,12 @@ QString QDeclarativeDebugClient::name() const QDeclarativeDebugClient::Status QDeclarativeDebugClient::status() const { Q_D(const QDeclarativeDebugClient); - if (!d->client - || !d->client->isConnected() - || !d->client->d->gotHello) + if (!d->connection + || !d->connection->isConnected() + || !d->connection->d->gotHello) return NotConnected; - if (d->client->d->serverPlugins.contains(d->name)) + if (d->connection->d->serverPlugins.contains(d->name)) return Enabled; return Unavailable; @@ -275,8 +275,8 @@ void QDeclarativeDebugClient::sendMessage(const QByteArray &message) QPacket pack; pack << d->name << message; - d->client->d->protocol->send(pack); - d->client->d->q->flush(); + d->connection->d->protocol->send(pack); + d->connection->d->q->flush(); } void QDeclarativeDebugClient::statusChanged(Status) -- cgit v0.12 From 5d251ef253065d68967ae3263b3cf7f1d93d7a00 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Thu, 18 Nov 2010 14:54:24 +0100 Subject: QDeclarativeDebug: Decouple QDDServer, QDDService classes Move QDeclarativeDebugServer class into it's own files and make the classes less interdependent. --- src/declarative/debugger/debugger.pri | 7 +- .../debugger/qdeclarativedebugserver.cpp | 366 +++++++++++++++++++++ .../debugger/qdeclarativedebugserver_p.h | 89 +++++ .../debugger/qdeclarativedebugservice.cpp | 319 +----------------- .../debugger/qdeclarativedebugservice_p_p.h | 71 ++++ 5 files changed, 541 insertions(+), 311 deletions(-) create mode 100644 src/declarative/debugger/qdeclarativedebugserver.cpp create mode 100644 src/declarative/debugger/qdeclarativedebugserver_p.h create mode 100644 src/declarative/debugger/qdeclarativedebugservice_p_p.h diff --git a/src/declarative/debugger/debugger.pri b/src/declarative/debugger/debugger.pri index 25f7687..144d896 100644 --- a/src/declarative/debugger/debugger.pri +++ b/src/declarative/debugger/debugger.pri @@ -7,13 +7,16 @@ SOURCES += \ $$PWD/qdeclarativedebugclient.cpp \ $$PWD/qdeclarativedebug.cpp \ $$PWD/qdeclarativedebugtrace.cpp \ - $$PWD/qdeclarativedebughelper.cpp + $$PWD/qdeclarativedebughelper.cpp \ + $$PWD/qdeclarativedebugserver.cpp HEADERS += \ $$PWD/qdeclarativedebuggerstatus_p.h \ $$PWD/qpacketprotocol_p.h \ $$PWD/qdeclarativedebugservice_p.h \ + $$PWD/qdeclarativedebugservice_p_p.h \ $$PWD/qdeclarativedebugclient_p.h \ $$PWD/qdeclarativedebug_p.h \ $$PWD/qdeclarativedebugtrace_p.h \ - $$PWD/qdeclarativedebughelper_p.h + $$PWD/qdeclarativedebughelper_p.h \ + $$PWD/qdeclarativedebugserver_p.h diff --git a/src/declarative/debugger/qdeclarativedebugserver.cpp b/src/declarative/debugger/qdeclarativedebugserver.cpp new file mode 100644 index 0000000..4bb4e2c --- /dev/null +++ b/src/declarative/debugger/qdeclarativedebugserver.cpp @@ -0,0 +1,366 @@ +/**************************************************************************** +** +** 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/qdeclarativedebugserver_p.h" +#include "private/qdeclarativedebugservice_p.h" +#include "private/qdeclarativedebugservice_p_p.h" +#include "private/qdeclarativeengine_p.h" + +#include "private/qpacketprotocol_p.h" + +#include + +#include +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +/* + QDeclarativeDebug Protocol (Version 1): + + handshake: + 1. Client sends + "QDeclarativeDebugServer" 0 version pluginNames + version: an int representing the highest protocol version the client knows + pluginNames: plugins available on client side + 2. Server sends + "QDeclarativeDebugClient" 0 version pluginNames + version: an int representing the highest protocol version the client & server know + pluginNames: plugins available on server side. plugins both in the client and server message are enabled. + client plugin advertisement + 1. Client sends + "QDeclarativeDebugServer" 1 pluginNames + server plugin advertisement + 1. Server sends + "QDeclarativeDebugClient" 1 pluginNames + plugin communication: + Everything send with a header different to "QDeclarativeDebugServer" is sent to the appropriate plugin. + */ + +const int protocolVersion = 1; + + +class QDeclarativeDebugServerPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QDeclarativeDebugServer) +public: + QDeclarativeDebugServerPrivate(); + + void advertisePlugins(); + + int port; + QTcpSocket *connection; + QPacketProtocol *protocol; + QHash plugins; + QStringList clientPlugins; + QTcpServer *tcpServer; + bool gotHello; +}; + +QDeclarativeDebugServerPrivate::QDeclarativeDebugServerPrivate() +: connection(0), protocol(0), gotHello(false) +{ +} + +void QDeclarativeDebugServerPrivate::advertisePlugins() +{ + if (!connection + || connection->state() != QTcpSocket::ConnectedState + || !gotHello) + return; + + QPacket pack; + pack << QString(QLatin1String("QDeclarativeDebugClient")) << 1 << plugins.keys(); + protocol->send(pack); + connection->flush(); +} + +void QDeclarativeDebugServer::listen() +{ + Q_D(QDeclarativeDebugServer); + + d->tcpServer = new QTcpServer(this); + QObject::connect(d->tcpServer, SIGNAL(newConnection()), this, SLOT(newConnection())); + if (d->tcpServer->listen(QHostAddress::Any, d->port)) + qWarning("QDeclarativeDebugServer: Waiting for connection on port %d...", d->port); + else + qWarning("QDeclarativeDebugServer: Unable to listen on port %d", d->port); +} + +void QDeclarativeDebugServer::waitForConnection() +{ + Q_D(QDeclarativeDebugServer); + d->tcpServer->waitForNewConnection(-1); +} + +void QDeclarativeDebugServer::newConnection() +{ + Q_D(QDeclarativeDebugServer); + + if (d->connection) { + qWarning("QDeclarativeDebugServer error: another client is already connected"); + QTcpSocket *faultyConnection = d->tcpServer->nextPendingConnection(); + delete faultyConnection; + return; + } + + d->connection = d->tcpServer->nextPendingConnection(); + d->connection->setParent(this); + d->protocol = new QPacketProtocol(d->connection, this); + QObject::connect(d->protocol, SIGNAL(readyRead()), this, SLOT(readyRead())); +} + +bool QDeclarativeDebugServer::hasDebuggingClient() const +{ + Q_D(const QDeclarativeDebugServer); + return d->connection + && (d->connection->state() == QTcpSocket::ConnectedState) + && d->gotHello; +} + +QDeclarativeDebugServer *QDeclarativeDebugServer::instance() +{ + static bool commandLineTested = false; + static QDeclarativeDebugServer *server = 0; + + if (!commandLineTested) { + commandLineTested = true; + +#ifndef QDECLARATIVE_NO_DEBUG_PROTOCOL + QApplicationPrivate *appD = static_cast(QObjectPrivate::get(qApp)); + // ### remove port definition when protocol is changed + int port = 0; + bool block = false; + bool ok = false; + + // format: qmljsdebugger=port:3768[,block] + if (!appD->qmljsDebugArgumentsString().isEmpty()) { + if (!QDeclarativeEnginePrivate::qml_debugging_enabled) { + const QString message = + QString::fromAscii("QDeclarativeDebugServer: Ignoring \"-qmljsdebugger=%1\". " + "Debugging has not been enabled.").arg( + appD->qmljsDebugArgumentsString()); + qWarning("%s", qPrintable(message)); + return 0; + } + + if (appD->qmljsDebugArgumentsString().indexOf(QLatin1String("port:")) == 0) { + int separatorIndex = appD->qmljsDebugArgumentsString().indexOf(QLatin1Char(',')); + port = appD->qmljsDebugArgumentsString().mid(5, separatorIndex - 5).toInt(&ok); + } + block = appD->qmljsDebugArgumentsString().contains(QLatin1String("block")); + + if (ok) { + server = new QDeclarativeDebugServer(port); + server->listen(); + if (block) { + server->waitForConnection(); + } + } else { + qWarning(QString::fromAscii("QDeclarativeDebugServer: Ignoring \"-qmljsdebugger=%1\". " + "Format is -qmljsdebugger=port:[,block]").arg( + appD->qmljsDebugArgumentsString()).toAscii().constData()); + } + } +#endif + } + + return server; +} + +QDeclarativeDebugServer::QDeclarativeDebugServer(int port) +: QObject(*(new QDeclarativeDebugServerPrivate)) +{ + Q_D(QDeclarativeDebugServer); + d->port = port; +} + +void QDeclarativeDebugServer::readyRead() +{ + Q_D(QDeclarativeDebugServer); + + if (!d->gotHello) { + QPacket hello = d->protocol->read(); + + QString name; + int op; + hello >> name >> op; + + if (name != QLatin1String("QDeclarativeDebugServer") + || op != 0) { + qWarning("QDeclarativeDebugServer: Invalid hello message"); + QObject::disconnect(d->protocol, SIGNAL(readyRead()), this, SLOT(readyRead())); + d->protocol->deleteLater(); + d->protocol = 0; + d->connection->deleteLater(); + d->connection = 0; + return; + } + + int version; + hello >> version >> d->clientPlugins; + + QHash::Iterator iter = d->plugins.begin(); + for (; iter != d->plugins.end(); ++iter) { + QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::Unavailable; + if (d->clientPlugins.contains(iter.key())) + newStatus = QDeclarativeDebugService::Enabled; + iter.value()->d_func()->status = newStatus; + iter.value()->statusChanged(newStatus); + } + + QPacket helloAnswer; + helloAnswer << QString(QLatin1String("QDeclarativeDebugClient")) << 0 << protocolVersion << d->plugins.keys(); + d->protocol->send(helloAnswer); + d->connection->flush(); + + d->gotHello = true; + qWarning("QDeclarativeDebugServer: Connection established"); + } + + QString debugServer(QLatin1String("QDeclarativeDebugServer")); + + while (d->protocol->packetsAvailable()) { + QPacket pack = d->protocol->read(); + + QString name; + pack >> name; + + if (name == debugServer) { + int op = -1; + pack >> op; + + if (op == 1) { + // Service Discovery + QStringList oldClientPlugins = d->clientPlugins; + pack >> d->clientPlugins; + + QHash::Iterator iter = d->plugins.begin(); + for (; iter != d->plugins.end(); ++iter) { + const QString pluginName = iter.key(); + QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::Unavailable; + if (d->clientPlugins.contains(pluginName)) + newStatus = QDeclarativeDebugService::Enabled; + + if (oldClientPlugins.contains(pluginName) + != d->clientPlugins.contains(pluginName)) { + iter.value()->d_func()->status = newStatus; + iter.value()->statusChanged(newStatus); + } + } + } else { + qWarning("QDeclarativeDebugServer: Invalid control message %d", op); + } + } else { + QByteArray message; + pack >> message; + + QHash::Iterator iter = + d->plugins.find(name); + if (iter == d->plugins.end()) { + qWarning() << "QDeclarativeDebugServer: Message received for missing plugin" << name; + } else { + (*iter)->messageReceived(message); + } + } + } +} + + +QList QDeclarativeDebugServer::services() const +{ + const Q_D(QDeclarativeDebugServer); + return d->plugins.values(); +} + +QStringList QDeclarativeDebugServer::serviceNames() const +{ + const Q_D(QDeclarativeDebugServer); + return d->plugins.keys(); +} + +bool QDeclarativeDebugServer::addService(QDeclarativeDebugService *service) +{ + Q_D(QDeclarativeDebugServer); + if (!service || d->plugins.contains(service->name())) + return false; + + d->plugins.insert(service->name(), service); + d->advertisePlugins(); + + QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::Unavailable; + if (d->clientPlugins.contains(service->name())) + newStatus = QDeclarativeDebugService::Enabled; + service->d_func()->status = newStatus; + service->statusChanged(newStatus); + return true; +} + +bool QDeclarativeDebugServer::removeService(QDeclarativeDebugService *service) +{ + Q_D(QDeclarativeDebugServer); + if (!service || !d->plugins.contains(service->name())) + return false; + + d->plugins.remove(service->name()); + d->advertisePlugins(); + + QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::NotConnected; + service->d_func()->server = 0; + service->d_func()->status = newStatus; + service->statusChanged(newStatus); + return true; +} + +void QDeclarativeDebugServer::sendMessage(QDeclarativeDebugService *service, + const QByteArray &message) +{ + Q_D(QDeclarativeDebugServer); + QPacket pack; + pack << service->name() << message; + d->protocol->send(pack); + d->connection->flush(); +} + +QT_END_NAMESPACE diff --git a/src/declarative/debugger/qdeclarativedebugserver_p.h b/src/declarative/debugger/qdeclarativedebugserver_p.h new file mode 100644 index 0000000..6840d63 --- /dev/null +++ b/src/declarative/debugger/qdeclarativedebugserver_p.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** 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 QDECLARATIVEDEBUGSERVER_H +#define QDECLARATIVEDEBUGSERVER_H + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class QDeclarativeDebugService; + +class QDeclarativeDebugServerPrivate; +class QDeclarativeDebugServer : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QDeclarativeDebugServer) + Q_DISABLE_COPY(QDeclarativeDebugServer) +public: + static QDeclarativeDebugServer *instance(); + void listen(); + void waitForConnection(); + bool hasDebuggingClient() const; + + QList services() const; + QStringList serviceNames() const; + + bool addService(QDeclarativeDebugService *service); + bool removeService(QDeclarativeDebugService *service); + + void sendMessage(QDeclarativeDebugService *service, const QByteArray &message); + +private Q_SLOTS: + void readyRead(); + void newConnection(); + +private: + friend class QDeclarativeDebugService; + friend class QDeclarativeDebugServicePrivate; + QDeclarativeDebugServer(int); +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QDECLARATIVEDEBUGSERVICE_H diff --git a/src/declarative/debugger/qdeclarativedebugservice.cpp b/src/declarative/debugger/qdeclarativedebugservice.cpp index 849df73..9d321da 100644 --- a/src/declarative/debugger/qdeclarativedebugservice.cpp +++ b/src/declarative/debugger/qdeclarativedebugservice.cpp @@ -40,301 +40,14 @@ ****************************************************************************/ #include "private/qdeclarativedebugservice_p.h" +#include "private/qdeclarativedebugservice_p_p.h" +#include "private/qdeclarativedebugserver_p.h" -#include "private/qpacketprotocol_p.h" -#include "private/qdeclarativeengine_p.h" - -#include -#include -#include -#include - -#include -#include -#include +#include +#include QT_BEGIN_NAMESPACE -/* - QDeclarativeDebug Protocol (Version 1): - - handshake: - 1. Client sends - "QDeclarativeDebugServer" 0 version pluginNames - version: an int representing the highest protocol version the client knows - pluginNames: plugins available on client side - 2. Server sends - "QDeclarativeDebugClient" 0 version pluginNames - version: an int representing the highest protocol version the client & server know - pluginNames: plugins available on server side. plugins both in the client and server message are enabled. - client plugin advertisement - 1. Client sends - "QDeclarativeDebugServer" 1 pluginNames - server plugin advertisement - 1. Server sends - "QDeclarativeDebugClient" 1 pluginNames - plugin communication: - Everything send with a header different to "QDeclarativeDebugServer" is sent to the appropriate plugin. - */ - -const int protocolVersion = 1; - -class QDeclarativeDebugServerPrivate; -class QDeclarativeDebugServer : public QObject -{ - Q_OBJECT - Q_DECLARE_PRIVATE(QDeclarativeDebugServer) - Q_DISABLE_COPY(QDeclarativeDebugServer) -public: - static QDeclarativeDebugServer *instance(); - void listen(); - void waitForConnection(); - bool hasDebuggingClient() const; - -private Q_SLOTS: - void readyRead(); - void newConnection(); - -private: - friend class QDeclarativeDebugService; - friend class QDeclarativeDebugServicePrivate; - QDeclarativeDebugServer(int); -}; - -class QDeclarativeDebugServerPrivate : public QObjectPrivate -{ - Q_DECLARE_PUBLIC(QDeclarativeDebugServer) -public: - QDeclarativeDebugServerPrivate(); - - void advertisePlugins(); - - int port; - QTcpSocket *connection; - QPacketProtocol *protocol; - QHash plugins; - QStringList clientPlugins; - QTcpServer *tcpServer; - bool gotHello; -}; - -class QDeclarativeDebugServicePrivate : public QObjectPrivate -{ - Q_DECLARE_PUBLIC(QDeclarativeDebugService) -public: - QDeclarativeDebugServicePrivate(); - - QString name; - QDeclarativeDebugServer *server; -}; - -QDeclarativeDebugServerPrivate::QDeclarativeDebugServerPrivate() -: connection(0), protocol(0), gotHello(false) -{ -} - -void QDeclarativeDebugServerPrivate::advertisePlugins() -{ - if (!connection - || connection->state() != QTcpSocket::ConnectedState - || !gotHello) - return; - - QPacket pack; - pack << QString(QLatin1String("QDeclarativeDebugClient")) << 1 << plugins.keys(); - protocol->send(pack); - connection->flush(); -} - -void QDeclarativeDebugServer::listen() -{ - Q_D(QDeclarativeDebugServer); - - d->tcpServer = new QTcpServer(this); - QObject::connect(d->tcpServer, SIGNAL(newConnection()), this, SLOT(newConnection())); - if (d->tcpServer->listen(QHostAddress::Any, d->port)) - qWarning("QDeclarativeDebugServer: Waiting for connection on port %d...", d->port); - else - qWarning("QDeclarativeDebugServer: Unable to listen on port %d", d->port); -} - -void QDeclarativeDebugServer::waitForConnection() -{ - Q_D(QDeclarativeDebugServer); - d->tcpServer->waitForNewConnection(-1); -} - -void QDeclarativeDebugServer::newConnection() -{ - Q_D(QDeclarativeDebugServer); - - if (d->connection) { - qWarning("QDeclarativeDebugServer error: another client is already connected"); - QTcpSocket *faultyConnection = d->tcpServer->nextPendingConnection(); - delete faultyConnection; - return; - } - - d->connection = d->tcpServer->nextPendingConnection(); - d->connection->setParent(this); - d->protocol = new QPacketProtocol(d->connection, this); - QObject::connect(d->protocol, SIGNAL(readyRead()), this, SLOT(readyRead())); -} - -bool QDeclarativeDebugServer::hasDebuggingClient() const -{ - Q_D(const QDeclarativeDebugServer); - return d->connection - && (d->connection->state() == QTcpSocket::ConnectedState) - && d->gotHello; -} - -QDeclarativeDebugServer *QDeclarativeDebugServer::instance() -{ - static bool commandLineTested = false; - static QDeclarativeDebugServer *server = 0; - - if (!commandLineTested) { - commandLineTested = true; - -#ifndef QDECLARATIVE_NO_DEBUG_PROTOCOL - QApplicationPrivate *appD = static_cast(QObjectPrivate::get(qApp)); - // ### remove port definition when protocol is changed - int port = 0; - bool block = false; - bool ok = false; - - // format: qmljsdebugger=port:3768[,block] - if (!appD->qmljsDebugArgumentsString().isEmpty()) { - if (!QDeclarativeEnginePrivate::qml_debugging_enabled) { - qWarning() << QString::fromLatin1("QDeclarativeDebugServer: Ignoring \"-qmljsdebugger=%1\". " - "Debugging has not been enabled.").arg( - appD->qmljsDebugArgumentsString()).toAscii().constData(); - return 0; - } - - if (appD->qmljsDebugArgumentsString().indexOf(QLatin1String("port:")) == 0) { - int separatorIndex = appD->qmljsDebugArgumentsString().indexOf(QLatin1Char(',')); - port = appD->qmljsDebugArgumentsString().mid(5, separatorIndex - 5).toInt(&ok); - } - block = appD->qmljsDebugArgumentsString().contains(QLatin1String("block")); - - if (ok) { - server = new QDeclarativeDebugServer(port); - server->listen(); - if (block) { - server->waitForConnection(); - } - } else { - const QString message = - QString::fromAscii("QDeclarativeDebugServer: Ignoring \"-qmljsdebugger=%1\". " - "Format is -qmljsdebugger=port:[,block]"). - arg(appD->qmljsDebugArgumentsString()); - qWarning("%s", qPrintable(message)); - } - } -#endif - } - - return server; -} - -QDeclarativeDebugServer::QDeclarativeDebugServer(int port) -: QObject(*(new QDeclarativeDebugServerPrivate)) -{ - Q_D(QDeclarativeDebugServer); - d->port = port; -} - -void QDeclarativeDebugServer::readyRead() -{ - Q_D(QDeclarativeDebugServer); - - if (!d->gotHello) { - QPacket hello = d->protocol->read(); - - QString name; - int op; - hello >> name >> op; - - if (name != QLatin1String("QDeclarativeDebugServer") - || op != 0) { - qWarning("QDeclarativeDebugServer: Invalid hello message"); - QObject::disconnect(d->protocol, SIGNAL(readyRead()), this, SLOT(readyRead())); - d->protocol->deleteLater(); - d->protocol = 0; - d->connection->deleteLater(); - d->connection = 0; - return; - } - - int version; - hello >> version >> d->clientPlugins; - - QHash::Iterator iter = d->plugins.begin(); - for (; iter != d->plugins.end(); ++iter) { - QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::Unavailable; - if (d->clientPlugins.contains(iter.key())) - newStatus = QDeclarativeDebugService::Enabled; - iter.value()->statusChanged(newStatus); - } - - QPacket helloAnswer; - helloAnswer << QString(QLatin1String("QDeclarativeDebugClient")) << 0 << protocolVersion << d->plugins.keys(); - d->protocol->send(helloAnswer); - d->connection->flush(); - - d->gotHello = true; - qWarning("QDeclarativeDebugServer: Connection established"); - } - - QString debugServer(QLatin1String("QDeclarativeDebugServer")); - - while (d->protocol->packetsAvailable()) { - QPacket pack = d->protocol->read(); - - QString name; - pack >> name; - - if (name == debugServer) { - int op = -1; - pack >> op; - - if (op == 1) { - // Service Discovery - QStringList oldClientPlugins = d->clientPlugins; - pack >> d->clientPlugins; - - QHash::Iterator iter = d->plugins.begin(); - for (; iter != d->plugins.end(); ++iter) { - const QString pluginName = iter.key(); - QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::Unavailable; - if (d->clientPlugins.contains(pluginName)) - newStatus = QDeclarativeDebugService::Enabled; - - if (oldClientPlugins.contains(pluginName) - != d->clientPlugins.contains(pluginName)) { - iter.value()->statusChanged(newStatus); - } - } - } else { - qWarning("QDeclarativeDebugServer: Invalid control message %d", op); - } - } else { - QByteArray message; - pack >> message; - - QHash::Iterator iter = - d->plugins.find(name); - if (iter == d->plugins.end()) { - qWarning() << "QDeclarativeDebugServer: Message received for missing plugin" << name; - } else { - (*iter)->messageReceived(message); - } - } - } -} - QDeclarativeDebugServicePrivate::QDeclarativeDebugServicePrivate() : server(0) { @@ -346,16 +59,16 @@ QDeclarativeDebugService::QDeclarativeDebugService(const QString &name, QObject Q_D(QDeclarativeDebugService); d->name = name; d->server = QDeclarativeDebugServer::instance(); + d->status = QDeclarativeDebugService::NotConnected; if (!d->server) return; - if (d->server->d_func()->plugins.contains(name)) { + if (d->server->serviceNames().contains(name)) { qWarning() << "QDeclarativeDebugService: Conflicting plugin name" << name; d->server = 0; } else { - d->server->d_func()->plugins.insert(name, this); - d->server->d_func()->advertisePlugins(); + d->server->addService(this); } } @@ -363,8 +76,7 @@ QDeclarativeDebugService::~QDeclarativeDebugService() { Q_D(const QDeclarativeDebugService); if (d->server) { - d->server->d_func()->plugins.remove(d->name); - d->server->d_func()->advertisePlugins(); + d->server->removeService(this); } } @@ -377,13 +89,7 @@ QString QDeclarativeDebugService::name() const QDeclarativeDebugService::Status QDeclarativeDebugService::status() const { Q_D(const QDeclarativeDebugService); - if (!d->server - || !d->server->hasDebuggingClient()) - return NotConnected; - if (d->server->d_func()->clientPlugins.contains(d->name)) - return Enabled; - - return Unavailable; + return d->status; } namespace { @@ -500,10 +206,7 @@ void QDeclarativeDebugService::sendMessage(const QByteArray &message) if (status() != Enabled) return; - QPacket pack; - pack << d->name << message; - d->server->d_func()->protocol->send(pack); - d->server->d_func()->connection->flush(); + d->server->sendMessage(this, message); } void QDeclarativeDebugService::statusChanged(Status) @@ -515,5 +218,3 @@ void QDeclarativeDebugService::messageReceived(const QByteArray &) } QT_END_NAMESPACE - -#include diff --git a/src/declarative/debugger/qdeclarativedebugservice_p_p.h b/src/declarative/debugger/qdeclarativedebugservice_p_p.h new file mode 100644 index 0000000..d2c8dda --- /dev/null +++ b/src/declarative/debugger/qdeclarativedebugservice_p_p.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** 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 QDECLARATIVEDEBUGSERVICE_P_H +#define QDECLARATIVEDEBUGSERVICE_P_H + +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class QDeclarativeDebugServer; + +class QDeclarativeDebugServicePrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QDeclarativeDebugService) +public: + QDeclarativeDebugServicePrivate(); + + QString name; + QDeclarativeDebugServer *server; + QDeclarativeDebugService::Status status; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QDECLARATIVEDEBUGSERVICE_P_H -- cgit v0.12 From 5336e1838a95d97d34863b668ff797582c226e79 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Wed, 24 Nov 2010 19:50:09 +0100 Subject: QDeclarativeDebug: Move networking code out of QDeclarativeDebugServer Move socket handling code out of QDeclarativeDebugServer into a QDeclarativeDebugServer(Tcp)Connection class. Reviewed-by: Christiaan Janssen --- src/declarative/debugger/debugger.pri | 8 +- .../debugger/qdeclarativedebugserver.cpp | 131 ++++++----------- .../debugger/qdeclarativedebugserver_p.h | 13 +- .../debugger/qdeclarativedebugserverconnection_p.h | 68 +++++++++ .../debugger/qdeclarativedebugserverplugin_p.h | 0 .../qdeclarativedebugservertcpconnection.cpp | 163 +++++++++++++++++++++ .../qdeclarativedebugservertcpconnection_p.h | 86 +++++++++++ src/declarative/debugger/qpacketprotocol.cpp | 8 + src/declarative/debugger/qpacketprotocol_p.h | 1 + 9 files changed, 383 insertions(+), 95 deletions(-) create mode 100644 src/declarative/debugger/qdeclarativedebugserverconnection_p.h create mode 100644 src/declarative/debugger/qdeclarativedebugserverplugin_p.h create mode 100644 src/declarative/debugger/qdeclarativedebugservertcpconnection.cpp create mode 100644 src/declarative/debugger/qdeclarativedebugservertcpconnection_p.h diff --git a/src/declarative/debugger/debugger.pri b/src/declarative/debugger/debugger.pri index 144d896..e7354dc 100644 --- a/src/declarative/debugger/debugger.pri +++ b/src/declarative/debugger/debugger.pri @@ -8,7 +8,8 @@ SOURCES += \ $$PWD/qdeclarativedebug.cpp \ $$PWD/qdeclarativedebugtrace.cpp \ $$PWD/qdeclarativedebughelper.cpp \ - $$PWD/qdeclarativedebugserver.cpp + $$PWD/qdeclarativedebugserver.cpp \ + $$PWD/qdeclarativedebugservertcpconnection.cpp HEADERS += \ $$PWD/qdeclarativedebuggerstatus_p.h \ @@ -19,4 +20,7 @@ HEADERS += \ $$PWD/qdeclarativedebug_p.h \ $$PWD/qdeclarativedebugtrace_p.h \ $$PWD/qdeclarativedebughelper_p.h \ - $$PWD/qdeclarativedebugserver_p.h + $$PWD/qdeclarativedebugserverplugin_p.h \ + $$PWD/qdeclarativedebugserver_p.h \ + $$PWD/qdeclarativedebugservertcpconnection_p.h \ + debugger/qdeclarativedebugserverconnection_p.h diff --git a/src/declarative/debugger/qdeclarativedebugserver.cpp b/src/declarative/debugger/qdeclarativedebugserver.cpp index 4bb4e2c..6085e3e 100644 --- a/src/declarative/debugger/qdeclarativedebugserver.cpp +++ b/src/declarative/debugger/qdeclarativedebugserver.cpp @@ -42,15 +42,11 @@ #include "private/qdeclarativedebugserver_p.h" #include "private/qdeclarativedebugservice_p.h" #include "private/qdeclarativedebugservice_p_p.h" +#include "private/qdeclarativedebugservertcpconnection_p.h" #include "private/qdeclarativeengine_p.h" -#include "private/qpacketprotocol_p.h" - #include -#include -#include - #include #include @@ -89,73 +85,36 @@ public: void advertisePlugins(); - int port; - QTcpSocket *connection; - QPacketProtocol *protocol; + QDeclarativeDebugServerConnection *connection; QHash plugins; QStringList clientPlugins; - QTcpServer *tcpServer; bool gotHello; }; -QDeclarativeDebugServerPrivate::QDeclarativeDebugServerPrivate() -: connection(0), protocol(0), gotHello(false) +QDeclarativeDebugServerPrivate::QDeclarativeDebugServerPrivate() : + connection(0), + gotHello(false) { } void QDeclarativeDebugServerPrivate::advertisePlugins() { - if (!connection - || connection->state() != QTcpSocket::ConnectedState - || !gotHello) + if (!gotHello) return; - QPacket pack; - pack << QString(QLatin1String("QDeclarativeDebugClient")) << 1 << plugins.keys(); - protocol->send(pack); - connection->flush(); -} - -void QDeclarativeDebugServer::listen() -{ - Q_D(QDeclarativeDebugServer); - - d->tcpServer = new QTcpServer(this); - QObject::connect(d->tcpServer, SIGNAL(newConnection()), this, SLOT(newConnection())); - if (d->tcpServer->listen(QHostAddress::Any, d->port)) - qWarning("QDeclarativeDebugServer: Waiting for connection on port %d...", d->port); - else - qWarning("QDeclarativeDebugServer: Unable to listen on port %d", d->port); -} - -void QDeclarativeDebugServer::waitForConnection() -{ - Q_D(QDeclarativeDebugServer); - d->tcpServer->waitForNewConnection(-1); -} - -void QDeclarativeDebugServer::newConnection() -{ - Q_D(QDeclarativeDebugServer); - - if (d->connection) { - qWarning("QDeclarativeDebugServer error: another client is already connected"); - QTcpSocket *faultyConnection = d->tcpServer->nextPendingConnection(); - delete faultyConnection; - return; + QByteArray message; + { + QDataStream out(&message, QIODevice::WriteOnly); + out << QString(QLatin1String("QDeclarativeDebugClient")) << 1 << plugins.keys(); } - - d->connection = d->tcpServer->nextPendingConnection(); - d->connection->setParent(this); - d->protocol = new QPacketProtocol(d->connection, this); - QObject::connect(d->protocol, SIGNAL(readyRead()), this, SLOT(readyRead())); + connection->send(message); } bool QDeclarativeDebugServer::hasDebuggingClient() const { Q_D(const QDeclarativeDebugServer); return d->connection - && (d->connection->state() == QTcpSocket::ConnectedState) + && d->connection->isConnected() && d->gotHello; } @@ -192,11 +151,17 @@ QDeclarativeDebugServer *QDeclarativeDebugServer::instance() block = appD->qmljsDebugArgumentsString().contains(QLatin1String("block")); if (ok) { - server = new QDeclarativeDebugServer(port); - server->listen(); + server = new QDeclarativeDebugServer(); + + QDeclarativeDebugServerTcpConnection *tcpConnection + = new QDeclarativeDebugServerTcpConnection(port, server); + + tcpConnection->listen(); if (block) { - server->waitForConnection(); + tcpConnection->waitForConnection(); } + + server->d_func()->connection = tcpConnection; } else { qWarning(QString::fromAscii("QDeclarativeDebugServer: Ignoring \"-qmljsdebugger=%1\". " "Format is -qmljsdebugger=port:[,block]").arg( @@ -209,37 +174,31 @@ QDeclarativeDebugServer *QDeclarativeDebugServer::instance() return server; } -QDeclarativeDebugServer::QDeclarativeDebugServer(int port) +QDeclarativeDebugServer::QDeclarativeDebugServer() : QObject(*(new QDeclarativeDebugServerPrivate)) { - Q_D(QDeclarativeDebugServer); - d->port = port; } -void QDeclarativeDebugServer::readyRead() +void QDeclarativeDebugServer::receiveMessage(const QByteArray &message) { Q_D(QDeclarativeDebugServer); + QDataStream in(message); if (!d->gotHello) { - QPacket hello = d->protocol->read(); QString name; int op; - hello >> name >> op; + in >> name >> op; if (name != QLatin1String("QDeclarativeDebugServer") || op != 0) { qWarning("QDeclarativeDebugServer: Invalid hello message"); - QObject::disconnect(d->protocol, SIGNAL(readyRead()), this, SLOT(readyRead())); - d->protocol->deleteLater(); - d->protocol = 0; - d->connection->deleteLater(); - d->connection = 0; + d->connection->disconnect(); return; } int version; - hello >> version >> d->clientPlugins; + in >> version >> d->clientPlugins; QHash::Iterator iter = d->plugins.begin(); for (; iter != d->plugins.end(); ++iter) { @@ -250,31 +209,30 @@ void QDeclarativeDebugServer::readyRead() iter.value()->statusChanged(newStatus); } - QPacket helloAnswer; - helloAnswer << QString(QLatin1String("QDeclarativeDebugClient")) << 0 << protocolVersion << d->plugins.keys(); - d->protocol->send(helloAnswer); - d->connection->flush(); + QByteArray helloAnswer; + { + QDataStream out(&helloAnswer, QIODevice::WriteOnly); + out << QString(QLatin1String("QDeclarativeDebugClient")) << 0 << protocolVersion << d->plugins.keys(); + } + d->connection->send(helloAnswer); d->gotHello = true; qWarning("QDeclarativeDebugServer: Connection established"); - } + } else { - QString debugServer(QLatin1String("QDeclarativeDebugServer")); - - while (d->protocol->packetsAvailable()) { - QPacket pack = d->protocol->read(); + QString debugServer(QLatin1String("QDeclarativeDebugServer")); QString name; - pack >> name; + in >> name; if (name == debugServer) { int op = -1; - pack >> op; + in >> op; if (op == 1) { // Service Discovery QStringList oldClientPlugins = d->clientPlugins; - pack >> d->clientPlugins; + in >> d->clientPlugins; QHash::Iterator iter = d->plugins.begin(); for (; iter != d->plugins.end(); ++iter) { @@ -294,7 +252,7 @@ void QDeclarativeDebugServer::readyRead() } } else { QByteArray message; - pack >> message; + in >> message; QHash::Iterator iter = d->plugins.find(name); @@ -307,7 +265,6 @@ void QDeclarativeDebugServer::readyRead() } } - QList QDeclarativeDebugServer::services() const { const Q_D(QDeclarativeDebugServer); @@ -357,10 +314,12 @@ void QDeclarativeDebugServer::sendMessage(QDeclarativeDebugService *service, const QByteArray &message) { Q_D(QDeclarativeDebugServer); - QPacket pack; - pack << service->name() << message; - d->protocol->send(pack); - d->connection->flush(); + QByteArray msg; + { + QDataStream out(&msg, QIODevice::WriteOnly); + out << service->name() << message; + } + d->connection->send(msg); } QT_END_NAMESPACE diff --git a/src/declarative/debugger/qdeclarativedebugserver_p.h b/src/declarative/debugger/qdeclarativedebugserver_p.h index 6840d63..93ab10b 100644 --- a/src/declarative/debugger/qdeclarativedebugserver_p.h +++ b/src/declarative/debugger/qdeclarativedebugserver_p.h @@ -43,6 +43,7 @@ #define QDECLARATIVEDEBUGSERVER_H #include +#include QT_BEGIN_HEADER @@ -60,8 +61,9 @@ class QDeclarativeDebugServer : public QObject Q_DISABLE_COPY(QDeclarativeDebugServer) public: static QDeclarativeDebugServer *instance(); - void listen(); - void waitForConnection(); + + void setConnection(QDeclarativeDebugServerConnection *connection); + bool hasDebuggingClient() const; QList services() const; @@ -71,15 +73,12 @@ public: bool removeService(QDeclarativeDebugService *service); void sendMessage(QDeclarativeDebugService *service, const QByteArray &message); - -private Q_SLOTS: - void readyRead(); - void newConnection(); + void receiveMessage(const QByteArray &message); private: friend class QDeclarativeDebugService; friend class QDeclarativeDebugServicePrivate; - QDeclarativeDebugServer(int); + QDeclarativeDebugServer(); }; QT_END_NAMESPACE diff --git a/src/declarative/debugger/qdeclarativedebugserverconnection_p.h b/src/declarative/debugger/qdeclarativedebugserverconnection_p.h new file mode 100644 index 0000000..4175126 --- /dev/null +++ b/src/declarative/debugger/qdeclarativedebugserverconnection_p.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** 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 QDECLARATIVEDEBUGSERVERCONNECTION_H +#define QDECLARATIVEDEBUGSERVERCONNECTION_H + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class QDeclarativeDebugServerConnection +{ +public: + QDeclarativeDebugServerConnection() {} + virtual ~QDeclarativeDebugServerConnection() {} + + virtual bool isConnected() const = 0; + virtual void send(const QByteArray &message) = 0; + virtual void disconnect() = 0; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QDECLARATIVEDEBUGSERVERCONNECTION_H diff --git a/src/declarative/debugger/qdeclarativedebugserverplugin_p.h b/src/declarative/debugger/qdeclarativedebugserverplugin_p.h new file mode 100644 index 0000000..e69de29 diff --git a/src/declarative/debugger/qdeclarativedebugservertcpconnection.cpp b/src/declarative/debugger/qdeclarativedebugservertcpconnection.cpp new file mode 100644 index 0000000..223c875 --- /dev/null +++ b/src/declarative/debugger/qdeclarativedebugservertcpconnection.cpp @@ -0,0 +1,163 @@ +/**************************************************************************** +** +** 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 "qdeclarativedebugservertcpconnection_p.h" + +#include "qdeclarativedebugserver_p.h" +#include "private/qpacketprotocol_p.h" + +#include +#include + + +QT_BEGIN_NAMESPACE + +class QDeclarativeDebugServerTcpConnectionPrivate { +public: + QDeclarativeDebugServerTcpConnectionPrivate(); + + int port; + QTcpSocket *socket; + QPacketProtocol *protocol; + QTcpServer *tcpServer; + + QDeclarativeDebugServer *debugServer; +}; + +QDeclarativeDebugServerTcpConnectionPrivate::QDeclarativeDebugServerTcpConnectionPrivate() : + port(0), + socket(0), + protocol(0), + tcpServer(0), + debugServer(0) +{ +} + +QDeclarativeDebugServerTcpConnection::QDeclarativeDebugServerTcpConnection(int port, QDeclarativeDebugServer *server) : + QObject(server), + d_ptr(new QDeclarativeDebugServerTcpConnectionPrivate) +{ + Q_D(QDeclarativeDebugServerTcpConnection); + d->port = port; + d->debugServer = server; +} + +QDeclarativeDebugServerTcpConnection::~QDeclarativeDebugServerTcpConnection() +{ + delete d_ptr; +} + +bool QDeclarativeDebugServerTcpConnection::isConnected() const +{ + Q_D(const QDeclarativeDebugServerTcpConnection); + return d->socket && d->socket->state() == QTcpSocket::ConnectedState; +} + +void QDeclarativeDebugServerTcpConnection::send(const QByteArray &message) +{ + Q_D(QDeclarativeDebugServerTcpConnection); + + if (!isConnected()) + return; + + QPacket pack; + pack.writeRawData(message.data(), message.length()); + + d->protocol->send(pack); + d->socket->flush(); +} + +void QDeclarativeDebugServerTcpConnection::disconnect() +{ + Q_D(QDeclarativeDebugServerTcpConnection); + + delete d->protocol; + d->protocol = 0; + delete d->socket; + d->socket = 0; +} + +void QDeclarativeDebugServerTcpConnection::listen() +{ + Q_D(QDeclarativeDebugServerTcpConnection); + + d->tcpServer = new QTcpServer(this); + QObject::connect(d->tcpServer, SIGNAL(newConnection()), this, SLOT(newConnection())); + if (d->tcpServer->listen(QHostAddress::Any, d->port)) + qWarning("QDeclarativeDebugServer: Waiting for connection on port %d...", d->port); + else + qWarning("QDeclarativeDebugServer: Unable to listen on port %d", d->port); +} + +void QDeclarativeDebugServerTcpConnection::waitForConnection() +{ + Q_D(QDeclarativeDebugServerTcpConnection); + d->tcpServer->waitForNewConnection(-1); +} + +void QDeclarativeDebugServerTcpConnection::readyRead() +{ + Q_D(QDeclarativeDebugServerTcpConnection); + QPacket packet = d->protocol->read(); + + QByteArray content = packet.data(); + d->debugServer->receiveMessage(content); +} + +void QDeclarativeDebugServerTcpConnection::newConnection() +{ + Q_D(QDeclarativeDebugServerTcpConnection); + + if (d->socket) { + qWarning("QDeclarativeDebugServer error: another client is already connected"); + QTcpSocket *faultyConnection = d->tcpServer->nextPendingConnection(); + delete faultyConnection; + return; + } + + d->socket = d->tcpServer->nextPendingConnection(); + d->socket->setParent(this); + d->protocol = new QPacketProtocol(d->socket, this); + QObject::connect(d->protocol, SIGNAL(readyRead()), this, SLOT(readyRead())); +} + + +QT_END_NAMESPACE diff --git a/src/declarative/debugger/qdeclarativedebugservertcpconnection_p.h b/src/declarative/debugger/qdeclarativedebugservertcpconnection_p.h new file mode 100644 index 0000000..f1c749ef --- /dev/null +++ b/src/declarative/debugger/qdeclarativedebugservertcpconnection_p.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** 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 QDECLARATIVEDEBUGSERVERTCPCONNECTION_H +#define QDECLARATIVEDEBUGSERVERTCPCONNECTION_H + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +#include + +class QDeclarativeDebugServer; +class QDeclarativeDebugServerTcpConnectionPrivate; +class QDeclarativeDebugServerTcpConnection : public QObject, public QDeclarativeDebugServerConnection +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QDeclarativeDebugServerTcpConnection) + Q_DISABLE_COPY(QDeclarativeDebugServerTcpConnection) + +public: + QDeclarativeDebugServerTcpConnection(int port, QDeclarativeDebugServer *server); + ~QDeclarativeDebugServerTcpConnection(); + + bool isConnected() const; + void send(const QByteArray &message); + void disconnect(); + + void listen(); + void waitForConnection(); + +private Q_SLOTS: + void readyRead(); + void newConnection(); + +private: + QDeclarativeDebugServerTcpConnectionPrivate *d_ptr; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QDECLARATIVEDEBUGSERVERTCPCONNECTION_H diff --git a/src/declarative/debugger/qpacketprotocol.cpp b/src/declarative/debugger/qpacketprotocol.cpp index c2f7709..ad1e767 100644 --- a/src/declarative/debugger/qpacketprotocol.cpp +++ b/src/declarative/debugger/qpacketprotocol.cpp @@ -452,6 +452,14 @@ bool QPacket::isEmpty() const } /*! + Returns raw packet data. + */ +QByteArray QPacket::data() const +{ + return b; +} + +/*! Clears data in the packet. This is useful for reusing one writable packet. For example \code diff --git a/src/declarative/debugger/qpacketprotocol_p.h b/src/declarative/debugger/qpacketprotocol_p.h index d153833..99fded5 100644 --- a/src/declarative/debugger/qpacketprotocol_p.h +++ b/src/declarative/debugger/qpacketprotocol_p.h @@ -98,6 +98,7 @@ public: void clear(); bool isEmpty() const; + QByteArray data() const; protected: friend class QPacketProtocol; -- cgit v0.12 From 21016c3b28674029a2a205da38f54e362e3635b9 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Fri, 26 Nov 2010 16:22:47 +0100 Subject: QDeclarativeDebug: Move Tcp server to separate plugin Reviewed-by: Christiaan Janssen --- src/declarative/debugger/debugger.pri | 4 +- .../debugger/qdeclarativedebugserver.cpp | 50 +++++- .../debugger/qdeclarativedebugserver_p.h | 2 +- .../debugger/qdeclarativedebugserverconnection_p.h | 9 +- .../qdeclarativedebugservertcpconnection.cpp | 163 ------------------- .../qdeclarativedebugservertcpconnection_p.h | 86 ---------- src/declarative/debugger/qpacketprotocol_p.h | 4 +- src/plugins/plugins.pro | 3 +- src/plugins/qmldebugging/qmldebugging.pro | 4 + .../tcpserver/qtcpserverconnection.cpp | 173 +++++++++++++++++++++ .../qmldebugging/tcpserver/qtcpserverconnection.h | 84 ++++++++++ src/plugins/qmldebugging/tcpserver/tcpserver.pro | 18 +++ 12 files changed, 334 insertions(+), 266 deletions(-) delete mode 100644 src/declarative/debugger/qdeclarativedebugservertcpconnection.cpp delete mode 100644 src/declarative/debugger/qdeclarativedebugservertcpconnection_p.h create mode 100644 src/plugins/qmldebugging/qmldebugging.pro create mode 100644 src/plugins/qmldebugging/tcpserver/qtcpserverconnection.cpp create mode 100644 src/plugins/qmldebugging/tcpserver/qtcpserverconnection.h create mode 100644 src/plugins/qmldebugging/tcpserver/tcpserver.pro diff --git a/src/declarative/debugger/debugger.pri b/src/declarative/debugger/debugger.pri index e7354dc..9152677 100644 --- a/src/declarative/debugger/debugger.pri +++ b/src/declarative/debugger/debugger.pri @@ -8,8 +8,7 @@ SOURCES += \ $$PWD/qdeclarativedebug.cpp \ $$PWD/qdeclarativedebugtrace.cpp \ $$PWD/qdeclarativedebughelper.cpp \ - $$PWD/qdeclarativedebugserver.cpp \ - $$PWD/qdeclarativedebugservertcpconnection.cpp + $$PWD/qdeclarativedebugserver.cpp HEADERS += \ $$PWD/qdeclarativedebuggerstatus_p.h \ @@ -22,5 +21,4 @@ HEADERS += \ $$PWD/qdeclarativedebughelper_p.h \ $$PWD/qdeclarativedebugserverplugin_p.h \ $$PWD/qdeclarativedebugserver_p.h \ - $$PWD/qdeclarativedebugservertcpconnection_p.h \ debugger/qdeclarativedebugserverconnection_p.h diff --git a/src/declarative/debugger/qdeclarativedebugserver.cpp b/src/declarative/debugger/qdeclarativedebugserver.cpp index 6085e3e..a269984 100644 --- a/src/declarative/debugger/qdeclarativedebugserver.cpp +++ b/src/declarative/debugger/qdeclarativedebugserver.cpp @@ -42,9 +42,10 @@ #include "private/qdeclarativedebugserver_p.h" #include "private/qdeclarativedebugservice_p.h" #include "private/qdeclarativedebugservice_p_p.h" -#include "private/qdeclarativedebugservertcpconnection_p.h" #include "private/qdeclarativeengine_p.h" +#include +#include #include #include @@ -89,6 +90,8 @@ public: QHash plugins; QStringList clientPlugins; bool gotHello; + + static QDeclarativeDebugServerConnection *loadConnectionPlugin(); }; QDeclarativeDebugServerPrivate::QDeclarativeDebugServerPrivate() : @@ -110,6 +113,36 @@ void QDeclarativeDebugServerPrivate::advertisePlugins() connection->send(message); } +QDeclarativeDebugServerConnection *QDeclarativeDebugServerPrivate::loadConnectionPlugin() +{ + QStringList pluginCandidates; + const QStringList paths = QCoreApplication::libraryPaths(); + foreach (const QString &libPath, paths) { + const QDir dir(libPath + QLatin1String("/qmldebugging")); + if (dir.exists()) { + QStringList plugins(dir.entryList(QDir::Files)); + foreach (const QString &pluginPath, plugins) { + pluginCandidates << dir.absoluteFilePath(pluginPath); + } + } + } + + foreach (const QString &pluginPath, pluginCandidates) { + QPluginLoader loader(pluginPath); + if (!loader.load()) { + continue; + } + QDeclarativeDebugServerConnection *connection = 0; + if (QObject *instance = loader.instance()) + connection = qobject_cast(instance); + + if (connection) + return connection; + loader.unload(); + } + return 0; +} + bool QDeclarativeDebugServer::hasDebuggingClient() const { Q_D(const QDeclarativeDebugServer); @@ -153,15 +186,18 @@ QDeclarativeDebugServer *QDeclarativeDebugServer::instance() if (ok) { server = new QDeclarativeDebugServer(); - QDeclarativeDebugServerTcpConnection *tcpConnection - = new QDeclarativeDebugServerTcpConnection(port, server); + QDeclarativeDebugServerConnection *connection + = QDeclarativeDebugServerPrivate::loadConnectionPlugin(); + if (connection) { + server->d_func()->connection = connection; - tcpConnection->listen(); - if (block) { - tcpConnection->waitForConnection(); + connection->setServer(server); + connection->setPort(port, block); + } else { + qWarning() << QString::fromAscii("QDeclarativeDebugServer: Ignoring\"-qmljsdebugger=%1\". " + "Remote debugger plugin has not been found.").arg(appD->qmljsDebugArgumentsString()); } - server->d_func()->connection = tcpConnection; } else { qWarning(QString::fromAscii("QDeclarativeDebugServer: Ignoring \"-qmljsdebugger=%1\". " "Format is -qmljsdebugger=port:[,block]").arg( diff --git a/src/declarative/debugger/qdeclarativedebugserver_p.h b/src/declarative/debugger/qdeclarativedebugserver_p.h index 93ab10b..ec3e60f 100644 --- a/src/declarative/debugger/qdeclarativedebugserver_p.h +++ b/src/declarative/debugger/qdeclarativedebugserver_p.h @@ -54,7 +54,7 @@ QT_MODULE(Declarative) class QDeclarativeDebugService; class QDeclarativeDebugServerPrivate; -class QDeclarativeDebugServer : public QObject +class Q_DECLARATIVE_EXPORT QDeclarativeDebugServer : public QObject { Q_OBJECT Q_DECLARE_PRIVATE(QDeclarativeDebugServer) diff --git a/src/declarative/debugger/qdeclarativedebugserverconnection_p.h b/src/declarative/debugger/qdeclarativedebugserverconnection_p.h index 4175126..631da74 100644 --- a/src/declarative/debugger/qdeclarativedebugserverconnection_p.h +++ b/src/declarative/debugger/qdeclarativedebugserverconnection_p.h @@ -42,7 +42,7 @@ #ifndef QDECLARATIVEDEBUGSERVERCONNECTION_H #define QDECLARATIVEDEBUGSERVERCONNECTION_H -#include +#include QT_BEGIN_HEADER @@ -50,17 +50,22 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) -class QDeclarativeDebugServerConnection +class QDeclarativeDebugServer; +class Q_DECLARATIVE_EXPORT QDeclarativeDebugServerConnection { public: QDeclarativeDebugServerConnection() {} virtual ~QDeclarativeDebugServerConnection() {} + virtual void setServer(QDeclarativeDebugServer *server) = 0; + virtual void setPort(int port, bool bock) = 0; virtual bool isConnected() const = 0; virtual void send(const QByteArray &message) = 0; virtual void disconnect() = 0; }; +Q_DECLARE_INTERFACE(QDeclarativeDebugServerConnection, "com.trolltech.Qt.QDeclarativeDebugServerConnection/1.0") + QT_END_NAMESPACE QT_END_HEADER diff --git a/src/declarative/debugger/qdeclarativedebugservertcpconnection.cpp b/src/declarative/debugger/qdeclarativedebugservertcpconnection.cpp deleted file mode 100644 index 223c875..0000000 --- a/src/declarative/debugger/qdeclarativedebugservertcpconnection.cpp +++ /dev/null @@ -1,163 +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 "qdeclarativedebugservertcpconnection_p.h" - -#include "qdeclarativedebugserver_p.h" -#include "private/qpacketprotocol_p.h" - -#include -#include - - -QT_BEGIN_NAMESPACE - -class QDeclarativeDebugServerTcpConnectionPrivate { -public: - QDeclarativeDebugServerTcpConnectionPrivate(); - - int port; - QTcpSocket *socket; - QPacketProtocol *protocol; - QTcpServer *tcpServer; - - QDeclarativeDebugServer *debugServer; -}; - -QDeclarativeDebugServerTcpConnectionPrivate::QDeclarativeDebugServerTcpConnectionPrivate() : - port(0), - socket(0), - protocol(0), - tcpServer(0), - debugServer(0) -{ -} - -QDeclarativeDebugServerTcpConnection::QDeclarativeDebugServerTcpConnection(int port, QDeclarativeDebugServer *server) : - QObject(server), - d_ptr(new QDeclarativeDebugServerTcpConnectionPrivate) -{ - Q_D(QDeclarativeDebugServerTcpConnection); - d->port = port; - d->debugServer = server; -} - -QDeclarativeDebugServerTcpConnection::~QDeclarativeDebugServerTcpConnection() -{ - delete d_ptr; -} - -bool QDeclarativeDebugServerTcpConnection::isConnected() const -{ - Q_D(const QDeclarativeDebugServerTcpConnection); - return d->socket && d->socket->state() == QTcpSocket::ConnectedState; -} - -void QDeclarativeDebugServerTcpConnection::send(const QByteArray &message) -{ - Q_D(QDeclarativeDebugServerTcpConnection); - - if (!isConnected()) - return; - - QPacket pack; - pack.writeRawData(message.data(), message.length()); - - d->protocol->send(pack); - d->socket->flush(); -} - -void QDeclarativeDebugServerTcpConnection::disconnect() -{ - Q_D(QDeclarativeDebugServerTcpConnection); - - delete d->protocol; - d->protocol = 0; - delete d->socket; - d->socket = 0; -} - -void QDeclarativeDebugServerTcpConnection::listen() -{ - Q_D(QDeclarativeDebugServerTcpConnection); - - d->tcpServer = new QTcpServer(this); - QObject::connect(d->tcpServer, SIGNAL(newConnection()), this, SLOT(newConnection())); - if (d->tcpServer->listen(QHostAddress::Any, d->port)) - qWarning("QDeclarativeDebugServer: Waiting for connection on port %d...", d->port); - else - qWarning("QDeclarativeDebugServer: Unable to listen on port %d", d->port); -} - -void QDeclarativeDebugServerTcpConnection::waitForConnection() -{ - Q_D(QDeclarativeDebugServerTcpConnection); - d->tcpServer->waitForNewConnection(-1); -} - -void QDeclarativeDebugServerTcpConnection::readyRead() -{ - Q_D(QDeclarativeDebugServerTcpConnection); - QPacket packet = d->protocol->read(); - - QByteArray content = packet.data(); - d->debugServer->receiveMessage(content); -} - -void QDeclarativeDebugServerTcpConnection::newConnection() -{ - Q_D(QDeclarativeDebugServerTcpConnection); - - if (d->socket) { - qWarning("QDeclarativeDebugServer error: another client is already connected"); - QTcpSocket *faultyConnection = d->tcpServer->nextPendingConnection(); - delete faultyConnection; - return; - } - - d->socket = d->tcpServer->nextPendingConnection(); - d->socket->setParent(this); - d->protocol = new QPacketProtocol(d->socket, this); - QObject::connect(d->protocol, SIGNAL(readyRead()), this, SLOT(readyRead())); -} - - -QT_END_NAMESPACE diff --git a/src/declarative/debugger/qdeclarativedebugservertcpconnection_p.h b/src/declarative/debugger/qdeclarativedebugservertcpconnection_p.h deleted file mode 100644 index f1c749ef..0000000 --- a/src/declarative/debugger/qdeclarativedebugservertcpconnection_p.h +++ /dev/null @@ -1,86 +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 QDECLARATIVEDEBUGSERVERTCPCONNECTION_H -#define QDECLARATIVEDEBUGSERVERTCPCONNECTION_H - -#include - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Declarative) - -#include - -class QDeclarativeDebugServer; -class QDeclarativeDebugServerTcpConnectionPrivate; -class QDeclarativeDebugServerTcpConnection : public QObject, public QDeclarativeDebugServerConnection -{ - Q_OBJECT - Q_DECLARE_PRIVATE(QDeclarativeDebugServerTcpConnection) - Q_DISABLE_COPY(QDeclarativeDebugServerTcpConnection) - -public: - QDeclarativeDebugServerTcpConnection(int port, QDeclarativeDebugServer *server); - ~QDeclarativeDebugServerTcpConnection(); - - bool isConnected() const; - void send(const QByteArray &message); - void disconnect(); - - void listen(); - void waitForConnection(); - -private Q_SLOTS: - void readyRead(); - void newConnection(); - -private: - QDeclarativeDebugServerTcpConnectionPrivate *d_ptr; -}; - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QDECLARATIVEDEBUGSERVERTCPCONNECTION_H diff --git a/src/declarative/debugger/qpacketprotocol_p.h b/src/declarative/debugger/qpacketprotocol_p.h index 99fded5..1c69cdd 100644 --- a/src/declarative/debugger/qpacketprotocol_p.h +++ b/src/declarative/debugger/qpacketprotocol_p.h @@ -59,7 +59,7 @@ class QPacket; class QPacketAutoSend; class QPacketProtocolPrivate; -class Q_DECLARATIVE_PRIVATE_EXPORT QPacketProtocol : public QObject +class Q_DECLARATIVE_EXPORT QPacketProtocol : public QObject { Q_OBJECT public: @@ -89,7 +89,7 @@ private: }; -class Q_DECLARATIVE_PRIVATE_EXPORT QPacket : public QDataStream +class Q_DECLARATIVE_EXPORT QPacket : public QDataStream { public: QPacket(); diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro index 722979d..07825d9 100644 --- a/src/plugins/plugins.pro +++ b/src/plugins/plugins.pro @@ -14,5 +14,4 @@ embedded:SUBDIRS *= gfxdrivers decorations mousedrivers kbddrivers symbian:SUBDIRS += s60 contains(QT_CONFIG, phonon): SUBDIRS *= phonon contains(QT_CONFIG, multimedia): SUBDIRS *= audio - - +contains(QT_CONFIG, declarative): SUBDIRS *= qmldebugging diff --git a/src/plugins/qmldebugging/qmldebugging.pro b/src/plugins/qmldebugging/qmldebugging.pro new file mode 100644 index 0000000..01cf1a9 --- /dev/null +++ b/src/plugins/qmldebugging/qmldebugging.pro @@ -0,0 +1,4 @@ +TEMPLATE = subdirs + +SUBDIRS = tcpserver + diff --git a/src/plugins/qmldebugging/tcpserver/qtcpserverconnection.cpp b/src/plugins/qmldebugging/tcpserver/qtcpserverconnection.cpp new file mode 100644 index 0000000..69c1ef5 --- /dev/null +++ b/src/plugins/qmldebugging/tcpserver/qtcpserverconnection.cpp @@ -0,0 +1,173 @@ +/**************************************************************************** +** +** 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 "qtcpserverconnection.h" + +#include +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +class QTcpServerConnectionPrivate { +public: + QTcpServerConnectionPrivate(); + + int port; + QTcpSocket *socket; + QPacketProtocol *protocol; + QTcpServer *tcpServer; + + QDeclarativeDebugServer *debugServer; +}; + +QTcpServerConnectionPrivate::QTcpServerConnectionPrivate() : + port(0), + socket(0), + protocol(0), + tcpServer(0), + debugServer(0) +{ +} + +QTcpServerConnection::QTcpServerConnection() : + d_ptr(new QTcpServerConnectionPrivate) +{ + +} + +QTcpServerConnection::~QTcpServerConnection() +{ + delete d_ptr; +} + +void QTcpServerConnection::setServer(QDeclarativeDebugServer *server) +{ + Q_D(QTcpServerConnection); + d->debugServer = server; +} + +bool QTcpServerConnection::isConnected() const +{ + Q_D(const QTcpServerConnection); + return d->socket && d->socket->state() == QTcpSocket::ConnectedState; +} + +void QTcpServerConnection::send(const QByteArray &message) +{ + Q_D(QTcpServerConnection); + + if (!isConnected()) + return; + + QPacket pack; + pack.writeRawData(message.data(), message.length()); + + d->protocol->send(pack); + d->socket->flush(); +} + +void QTcpServerConnection::disconnect() +{ + Q_D(QTcpServerConnection); + + delete d->protocol; + d->protocol = 0; + delete d->socket; + d->socket = 0; +} + +void QTcpServerConnection::setPort(int port, bool block) +{ + Q_D(QTcpServerConnection); + d->port = port; + + listen(); + if (block) + d->tcpServer->waitForNewConnection(-1); +} + +void QTcpServerConnection::listen() +{ + Q_D(QTcpServerConnection); + + d->tcpServer = new QTcpServer(this); + QObject::connect(d->tcpServer, SIGNAL(newConnection()), this, SLOT(newConnection())); + if (d->tcpServer->listen(QHostAddress::Any, d->port)) + qWarning("QDeclarativeDebugServer: Waiting for connection on port %d...", d->port); + else + qWarning("QDeclarativeDebugServer: Unable to listen on port %d", d->port); +} + + +void QTcpServerConnection::readyRead() +{ + Q_D(QTcpServerConnection); + QPacket packet = d->protocol->read(); + + QByteArray content = packet.data(); + d->debugServer->receiveMessage(content); +} + +void QTcpServerConnection::newConnection() +{ + Q_D(QTcpServerConnection); + + if (d->socket) { + qWarning("QDeclarativeDebugServer: Another client is already connected"); + QTcpSocket *faultyConnection = d->tcpServer->nextPendingConnection(); + delete faultyConnection; + return; + } + + d->socket = d->tcpServer->nextPendingConnection(); + d->socket->setParent(this); + d->protocol = new QPacketProtocol(d->socket, this); + QObject::connect(d->protocol, SIGNAL(readyRead()), this, SLOT(readyRead())); +} + + +Q_EXPORT_PLUGIN2(tcpserver, QTcpServerConnection) + +QT_END_NAMESPACE + diff --git a/src/plugins/qmldebugging/tcpserver/qtcpserverconnection.h b/src/plugins/qmldebugging/tcpserver/qtcpserverconnection.h new file mode 100644 index 0000000..a6e17e6 --- /dev/null +++ b/src/plugins/qmldebugging/tcpserver/qtcpserverconnection.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** 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 QTCPSERVERCONNECTION_H +#define QTCPSERVERCONNECTION_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QDeclarativeDebugServer; +class QTcpServerConnectionPrivate; +class QTcpServerConnection : public QObject, public QDeclarativeDebugServerConnection +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QTcpServerConnection) + Q_DISABLE_COPY(QTcpServerConnection) + Q_INTERFACES(QDeclarativeDebugServerConnection) + + +public: + QTcpServerConnection(); + ~QTcpServerConnection(); + + void setServer(QDeclarativeDebugServer *server); + void setPort(int port, bool bock); + + bool isConnected() const; + void send(const QByteArray &message); + void disconnect(); + + void listen(); + void waitForConnection(); + +private Q_SLOTS: + void readyRead(); + void newConnection(); + +private: + QTcpServerConnectionPrivate *d_ptr; +}; + +QT_END_NAMESPACE + +#endif // QTCPSERVERCONNECTION_H diff --git a/src/plugins/qmldebugging/tcpserver/tcpserver.pro b/src/plugins/qmldebugging/tcpserver/tcpserver.pro new file mode 100644 index 0000000..e90fb34 --- /dev/null +++ b/src/plugins/qmldebugging/tcpserver/tcpserver.pro @@ -0,0 +1,18 @@ +TARGET = tcpserver +QT += declarative network + +include(../../qpluginbase.pri) + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/qmldebugging +QTDIR_build:REQUIRES += "contains(QT_CONFIG, declarative)" + +SOURCES += \ + qtcpserverconnection.cpp + +HEADERS += \ + qtcpserverconnection.h + +target.path += $$[QT_INSTALL_PLUGINS]/qmldebugging +INSTALLS += target + +symbian:TARGET.UID3=0x20031E90 \ No newline at end of file -- cgit v0.12 From 35ae0b8146bca7a61203ee347654aed27951439c Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Thu, 9 Dec 2010 13:06:08 +0100 Subject: QDeclarativeDebug: Include debugger plugin in qmlviewer.sis Developers that want to debug qml on their device have to now install qmlviewer.sis. Reviewed-by: Christiaan Janssen --- tools/qml/qml.pro | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/qml/qml.pro b/tools/qml/qml.pro index bdac6e3..9b07ebe 100644 --- a/tools/qml/qml.pro +++ b/tools/qml/qml.pro @@ -43,6 +43,11 @@ symbian { contains(QT_CONFIG, s60): { LIBS += -lavkon -lcone } + + # Deploy plugin for remote debugging + qmldebuggingplugin.sources = $$QT_BUILD_TREE/plugins/qmldebugging/tcpserver$${QT_LIBINFIX}.dll + qmldebuggingplugin.path = c:$$QT_PLUGINS_BASE_DIR/qmldebugging + DEPLOYMENT += qmldebuggingplugin } mac { QMAKE_INFO_PLIST=Info_mac.plist -- cgit v0.12 From 3290135e88bd8a01e20842c9d1cdca5fe569bf62 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Thu, 16 Dec 2010 14:39:15 +0100 Subject: Symbian compile fix armv5 complained that the call to QChar::category() was ambiguous, because there is a version taking an uint, and a version taking ushort as argument. Reviewed-by: Christiaan Janssen --- src/script/bridge/qscriptdeclarativeclass.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/script/bridge/qscriptdeclarativeclass.cpp b/src/script/bridge/qscriptdeclarativeclass.cpp index 92248a0..13736bc 100644 --- a/src/script/bridge/qscriptdeclarativeclass.cpp +++ b/src/script/bridge/qscriptdeclarativeclass.cpp @@ -473,7 +473,7 @@ bool QScriptDeclarativeClass::startsWithUpper(const Identifier &identifier) JSC::UString::Rep *r = (JSC::UString::Rep *)identifier; if (r->size() < 1) return false; - return QChar::category(r->data()[0]) == QChar::Letter_Uppercase; + return QChar::category((ushort)(r->data()[0])) == QChar::Letter_Uppercase; } quint32 QScriptDeclarativeClass::toArrayIndex(const Identifier &identifier, bool *ok) -- cgit v0.12 From 3fe6eab1e6e451457b9c060b6b643b86d3f82557 Mon Sep 17 00:00:00 2001 From: Joona Petrell Date: Mon, 20 Dec 2010 12:07:22 +1000 Subject: Fix spelling in declarative autotests Task-number: Reviewed-by: Martin Jones --- .../qdeclarativeecmascript/data/nonExistantAttachedObject.qml | 5 ----- .../qdeclarativeecmascript/data/nonExistentAttachedObject.qml | 5 +++++ .../qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp | 8 ++++---- .../qdeclarativeinstruction/tst_qdeclarativeinstruction.cpp | 2 +- .../declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp | 6 +++--- 5 files changed, 13 insertions(+), 13 deletions(-) delete mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/nonExistantAttachedObject.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/nonExistentAttachedObject.qml diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/nonExistantAttachedObject.qml b/tests/auto/declarative/qdeclarativeecmascript/data/nonExistantAttachedObject.qml deleted file mode 100644 index f9585db..0000000 --- a/tests/auto/declarative/qdeclarativeecmascript/data/nonExistantAttachedObject.qml +++ /dev/null @@ -1,5 +0,0 @@ -import Qt.test 1.0 - -MyQmlObject { - stringProperty: MyQmlContainer.prop -} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/nonExistentAttachedObject.qml b/tests/auto/declarative/qdeclarativeecmascript/data/nonExistentAttachedObject.qml new file mode 100644 index 0000000..f9585db --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/nonExistentAttachedObject.qml @@ -0,0 +1,5 @@ +import Qt.test 1.0 + +MyQmlObject { + stringProperty: MyQmlContainer.prop +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp index 77fab91..4228bc4 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp +++ b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp @@ -105,7 +105,7 @@ private slots: void constantsOverrideBindings(); void outerBindingOverridesInnerBinding(); void aliasPropertyAndBinding(); - void nonExistantAttachedObject(); + void nonExistentAttachedObject(); void scope(); void signalParameterTypes(); void objectsCompareAsEqual(); @@ -643,7 +643,7 @@ void tst_qdeclarativeecmascript::attachedProperties() void tst_qdeclarativeecmascript::enums() { - // Existant enums + // Existent enums { QDeclarativeComponent component(&engine, TEST_FILE("enums.1.qml")); QObject *object = component.create(); @@ -785,9 +785,9 @@ Access a non-existent attached object. Tests for a regression where this used to crash. */ -void tst_qdeclarativeecmascript::nonExistantAttachedObject() +void tst_qdeclarativeecmascript::nonExistentAttachedObject() { - QDeclarativeComponent component(&engine, TEST_FILE("nonExistantAttachedObject.qml")); + QDeclarativeComponent component(&engine, TEST_FILE("nonExistentAttachedObject.qml")); QString warning = component.url().toString() + ":4: Unable to assign [undefined] to QString stringProperty"; QTest::ignoreMessage(QtWarningMsg, qPrintable(warning)); diff --git a/tests/auto/declarative/qdeclarativeinstruction/tst_qdeclarativeinstruction.cpp b/tests/auto/declarative/qdeclarativeinstruction/tst_qdeclarativeinstruction.cpp index 4470d65..304ce61 100644 --- a/tests/auto/declarative/qdeclarativeinstruction/tst_qdeclarativeinstruction.cpp +++ b/tests/auto/declarative/qdeclarativeinstruction/tst_qdeclarativeinstruction.cpp @@ -512,7 +512,7 @@ void tst_qdeclarativeinstruction::dump() { QDeclarativeInstruction i; i.line = 50; - i.type = (QDeclarativeInstruction::Type)(1234); // Non-existant + i.type = (QDeclarativeInstruction::Type)(1234); // Non-existent data->bytecode << i; } diff --git a/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp b/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp index 50463b7..6410853 100644 --- a/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp +++ b/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp @@ -947,7 +947,7 @@ void tst_qdeclarativelanguage::aliasProperties() object->setProperty("value", QVariant(13)); QCOMPARE(object->property("valueAlias").toInt(), 13); - // Write throught alias + // Write through alias object->setProperty("valueAlias", QVariant(19)); QCOMPARE(object->property("valueAlias").toInt(), 19); QCOMPARE(object->property("value").toInt(), 19); @@ -1109,7 +1109,7 @@ void tst_qdeclarativelanguage::aliasProperties() object->setProperty("rectProperty", QVariant(QRect(33, 12, 99, 100))); QCOMPARE(object->property("valueAlias").toRect(), QRect(33, 12, 99, 100)); - // Write throught alias + // Write through alias object->setProperty("valueAlias", QVariant(QRect(3, 3, 4, 9))); QCOMPARE(object->property("valueAlias").toRect(), QRect(3, 3, 4, 9)); QCOMPARE(object->property("rectProperty").toRect(), QRect(3, 3, 4, 9)); @@ -1129,7 +1129,7 @@ void tst_qdeclarativelanguage::aliasProperties() object->setProperty("rectProperty", QVariant(QRect(33, 8, 102, 111))); QCOMPARE(object->property("aliasProperty").toInt(), 33); - // Write throught alias + // Write through alias object->setProperty("aliasProperty", QVariant(4)); QCOMPARE(object->property("aliasProperty").toInt(), 4); QCOMPARE(object->property("rectProperty").toRect(), QRect(4, 8, 102, 111)); -- cgit v0.12 From ee4a2417950dc9b411660fa229908619eff956a2 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Mon, 20 Dec 2010 15:42:52 +1000 Subject: Add copyright header --- .../touchinteraction/pincharea/flickresize.qml | 40 ++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/examples/declarative/touchinteraction/pincharea/flickresize.qml b/examples/declarative/touchinteraction/pincharea/flickresize.qml index 8034e29..8f29d6d 100644 --- a/examples/declarative/touchinteraction/pincharea/flickresize.qml +++ b/examples/declarative/touchinteraction/pincharea/flickresize.qml @@ -1,3 +1,43 @@ +/**************************************************************************** +** +** 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 examples 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 QtQuick 1.1 Rectangle { -- cgit v0.12 From 6b37f71b318445a338c4afe5ba8a5ccaff573518 Mon Sep 17 00:00:00 2001 From: Joona Petrell Date: Mon, 20 Dec 2010 17:04:41 +1000 Subject: Update Minehunt demo warning message The message was talking about a C++ plugin when the demo is nowadays in a form of a standalone executable. Task-number: Reviewed-by: Bea Lam --- demos/declarative/minehunt/minehunt.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demos/declarative/minehunt/minehunt.qml b/demos/declarative/minehunt/minehunt.qml index eb67b06..88ecd6d 100644 --- a/demos/declarative/minehunt/minehunt.qml +++ b/demos/declarative/minehunt/minehunt.qml @@ -104,7 +104,7 @@ Item { anchors.centerIn: parent; width: parent.width - 20 horizontalAlignment: Text.AlignHCenter wrapMode: Text.WordWrap - text: "Minehunt will not run properly if the C++ plugin is not compiled.\n\nPlease see README." + text: "Minehunt demo has to be compiled to run.\n\nPlease see README." color: "white"; font.bold: true; font.pixelSize: 14 visible: tiles == undefined } -- cgit v0.12 From 1476bf8d45b4f1ab6c56770939eb81c4c1b390ad Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Mon, 20 Dec 2010 14:29:19 +1000 Subject: Optimize name lookup for QDeclarativeProperty. If the property is constructed by passing in the property name (and we've verified that it is valid), we can cache that name immediately rather than reconstructing it on the first call to name(). Task-number: QTBUG-15331 Reviewed-by: Martin Jones --- src/declarative/qml/qdeclarativeproperty.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/declarative/qml/qdeclarativeproperty.cpp b/src/declarative/qml/qdeclarativeproperty.cpp index 60edd64..8eaa98b 100644 --- a/src/declarative/qml/qdeclarativeproperty.cpp +++ b/src/declarative/qml/qdeclarativeproperty.cpp @@ -315,6 +315,8 @@ void QDeclarativePropertyPrivate::initProperty(QObject *obj, const QString &name if (property && !(property->flags & QDeclarativePropertyCache::Data::IsFunction)) { object = currentObject; core = *property; + nameCache = terminal; + isNameCached = true; } } -- cgit v0.12 From a764a0b5d66e13fb69a5b69330c5edfecf89ee8b Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Tue, 21 Dec 2010 08:53:00 +1000 Subject: Optimize QByteArray to QString conversion in PropertyChanges. Perform the conversion once at compile time, rather than many times later. Task-number: QTBUG-15331 Reviewed-by: Martin Jones --- .../util/qdeclarativepropertychanges.cpp | 72 +++++++++++----------- .../util/qdeclarativepropertychanges_p.h | 18 +++--- src/declarative/util/qdeclarativestate.cpp | 24 ++++---- src/declarative/util/qdeclarativestate_p.h | 12 ++-- 4 files changed, 62 insertions(+), 64 deletions(-) diff --git a/src/declarative/util/qdeclarativepropertychanges.cpp b/src/declarative/util/qdeclarativepropertychanges.cpp index 400803e..6737382 100644 --- a/src/declarative/util/qdeclarativepropertychanges.cpp +++ b/src/declarative/util/qdeclarativepropertychanges.cpp @@ -220,12 +220,12 @@ public: void decode(); - QList > properties; - QList > expressions; + QList > properties; + QList > expressions; QList ids; QList signalReplacements; - QDeclarativeProperty property(const QByteArray &); + QDeclarativeProperty property(const QString &); }; void @@ -293,7 +293,7 @@ QDeclarativePropertyChangesParser::compile(const QList> count; for (int ii = 0; ii < count; ++ii) { - QByteArray name; + QString name; bool isScript; QVariant data; QDeclarativeBinding::Identifier id; @@ -405,15 +405,15 @@ void QDeclarativePropertyChanges::setRestoreEntryValues(bool v) } QDeclarativeProperty -QDeclarativePropertyChangesPrivate::property(const QByteArray &property) +QDeclarativePropertyChangesPrivate::property(const QString &property) { Q_Q(QDeclarativePropertyChanges); - QDeclarativeProperty prop(object, QString::fromUtf8(property), qmlContext(q)); + QDeclarativeProperty prop(object, property, qmlContext(q)); if (!prop.isValid()) { - qmlInfo(q) << QDeclarativePropertyChanges::tr("Cannot assign to non-existent property \"%1\"").arg(QString::fromUtf8(property)); + qmlInfo(q) << QDeclarativePropertyChanges::tr("Cannot assign to non-existent property \"%1\"").arg(property); return QDeclarativeProperty(); } else if (!(prop.type() & QDeclarativeProperty::SignalProperty) && !prop.isWritable()) { - qmlInfo(q) << QDeclarativePropertyChanges::tr("Cannot assign to read-only property \"%1\"").arg(QString::fromUtf8(property)); + qmlInfo(q) << QDeclarativePropertyChanges::tr("Cannot assign to read-only property \"%1\"").arg(property); return QDeclarativeProperty(); } return prop; @@ -429,9 +429,7 @@ QDeclarativePropertyChanges::ActionList QDeclarativePropertyChanges::actions() for (int ii = 0; ii < d->properties.count(); ++ii) { - QByteArray property = d->properties.at(ii).first; - - QDeclarativeAction a(d->object, QString::fromUtf8(property), + QDeclarativeAction a(d->object, d->properties.at(ii).first, qmlContext(this), d->properties.at(ii).second); if (a.property.isValid()) { @@ -453,7 +451,7 @@ QDeclarativePropertyChanges::ActionList QDeclarativePropertyChanges::actions() for (int ii = 0; ii < d->expressions.count(); ++ii) { - QByteArray property = d->expressions.at(ii).first; + const QString &property = d->expressions.at(ii).first; QDeclarativeProperty prop = d->property(property); if (prop.isValid()) { @@ -462,7 +460,7 @@ QDeclarativePropertyChanges::ActionList QDeclarativePropertyChanges::actions() a.property = prop; a.fromValue = a.property.read(); a.specifiedObject = d->object; - a.specifiedProperty = QString::fromUtf8(property); + a.specifiedProperty = property; if (d->isExplicit) { a.toValue = d->expressions.at(ii).second->evaluate(); @@ -518,10 +516,10 @@ void QDeclarativePropertyChanges::setIsExplicit(bool e) d->isExplicit = e; } -bool QDeclarativePropertyChanges::containsValue(const QByteArray &name) const +bool QDeclarativePropertyChanges::containsValue(const QString &name) const { Q_D(const QDeclarativePropertyChanges); - typedef QPair PropertyEntry; + typedef QPair PropertyEntry; QListIterator propertyIterator(d->properties); while (propertyIterator.hasNext()) { @@ -534,10 +532,10 @@ bool QDeclarativePropertyChanges::containsValue(const QByteArray &name) const return false; } -bool QDeclarativePropertyChanges::containsExpression(const QByteArray &name) const +bool QDeclarativePropertyChanges::containsExpression(const QString &name) const { Q_D(const QDeclarativePropertyChanges); - typedef QPair ExpressionEntry; + typedef QPair ExpressionEntry; QListIterator expressionIterator(d->expressions); while (expressionIterator.hasNext()) { @@ -550,16 +548,16 @@ bool QDeclarativePropertyChanges::containsExpression(const QByteArray &name) con return false; } -bool QDeclarativePropertyChanges::containsProperty(const QByteArray &name) const +bool QDeclarativePropertyChanges::containsProperty(const QString &name) const { return containsValue(name) || containsExpression(name); } -void QDeclarativePropertyChanges::changeValue(const QByteArray &name, const QVariant &value) +void QDeclarativePropertyChanges::changeValue(const QString &name, const QVariant &value) { Q_D(QDeclarativePropertyChanges); - typedef QPair PropertyEntry; - typedef QPair ExpressionEntry; + typedef QPair PropertyEntry; + typedef QPair ExpressionEntry; QMutableListIterator expressionIterator(d->expressions); while (expressionIterator.hasNext()) { @@ -596,7 +594,7 @@ void QDeclarativePropertyChanges::changeValue(const QByteArray &name, const QVar action.property = d->property(name); action.fromValue = action.property.read(); action.specifiedObject = object(); - action.specifiedProperty = QString::fromUtf8(name); + action.specifiedProperty = name; action.toValue = value; propertyIterator.insert(PropertyEntry(name, value)); @@ -609,11 +607,11 @@ void QDeclarativePropertyChanges::changeValue(const QByteArray &name, const QVar } } -void QDeclarativePropertyChanges::changeExpression(const QByteArray &name, const QString &expression) +void QDeclarativePropertyChanges::changeExpression(const QString &name, const QString &expression) { Q_D(QDeclarativePropertyChanges); - typedef QPair PropertyEntry; - typedef QPair ExpressionEntry; + typedef QPair PropertyEntry; + typedef QPair ExpressionEntry; bool hadValue = false; @@ -667,7 +665,7 @@ void QDeclarativePropertyChanges::changeExpression(const QByteArray &name, const action.property = d->property(name); action.fromValue = action.property.read(); action.specifiedObject = object(); - action.specifiedProperty = QString::fromUtf8(name); + action.specifiedProperty = name; if (d->isExplicit) { @@ -690,11 +688,11 @@ void QDeclarativePropertyChanges::changeExpression(const QByteArray &name, const // what about the signal handler? } -QVariant QDeclarativePropertyChanges::property(const QByteArray &name) const +QVariant QDeclarativePropertyChanges::property(const QString &name) const { Q_D(const QDeclarativePropertyChanges); - typedef QPair PropertyEntry; - typedef QPair ExpressionEntry; + typedef QPair PropertyEntry; + typedef QPair ExpressionEntry; QListIterator propertyIterator(d->properties); while (propertyIterator.hasNext()) { @@ -715,11 +713,11 @@ QVariant QDeclarativePropertyChanges::property(const QByteArray &name) const return QVariant(); } -void QDeclarativePropertyChanges::removeProperty(const QByteArray &name) +void QDeclarativePropertyChanges::removeProperty(const QString &name) { Q_D(QDeclarativePropertyChanges); - typedef QPair PropertyEntry; - typedef QPair ExpressionEntry; + typedef QPair PropertyEntry; + typedef QPair ExpressionEntry; QMutableListIterator expressionIterator(d->expressions); while (expressionIterator.hasNext()) { @@ -742,10 +740,10 @@ void QDeclarativePropertyChanges::removeProperty(const QByteArray &name) } } -QVariant QDeclarativePropertyChanges::value(const QByteArray &name) const +QVariant QDeclarativePropertyChanges::value(const QString &name) const { Q_D(const QDeclarativePropertyChanges); - typedef QPair PropertyEntry; + typedef QPair PropertyEntry; QListIterator propertyIterator(d->properties); while (propertyIterator.hasNext()) { @@ -758,10 +756,10 @@ QVariant QDeclarativePropertyChanges::value(const QByteArray &name) const return QVariant(); } -QString QDeclarativePropertyChanges::expression(const QByteArray &name) const +QString QDeclarativePropertyChanges::expression(const QString &name) const { Q_D(const QDeclarativePropertyChanges); - typedef QPair ExpressionEntry; + typedef QPair ExpressionEntry; QListIterator expressionIterator(d->expressions); while (expressionIterator.hasNext()) { diff --git a/src/declarative/util/qdeclarativepropertychanges_p.h b/src/declarative/util/qdeclarativepropertychanges_p.h index 449574c..1a98cec 100644 --- a/src/declarative/util/qdeclarativepropertychanges_p.h +++ b/src/declarative/util/qdeclarativepropertychanges_p.h @@ -75,19 +75,19 @@ public: virtual ActionList actions(); - bool containsProperty(const QByteArray &name) const; - bool containsValue(const QByteArray &name) const; - bool containsExpression(const QByteArray &name) const; - void changeValue(const QByteArray &name, const QVariant &value); - void changeExpression(const QByteArray &name, const QString &expression); - void removeProperty(const QByteArray &name); - QVariant value(const QByteArray &name) const; - QString expression(const QByteArray &name) const; + bool containsProperty(const QString &name) const; + bool containsValue(const QString &name) const; + bool containsExpression(const QString &name) const; + void changeValue(const QString &name, const QVariant &value); + void changeExpression(const QString &name, const QString &expression); + void removeProperty(const QString &name); + QVariant value(const QString &name) const; + QString expression(const QString &name) const; void detachFromState(); void attachToState(); - QVariant property(const QByteArray &name) const; + QVariant property(const QString &name) const; }; class QDeclarativePropertyChangesParser : public QDeclarativeCustomParser diff --git a/src/declarative/util/qdeclarativestate.cpp b/src/declarative/util/qdeclarativestate.cpp index 6925e03..cde6f00 100644 --- a/src/declarative/util/qdeclarativestate.cpp +++ b/src/declarative/util/qdeclarativestate.cpp @@ -370,7 +370,7 @@ void QDeclarativeAction::deleteFromBinding() } } -bool QDeclarativeState::containsPropertyInRevertList(QObject *target, const QByteArray &name) const +bool QDeclarativeState::containsPropertyInRevertList(QObject *target, const QString &name) const { Q_D(const QDeclarativeState); @@ -379,7 +379,7 @@ bool QDeclarativeState::containsPropertyInRevertList(QObject *target, const QByt while (revertListIterator.hasNext()) { const QDeclarativeSimpleAction &simpleAction = revertListIterator.next(); - if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty().toUtf8() == name) + if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name) return true; } } @@ -387,7 +387,7 @@ bool QDeclarativeState::containsPropertyInRevertList(QObject *target, const QByt return false; } -bool QDeclarativeState::changeValueInRevertList(QObject *target, const QByteArray &name, const QVariant &revertValue) +bool QDeclarativeState::changeValueInRevertList(QObject *target, const QString &name, const QVariant &revertValue) { Q_D(QDeclarativeState); @@ -396,7 +396,7 @@ bool QDeclarativeState::changeValueInRevertList(QObject *target, const QByteArra while (revertListIterator.hasNext()) { QDeclarativeSimpleAction &simpleAction = revertListIterator.next(); - if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty().toUtf8() == name) { + if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name) { simpleAction.setValue(revertValue); return true; } @@ -406,7 +406,7 @@ bool QDeclarativeState::changeValueInRevertList(QObject *target, const QByteArra return false; } -bool QDeclarativeState::changeBindingInRevertList(QObject *target, const QByteArray &name, QDeclarativeAbstractBinding *binding) +bool QDeclarativeState::changeBindingInRevertList(QObject *target, const QString &name, QDeclarativeAbstractBinding *binding) { Q_D(QDeclarativeState); @@ -415,7 +415,7 @@ bool QDeclarativeState::changeBindingInRevertList(QObject *target, const QByteAr while (revertListIterator.hasNext()) { QDeclarativeSimpleAction &simpleAction = revertListIterator.next(); - if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty().toUtf8() == name) { + if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name) { if (simpleAction.binding()) simpleAction.binding()->destroy(); @@ -428,7 +428,7 @@ bool QDeclarativeState::changeBindingInRevertList(QObject *target, const QByteAr return false; } -bool QDeclarativeState::removeEntryFromRevertList(QObject *target, const QByteArray &name) +bool QDeclarativeState::removeEntryFromRevertList(QObject *target, const QString &name) { Q_D(QDeclarativeState); @@ -437,7 +437,7 @@ bool QDeclarativeState::removeEntryFromRevertList(QObject *target, const QByteAr while (revertListIterator.hasNext()) { QDeclarativeSimpleAction &simpleAction = revertListIterator.next(); - if (simpleAction.property().object() == target && simpleAction.property().name().toUtf8() == name) { + if (simpleAction.property().object() == target && simpleAction.property().name() == name) { QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::binding(simpleAction.property()); if (oldBinding) { QDeclarativePropertyPrivate::setBinding(simpleAction.property(), 0); @@ -517,7 +517,7 @@ void QDeclarativeState::addEntriesToRevertList(const QList & } } -QVariant QDeclarativeState::valueInRevertList(QObject *target, const QByteArray &name) const +QVariant QDeclarativeState::valueInRevertList(QObject *target, const QString &name) const { Q_D(const QDeclarativeState); @@ -526,7 +526,7 @@ QVariant QDeclarativeState::valueInRevertList(QObject *target, const QByteArray while (revertListIterator.hasNext()) { const QDeclarativeSimpleAction &simpleAction = revertListIterator.next(); - if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty().toUtf8() == name) + if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name) return simpleAction.value(); } } @@ -534,7 +534,7 @@ QVariant QDeclarativeState::valueInRevertList(QObject *target, const QByteArray return QVariant(); } -QDeclarativeAbstractBinding *QDeclarativeState::bindingInRevertList(QObject *target, const QByteArray &name) const +QDeclarativeAbstractBinding *QDeclarativeState::bindingInRevertList(QObject *target, const QString &name) const { Q_D(const QDeclarativeState); @@ -543,7 +543,7 @@ QDeclarativeAbstractBinding *QDeclarativeState::bindingInRevertList(QObject *tar while (revertListIterator.hasNext()) { const QDeclarativeSimpleAction &simpleAction = revertListIterator.next(); - if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty().toUtf8() == name) + if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name) return simpleAction.binding(); } } diff --git a/src/declarative/util/qdeclarativestate_p.h b/src/declarative/util/qdeclarativestate_p.h index 7b9c18a..dd43a50 100644 --- a/src/declarative/util/qdeclarativestate_p.h +++ b/src/declarative/util/qdeclarativestate_p.h @@ -180,15 +180,15 @@ public: QDeclarativeStateGroup *stateGroup() const; void setStateGroup(QDeclarativeStateGroup *); - bool containsPropertyInRevertList(QObject *target, const QByteArray &name) const; - bool changeValueInRevertList(QObject *target, const QByteArray &name, const QVariant &revertValue); - bool changeBindingInRevertList(QObject *target, const QByteArray &name, QDeclarativeAbstractBinding *binding); - bool removeEntryFromRevertList(QObject *target, const QByteArray &name); + bool containsPropertyInRevertList(QObject *target, const QString &name) const; + bool changeValueInRevertList(QObject *target, const QString &name, const QVariant &revertValue); + bool changeBindingInRevertList(QObject *target, const QString &name, QDeclarativeAbstractBinding *binding); + bool removeEntryFromRevertList(QObject *target, const QString &name); void addEntryToRevertList(const QDeclarativeAction &action); void removeAllEntriesFromRevertList(QObject *target); void addEntriesToRevertList(const QList &actions); - QVariant valueInRevertList(QObject *target, const QByteArray &name) const; - QDeclarativeAbstractBinding *bindingInRevertList(QObject *target, const QByteArray &name) const; + QVariant valueInRevertList(QObject *target, const QString &name) const; + QDeclarativeAbstractBinding *bindingInRevertList(QObject *target, const QString &name) const; bool isStateActive() const; -- cgit v0.12 From 3468ee1a47bc646fe2af5de38425ee917ea92f59 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Tue, 21 Dec 2010 13:52:44 +1000 Subject: Fix potential crash in PropertyChanges binding rewrite handling. This fixes the autotest regression for tst_qdeclarativestates::editProperties introduced by 488e616b50707e5b37162e6d0cfc71a1ffdf9bef. Reviewed-by: Joona Petrell --- src/declarative/qml/qdeclarativebinding.cpp | 5 ++ src/declarative/qml/qdeclarativebinding_p.h | 1 + .../util/qdeclarativepropertychanges.cpp | 63 ++++++++++++---------- 3 files changed, 42 insertions(+), 27 deletions(-) diff --git a/src/declarative/qml/qdeclarativebinding.cpp b/src/declarative/qml/qdeclarativebinding.cpp index 1ead6ce..223d057 100644 --- a/src/declarative/qml/qdeclarativebinding.cpp +++ b/src/declarative/qml/qdeclarativebinding.cpp @@ -209,6 +209,8 @@ void QDeclarativeAbstractBinding::setEnabled(bool enabled, QDeclarativePropertyP if (enabled) update(flags); } +QDeclarativeBinding::Identifier QDeclarativeBinding::Invalid = -1; + void QDeclarativeBindingPrivate::refresh() { Q_Q(QDeclarativeBinding); @@ -238,6 +240,9 @@ QDeclarativeBinding * QDeclarativeBinding::createBinding(Identifier id, QObject *obj, QDeclarativeContext *ctxt, const QString &url, int lineNumber, QObject *parent) { + if (id < 0) + return 0; + QDeclarativeContextData *ctxtdata = QDeclarativeContextData::get(ctxt); QDeclarativeEnginePrivate *engine = QDeclarativeEnginePrivate::get(qmlEngine(obj)); diff --git a/src/declarative/qml/qdeclarativebinding_p.h b/src/declarative/qml/qdeclarativebinding_p.h index 787a3b9..69931d9 100644 --- a/src/declarative/qml/qdeclarativebinding_p.h +++ b/src/declarative/qml/qdeclarativebinding_p.h @@ -163,6 +163,7 @@ public: virtual QString expression() const; typedef int Identifier; + static Identifier Invalid; static QDeclarativeBinding *createBinding(Identifier, QObject *, QDeclarativeContext *, const QString &, int, QObject *parent=0); public Q_SLOTS: diff --git a/src/declarative/util/qdeclarativepropertychanges.cpp b/src/declarative/util/qdeclarativepropertychanges.cpp index 6737382..47f03a1 100644 --- a/src/declarative/util/qdeclarativepropertychanges.cpp +++ b/src/declarative/util/qdeclarativepropertychanges.cpp @@ -220,9 +220,19 @@ public: void decode(); + class ExpressionChange { + public: + ExpressionChange(const QString &_name, + QDeclarativeBinding::Identifier _id, + QDeclarativeExpression *_expr) + : name(_name), id(_id), expression(_expr) {} + QString name; + QDeclarativeBinding::Identifier id; + QDeclarativeExpression *expression; + }; + QList > properties; - QList > expressions; - QList ids; + QList expressions; QList signalReplacements; QDeclarativeProperty property(const QString &); @@ -315,7 +325,7 @@ void QDeclarativePropertyChangesPrivate::decode() QString name; bool isScript; QVariant data; - QDeclarativeBinding::Identifier id; + QDeclarativeBinding::Identifier id = QDeclarativeBinding::Invalid; ds >> name; ds >> isScript; ds >> data; @@ -337,8 +347,7 @@ void QDeclarativePropertyChangesPrivate::decode() QDeclarativeData *ddata = QDeclarativeData::get(q); if (ddata && ddata->outerContext && !ddata->outerContext->url.isEmpty()) expression->setSourceLocation(ddata->outerContext->url.toString(), ddata->lineNumber); - expressions << qMakePair(name, expression); - ids << id; + expressions << ExpressionChange(name, id, expression); } else { properties << qMakePair(name, data); } @@ -366,7 +375,7 @@ QDeclarativePropertyChanges::~QDeclarativePropertyChanges() { Q_D(QDeclarativePropertyChanges); for(int ii = 0; ii < d->expressions.count(); ++ii) - delete d->expressions.at(ii).second; + delete d->expressions.at(ii).expression; for(int ii = 0; ii < d->signalReplacements.count(); ++ii) delete d->signalReplacements.at(ii); } @@ -451,7 +460,7 @@ QDeclarativePropertyChanges::ActionList QDeclarativePropertyChanges::actions() for (int ii = 0; ii < d->expressions.count(); ++ii) { - const QString &property = d->expressions.at(ii).first; + const QString &property = d->expressions.at(ii).name; QDeclarativeProperty prop = d->property(property); if (prop.isValid()) { @@ -463,12 +472,12 @@ QDeclarativePropertyChanges::ActionList QDeclarativePropertyChanges::actions() a.specifiedProperty = property; if (d->isExplicit) { - a.toValue = d->expressions.at(ii).second->evaluate(); + a.toValue = d->expressions.at(ii).expression->evaluate(); } else { - QDeclarativeExpression *e = d->expressions.at(ii).second; + QDeclarativeExpression *e = d->expressions.at(ii).expression; - QDeclarativeBinding::Identifier id = d->ids.at(ii); - QDeclarativeBinding *newBinding = QDeclarativeBinding::createBinding(id, object(), qmlContext(this), e->sourceFile(), e->lineNumber()); + QDeclarativeBinding::Identifier id = d->expressions.at(ii).id; + QDeclarativeBinding *newBinding = id != QDeclarativeBinding::Invalid ? QDeclarativeBinding::createBinding(id, object(), qmlContext(this), e->sourceFile(), e->lineNumber()) : 0; if (!newBinding) { newBinding = new QDeclarativeBinding(e->expression(), object(), qmlContext(this)); newBinding->setSourceLocation(e->sourceFile(), e->lineNumber()); @@ -535,12 +544,12 @@ bool QDeclarativePropertyChanges::containsValue(const QString &name) const bool QDeclarativePropertyChanges::containsExpression(const QString &name) const { Q_D(const QDeclarativePropertyChanges); - typedef QPair ExpressionEntry; + typedef QDeclarativePropertyChangesPrivate::ExpressionChange ExpressionEntry; QListIterator expressionIterator(d->expressions); while (expressionIterator.hasNext()) { const ExpressionEntry &entry = expressionIterator.next(); - if (entry.first == name) { + if (entry.name == name) { return true; } } @@ -557,12 +566,12 @@ void QDeclarativePropertyChanges::changeValue(const QString &name, const QVarian { Q_D(QDeclarativePropertyChanges); typedef QPair PropertyEntry; - typedef QPair ExpressionEntry; + typedef QDeclarativePropertyChangesPrivate::ExpressionChange ExpressionEntry; QMutableListIterator expressionIterator(d->expressions); while (expressionIterator.hasNext()) { const ExpressionEntry &entry = expressionIterator.next(); - if (entry.first == name) { + if (entry.name == name) { expressionIterator.remove(); if (state() && state()->isStateActive()) { QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::binding(d->property(name)); @@ -611,7 +620,7 @@ void QDeclarativePropertyChanges::changeExpression(const QString &name, const QS { Q_D(QDeclarativePropertyChanges); typedef QPair PropertyEntry; - typedef QPair ExpressionEntry; + typedef QDeclarativePropertyChangesPrivate::ExpressionChange ExpressionEntry; bool hadValue = false; @@ -628,8 +637,8 @@ void QDeclarativePropertyChanges::changeExpression(const QString &name, const QS QMutableListIterator expressionIterator(d->expressions); while (expressionIterator.hasNext()) { const ExpressionEntry &entry = expressionIterator.next(); - if (entry.first == name) { - entry.second->setExpression(expression); + if (entry.name == name) { + entry.expression->setExpression(expression); if (state() && state()->isStateActive()) { QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::binding(d->property(name)); if (oldBinding) { @@ -646,7 +655,7 @@ void QDeclarativePropertyChanges::changeExpression(const QString &name, const QS } QDeclarativeExpression *newExpression = new QDeclarativeExpression(qmlContext(this), d->object, expression); - expressionIterator.insert(ExpressionEntry(name, newExpression)); + expressionIterator.insert(ExpressionEntry(name, QDeclarativeBinding::Invalid, newExpression)); if (state() && state()->isStateActive()) { if (hadValue) { @@ -692,7 +701,7 @@ QVariant QDeclarativePropertyChanges::property(const QString &name) const { Q_D(const QDeclarativePropertyChanges); typedef QPair PropertyEntry; - typedef QPair ExpressionEntry; + typedef QDeclarativePropertyChangesPrivate::ExpressionChange ExpressionEntry; QListIterator propertyIterator(d->properties); while (propertyIterator.hasNext()) { @@ -705,8 +714,8 @@ QVariant QDeclarativePropertyChanges::property(const QString &name) const QListIterator expressionIterator(d->expressions); while (expressionIterator.hasNext()) { const ExpressionEntry &entry = expressionIterator.next(); - if (entry.first == name) { - return QVariant(entry.second->expression()); + if (entry.name == name) { + return QVariant(entry.expression->expression()); } } @@ -717,12 +726,12 @@ void QDeclarativePropertyChanges::removeProperty(const QString &name) { Q_D(QDeclarativePropertyChanges); typedef QPair PropertyEntry; - typedef QPair ExpressionEntry; + typedef QDeclarativePropertyChangesPrivate::ExpressionChange ExpressionEntry; QMutableListIterator expressionIterator(d->expressions); while (expressionIterator.hasNext()) { const ExpressionEntry &entry = expressionIterator.next(); - if (entry.first == name) { + if (entry.name == name) { expressionIterator.remove(); state()->removeEntryFromRevertList(object(), name); return; @@ -759,13 +768,13 @@ QVariant QDeclarativePropertyChanges::value(const QString &name) const QString QDeclarativePropertyChanges::expression(const QString &name) const { Q_D(const QDeclarativePropertyChanges); - typedef QPair ExpressionEntry; + typedef QDeclarativePropertyChangesPrivate::ExpressionChange ExpressionEntry; QListIterator expressionIterator(d->expressions); while (expressionIterator.hasNext()) { const ExpressionEntry &entry = expressionIterator.next(); - if (entry.first == name) { - return entry.second->expression(); + if (entry.name == name) { + return entry.expression->expression(); } } -- cgit v0.12 From 956c026be3f0a701024aaa466e158a3744284a83 Mon Sep 17 00:00:00 2001 From: Christopher Ham Date: Tue, 21 Dec 2010 17:05:04 +1000 Subject: ContentX and ContentY reset on flow change The gridView should be visible when the flow is changed, regardless of the content position before the flow change. Task-number: QTBUG-16230 Reviewed-by: Martin Jones --- src/declarative/graphicsitems/qdeclarativegridview.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/declarative/graphicsitems/qdeclarativegridview.cpp b/src/declarative/graphicsitems/qdeclarativegridview.cpp index 4a6a9dc..5aa88b5 100644 --- a/src/declarative/graphicsitems/qdeclarativegridview.cpp +++ b/src/declarative/graphicsitems/qdeclarativegridview.cpp @@ -1606,6 +1606,8 @@ void QDeclarativeGridView::setFlow(Flow flow) setContentHeight(-1); setFlickableDirection(QDeclarativeFlickable::HorizontalFlick); } + setContentX(0); + setContentY(0); d->clear(); d->updateGrid(); refill(); -- cgit v0.12 From 5af714b2f1ec9dd85707809397751128c95a93bf Mon Sep 17 00:00:00 2001 From: Christopher Ham Date: Tue, 21 Dec 2010 17:23:46 +1000 Subject: Adding autotest coverage to QDecalarativeGridView Tests added for snapping, and adding coverage for TopToBottom flow Reviewed-by: Martin Jones --- .../tst_qdeclarativegridview.cpp | 92 ++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp b/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp index fd5d140..bd9885d 100644 --- a/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp +++ b/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp @@ -78,6 +78,7 @@ private slots: void componentChanges(); void modelChanges(); void positionViewAtIndex(); + void snapping(); void resetModel(); void enforceRange(); void QTBUG_8456(); @@ -993,6 +994,7 @@ void tst_QDeclarativeGridView::positionViewAtIndex() // Position on a currently visible item gridview->positionViewAtIndex(4, QDeclarativeGridView::Beginning); + QTRY_COMPARE(gridview->indexAt(120, 90), 4); QTRY_COMPARE(gridview->contentY(), 60.); // Confirm items positioned correctly @@ -1007,6 +1009,7 @@ void tst_QDeclarativeGridView::positionViewAtIndex() // Position on an item beyond the visible items gridview->positionViewAtIndex(21, QDeclarativeGridView::Beginning); + QTRY_COMPARE(gridview->indexAt(40, 450), 21); QTRY_COMPARE(gridview->contentY(), 420.); // Confirm items positioned correctly @@ -1021,6 +1024,7 @@ void tst_QDeclarativeGridView::positionViewAtIndex() // Position on an item that would leave empty space if positioned at the top gridview->positionViewAtIndex(31, QDeclarativeGridView::Beginning); + QTRY_COMPARE(gridview->indexAt(120, 630), 31); QTRY_COMPARE(gridview->contentY(), 520.); // Confirm items positioned correctly @@ -1035,6 +1039,9 @@ void tst_QDeclarativeGridView::positionViewAtIndex() // Position at the beginning again gridview->positionViewAtIndex(0, QDeclarativeGridView::Beginning); + QTRY_COMPARE(gridview->indexAt(0, 0), 0); + QTRY_COMPARE(gridview->indexAt(40, 30), 0); + QTRY_COMPARE(gridview->indexAt(80, 60), 4); QTRY_COMPARE(gridview->contentY(), 0.); // Confirm items positioned correctly @@ -1088,6 +1095,82 @@ void tst_QDeclarativeGridView::positionViewAtIndex() gridview->positionViewAtIndex(20, QDeclarativeGridView::Contain); QTRY_COMPARE(gridview->contentY(), 100.); + // Test for Top To Bottom layout + ctxt->setContextProperty("testTopToBottom", QVariant(true)); + + // Confirm items positioned correctly + itemCount = findItems(contentItem, "wrapper").count(); + for (int i = 0; i < model.count() && i < itemCount-1; ++i) { + QDeclarativeItem *item = findItem(contentItem, "wrapper", i); + if (!item) qWarning() << "Item" << i << "not found"; + QTRY_VERIFY(item); + QTRY_COMPARE(item->x(), (i/5)*80.); + QTRY_COMPARE(item->y(), (i%5)*60.); + } + + // Position at End + gridview->positionViewAtIndex(30, QDeclarativeGridView::End); + QTRY_COMPARE(gridview->contentX(), 320.); + QTRY_COMPARE(gridview->contentY(), 0.); + + // Position in Center + gridview->positionViewAtIndex(15, QDeclarativeGridView::Center); + QTRY_COMPARE(gridview->contentX(), 160.); + + // Ensure at least partially visible + gridview->positionViewAtIndex(15, QDeclarativeGridView::Visible); + QTRY_COMPARE(gridview->contentX(), 160.); + + gridview->setContentX(170); + gridview->positionViewAtIndex(25, QDeclarativeGridView::Visible); + QTRY_COMPARE(gridview->contentX(), 170.); + + gridview->positionViewAtIndex(30, QDeclarativeGridView::Visible); + QTRY_COMPARE(gridview->contentX(), 320.); + + gridview->setContentX(170); + gridview->positionViewAtIndex(25, QDeclarativeGridView::Contain); + QTRY_COMPARE(gridview->contentX(), 240.); + + delete canvas; +} + +void tst_QDeclarativeGridView::snapping() +{ + 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); + ctxt->setContextProperty("testTopToBottom", QVariant(false)); + + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview1.qml")); + qApp->processEvents(); + + QDeclarativeGridView *gridview = findItem(canvas->rootObject(), "grid"); + QTRY_VERIFY(gridview != 0); + + gridview->setHeight(220); + QCOMPARE(gridview->height(), 220.); + + gridview->positionViewAtIndex(12, QDeclarativeGridView::Visible); + QCOMPARE(gridview->contentY(), 80.); + + gridview->setContentY(0); + QCOMPARE(gridview->contentY(), 0.); + + gridview->setSnapMode(QDeclarativeGridView::SnapToRow); + QCOMPARE(gridview->snapMode(), QDeclarativeGridView::SnapToRow); + + gridview->positionViewAtIndex(12, QDeclarativeGridView::Visible); + QCOMPARE(gridview->contentY(), 60.); + + gridview->positionViewAtIndex(15, QDeclarativeGridView::End); + QCOMPARE(gridview->contentY(), 120.); + delete canvas; } @@ -1231,6 +1314,15 @@ void tst_QDeclarativeGridView::manualHighlight() QTRY_COMPARE(gridview->currentItem(), findItem(contentItem, "wrapper", 2)); QTRY_COMPARE(gridview->highlightItem()->y() - 5, gridview->currentItem()->y()); QTRY_COMPARE(gridview->highlightItem()->x() - 5, gridview->currentItem()->x()); + + gridview->setFlow(QDeclarativeGridView::TopToBottom); + QTRY_COMPARE(gridview->flow(), QDeclarativeGridView::TopToBottom); + + gridview->setCurrentIndex(0); + QTRY_COMPARE(gridview->currentIndex(), 0); + QTRY_COMPARE(gridview->currentItem(), findItem(contentItem, "wrapper", 0)); + QTRY_COMPARE(gridview->highlightItem()->y() - 5, gridview->currentItem()->y()); + QTRY_COMPARE(gridview->highlightItem()->x() - 5, gridview->currentItem()->x()); } void tst_QDeclarativeGridView::footer() -- cgit v0.12 From 111e306c9991a0d89b0001b476e466891974945f Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Tue, 21 Dec 2010 09:12:58 +0100 Subject: QDeclarativeDebug: Remove unused file Got added in 5336e1838a95d97. --- src/declarative/debugger/debugger.pri | 1 - src/declarative/debugger/qdeclarativedebugserverplugin_p.h | 0 2 files changed, 1 deletion(-) delete mode 100644 src/declarative/debugger/qdeclarativedebugserverplugin_p.h diff --git a/src/declarative/debugger/debugger.pri b/src/declarative/debugger/debugger.pri index 9152677..75287b4 100644 --- a/src/declarative/debugger/debugger.pri +++ b/src/declarative/debugger/debugger.pri @@ -19,6 +19,5 @@ HEADERS += \ $$PWD/qdeclarativedebug_p.h \ $$PWD/qdeclarativedebugtrace_p.h \ $$PWD/qdeclarativedebughelper_p.h \ - $$PWD/qdeclarativedebugserverplugin_p.h \ $$PWD/qdeclarativedebugserver_p.h \ debugger/qdeclarativedebugserverconnection_p.h diff --git a/src/declarative/debugger/qdeclarativedebugserverplugin_p.h b/src/declarative/debugger/qdeclarativedebugserverplugin_p.h deleted file mode 100644 index e69de29..0000000 -- cgit v0.12 From 042e797a21a88ccafbaf54bbcfbf1e8d75b33740 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Wed, 22 Dec 2010 10:29:43 +1000 Subject: Optimization: make QDeclarativePropertyPrivate shared. Task-number: QTBUG-15331 Reviewed-by: Aaron Kennedy --- src/declarative/qml/qdeclarativeproperty.cpp | 98 +++++++++++++++++----------- src/declarative/qml/qdeclarativeproperty_p.h | 13 +--- 2 files changed, 64 insertions(+), 47 deletions(-) diff --git a/src/declarative/qml/qdeclarativeproperty.cpp b/src/declarative/qml/qdeclarativeproperty.cpp index 8eaa98b..d7cf6cc 100644 --- a/src/declarative/qml/qdeclarativeproperty.cpp +++ b/src/declarative/qml/qdeclarativeproperty.cpp @@ -106,15 +106,16 @@ qWarning() << "Pixel size should now be 24:" << property.read().toInt(); Create an invalid QDeclarativeProperty. */ QDeclarativeProperty::QDeclarativeProperty() -: d(new QDeclarativePropertyPrivate) +: d(0) { - d->q = this; } /*! \internal */ QDeclarativeProperty::~QDeclarativeProperty() { - delete d; d = 0; + if (d) + d->release(); + d = 0; } /*! @@ -124,7 +125,6 @@ QDeclarativeProperty::~QDeclarativeProperty() QDeclarativeProperty::QDeclarativeProperty(QObject *obj) : d(new QDeclarativePropertyPrivate) { - d->q = this; d->initDefault(obj); } @@ -137,7 +137,6 @@ QDeclarativeProperty::QDeclarativeProperty(QObject *obj) QDeclarativeProperty::QDeclarativeProperty(QObject *obj, QDeclarativeContext *ctxt) : d(new QDeclarativePropertyPrivate) { - d->q = this; d->context = ctxt?QDeclarativeContextData::get(ctxt):0; d->engine = ctxt?ctxt->engine():0; d->initDefault(obj); @@ -152,7 +151,6 @@ QDeclarativeProperty::QDeclarativeProperty(QObject *obj, QDeclarativeContext *ct QDeclarativeProperty::QDeclarativeProperty(QObject *obj, QDeclarativeEngine *engine) : d(new QDeclarativePropertyPrivate) { - d->q = this; d->context = 0; d->engine = engine; d->initDefault(obj); @@ -178,7 +176,6 @@ void QDeclarativePropertyPrivate::initDefault(QObject *obj) QDeclarativeProperty::QDeclarativeProperty(QObject *obj, const QString &name) : d(new QDeclarativePropertyPrivate) { - d->q = this; d->initProperty(obj, name); if (!isValid()) d->object = 0; } @@ -190,7 +187,6 @@ QDeclarativeProperty::QDeclarativeProperty(QObject *obj, const QString &name) QDeclarativeProperty::QDeclarativeProperty(QObject *obj, const QString &name, QDeclarativeContext *ctxt) : d(new QDeclarativePropertyPrivate) { - d->q = this; d->context = ctxt?QDeclarativeContextData::get(ctxt):0; d->engine = ctxt?ctxt->engine():0; d->initProperty(obj, name); @@ -205,7 +201,6 @@ QDeclarativeProperty::QDeclarativeProperty(QObject *obj, const QString &name, QD QDeclarativeProperty::QDeclarativeProperty(QObject *obj, const QString &name, QDeclarativeEngine *engine) : d(new QDeclarativePropertyPrivate) { - d->q = this; d->context = 0; d->engine = engine; d->initProperty(obj, name); @@ -324,9 +319,10 @@ void QDeclarativePropertyPrivate::initProperty(QObject *obj, const QString &name Create a copy of \a other. */ QDeclarativeProperty::QDeclarativeProperty(const QDeclarativeProperty &other) -: d(new QDeclarativePropertyPrivate(*other.d)) { - d->q = this; + d = other.d; + if (d) + d->addref(); } /*! @@ -355,13 +351,13 @@ QDeclarativeProperty::QDeclarativeProperty(const QDeclarativeProperty &other) */ QDeclarativeProperty::PropertyTypeCategory QDeclarativeProperty::propertyTypeCategory() const { - return d->propertyTypeCategory(); + return d ? d->propertyTypeCategory() : InvalidCategory; } QDeclarativeProperty::PropertyTypeCategory QDeclarativePropertyPrivate::propertyTypeCategory() const { - uint type = q->type(); + uint type = this->type(); if (isValueType()) { return QDeclarativeProperty::Normal; @@ -388,6 +384,8 @@ QDeclarativePropertyPrivate::propertyTypeCategory() const */ const char *QDeclarativeProperty::propertyTypeName() const { + if (!d) + return 0; if (d->isValueType()) { QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(d->context); @@ -414,6 +412,8 @@ const char *QDeclarativeProperty::propertyTypeName() const */ bool QDeclarativeProperty::operator==(const QDeclarativeProperty &other) const { + if (!d || !other.d) + return false; // category is intentially omitted here as it is generated // from the other members return d->object == other.d->object && @@ -427,7 +427,7 @@ bool QDeclarativeProperty::operator==(const QDeclarativeProperty &other) const */ int QDeclarativeProperty::propertyType() const { - return d->propertyType(); + return d ? d->propertyType() : QVariant::Invalid; } bool QDeclarativePropertyPrivate::isValueType() const @@ -437,7 +437,7 @@ bool QDeclarativePropertyPrivate::isValueType() const int QDeclarativePropertyPrivate::propertyType() const { - uint type = q->type(); + uint type = this->type(); if (isValueType()) { return valueType.valueTypePropType; } else if (type & QDeclarativeProperty::Property) { @@ -450,17 +450,22 @@ int QDeclarativePropertyPrivate::propertyType() const } } +QDeclarativeProperty::Type QDeclarativePropertyPrivate::type() const +{ + if (core.flags & QDeclarativePropertyCache::Data::IsFunction) + return QDeclarativeProperty::SignalProperty; + else if (core.isValid()) + return QDeclarativeProperty::Property; + else + return QDeclarativeProperty::Invalid; +} + /*! Returns the type of the property. */ QDeclarativeProperty::Type QDeclarativeProperty::type() const { - if (d->core.flags & QDeclarativePropertyCache::Data::IsFunction) - return SignalProperty; - else if (d->core.isValid()) - return Property; - else - return Invalid; + return d ? d->type() : Invalid; } /*! @@ -484,7 +489,7 @@ bool QDeclarativeProperty::isSignalProperty() const */ QObject *QDeclarativeProperty::object() const { - return d->object; + return d ? d->object : 0; } /*! @@ -492,15 +497,11 @@ QObject *QDeclarativeProperty::object() const */ QDeclarativeProperty &QDeclarativeProperty::operator=(const QDeclarativeProperty &other) { - d->context = other.d->context; - d->engine = other.d->engine; - d->object = other.d->object; - - d->isNameCached = other.d->isNameCached; - d->core = other.d->core; - d->nameCache = other.d->nameCache; - - d->valueType = other.d->valueType; + if (d) + d->release(); + d = other.d; + if (d) + d->addref(); return *this; } @@ -510,6 +511,8 @@ QDeclarativeProperty &QDeclarativeProperty::operator=(const QDeclarativeProperty */ bool QDeclarativeProperty::isWritable() const { + if (!d) + return false; if (!d->object) return false; if (d->core.flags & QDeclarativePropertyCache::Data::IsQList) //list @@ -527,6 +530,8 @@ bool QDeclarativeProperty::isWritable() const */ bool QDeclarativeProperty::isDesignable() const { + if (!d) + return false; if (type() & Property && d->core.isValid() && d->object) return d->object->metaObject()->property(d->core.coreIndex).isDesignable(); else @@ -538,6 +543,8 @@ bool QDeclarativeProperty::isDesignable() const */ bool QDeclarativeProperty::isResettable() const { + if (!d) + return false; if (type() & Property && d->core.isValid() && d->object) return d->core.flags & QDeclarativePropertyCache::Data::IsResettable; else @@ -550,6 +557,8 @@ bool QDeclarativeProperty::isResettable() const */ bool QDeclarativeProperty::isValid() const { + if (!d) + return false; return type() != Invalid; } @@ -558,6 +567,8 @@ bool QDeclarativeProperty::isValid() const */ QString QDeclarativeProperty::name() const { + if (!d) + return QString(); if (!d->isNameCached) { // ### if (!d->object) { @@ -594,6 +605,8 @@ QString QDeclarativeProperty::name() const */ QMetaProperty QDeclarativeProperty::property() const { + if (!d) + return QMetaProperty(); if (type() & Property && d->core.isValid() && d->object) return d->object->metaObject()->property(d->core.coreIndex); else @@ -606,6 +619,8 @@ QMetaProperty QDeclarativeProperty::property() const */ QMetaMethod QDeclarativeProperty::method() const { + if (!d) + return QMetaMethod(); if (type() & SignalProperty && d->object) return d->object->metaObject()->method(d->core.coreIndex); else @@ -619,7 +634,7 @@ QMetaMethod QDeclarativeProperty::method() const QDeclarativeAbstractBinding * QDeclarativePropertyPrivate::binding(const QDeclarativeProperty &that) { - if (!that.isProperty() || !that.d->object) + if (!that.d || !that.isProperty() || !that.d->object) return 0; return binding(that.d->object, that.d->core.coreIndex, that.d->valueType.valueTypeCoreIdx); @@ -643,7 +658,7 @@ QDeclarativePropertyPrivate::setBinding(const QDeclarativeProperty &that, QDeclarativeAbstractBinding *newBinding, WriteFlags flags) { - if (!that.isProperty() || !that.d->object) { + if (!that.d || !that.isProperty() || !that.d->object) { if (newBinding) newBinding->destroy(); return 0; @@ -893,6 +908,8 @@ QDeclarativePropertyPrivate::setSignalExpression(const QDeclarativeProperty &tha */ QVariant QDeclarativeProperty::read() const { + if (!d) + return QVariant(); if (!d->object) return QVariant(); @@ -1034,8 +1051,10 @@ bool QDeclarativePropertyPrivate::writeEnumProperty(const QMetaProperty &prop, i bool QDeclarativePropertyPrivate::writeValueProperty(const QVariant &value, WriteFlags flags) { // Remove any existing bindings on this property - if (!(flags & DontRemoveBinding)) { - QDeclarativeAbstractBinding *binding = setBinding(*q, 0); + if (!(flags & DontRemoveBinding) && + (type() & QDeclarativeProperty::Property) && object) { + QDeclarativeAbstractBinding *binding = setBinding(object, core.coreIndex, + valueType.valueTypeCoreIdx, 0, flags); if (binding) binding->destroy(); } @@ -1314,6 +1333,8 @@ bool QDeclarativeProperty::reset() const bool QDeclarativePropertyPrivate::write(const QDeclarativeProperty &that, const QVariant &value, WriteFlags flags) { + if (!that.d) + return false; if (that.d->object && that.type() & QDeclarativeProperty::Property && that.d->core.isValid() && that.isWritable()) return that.d->writeValueProperty(value, flags); @@ -1392,12 +1413,12 @@ bool QDeclarativeProperty::connectNotifySignal(QObject *dest, const char *slot) */ int QDeclarativeProperty::index() const { - return d->core.coreIndex; + return d ? d->core.coreIndex : -1; } int QDeclarativePropertyPrivate::valueTypeCoreIndex(const QDeclarativeProperty &that) { - return that.d->valueType.valueTypeCoreIdx; + return that.d ? that.d->valueType.valueTypeCoreIdx : -1; } /*! @@ -1406,6 +1427,8 @@ int QDeclarativePropertyPrivate::valueTypeCoreIndex(const QDeclarativeProperty & */ int QDeclarativePropertyPrivate::bindingIndex(const QDeclarativeProperty &that) { + if (!that.d) + return -1; int rv = that.d->core.coreIndex; if (rv != -1 && that.d->valueType.valueTypeCoreIdx != -1) rv = rv | (that.d->valueType.valueTypeCoreIdx << 24); @@ -1457,6 +1480,7 @@ QDeclarativePropertyPrivate::restore(const QByteArray &data, QObject *object, QD if (data.isEmpty()) return prop; + prop.d = new QDeclarativePropertyPrivate; prop.d->object = object; prop.d->context = ctxt; prop.d->engine = ctxt->engine; diff --git a/src/declarative/qml/qdeclarativeproperty_p.h b/src/declarative/qml/qdeclarativeproperty_p.h index 6392f88..f7d24f1 100644 --- a/src/declarative/qml/qdeclarativeproperty_p.h +++ b/src/declarative/qml/qdeclarativeproperty_p.h @@ -65,23 +65,15 @@ QT_BEGIN_NAMESPACE class QDeclarativeContext; class QDeclarativeEnginePrivate; class QDeclarativeExpression; -class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativePropertyPrivate +class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativePropertyPrivate : public QDeclarativeRefCount { public: enum WriteFlag { BypassInterceptor = 0x01, DontRemoveBinding = 0x02, RemoveBindingOnAliasWrite = 0x04 }; Q_DECLARE_FLAGS(WriteFlags, WriteFlag) QDeclarativePropertyPrivate() - : q(0), context(0), engine(0), object(0), isNameCached(false) {} - + : context(0), engine(0), object(0), isNameCached(false) {} - QDeclarativePropertyPrivate(const QDeclarativePropertyPrivate &other) - : q(0), context(other.context), engine(other.engine), object(other.object), - isNameCached(other.isNameCached), - core(other.core), nameCache(other.nameCache), - valueType(other.valueType) {} - - QDeclarativeProperty *q; QDeclarativeContextData *context; QDeclarativeEngine *engine; QDeclarativeGuard object; @@ -98,6 +90,7 @@ public: bool isValueType() const; int propertyType() const; + QDeclarativeProperty::Type type() const; QDeclarativeProperty::PropertyTypeCategory propertyTypeCategory() const; QVariant readValueProperty(); -- cgit v0.12 From 2de60ba30f86a9dd338359f7269b62ca5d0a2c46 Mon Sep 17 00:00:00 2001 From: Joona Petrell Date: Thu, 30 Dec 2010 17:16:16 +1000 Subject: Forward qmlviewer traces to system's default message handler on Symbian Task-number: QTBUG-16353 Reviewed-by: Christopher Ham --- tools/qml/main.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tools/qml/main.cpp b/tools/qml/main.cpp index b9513b9..2df96c0 100644 --- a/tools/qml/main.cpp +++ b/tools/qml/main.cpp @@ -88,6 +88,9 @@ void myMessageOutput(QtMsgType type, const char *msg) ::write(fd, "\n", 1); ::fsync(fd); + if (systemMsgOutput) + systemMsgOutput(type, msg); + switch (type) { case QtFatalMsg: abort(); @@ -529,11 +532,7 @@ QDeclarativeViewer *openFile(const QString &fileName) int main(int argc, char ** argv) { -#if defined (Q_OS_SYMBIAN) - qInstallMsgHandler(myMessageOutput); -#else systemMsgOutput = qInstallMsgHandler(myMessageOutput); -#endif #if defined (Q_WS_X11) || defined (Q_WS_MAC) //### default to using raster graphics backend for now -- cgit v0.12 From 22daf9fbdfaa859db6414d39d9354e7d46f63005 Mon Sep 17 00:00:00 2001 From: Joona Petrell Date: Thu, 30 Dec 2010 17:52:30 +1000 Subject: Add convenience deselect() functions to TextInput and TextEdit Task-number: QTBUG-16059 Reviewed-by: Christopher Ham --- src/declarative/graphicsitems/qdeclarativetextedit.cpp | 13 +++++++++++++ src/declarative/graphicsitems/qdeclarativetextedit_p.h | 1 + src/declarative/graphicsitems/qdeclarativetextinput.cpp | 11 +++++++++++ src/declarative/graphicsitems/qdeclarativetextinput_p.h | 1 + .../qdeclarativetextedit/tst_qdeclarativetextedit.cpp | 7 +++++++ .../qdeclarativetextinput/tst_qdeclarativetextinput.cpp | 7 +++++++ 6 files changed, 40 insertions(+) diff --git a/src/declarative/graphicsitems/qdeclarativetextedit.cpp b/src/declarative/graphicsitems/qdeclarativetextedit.cpp index f37fa62..c1314ff 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextedit.cpp @@ -996,6 +996,19 @@ void QDeclarativeTextEditPrivate::focusChanged(bool hasFocus) } /*! + \qmlmethod void TextEdit::deselect() + + Removes active text selection. +*/ +void QDeclarativeTextEdit::deselect() +{ + Q_D(QDeclarativeTextEdit); + QTextCursor c = d->control->textCursor(); + c.clearSelection(); + d->control->setTextCursor(c); +} + +/*! \qmlmethod void TextEdit::selectAll() Causes all text to be selected. diff --git a/src/declarative/graphicsitems/qdeclarativetextedit_p.h b/src/declarative/graphicsitems/qdeclarativetextedit_p.h index 7f12c85..691d995 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextedit_p.h @@ -223,6 +223,7 @@ Q_SIGNALS: void selectByMouseChanged(bool selectByMouse); public Q_SLOTS: + void deselect(); void selectAll(); void selectWord(); void select(int start, int end); diff --git a/src/declarative/graphicsitems/qdeclarativetextinput.cpp b/src/declarative/graphicsitems/qdeclarativetextinput.cpp index 4649be8..4e1c297 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextinput.cpp @@ -1166,6 +1166,17 @@ QVariant QDeclarativeTextInput::inputMethodQuery(Qt::InputMethodQuery property) } /*! + \qmlmethod void TextInput::deselect() + + Removes active text selection. +*/ +void QDeclarativeTextInput::deselect() +{ + Q_D(QDeclarativeTextInput); + d->control->deselect(); +} + +/*! \qmlmethod void TextInput::selectAll() Causes all text to be selected. diff --git a/src/declarative/graphicsitems/qdeclarativetextinput_p.h b/src/declarative/graphicsitems/qdeclarativetextinput_p.h index 06f77e5..878f040 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextinput_p.h @@ -231,6 +231,7 @@ protected: void focusInEvent(QFocusEvent *event); public Q_SLOTS: + void deselect(); void selectAll(); void selectWord(); void select(int start, int end); diff --git a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp index a7971cc..c0bb46e 100644 --- a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp +++ b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp @@ -689,6 +689,13 @@ void tst_qdeclarativetextedit::selection() QVERIFY(textEditObject->selectedText().size() == 10); textEditObject->select(0,100); QVERIFY(textEditObject->selectedText().size() == 10); + + textEditObject->deselect(); + QVERIFY(textEditObject->selectedText().isNull()); + textEditObject->select(0,10); + QVERIFY(textEditObject->selectedText().size() == 10); + textEditObject->deselect(); + QVERIFY(textEditObject->selectedText().isNull()); } void tst_qdeclarativetextedit::mouseSelection_data() diff --git a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp index 76e0102..589ffa6 100644 --- a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp +++ b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp @@ -392,6 +392,13 @@ void tst_qdeclarativetextinput::selection() textinputObject->select(0,100); QVERIFY(textinputObject->selectedText().size() == 10); + textinputObject->deselect(); + QVERIFY(textinputObject->selectedText().isNull()); + textinputObject->select(0,10); + QVERIFY(textinputObject->selectedText().size() == 10); + textinputObject->deselect(); + QVERIFY(textinputObject->selectedText().isNull()); + delete textinputObject; } -- cgit v0.12 From e8b736c44426fd4ae832e82a9e624c9737a40213 Mon Sep 17 00:00:00 2001 From: Joona Petrell Date: Fri, 31 Dec 2010 11:28:08 +1000 Subject: Use deselect() function in text selection example Task-number: QTBUG-16059 Reviewed-by: Christopher Ham --- examples/declarative/text/textselection/textselection.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/declarative/text/textselection/textselection.qml b/examples/declarative/text/textselection/textselection.qml index f343be5..c6f44a0 100644 --- a/examples/declarative/text/textselection/textselection.qml +++ b/examples/declarative/text/textselection/textselection.qml @@ -265,7 +265,7 @@ Rectangle { anchors.fill: parent onClicked: { edit.cursorPosition = edit.selectionEnd; - edit.select(edit.cursorPosition, edit.cursorPosition); + edit.deselect(); editor.state = "" } } -- cgit v0.12 From 59ec08d255b7d7bd8975bdbfd0b0a42c1b6ed2a0 Mon Sep 17 00:00:00 2001 From: Joona Petrell Date: Fri, 31 Dec 2010 15:49:48 +1000 Subject: Provide qmlviewer warning window also on Symbian Task-number: QTBUG-10800 Reviewed-by: Christopher Ham --- tools/qml/loggerwidget.cpp | 9 +++++++++ tools/qml/main.cpp | 49 ++++++++++++++++++---------------------------- tools/qml/qmlruntime.cpp | 8 +++++++- 3 files changed, 35 insertions(+), 31 deletions(-) diff --git a/tools/qml/loggerwidget.cpp b/tools/qml/loggerwidget.cpp index 8aa029f..f601d95 100644 --- a/tools/qml/loggerwidget.cpp +++ b/tools/qml/loggerwidget.cpp @@ -64,6 +64,14 @@ LoggerWidget::LoggerWidget(QWidget *parent) : m_plainTextEdit = new QPlainTextEdit(); +#if defined(Q_OS_SYMBIAN) + m_plainTextEdit->setReadOnly(true); + QAction* backAction = new QAction( tr("Back"), this ); + backAction->setSoftKeyRole( QAction::NegativeSoftKey ); + connect(backAction, SIGNAL(triggered()), this, SLOT(hide())); + addAction( backAction ); +#endif + #ifdef Q_WS_MAEMO_5 new TextEditAutoResizer(m_plainTextEdit); setAttribute(Qt::WA_Maemo5StackedWindow); @@ -74,6 +82,7 @@ LoggerWidget::LoggerWidget(QWidget *parent) : #else setCentralWidget(m_plainTextEdit); #endif + readSettings(); setupPreferencesMenu(); } diff --git a/tools/qml/main.cpp b/tools/qml/main.cpp index 2df96c0..b5a4fd0 100644 --- a/tools/qml/main.cpp +++ b/tools/qml/main.cpp @@ -72,36 +72,15 @@ void exitApp(int i) exit(i); } +QWeakPointer logger; +static QAtomicInt recursiveLock(0); + #if defined (Q_OS_SYMBIAN) #include #include #include #include - -void myMessageOutput(QtMsgType type, const char *msg) -{ - static int fd = -1; - if (fd == -1) - fd = ::open("E:\\qml.log", O_WRONLY | O_CREAT); - - ::write(fd, msg, strlen(msg)); - ::write(fd, "\n", 1); - ::fsync(fd); - - if (systemMsgOutput) - systemMsgOutput(type, msg); - - switch (type) { - case QtFatalMsg: - abort(); - } -} - -#else // !defined (Q_OS_SYMBIAN) - -QWeakPointer logger; - -static QAtomicInt recursiveLock(0); +#endif void myMessageOutput(QtMsgType type, const char *msg) { @@ -118,7 +97,21 @@ void myMessageOutput(QtMsgType type, const char *msg) warnings += QLatin1Char('\n'); } } - if (systemMsgOutput) { // Windows +#if defined (Q_OS_SYMBIAN) + static int fd = -1; + if (fd == -1) + fd = ::open("E:\\qml.log", O_WRONLY | O_CREAT); + + ::write(fd, msg, strlen(msg)); + ::write(fd, "\n", 1); + ::fsync(fd); + switch (type) { + case QtFatalMsg: + abort(); + } +#endif + + if (systemMsgOutput) { systemMsgOutput(type, msg); } else { // Unix fprintf(stderr, "%s\n", msg); @@ -126,8 +119,6 @@ void myMessageOutput(QtMsgType type, const char *msg) } } -#endif - static QDeclarativeViewer* globalViewer = 0; // The qml file that is shown if the user didn't specify a QML file @@ -472,7 +463,6 @@ static QDeclarativeViewer *createViewer() viewer->setScript(opts.script); } -#if !defined(Q_OS_SYMBIAN) logger = viewer->warningsWidget(); if (opts.warningsConfig == ShowWarnings) { logger.data()->setDefaultVisibility(LoggerWidget::ShowWarnings); @@ -480,7 +470,6 @@ static QDeclarativeViewer *createViewer() } else if (opts.warningsConfig == HideWarnings){ logger.data()->setDefaultVisibility(LoggerWidget::HideWarnings); } -#endif if (opts.experimentalGestures) viewer->enableExperimentalGestures(); diff --git a/tools/qml/qmlruntime.cpp b/tools/qml/qmlruntime.cpp index 142e4c5..b829528 100644 --- a/tools/qml/qmlruntime.cpp +++ b/tools/qml/qmlruntime.cpp @@ -742,8 +742,10 @@ void QDeclarativeViewer::createMenu() connect(slowAction, SIGNAL(triggered(bool)), this, SLOT(setSlowMode(bool))); showWarningsWindow = new QAction(tr("Show Warnings"), this); +#if !defined(Q_OS_SYMBIAN) showWarningsWindow->setCheckable((true)); showWarningsWindow->setChecked(loggerWindow->isVisible()); +#endif connect(showWarningsWindow, SIGNAL(triggered(bool)), this, SLOT(showWarnings(bool))); QAction *proxyAction = new QAction(tr("HTTP &Proxy..."), this); @@ -826,11 +828,11 @@ void QDeclarativeViewer::createMenu() QMenu *recordMenu = menu->addMenu(tr("&Recording")); recordMenu->addAction(snapshotAction); recordMenu->addAction(recordAction); +#endif // ! Q_OS_SYMBIAN QMenu *debugMenu = menu->addMenu(tr("&Debugging")); debugMenu->addAction(slowAction); debugMenu->addAction(showWarningsWindow); -#endif // ! Q_OS_SYMBIAN QMenu *settingsMenu = menu->addMenu(tr("&Settings")); settingsMenu->addAction(proxyAction); @@ -914,7 +916,11 @@ void QDeclarativeViewer::toggleFullScreen() void QDeclarativeViewer::showWarnings(bool show) { +#if defined(Q_OS_SYMBIAN) + loggerWindow->showMaximized(); +#else loggerWindow->setVisible(show); +#endif } void QDeclarativeViewer::warningsWidgetOpened() -- cgit v0.12 From 086f33dd4c70be03adcbc1703997afa27add920b Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Tue, 4 Jan 2011 15:03:53 +1000 Subject: Fix results of number() queries for zero and non-number values Use xs:string() to test whether a value is empty, instead of using a simple boolean check which fails for zero-type values. This fix also means 'NaN' is returned for non-number (including empty) values. Task-number: QTBUG-16423, QTBUG-16265 Reviewed-by: Michael Brasser --- src/declarative/util/qdeclarativexmllistmodel.cpp | 2 +- .../qdeclarativexmllistmodel/data/model2.qml | 11 ---- .../tst_qdeclarativexmllistmodel.cpp | 76 ++++++++++++++++++---- 3 files changed, 64 insertions(+), 25 deletions(-) delete mode 100644 tests/auto/declarative/qdeclarativexmllistmodel/data/model2.qml diff --git a/src/declarative/util/qdeclarativexmllistmodel.cpp b/src/declarative/util/qdeclarativexmllistmodel.cpp index 49a12b1..f5c3ad4 100644 --- a/src/declarative/util/qdeclarativexmllistmodel.cpp +++ b/src/declarative/util/qdeclarativexmllistmodel.cpp @@ -382,7 +382,7 @@ void QDeclarativeXmlQuery::doSubQueryJob() for (int i = 0; i < queries.size(); ++i) { QList resultList; if (!queries[i].isEmpty()) { - subquery.setQuery(m_prefix + QLatin1String("(let $v := ") + queries[i] + QLatin1String(" return if ($v) then ") + queries[i] + QLatin1String(" else \"\")")); + subquery.setQuery(m_prefix + QLatin1String("(let $v := string(") + queries[i] + QLatin1String(") return if ($v) then ") + queries[i] + QLatin1String(" else \"\")")); if (subquery.isValid()) { QXmlResultItems resultItems; subquery.evaluateTo(&resultItems); diff --git a/tests/auto/declarative/qdeclarativexmllistmodel/data/model2.qml b/tests/auto/declarative/qdeclarativexmllistmodel/data/model2.qml deleted file mode 100644 index e56aafa..0000000 --- a/tests/auto/declarative/qdeclarativexmllistmodel/data/model2.qml +++ /dev/null @@ -1,11 +0,0 @@ -import QtQuick 1.0 - -XmlListModel { - source: "model.xml" - query: "/Pets/Pet" - XmlRole { name: "name"; query: "name/string()" } - XmlRole { name: "type"; query: "type/string()" } - XmlRole { name: "age"; query: "age/number()" } - XmlRole { name: "size"; query: "size/string()" } - XmlRole { name: "tricks"; query: "tricks/string()" } -} diff --git a/tests/auto/declarative/qdeclarativexmllistmodel/tst_qdeclarativexmllistmodel.cpp b/tests/auto/declarative/qdeclarativexmllistmodel/tst_qdeclarativexmllistmodel.cpp index a14f942..3e81c53 100644 --- a/tests/auto/declarative/qdeclarativexmllistmodel/tst_qdeclarativexmllistmodel.cpp +++ b/tests/auto/declarative/qdeclarativexmllistmodel/tst_qdeclarativexmllistmodel.cpp @@ -38,6 +38,12 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#include + +#include +#include +#include + #include #include #include @@ -75,7 +81,8 @@ private slots: } void buildModel(); - void missingFields(); + void testTypes(); + void testTypes_data(); void cdata(); void attributes(); void roles(); @@ -158,27 +165,70 @@ void tst_qdeclarativexmllistmodel::buildModel() delete model; } -void tst_qdeclarativexmllistmodel::missingFields() +void tst_qdeclarativexmllistmodel::testTypes() { - QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/model2.qml")); + QFETCH(QString, xml); + QFETCH(QString, roleName); + QFETCH(QVariant, expectedValue); + + QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/testtypes.qml")); QDeclarativeXmlListModel *model = qobject_cast(component.create()); QVERIFY(model != 0); - QTRY_COMPARE(model->count(), 9); + model->setXml(xml.toUtf8()); + model->reload(); + QTRY_COMPARE(model->count(), 1); - QList roles; - roles << Qt::UserRole << Qt::UserRole + 1 << Qt::UserRole + 2 << Qt::UserRole + 3 << Qt::UserRole + 4; - QHash data = model->data(5, roles); - QVERIFY(data.count() == 5); - QCOMPARE(data.value(Qt::UserRole+3).toString(), QLatin1String("")); - QCOMPARE(data.value(Qt::UserRole+4).toString(), QLatin1String("")); + int role = -1; + foreach (int i, model->roles()) { + if (model->toString(i) == roleName) { + role = i; + break; + } + } + QVERIFY(role >= 0); - data = model->data(7, roles); - QVERIFY(data.count() == 5); - QCOMPARE(data.value(Qt::UserRole+2).toString(), QLatin1String("")); + if (expectedValue.toString() == "nan") + QVERIFY(qIsNaN(model->data(0, role).toDouble())); + else + QCOMPARE(model->data(0, role), expectedValue); delete model; } +void tst_qdeclarativexmllistmodel::testTypes_data() +{ + QTest::addColumn("xml"); + QTest::addColumn("roleName"); + QTest::addColumn("expectedValue"); + + QTest::newRow("missing string field") << "" + << "stringValue" << QVariant(""); + QTest::newRow("empty string") << "" + << "stringValue" << QVariant(""); + QTest::newRow("1-char string") << "5" + << "stringValue" << QVariant("5"); + QTest::newRow("string ok") << "abc def g" + << "stringValue" << QVariant("abc def g"); + + QTest::newRow("missing number field") << "" + << "numberValue" << QVariant(""); + double nan = qQNaN(); + QTest::newRow("empty number field") << "" + << "numberValue" << QVariant(nan); + QTest::newRow("number field with string") << "a string" + << "numberValue" << QVariant(nan); + QTest::newRow("-1") << "-1" + << "numberValue" << QVariant("-1"); + QTest::newRow("-1.5") << "-1.5" + << "numberValue" << QVariant("-1.5"); + QTest::newRow("0") << "0" + << "numberValue" << QVariant("0"); + QTest::newRow("+1") << "1" + << "numberValue" << QVariant("1"); + QTest::newRow("+1.5") << "1.5" + << "numberValue" << QVariant("1.5"); +} + void tst_qdeclarativexmllistmodel::cdata() { QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/recipes.qml")); -- cgit v0.12 From 31460847fed4bc0867c3fd78466fed32e407fafb Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Tue, 4 Jan 2011 14:21:26 +1000 Subject: Fix translation in Connections element. Provide the component's file name to the expression as the translation context. Task-number: QTBUG-10300 Reviewed-by: Martin Jones --- src/declarative/util/qdeclarativeconnections.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/declarative/util/qdeclarativeconnections.cpp b/src/declarative/util/qdeclarativeconnections.cpp index 15e5ac5..e102f2c 100644 --- a/src/declarative/util/qdeclarativeconnections.cpp +++ b/src/declarative/util/qdeclarativeconnections.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -257,7 +258,11 @@ void QDeclarativeConnections::connectSignals() if (prop.isValid() && (prop.type() & QDeclarativeProperty::SignalProperty)) { QDeclarativeBoundSignal *signal = new QDeclarativeBoundSignal(target(), prop.method(), this); - signal->setExpression(new QDeclarativeExpression(qmlContext(this), 0, script)); + QDeclarativeExpression *expression = new QDeclarativeExpression(qmlContext(this), 0, script); + QDeclarativeData *ddata = QDeclarativeData::get(this); + if (ddata && ddata->outerContext && !ddata->outerContext->url.isEmpty()) + expression->setSourceLocation(ddata->outerContext->url.toString(), ddata->lineNumber); + signal->setExpression(expression); d->boundsignals += signal; } else { if (!d->ignoreUnknownSignals) -- cgit v0.12 From 7a979f8dab64c33a7088b70ca5bff69b881ee55d Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Wed, 5 Jan 2011 10:40:47 +1000 Subject: Add clarifications to QML SQL docs. Reviewed-by: Bea Lam --- doc/src/declarative/globalobject.qdoc | 7 ++++--- src/declarative/qml/qdeclarativesqldatabase.cpp | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/doc/src/declarative/globalobject.qdoc b/doc/src/declarative/globalobject.qdoc index ffc84f9..ef8de5e 100644 --- a/doc/src/declarative/globalobject.qdoc +++ b/doc/src/declarative/globalobject.qdoc @@ -141,8 +141,9 @@ using the Offline Storage API. \section3 db = openDatabaseSync(identifier, version, description, estimated_size, callback(db)) Returns the database identified by \e identifier. If the database does not already exist, it -is created with the properties \e description and \e estimated_size and the function \e callback -is called with the database as a parameter. +is created, and the function \e callback is called with the database as a parameter. \e description +and \e estimated_size are written to the INI file (described below), but are otherwise currently +unused. May throw exception with code property SQLException.DATABASE_ERR, or SQLException.VERSION_ERR. @@ -153,7 +154,7 @@ When a database is first created, an INI file is also created specifying its cha \row \o Name \o The name of the database passed to \c openDatabase() \row \o Version \o The version of the database passed to \c openDatabase() \row \o Description \o The description of the database passed to \c openDatabase() -\row \o EstimatedSize \o The estimated size of the database passed to \c openDatabase() +\row \o EstimatedSize \o The estimated size (in bytes) of the database passed to \c openDatabase() \row \o Driver \o Currently "QSQLITE" \endtable diff --git a/src/declarative/qml/qdeclarativesqldatabase.cpp b/src/declarative/qml/qdeclarativesqldatabase.cpp index bda02a5..a774c02 100644 --- a/src/declarative/qml/qdeclarativesqldatabase.cpp +++ b/src/declarative/qml/qdeclarativesqldatabase.cpp @@ -351,7 +351,7 @@ static QScriptValue qmlsqldatabase_read_transaction(QScriptContext *context, QSc } /* - Currently documented in doc/src/declarastive/globalobject.qdoc + Currently documented in doc/src/declarative/globalobject.qdoc */ static QScriptValue qmlsqldatabase_open_sync(QScriptContext *context, QScriptEngine *engine) { -- cgit v0.12 From 3f80a24c5d375dd173d18c2a4227301f1afba2e3 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Mon, 6 Dec 2010 14:23:47 +1000 Subject: Allow a revision to be associated with properties and methods. Allows a revision to be associated with properties via: Q_PROPERTY(int prop READ prop1 REVISION 1) Allows a revision to be associated with methods via either: public slots Q_REVISION(1): void method1(); or: public slots: Q_REVISION void method1(); Private revision() methods are added to QMetaProperty and QMetaMethod to access the revision info. This is private API for use by QML for now. Task-number: QTBUG-13451 Reviewed-by: Kent Hansen --- src/corelib/kernel/qmetaobject.cpp | 48 +++++++++++++ src/corelib/kernel/qmetaobject.h | 3 + src/corelib/kernel/qmetaobject_p.h | 6 +- src/corelib/kernel/qobjectdefs.h | 2 + src/tools/moc/generator.cpp | 36 +++++++++- src/tools/moc/generator.h | 1 + src/tools/moc/keywords.cpp | 20 ++++-- src/tools/moc/moc.cpp | 82 ++++++++++++++++++++-- src/tools/moc/moc.h | 13 +++- src/tools/moc/token.cpp | 1 + src/tools/moc/token.h | 1 + src/tools/moc/util/generate_keywords.cpp | 1 + tests/auto/moc/tst_moc.cpp | 113 +++++++++++++++++++++++++++++++ 13 files changed, 311 insertions(+), 16 deletions(-) diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 9854e68..dd5f231 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -1369,6 +1369,25 @@ int QMetaMethod::methodIndex() const } /*! + \internal + + Returns the method revision if one was + specified by Q_REVISION, otherwise returns 0. + */ +int QMetaMethod::revision() const +{ + if (!mobj) + return 0; + if ((QMetaMethod::Access)(mobj->d.data[handle + 4] & MethodRevisioned)) { + int offset = priv(mobj->d.data)->methodData + + priv(mobj->d.data)->methodCount * 5 + + (handle - priv(mobj->d.data)->methodData) / 5; + return mobj->d.data[offset]; + } + return 0; +} + +/*! Returns the access specification of this method (private, protected, or public). @@ -2389,6 +2408,35 @@ int QMetaProperty::notifySignalIndex() const } /*! + \internal + + Returns the property revision if one was + specified by REVISION, otherwise returns 0. + */ +int QMetaProperty::revision() const +{ + if (!mobj) + return 0; + int flags = mobj->d.data[handle + 2]; + if (flags & Revisioned) { + int offset = priv(mobj->d.data)->propertyData + + priv(mobj->d.data)->propertyCount * 3 + idx; + // Revision data is placed after NOTIFY data, if present. + // Iterate through properties to discover whether we have NOTIFY signals. + for (int i = 0; i < priv(mobj->d.data)->propertyCount; ++i) { + int handle = priv(mobj->d.data)->propertyData + 3*i; + if (mobj->d.data[handle + 2] & Notify) { + offset += priv(mobj->d.data)->propertyCount; + break; + } + } + return mobj->d.data[offset]; + } else { + return 0; + } +} + +/*! Returns true if this property is writable; otherwise returns false. diff --git a/src/corelib/kernel/qmetaobject.h b/src/corelib/kernel/qmetaobject.h index b700351..1ab08ee 100644 --- a/src/corelib/kernel/qmetaobject.h +++ b/src/corelib/kernel/qmetaobject.h @@ -70,6 +70,7 @@ public: enum Attributes { Compatibility = 0x1, Cloned = 0x2, Scriptable = 0x4 }; int attributes() const; int methodIndex() const; + int revision() const; inline const QMetaObject *enclosingMetaObject() const { return mobj; } @@ -200,6 +201,8 @@ public: QMetaMethod notifySignal() const; int notifySignalIndex() const; + int revision() const; + QVariant read(const QObject *obj) const; bool write(QObject *obj, const QVariant &value) const; bool reset(QObject *obj) const; diff --git a/src/corelib/kernel/qmetaobject_p.h b/src/corelib/kernel/qmetaobject_p.h index 4a03874..7b103e2 100644 --- a/src/corelib/kernel/qmetaobject_p.h +++ b/src/corelib/kernel/qmetaobject_p.h @@ -78,7 +78,8 @@ enum PropertyFlags { ResolveEditable = 0x00080000, User = 0x00100000, ResolveUser = 0x00200000, - Notify = 0x00400000 + Notify = 0x00400000, + Revisioned = 0x00800000 }; enum MethodFlags { @@ -95,7 +96,8 @@ enum MethodFlags { MethodCompatibility = 0x10, MethodCloned = 0x20, - MethodScriptable = 0x40 + MethodScriptable = 0x40, + MethodRevisioned = 0x80 }; enum MetaObjectFlags { diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h index 555a1f5..d1a8f06 100644 --- a/src/corelib/kernel/qobjectdefs.h +++ b/src/corelib/kernel/qobjectdefs.h @@ -79,6 +79,7 @@ class QString; #define Q_INTERFACES(x) #define Q_PROPERTY(text) #define Q_PRIVATE_PROPERTY(d, text) +#define Q_REVISION(v) #define Q_OVERRIDE(text) #define Q_ENUMS(x) #define Q_FLAGS(x) @@ -180,6 +181,7 @@ private: #define Q_INTERFACES(x) Q_INTERFACES(x) #define Q_PROPERTY(text) Q_PROPERTY(text) #define Q_PRIVATE_PROPERTY(d, text) Q_PRIVATE_PROPERTY(d, text) +#define Q_REVISION(v) Q_REVISION(v) #define Q_OVERRIDE(text) Q_OVERRIDE(text) #define Q_ENUMS(x) Q_ENUMS(x) #define Q_FLAGS(x) Q_FLAGS(x) diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp index c3bbba1..ea5b474 100644 --- a/src/tools/moc/generator.cpp +++ b/src/tools/moc/generator.cpp @@ -181,10 +181,14 @@ void Generator::generateCode() int methodCount = cdef->signalList.count() + cdef->slotList.count() + cdef->methodList.count(); fprintf(out, " %4d, %4d, // methods\n", methodCount, methodCount ? index : 0); index += methodCount * 5; + if (cdef->revisionedMethods) + index += methodCount; fprintf(out, " %4d, %4d, // properties\n", cdef->propertyList.count(), cdef->propertyList.count() ? index : 0); index += cdef->propertyList.count() * 3; if(cdef->notifyableProperties) index += cdef->propertyList.count(); + if (cdef->revisionedProperties) + index += cdef->propertyList.count(); fprintf(out, " %4d, %4d, // enums/sets\n", cdef->enumList.count(), cdef->enumList.count() ? index : 0); int enumsIndex = index; @@ -217,6 +221,14 @@ void Generator::generateCode() // generateFunctions(cdef->methodList, "method", MethodMethod); +// +// Build method version arrays +// + if (cdef->revisionedMethods) { + generateFunctionRevisions(cdef->signalList, "signal"); + generateFunctionRevisions(cdef->slotList, "slot"); + generateFunctionRevisions(cdef->methodList, "method"); + } // // Build property array @@ -456,7 +468,7 @@ void Generator::generateFunctions(QList& list, const char *functype } sig += ')'; - char flags = type; + unsigned char flags = type; if (f.access == FunctionDef::Private) flags |= AccessPrivate; else if (f.access == FunctionDef::Public) @@ -475,11 +487,23 @@ void Generator::generateFunctions(QList& list, const char *functype flags |= MethodCloned; if (f.isScriptable) flags |= MethodScriptable; + if (f.revision > 0) + flags |= MethodRevisioned; fprintf(out, " %4d, %4d, %4d, %4d, 0x%02x,\n", strreg(sig), strreg(arguments), strreg(f.normalizedType), strreg(f.tag), flags); } } +void Generator::generateFunctionRevisions(QList& list, const char *functype) +{ + if (list.count()) + fprintf(out, "\n // %ss: revision\n", functype); + for (int i = 0; i < list.count(); ++i) { + const FunctionDef &f = list.at(i); + fprintf(out, " %4d,\n", f.revision); + } +} + void Generator::generateProperties() { // @@ -537,6 +561,9 @@ void Generator::generateProperties() if (p.notifyId != -1) flags |= Notify; + if (p.revision > 0) + flags |= Revisioned; + if (p.constant) flags |= Constant; if (p.final) @@ -562,6 +589,13 @@ void Generator::generateProperties() p.notifyId); } } + if (cdef->revisionedProperties) { + fprintf(out, "\n // properties: revision\n"); + for (int i = 0; i < cdef->propertyList.count(); ++i) { + const PropertyDef &p = cdef->propertyList.at(i); + fprintf(out, " %4d,\n", p.revision); + } + } } void Generator::generateEnums(int index) diff --git a/src/tools/moc/generator.h b/src/tools/moc/generator.h index fb6ad747..72b2b17 100644 --- a/src/tools/moc/generator.h +++ b/src/tools/moc/generator.h @@ -58,6 +58,7 @@ public: private: void generateClassInfos(); void generateFunctions(QList &list, const char *functype, int type); + void generateFunctionRevisions(QList& list, const char *functype); void generateEnums(int index); void generateProperties(); void generateMetacall(); diff --git a/src/tools/moc/keywords.cpp b/src/tools/moc/keywords.cpp index df1ba0d..7b84fd7 100644 --- a/src/tools/moc/keywords.cpp +++ b/src/tools/moc/keywords.cpp @@ -43,12 +43,12 @@ // DO NOT EDIT. static const short keyword_trans[][128] = { - {0,0,0,0,0,0,0,0,0,533,530,0,0,0,0,0, + {0,0,0,0,0,0,0,0,0,541,538,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 533,252,531,534,0,38,239,532,25,26,236,234,30,235,27,237, + 541,252,539,542,0,38,239,540,25,26,236,234,30,235,27,237, 22,22,22,22,22,22,22,22,22,22,34,41,23,39,24,43, 0,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,21,8,8,8,8,8,8,8,8,8,31,535,32,238,8, + 8,21,8,8,8,8,8,8,8,8,8,31,543,32,238,8, 0,1,2,3,4,5,6,7,8,9,8,8,10,11,12,13, 14,8,15,16,17,18,19,20,8,8,8,36,245,37,248,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -190,7 +190,7 @@ static const short keyword_trans[][128] = { {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,42,0,0,0,28,0, - 538,538,538,538,538,538,538,538,538,538,0,0,0,0,0,0, + 546,546,546,546,546,546,546,546,546,546,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -349,7 +349,7 @@ static const short keyword_trans[][128] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,537,0,0,0,0,536, + 0,0,0,0,0,0,0,0,0,0,545,0,0,0,0,544, 0,0,0,0,0,0,0,0,0,0,0,0,0,258,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -392,7 +392,7 @@ static const short keyword_trans[][128] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,439,388,378,383,364,0,448,0,0,0,0,0,358, - 370,0,0,436,0,0,0,0,0,0,0,0,0,0,0,0, + 370,0,530,436,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -983,6 +983,14 @@ static const struct {CHARACTER, 0, 84, 528, CHARACTER}, {CHARACTER, 0, 89, 529, CHARACTER}, {Q_PRIVATE_PROPERTY_TOKEN, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 69, 531, CHARACTER}, + {CHARACTER, 0, 86, 532, CHARACTER}, + {CHARACTER, 0, 73, 533, CHARACTER}, + {CHARACTER, 0, 83, 534, CHARACTER}, + {CHARACTER, 0, 73, 535, CHARACTER}, + {CHARACTER, 0, 79, 536, CHARACTER}, + {CHARACTER, 0, 78, 537, CHARACTER}, + {Q_REVISION_TOKEN, 0, 0, 0, CHARACTER}, {NEWLINE, 0, 0, 0, NOTOKEN}, {QUOTE, 0, 0, 0, NOTOKEN}, {SINGLEQUOTE, 0, 0, 0, NOTOKEN}, diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp index 2c24165..b8b823c 100644 --- a/src/tools/moc/moc.cpp +++ b/src/tools/moc/moc.cpp @@ -335,6 +335,23 @@ bool Moc::testFunctionAttribute(Token tok, FunctionDef *def) return false; } +bool Moc::testFunctionRevision(FunctionDef *def) +{ + if (test(Q_REVISION_TOKEN)) { + next(LPAREN); + QByteArray revision = lexemUntil(RPAREN); + revision.remove(0, 1); + revision.chop(1); + bool ok = false; + def->revision = revision.toInt(&ok); + if (!ok || def->revision < 0) + error("Invalid revision"); + return true; + } + + return false; +} + // returns false if the function should be ignored bool Moc::parseFunction(FunctionDef *def, bool inMacro) { @@ -342,7 +359,7 @@ bool Moc::parseFunction(FunctionDef *def, bool inMacro) //skip modifiers and attributes while (test(INLINE) || test(STATIC) || (test(VIRTUAL) && (def->isVirtual = true)) //mark as virtual - || testFunctionAttribute(def)) {} + || testFunctionAttribute(def) || testFunctionRevision(def)) {} bool templateFunction = (lookup() == TEMPLATE); def->type = parseType(); if (def->type.name.isEmpty()) { @@ -433,7 +450,7 @@ bool Moc::parseMaybeFunction(const ClassDef *cdef, FunctionDef *def) //skip modifiers and attributes while (test(EXPLICIT) || test(INLINE) || test(STATIC) || (test(VIRTUAL) && (def->isVirtual = true)) //mark as virtual - || testFunctionAttribute(def)) {} + || testFunctionAttribute(def) || testFunctionRevision(def)) {} bool tilde = test(TILDE); def->type = parseType(); if (def->type.name.isEmpty()) @@ -694,6 +711,8 @@ void Moc::parse() funcDef.arguments.removeLast(); def.slotList += funcDef; } + if (funcDef.revision > 0) + ++def.revisionedMethods; } else if (funcDef.isSignal) { def.signalList += funcDef; while (funcDef.arguments.size() > 0 && funcDef.arguments.last().isDefault) { @@ -701,6 +720,8 @@ void Moc::parse() funcDef.arguments.removeLast(); def.signalList += funcDef; } + if (funcDef.revision > 0) + ++def.revisionedMethods; } else if (funcDef.isInvokable) { def.methodList += funcDef; while (funcDef.arguments.size() > 0 && funcDef.arguments.last().isDefault) { @@ -708,6 +729,8 @@ void Moc::parse() funcDef.arguments.removeLast(); def.methodList += funcDef; } + if (funcDef.revision > 0) + ++def.revisionedMethods; } } } else { @@ -806,6 +829,18 @@ QList Moc::generate(bool ignoreProperties) void Moc::parseSlots(ClassDef *def, FunctionDef::Access access) { + int defaultRevision = -1; + if (test(Q_REVISION_TOKEN)) { + next(LPAREN); + QByteArray revision = lexemUntil(RPAREN); + revision.remove(0, 1); + revision.chop(1); + bool ok = false; + defaultRevision = revision.toInt(&ok); + if (!ok || defaultRevision < 0) + error("Invalid revision"); + } + next(COLON); while (inClass(def) && hasNext()) { switch (next()) { @@ -831,6 +866,12 @@ void Moc::parseSlots(ClassDef *def, FunctionDef::Access access) funcDef.access = access; if (!parseFunction(&funcDef)) continue; + if (funcDef.revision > 0) { + ++def->revisionedMethods; + } else if (defaultRevision != -1) { + funcDef.revision = defaultRevision; + ++def->revisionedMethods; + } def->slotList += funcDef; while (funcDef.arguments.size() > 0 && funcDef.arguments.last().isDefault) { funcDef.wasCloned = true; @@ -842,6 +883,18 @@ void Moc::parseSlots(ClassDef *def, FunctionDef::Access access) void Moc::parseSignals(ClassDef *def) { + int defaultRevision = -1; + if (test(Q_REVISION_TOKEN)) { + next(LPAREN); + QByteArray revision = lexemUntil(RPAREN); + revision.remove(0, 1); + revision.chop(1); + bool ok = false; + defaultRevision = revision.toInt(&ok); + if (!ok || defaultRevision < 0) + error("Invalid revision"); + } + next(COLON); while (inClass(def) && hasNext()) { switch (next()) { @@ -869,6 +922,12 @@ void Moc::parseSignals(ClassDef *def) warning("Signals cannot be declared virtual"); if (funcDef.inlineCode) error("Not a signal declaration"); + if (funcDef.revision > 0) { + ++def->revisionedMethods; + } else if (defaultRevision != -1) { + funcDef.revision = defaultRevision; + ++def->revisionedMethods; + } def->signalList += funcDef; while (funcDef.arguments.size() > 0 && funcDef.arguments.last().isDefault) { funcDef.wasCloned = true; @@ -911,7 +970,6 @@ void Moc::createPropertyDef(PropertyDef &propDef) propDef.name = lexem(); while (test(IDENTIFIER)) { QByteArray l = lexem(); - if (l[0] == 'C' && l == "CONSTANT") { propDef.constant = true; continue; @@ -923,6 +981,10 @@ void Moc::createPropertyDef(PropertyDef &propDef) QByteArray v, v2; if (test(LPAREN)) { v = lexemUntil(RPAREN); + } else if (test(INTEGER_LITERAL)) { + v = lexem(); + if (l != "REVISION") + error(1); } else { next(IDENTIFIER); v = lexem(); @@ -937,7 +999,12 @@ void Moc::createPropertyDef(PropertyDef &propDef) propDef.read = v; else if (l == "RESET") propDef.reset = v + v2; - else + else if (l == "REVISION") { + bool ok = false; + propDef.revision = v.toInt(&ok); + if (!ok || propDef.revision < 0) + error(1); + } else error(2); break; case 'S': @@ -1002,6 +1069,8 @@ void Moc::parseProperty(ClassDef *def) if(!propDef.notify.isEmpty()) def->notifyableProperties++; + if (propDef.revision > 0) + ++def->revisionedProperties; def->propertyList += propDef; } @@ -1028,6 +1097,8 @@ void Moc::parsePrivateProperty(ClassDef *def) if(!propDef.notify.isEmpty()) def->notifyableProperties++; + if (propDef.revision > 0) + ++def->revisionedProperties; def->propertyList += propDef; } @@ -1177,6 +1248,9 @@ void Moc::parseSlotInPrivate(ClassDef *def, FunctionDef::Access access) funcDef.arguments.removeLast(); def->slotList += funcDef; } + if (funcDef.revision > 0) + ++def->revisionedMethods; + } QByteArray Moc::lexemUntil(Token target) diff --git a/src/tools/moc/moc.h b/src/tools/moc/moc.h index 5e47d9a..c07ec0b 100644 --- a/src/tools/moc/moc.h +++ b/src/tools/moc/moc.h @@ -86,7 +86,7 @@ struct FunctionDef FunctionDef(): returnTypeIsVolatile(false), access(Private), isConst(false), isVirtual(false), inlineCode(false), wasCloned(false), isCompat(false), isInvokable(false), isScriptable(false), isSlot(false), isSignal(false), - isConstructor(false), isDestructor(false), isAbstract(false) {} + isConstructor(false), isDestructor(false), isAbstract(false), revision(0) {} Type type; QByteArray normalizedType; QByteArray tag; @@ -111,11 +111,13 @@ struct FunctionDef bool isConstructor; bool isDestructor; bool isAbstract; + + int revision; }; struct PropertyDef { - PropertyDef():notifyId(-1), constant(false), final(false), gspec(ValueSpec){} + PropertyDef():notifyId(-1), constant(false), final(false), gspec(ValueSpec), revision(0){} QByteArray name, type, read, write, reset, designable, scriptable, editable, stored, user, notify, inPrivateClass; int notifyId; bool constant; @@ -128,6 +130,7 @@ struct PropertyDef s += name.mid(1); return (s == write); } + int revision; }; @@ -139,7 +142,8 @@ struct ClassInfoDef struct ClassDef { ClassDef(): - hasQObject(false), hasQGadget(false), notifyableProperties(0), begin(0), end(0){} + hasQObject(false), hasQGadget(false), notifyableProperties(0) + , revisionedMethods(0), revisionedProperties(0), begin(0), end(0){} QByteArray classname; QByteArray qualified; QList > superclassList; @@ -164,6 +168,8 @@ struct ClassDef { QMap enumDeclarations; QList enumList; QMap flagAliases; + int revisionedMethods; + int revisionedProperties; int begin; int end; @@ -236,6 +242,7 @@ public: // in FunctionDef accordingly bool testFunctionAttribute(FunctionDef *def); bool testFunctionAttribute(Token tok, FunctionDef *def); + bool testFunctionRevision(FunctionDef *def); void checkSuperClasses(ClassDef *def); void checkProperties(ClassDef* cdef); diff --git a/src/tools/moc/token.cpp b/src/tools/moc/token.cpp index 3da9446..27d5146 100644 --- a/src/tools/moc/token.cpp +++ b/src/tools/moc/token.cpp @@ -180,6 +180,7 @@ const char *tokenTypeName(Token t) case Q_SLOT_TOKEN: return "Q_SLOT_TOKEN"; case Q_PRIVATE_SLOT_TOKEN: return "Q_PRIVATE_SLOT_TOKEN"; case Q_PRIVATE_PROPERTY_TOKEN: return "Q_PRIVATE_PROPERTY_TOKEN"; + case Q_REVISION_TOKEN: return "Q_REVISION_TOKEN"; case SPECIAL_TREATMENT_MARK: return "SPECIAL_TREATMENT_MARK"; case MOC_INCLUDE_BEGIN: return "MOC_INCLUDE_BEGIN"; case MOC_INCLUDE_END: return "MOC_INCLUDE_END"; diff --git a/src/tools/moc/token.h b/src/tools/moc/token.h index 6ca3d84..8b72eb6 100644 --- a/src/tools/moc/token.h +++ b/src/tools/moc/token.h @@ -186,6 +186,7 @@ enum Token { Q_INVOKABLE_TOKEN, Q_SCRIPTABLE_TOKEN, Q_PRIVATE_PROPERTY_TOKEN, + Q_REVISION_TOKEN, Q_META_TOKEN_END, SPECIAL_TREATMENT_MARK = Q_META_TOKEN_END, MOC_INCLUDE_BEGIN, diff --git a/src/tools/moc/util/generate_keywords.cpp b/src/tools/moc/util/generate_keywords.cpp index 88f187d..e9463e1 100644 --- a/src/tools/moc/util/generate_keywords.cpp +++ b/src/tools/moc/util/generate_keywords.cpp @@ -249,6 +249,7 @@ static const Keyword keywords[] = { { "Q_SLOT", "Q_SLOT_TOKEN" }, { "Q_SCRIPTABLE", "Q_SCRIPTABLE_TOKEN" }, { "Q_PRIVATE_PROPERTY", "Q_PRIVATE_PROPERTY_TOKEN" }, + { "Q_REVISION", "Q_REVISION_TOKEN" }, { "\n", "NEWLINE" }, { "\"", "QUOTE" }, { "\'", "SINGLEQUOTE" }, diff --git a/tests/auto/moc/tst_moc.cpp b/tests/auto/moc/tst_moc.cpp index bb23f49..a634349 100644 --- a/tests/auto/moc/tst_moc.cpp +++ b/tests/auto/moc/tst_moc.cpp @@ -493,6 +493,7 @@ private slots: void QTBUG5590_dummyProperty(); void QTBUG12260_defaultTemplate(); void notifyError(); + void revisions(); signals: void sigWithUnsignedArg(unsigned foo); void sigWithSignedArg(signed foo); @@ -507,6 +508,7 @@ private: bool user2() { return false; }; bool user3() { return false; }; bool userFunction(){ return false; }; + template void revisions_T(); private: QString qtIncludePath; @@ -1384,6 +1386,117 @@ void tst_Moc::notifyError() #endif } +// If changed, update VersionTestNotify below +class VersionTest : public QObject +{ + Q_OBJECT + Q_PROPERTY(int prop1 READ foo) + Q_PROPERTY(int prop2 READ foo REVISION 2) + Q_ENUMS(TestEnum); + +public: + int foo() const { return 0; } + + Q_INVOKABLE void method1() {} + Q_INVOKABLE Q_REVISION(4) void method2() {} + + enum TestEnum { One, Two }; + +public slots: + void slot1() {} + Q_REVISION(3) void slot2() {} + +signals: + void signal1(); + Q_REVISION(5) void signal2(); + +public slots Q_REVISION(6): + void slot3() {} + void slot4() {} + +signals Q_REVISION(7): + void signal3(); + void signal4(); +}; + +// If changed, update VersionTest above +class VersionTestNotify : public QObject +{ + Q_OBJECT + Q_PROPERTY(int prop1 READ foo NOTIFY fooChanged) + Q_PROPERTY(int prop2 READ foo REVISION 2) + Q_ENUMS(TestEnum); + +public: + int foo() const { return 0; } + + Q_INVOKABLE void method1() {} + Q_INVOKABLE Q_REVISION(4) void method2() {} + + enum TestEnum { One, Two }; + +public slots: + void slot1() {} + Q_REVISION(3) void slot2() {} + +signals: + void fooChanged(); + void signal1(); + Q_REVISION(5) void signal2(); + +public slots Q_REVISION(6): + void slot3() {} + void slot4() {} + +signals Q_REVISION(7): + void signal3(); + void signal4(); +}; + +template +void tst_Moc::revisions_T() +{ + int idx = T::staticMetaObject.indexOfProperty("prop1"); + QVERIFY(T::staticMetaObject.property(idx).revision() == 0); + idx = T::staticMetaObject.indexOfProperty("prop2"); + QVERIFY(T::staticMetaObject.property(idx).revision() == 2); + + idx = T::staticMetaObject.indexOfMethod("method1()"); + QVERIFY(T::staticMetaObject.method(idx).revision() == 0); + idx = T::staticMetaObject.indexOfMethod("method2()"); + QVERIFY(T::staticMetaObject.method(idx).revision() == 4); + + idx = T::staticMetaObject.indexOfSlot("slot1()"); + QVERIFY(T::staticMetaObject.method(idx).revision() == 0); + idx = T::staticMetaObject.indexOfSlot("slot2()"); + QVERIFY(T::staticMetaObject.method(idx).revision() == 3); + + idx = T::staticMetaObject.indexOfSlot("slot3()"); + QVERIFY(T::staticMetaObject.method(idx).revision() == 6); + idx = T::staticMetaObject.indexOfSlot("slot4()"); + QVERIFY(T::staticMetaObject.method(idx).revision() == 6); + + idx = T::staticMetaObject.indexOfSignal("signal1()"); + QVERIFY(T::staticMetaObject.method(idx).revision() == 0); + idx = T::staticMetaObject.indexOfSignal("signal2()"); + QVERIFY(T::staticMetaObject.method(idx).revision() == 5); + + idx = T::staticMetaObject.indexOfSignal("signal3()"); + QVERIFY(T::staticMetaObject.method(idx).revision() == 7); + idx = T::staticMetaObject.indexOfSignal("signal4()"); + QVERIFY(T::staticMetaObject.method(idx).revision() == 7); + + idx = T::staticMetaObject.indexOfEnumerator("TestEnum"); + QCOMPARE(T::staticMetaObject.enumerator(idx).keyCount(), 2); + QCOMPARE(T::staticMetaObject.enumerator(idx).key(0), "One"); +} + +// test using both class that has properties with and without NOTIFY signals +void tst_Moc::revisions() +{ + revisions_T(); + revisions_T(); +} QTEST_APPLESS_MAIN(tst_Moc) #include "tst_moc.moc" -- cgit v0.12 From ffd499eb6ff64df1833625f64dbbf92e0e0746d4 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Wed, 5 Jan 2011 13:57:17 +1000 Subject: Support property/method versions in QML Use metaobject revisioning to exclude properties/revisions added in later versions from interfering with earlier versions. Task-number: QTBUG-13451 Reviewed-by: Aaron Kennedy --- src/declarative/qml/qdeclarative.h | 77 +++++++++- .../qml/qdeclarativecompiledbindings.cpp | 4 + src/declarative/qml/qdeclarativecompiler.cpp | 17 ++- src/declarative/qml/qdeclarativedata_p.h | 5 +- src/declarative/qml/qdeclarativeinstruction_p.h | 1 + src/declarative/qml/qdeclarativemetatype.cpp | 83 ++++++++++- src/declarative/qml/qdeclarativemetatype_p.h | 5 + .../qml/qdeclarativeobjectscriptclass.cpp | 14 ++ src/declarative/qml/qdeclarativeprivate.h | 1 + src/declarative/qml/qdeclarativepropertycache.cpp | 3 +- src/declarative/qml/qdeclarativepropertycache_p.h | 4 +- src/declarative/qml/qdeclarativescriptparser.cpp | 1 - src/declarative/qml/qdeclarativevaluetype.cpp | 1 + src/declarative/qml/qdeclarativevme.cpp | 4 + src/declarative/qml/qmetaobjectbuilder.cpp | 33 +---- src/declarative/qml/qmetaobjectbuilder_p.h | 2 - .../util/qdeclarativeopenmetaobject.cpp | 1 - .../data/metaobjectRevision.qml | 7 + .../data/metaobjectRevision2.qml | 9 ++ .../data/metaobjectRevision3.qml | 8 + .../data/metaobjectRevisionErrors.qml | 14 ++ .../data/metaobjectRevisionErrors2.qml | 24 +++ .../data/metaobjectRevisionErrors3.qml | 36 +++++ .../qdeclarativeecmascript/testtypes.cpp | 9 ++ .../declarative/qdeclarativeecmascript/testtypes.h | 161 ++++++++++++++++++++ .../tst_qdeclarativeecmascript.cpp | 82 +++++++++++ .../data/metaobjectRevision.1.errors.txt | 1 + .../data/metaobjectRevision.1.qml | 8 + .../data/metaobjectRevision.2.errors.txt | 1 + .../data/metaobjectRevision.2.qml | 7 + .../data/metaobjectRevision.3.errors.txt | 1 + .../data/metaobjectRevision.3.qml | 10 ++ .../qdeclarativelanguage/data/revisions10.qml | 8 + .../qdeclarativelanguage/data/revisions11.qml | 10 ++ .../data/revisionsbasesub11.qml | 16 ++ .../qdeclarativelanguage/data/revisionssub10.qml | 10 ++ .../qdeclarativelanguage/data/revisionssub11.qml | 12 ++ .../declarative/qdeclarativelanguage/testtypes.cpp | 9 ++ .../declarative/qdeclarativelanguage/testtypes.h | 163 +++++++++++++++++++++ .../tst_qdeclarativelanguage.cpp | 62 ++++++++ .../qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp | 12 +- 41 files changed, 883 insertions(+), 53 deletions(-) create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevision.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevision2.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevision3.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevisionErrors.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevisionErrors2.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevisionErrors3.qml create mode 100644 tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.1.errors.txt create mode 100644 tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.1.qml create mode 100644 tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.2.errors.txt create mode 100644 tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.2.qml create mode 100644 tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.3.errors.txt create mode 100644 tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.3.qml create mode 100644 tests/auto/declarative/qdeclarativelanguage/data/revisions10.qml create mode 100644 tests/auto/declarative/qdeclarativelanguage/data/revisions11.qml create mode 100644 tests/auto/declarative/qdeclarativelanguage/data/revisionsbasesub11.qml create mode 100644 tests/auto/declarative/qdeclarativelanguage/data/revisionssub10.qml create mode 100644 tests/auto/declarative/qdeclarativelanguage/data/revisionssub11.qml diff --git a/src/declarative/qml/qdeclarative.h b/src/declarative/qml/qdeclarative.h index f0c62f4..8a6d068 100644 --- a/src/declarative/qml/qdeclarative.h +++ b/src/declarative/qml/qdeclarative.h @@ -113,6 +113,7 @@ int qmlRegisterType() 0, 0, + 0, 0 }; @@ -148,6 +149,7 @@ int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMin 0, 0, + 0, 0 }; @@ -181,12 +183,82 @@ int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const c 0, 0, + 0, 0 }; return QDeclarativePrivate::qmlregister(QDeclarativePrivate::TypeRegistration, &type); } +template +int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const char *qmlName) +{ + QByteArray name(T::staticMetaObject.className()); + + QByteArray pointerName(name + '*'); + QByteArray listName("QDeclarativeListProperty<" + name + ">"); + + QDeclarativePrivate::RegisterType type = { + 1, + + qRegisterMetaType(pointerName.constData()), + qRegisterMetaType >(listName.constData()), + sizeof(T), QDeclarativePrivate::createInto, + QString(), + + uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject, + + QDeclarativePrivate::attachedPropertiesFunc(), + QDeclarativePrivate::attachedPropertiesMetaObject(), + + QDeclarativePrivate::StaticCastSelector::cast(), + QDeclarativePrivate::StaticCastSelector::cast(), + QDeclarativePrivate::StaticCastSelector::cast(), + + 0, 0, + + 0, + metaObjectRevision + }; + + return QDeclarativePrivate::qmlregister(QDeclarativePrivate::TypeRegistration, &type); +} + +template +int qmlRegisterRevision(const char *uri, int versionMajor, int versionMinor) +{ + QByteArray name(T::staticMetaObject.className()); + + QByteArray pointerName(name + '*'); + QByteArray listName("QDeclarativeListProperty<" + name + ">"); + + QDeclarativePrivate::RegisterType type = { + 1, + + qRegisterMetaType(pointerName.constData()), + qRegisterMetaType >(listName.constData()), + sizeof(T), QDeclarativePrivate::createInto, + QString(), + + uri, versionMajor, versionMinor, 0, &T::staticMetaObject, + + QDeclarativePrivate::attachedPropertiesFunc(), + QDeclarativePrivate::attachedPropertiesMetaObject(), + + QDeclarativePrivate::StaticCastSelector::cast(), + QDeclarativePrivate::StaticCastSelector::cast(), + QDeclarativePrivate::StaticCastSelector::cast(), + + 0, 0, + + 0, + metaObjectRevision + }; + + return QDeclarativePrivate::qmlregister(QDeclarativePrivate::TypeRegistration, &type); +} + + template int qmlRegisterExtendedType() { @@ -214,6 +286,7 @@ int qmlRegisterExtendedType() QDeclarativePrivate::createParent, &E::staticMetaObject, + 0, 0 }; @@ -255,6 +328,7 @@ int qmlRegisterExtendedType(const char *uri, int versionMajor, int versionMinor, QDeclarativePrivate::createParent, &E::staticMetaObject, + 0, 0 }; @@ -309,7 +383,8 @@ int qmlRegisterCustomType(const char *uri, int versionMajor, int versionMinor, 0, 0, - parser + parser, + 0 }; return QDeclarativePrivate::qmlregister(QDeclarativePrivate::TypeRegistration, &type); diff --git a/src/declarative/qml/qdeclarativecompiledbindings.cpp b/src/declarative/qml/qdeclarativecompiledbindings.cpp index 48f8b84..619016b 100644 --- a/src/declarative/qml/qdeclarativecompiledbindings.cpp +++ b/src/declarative/qml/qdeclarativecompiledbindings.cpp @@ -2527,6 +2527,10 @@ bool QDeclarativeBindingCompilerPrivate::fetch(Result &rv, const QMetaObject *mo rv.metaObject = 0; rv.type = 0; + //XXX binding optimizer doesn't handle properties with a revision + if (prop.revision() > 0) + return false; + int fastFetchIndex = fastProperties()->accessorIndexForProperty(mo, idx); Instr fetch; diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp index b2b0990..0c56165 100644 --- a/src/declarative/qml/qdeclarativecompiler.cpp +++ b/src/declarative/qml/qdeclarativecompiler.cpp @@ -902,6 +902,7 @@ void QDeclarativeCompiler::genObject(QDeclarativeParser::Object *obj) create.line = obj->location.start.line; create.createSimple.create = output->types.at(obj->type).type->createFunction(); create.createSimple.typeSize = output->types.at(obj->type).type->createSize(); + create.createSimple.type = obj->type; create.createSimple.column = obj->location.start.column; output->bytecode << create; @@ -1351,7 +1352,8 @@ bool QDeclarativeCompiler::buildSignal(QDeclarativeParser::Property *prop, QDecl if(name[0] >= 'A' && name[0] <= 'Z') name[0] = name[0] - 'A' + 'a'; - int sigIdx = QDeclarativePropertyPrivate::findSignalByName(obj->metaObject(), name).methodIndex(); + QMetaMethod method = QDeclarativePropertyPrivate::findSignalByName(obj->metaObject(), name); + int sigIdx = method.methodIndex(); if (sigIdx == -1) { @@ -1364,6 +1366,13 @@ bool QDeclarativeCompiler::buildSignal(QDeclarativeParser::Property *prop, QDecl if (prop->value || prop->values.count() != 1) COMPILE_EXCEPTION(prop, tr("Incorrectly specified signal assignment")); + if (method.revision() > 0) { + QDeclarativeType *type = output->types.at(obj->type).type; + if (!type->isMethodAvailable(sigIdx, method.revision())) { + COMPILE_EXCEPTION(prop, tr("Signal \"%1\" not available in %2 %3.%4").arg(QString::fromUtf8(prop->name)).arg(QString::fromUtf8(type->qmlTypeName())).arg(obj->majorVersion).arg(obj->minorVersion)); + } + } + prop->index = sigIdx; obj->addSignalProperty(prop); @@ -1481,6 +1490,12 @@ bool QDeclarativeCompiler::buildProperty(QDeclarativeParser::Property *prop, // successful index resolution if (p.name()) { prop->type = p.userType(); + if (p.revision() > 0) { + QDeclarativeType *type = output->types.at(obj->type).type; + if (!type->isPropertyAvailable(prop->index, p.revision())) { + COMPILE_EXCEPTION(prop, tr("Property \"%1\" not available in %2 %3.%4").arg(QString::fromUtf8(prop->name)).arg(QString::fromUtf8(type->qmlTypeName())).arg(obj->majorVersion).arg(obj->minorVersion)); + } + } } // Check if this is an alias diff --git a/src/declarative/qml/qdeclarativedata_p.h b/src/declarative/qml/qdeclarativedata_p.h index 4767169..81f279c 100644 --- a/src/declarative/qml/qdeclarativedata_p.h +++ b/src/declarative/qml/qdeclarativedata_p.h @@ -66,6 +66,7 @@ class QDeclarativePropertyCache; class QDeclarativeContextData; class QDeclarativeNotifier; class QDeclarativeDataExtended; +class QDeclarativeType; // This class is structured in such a way, that simply zero'ing it is the // default state for elemental object allocations. This is crucial in the // workings of the QDeclarativeInstruction::CreateSimpleObject instruction. @@ -77,7 +78,7 @@ public: : ownMemory(true), ownContext(false), indestructible(true), explicitIndestructibleSet(false), context(0), outerContext(0), bindings(0), nextContextObject(0), prevContextObject(0), bindingBitsSize(0), bindingBits(0), lineNumber(0), columnNumber(0), deferredComponent(0), deferredIdx(0), - scriptValue(0), objectDataRefCount(0), propertyCache(0), guards(0), extendedData(0) { + scriptValue(0), objectDataRefCount(0), propertyCache(0), guards(0), type(0), extendedData(0) { init(); } @@ -136,6 +137,8 @@ public: QDeclarativeGuard *guards; + const QDeclarativeType *type; + static QDeclarativeData *get(const QObject *object, bool create = false) { QObjectPrivate *priv = QObjectPrivate::get(const_cast(object)); if (priv->wasDeleted) { diff --git a/src/declarative/qml/qdeclarativeinstruction_p.h b/src/declarative/qml/qdeclarativeinstruction_p.h index 94676fc..4030bab 100644 --- a/src/declarative/qml/qdeclarativeinstruction_p.h +++ b/src/declarative/qml/qdeclarativeinstruction_p.h @@ -182,6 +182,7 @@ public: struct CreateSimpleInstruction { void (*create)(void *); int typeSize; + int type; ushort column; }; struct StoreMetaInstruction { diff --git a/src/declarative/qml/qdeclarativemetatype.cpp b/src/declarative/qml/qdeclarativemetatype.cpp index 7a78a1f..1f387c4 100644 --- a/src/declarative/qml/qdeclarativemetatype.cpp +++ b/src/declarative/qml/qdeclarativemetatype.cpp @@ -134,10 +134,13 @@ public: bool m_isInterface : 1; const char *m_iid; + QByteArray m_module; QByteArray m_name; int m_version_maj; int m_version_min; int m_typeId; int m_listId; + int m_revision; + mutable QDeclarativeType *m_superType; int m_allocationSize; void (*m_newFunc)(void *); @@ -155,6 +158,7 @@ public: int m_index; QDeclarativeCustomParser *m_customParser; mutable volatile bool m_isSetup:1; + mutable bool m_haveSuperType : 1; mutable QList m_metaObjects; static QHash m_attachedPropertyIds; @@ -163,10 +167,10 @@ public: QHash QDeclarativeTypePrivate::m_attachedPropertyIds; QDeclarativeTypePrivate::QDeclarativeTypePrivate() -: m_isInterface(false), m_iid(0), m_typeId(0), m_listId(0), +: m_isInterface(false), m_iid(0), m_typeId(0), m_listId(0), m_revision(0), m_superType(0), m_allocationSize(0), m_newFunc(0), m_baseMetaObject(0), m_attachedPropertiesFunc(0), m_attachedPropertiesType(0), m_parserStatusCast(-1), m_propertyValueSourceCast(-1), m_propertyValueInterceptorCast(-1), - m_extFunc(0), m_extMetaObject(0), m_index(-1), m_customParser(0), m_isSetup(false) + m_extFunc(0), m_extMetaObject(0), m_index(-1), m_customParser(0), m_isSetup(false), m_haveSuperType(false) { } @@ -192,9 +196,11 @@ QDeclarativeType::QDeclarativeType(int index, const QDeclarativePrivate::Registe if (type.uri) name += '/'; name += type.elementName; + d->m_module = type.uri; d->m_name = name; d->m_version_maj = type.versionMajor; d->m_version_min = type.versionMinor; + d->m_revision = type.revision; d->m_typeId = type.typeId; d->m_listId = type.listId; d->m_allocationSize = type.objectSize; @@ -243,6 +249,56 @@ bool QDeclarativeType::availableInVersion(int vmajor, int vminor) const return vmajor > d->m_version_maj || (vmajor == d->m_version_maj && vminor >= d->m_version_min); } +bool QDeclarativeType::availableInVersion(const QByteArray &module, int vmajor, int vminor) const +{ + return module == d->m_module && (vmajor > d->m_version_maj || (vmajor == d->m_version_maj && vminor >= d->m_version_min)); +} + +// returns the nearest _registered_ super class +QDeclarativeType *QDeclarativeType::superType() const +{ + if (!d->m_haveSuperType) { + const QMetaObject *mo = d->m_baseMetaObject->superClass(); + while (mo && !d->m_superType) { + d->m_superType = QDeclarativeMetaType::qmlType(mo, d->m_module, d->m_version_maj, d->m_version_min); + mo = mo->superClass(); + } + d->m_haveSuperType = true; + } + + return d->m_superType; +} + +bool QDeclarativeType::isPropertyAvailable(int index, int revision) const +{ + if (revision == 0) + return true; + + if (index < d->m_baseMetaObject->propertyOffset()) { + if (QDeclarativeType *super = superType()) + return super->isPropertyAvailable(index, revision); + } else if (index < d->m_baseMetaObject->propertyOffset() + d->m_baseMetaObject->propertyCount()) { + return d->m_revision >= revision; + } + + return false; +} + +bool QDeclarativeType::isMethodAvailable(int index, int revision) const +{ + if (revision == 0) + return true; + + if (index < d->m_baseMetaObject->methodOffset()) { + if (QDeclarativeType *super = superType()) + return super->isMethodAvailable(index, revision); + } else if (index < d->m_baseMetaObject->methodOffset() + d->m_baseMetaObject->methodCount()) { + return d->m_revision >= revision; + } + + return false; +} + static void clone(QMetaObjectBuilder &builder, const QMetaObject *mo, const QMetaObject *ignoreStart, const QMetaObject *ignoreEnd) { @@ -572,7 +628,7 @@ int registerType(const QDeclarativePrivate::RegisterType &type) if (!dtype->qmlTypeName().isEmpty()) data->nameToType.insertMulti(dtype->qmlTypeName(), dtype); - data->metaObjectToType.insert(dtype->baseMetaObject(), dtype); + data->metaObjectToType.insertMulti(dtype->baseMetaObject(), dtype); if (data->objects.size() <= type.typeId) data->objects.resize(type.typeId + 16); @@ -862,6 +918,27 @@ QDeclarativeType *QDeclarativeMetaType::qmlType(const QMetaObject *metaObject) } /*! + Returns the type (if any) that corresponds to the \a metaObject in version specified + by \a version_major and \a version_minor in module specified by \a uri. Returns null if no + type is registered. +*/ +QDeclarativeType *QDeclarativeMetaType::qmlType(const QMetaObject *metaObject, const QByteArray &module, int version_major, int version_minor) +{ + QReadLocker lock(metaTypeDataLock()); + QDeclarativeMetaTypeData *data = metaTypeData(); + + QDeclarativeMetaTypeData::MetaObjects::const_iterator it = data->metaObjectToType.find(metaObject); + while (it != data->metaObjectToType.end() && it.key() == metaObject) { + QDeclarativeType *t = *it; + if (version_major < 0 || t->availableInVersion(module, version_major,version_minor)) + return t; + ++it; + } + + return 0; +} + +/*! Returns the type (if any) that corresponds to the QVariant::Type \a userType. Returns null if no type is registered. */ diff --git a/src/declarative/qml/qdeclarativemetatype_p.h b/src/declarative/qml/qdeclarativemetatype_p.h index 9c486d3..d9a3795 100644 --- a/src/declarative/qml/qdeclarativemetatype_p.h +++ b/src/declarative/qml/qdeclarativemetatype_p.h @@ -76,6 +76,7 @@ public: static QDeclarativeType *qmlType(const QByteArray &, int, int); static QDeclarativeType *qmlType(const QMetaObject *); + static QDeclarativeType *qmlType(const QMetaObject *metaObject, const QByteArray &module, int version_major, int version_minor); static QDeclarativeType *qmlType(int); static QMetaProperty defaultProperty(const QMetaObject *); @@ -115,6 +116,9 @@ public: int majorVersion() const; int minorVersion() const; bool availableInVersion(int vmajor, int vminor) const; + bool availableInVersion(const QByteArray &module, int vmajor, int vminor) const; + bool isPropertyAvailable(int index, int revision) const; + bool isMethodAvailable(int index, int revision) const; QObject *create() const; void create(QObject **, void **, size_t) const; @@ -149,6 +153,7 @@ public: int index() const; private: + QDeclarativeType *superType() const; friend class QDeclarativeTypePrivate; friend struct QDeclarativeMetaTypeData; friend int registerType(const QDeclarativePrivate::RegisterType &); diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp index b0bc5bb..090eeda 100644 --- a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp +++ b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp @@ -166,6 +166,20 @@ QDeclarativeObjectScriptClass::queryProperty(QObject *obj, const Identifier &nam QDeclarativeEnginePrivate *enginePrivate = QDeclarativeEnginePrivate::get(engine); lastData = QDeclarativePropertyCache::property(engine, obj, name, local); + if (lastData && lastData->revision > 0 && (hints & ImplicitObject)) { + QDeclarativeData *data = QDeclarativeData::get(obj); + if (data) { + if (!data->type) { + lastData = 0; + } else if (lastData->flags & QDeclarativePropertyCache::Data::IsFunction) { + if (!data->type->isMethodAvailable(lastData->coreIndex, lastData->revision)) + lastData = 0; + } else if (!data->type->isPropertyAvailable(lastData->coreIndex, lastData->revision)) { + lastData = 0; + } + } + } + if (lastData) return QScriptClass::HandlesReadAccess | QScriptClass::HandlesWriteAccess; diff --git a/src/declarative/qml/qdeclarativeprivate.h b/src/declarative/qml/qdeclarativeprivate.h index 388c92e..a4fc4c1 100644 --- a/src/declarative/qml/qdeclarativeprivate.h +++ b/src/declarative/qml/qdeclarativeprivate.h @@ -214,6 +214,7 @@ namespace QDeclarativePrivate const QMetaObject *extensionMetaObject; QDeclarativeCustomParser *customParser; + int revision; }; struct RegisterInterface { diff --git a/src/declarative/qml/qdeclarativepropertycache.cpp b/src/declarative/qml/qdeclarativepropertycache.cpp index dd9a224..76c9eb9 100644 --- a/src/declarative/qml/qdeclarativepropertycache.cpp +++ b/src/declarative/qml/qdeclarativepropertycache.cpp @@ -88,6 +88,7 @@ void QDeclarativePropertyCache::Data::load(const QMetaProperty &p, QDeclarativeE coreIndex = p.propertyIndex(); notifyIndex = p.notifySignalIndex(); flags = flagsForProperty(p, engine); + revision = p.revision(); } void QDeclarativePropertyCache::Data::load(const QMetaMethod &m) @@ -106,6 +107,7 @@ void QDeclarativePropertyCache::Data::load(const QMetaMethod &m) QList params = m.parameterTypes(); if (!params.isEmpty()) flags |= Data::HasArguments; + revision = m.revision(); } @@ -235,7 +237,6 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb Data::Flag propertyFlags, Data::Flag methodFlags, Data::Flag signalFlags) { QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(engine); - int methodCount = metaObject->methodCount(); // 3 to block the destroyed signal and the deleteLater() slot int methodOffset = qMax(3, metaObject->methodOffset()); diff --git a/src/declarative/qml/qdeclarativepropertycache_p.h b/src/declarative/qml/qdeclarativepropertycache_p.h index f7c5daa..3f7f9ef 100644 --- a/src/declarative/qml/qdeclarativepropertycache_p.h +++ b/src/declarative/qml/qdeclarativepropertycache_p.h @@ -110,6 +110,7 @@ public: int notifyIndex; // When !IsFunction int relatedIndex; // When IsFunction }; + int revision; static Flags flagsForProperty(const QMetaProperty &, QDeclarativeEngine *engine = 0); void load(const QMetaProperty &, QDeclarativeEngine *engine = 0); @@ -176,7 +177,8 @@ bool QDeclarativePropertyCache::Data::operator==(const QDeclarativePropertyCache return flags == other.flags && propType == other.propType && coreIndex == other.coreIndex && - notifyIndex == other.notifyIndex; + notifyIndex == other.notifyIndex && + revision == other.revision; } QDeclarativePropertyCache::Data * diff --git a/src/declarative/qml/qdeclarativescriptparser.cpp b/src/declarative/qml/qdeclarativescriptparser.cpp index 57cc9ab..e32a3d2 100644 --- a/src/declarative/qml/qdeclarativescriptparser.cpp +++ b/src/declarative/qml/qdeclarativescriptparser.cpp @@ -307,7 +307,6 @@ ProcessAST::defineObjectBinding(AST::UiQualifiedId *propertyName, obj->location = location; if (propertyCount) { - Property *prop = currentProperty(); Value *v = new Value; v->object = obj; diff --git a/src/declarative/qml/qdeclarativevaluetype.cpp b/src/declarative/qml/qdeclarativevaluetype.cpp index 5dc6ffd..bf02de8 100644 --- a/src/declarative/qml/qdeclarativevaluetype.cpp +++ b/src/declarative/qml/qdeclarativevaluetype.cpp @@ -71,6 +71,7 @@ int qmlRegisterValueTypeEnums(const char *uri, int versionMajor, int versionMino 0, 0, + 0, 0 }; diff --git a/src/declarative/qml/qdeclarativevme.cpp b/src/declarative/qml/qdeclarativevme.cpp index c742dec..6ee653b 100644 --- a/src/declarative/qml/qdeclarativevme.cpp +++ b/src/declarative/qml/qdeclarativevme.cpp @@ -194,6 +194,8 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack &stack, QDeclarativeData *ddata = QDeclarativeData::get(o); Q_ASSERT(ddata); + if (types.at(instr.create.type).type) + ddata->type = types.at(instr.create.type).type; if (stack.isEmpty()) { if (ddata->context) { @@ -249,6 +251,8 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack &stack, QDeclarativeData *ddata = (QDeclarativeData *)(((const char *)o) + instr.createSimple.typeSize); + if (types.at(instr.createSimple.type).type) + ddata->type = types.at(instr.createSimple.type).type; ddata->lineNumber = instr.line; ddata->columnNumber = instr.createSimple.column; diff --git a/src/declarative/qml/qmetaobjectbuilder.cpp b/src/declarative/qml/qmetaobjectbuilder.cpp index dfe89f8..60cd6a9 100644 --- a/src/declarative/qml/qmetaobjectbuilder.cpp +++ b/src/declarative/qml/qmetaobjectbuilder.cpp @@ -122,7 +122,7 @@ enum PropertyFlags { User = 0x00100000, ResolveUser = 0x00200000, Notify = 0x00400000, - Dynamic = 0x00800000 + Revisioned = 0x00800000 }; enum MethodFlags { @@ -139,7 +139,8 @@ enum MethodFlags { MethodCompatibility = 0x10, MethodCloned = 0x20, - MethodScriptable = 0x40 + MethodScriptable = 0x40, + MethodRevisioned = 0x80 }; struct QMetaObjectPrivate @@ -2277,21 +2278,6 @@ bool QMetaPropertyBuilder::isEnumOrFlag() const } /*! - Returns true if the property has the dynamic flag set; - otherwise returns false. The default value is false. - - \sa setDynamic() -*/ -bool QMetaPropertyBuilder::isDynamic() const -{ - QMetaPropertyBuilderPrivate *d = d_func(); - if (d) - return d->flag(Dynamic); - else - return false; -} - -/*! Sets this property to readable if \a value is true. \sa isReadable(), setWritable() @@ -2415,19 +2401,6 @@ void QMetaPropertyBuilder::setEnumOrFlag(bool value) } /*! - Sets this property to have the dynamic flag if \a value is - true. - - \sa isDynamic() -*/ -void QMetaPropertyBuilder::setDynamic(bool value) -{ - QMetaPropertyBuilderPrivate *d = d_func(); - if (d) - d->setFlag(Dynamic, value); -} - -/*! \class QMetaEnumBuilder \internal \brief The QMetaEnumBuilder class enables modifications to an enumerator definition on a meta object builder. diff --git a/src/declarative/qml/qmetaobjectbuilder_p.h b/src/declarative/qml/qmetaobjectbuilder_p.h index a90ba63..c270f60 100644 --- a/src/declarative/qml/qmetaobjectbuilder_p.h +++ b/src/declarative/qml/qmetaobjectbuilder_p.h @@ -258,7 +258,6 @@ public: bool isUser() const; bool hasStdCppSet() const; bool isEnumOrFlag() const; - bool isDynamic() const; void setReadable(bool value); void setWritable(bool value); @@ -270,7 +269,6 @@ public: void setUser(bool value); void setStdCppSet(bool value); void setEnumOrFlag(bool value); - void setDynamic(bool value); private: const QMetaObjectBuilder *_mobj; diff --git a/src/declarative/util/qdeclarativeopenmetaobject.cpp b/src/declarative/util/qdeclarativeopenmetaobject.cpp index c611435..1426cea 100644 --- a/src/declarative/util/qdeclarativeopenmetaobject.cpp +++ b/src/declarative/util/qdeclarativeopenmetaobject.cpp @@ -97,7 +97,6 @@ int QDeclarativeOpenMetaObjectType::createProperty(const QByteArray &name) int id = d->mob.propertyCount(); d->mob.addSignal("__" + QByteArray::number(id) + "()"); QMetaPropertyBuilder build = d->mob.addProperty(name, "QVariant", id); - build.setDynamic(true); propertyCreated(id, build); qFree(d->mem); d->mem = d->mob.toMetaObject(); diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevision.qml b/tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevision.qml new file mode 100644 index 0000000..77accd8 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevision.qml @@ -0,0 +1,7 @@ +import Qt.test 1.1 + +MyRevisionedClass +{ + prop1: prop2 + onSignal1: method2() +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevision2.qml b/tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevision2.qml new file mode 100644 index 0000000..36057cb --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevision2.qml @@ -0,0 +1,9 @@ +import Qt.test 1.1 + +MyRevisionedSubclass +{ + prop1: prop3 + onSignal1: method2() + prop3: prop4 + onSignal3: method4() +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevision3.qml b/tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevision3.qml new file mode 100644 index 0000000..81769e9 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevision3.qml @@ -0,0 +1,8 @@ +import Qt.test 1.0 + +MyRevisionedSubclass +{ + prop1: prop3 + onSignal1: method1() + onSignal3: method3() +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevisionErrors.qml b/tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevisionErrors.qml new file mode 100644 index 0000000..44d421e --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevisionErrors.qml @@ -0,0 +1,14 @@ +import QtQuick 1.0 +import Qt.test 1.0 + +MyRevisionedClass +{ + // Will not hit optimizer + property real p1: prop1 % 3 + property real p2: prop2 % 3 + + // Should hit optimizer + property real p3: prop2 + + Component.onCompleted: method2() +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevisionErrors2.qml b/tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevisionErrors2.qml new file mode 100644 index 0000000..121642e --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevisionErrors2.qml @@ -0,0 +1,24 @@ +import QtQuick 1.0 +import Qt.test 1.0 + +MyRevisionedSubclass +{ + // Will not hit optimizer + property real p1: prop1 % 3 + property real p2: prop2 % 3 + property real p3: prop3 % 3 + property real p4: prop4 % 3 + + // Should hit optimizer + property real p5: prop1 + property real p6: prop2 + property real p7: prop3 + property real p8: prop4 + + Component.onCompleted: { + method1() + method2() + method3() + method4() + } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevisionErrors3.qml b/tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevisionErrors3.qml new file mode 100644 index 0000000..123650e --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevisionErrors3.qml @@ -0,0 +1,36 @@ +import QtQuick 1.0 +import Qt.test 1.1 + +MyRevisionedSubclass +{ + // Will not hit optimizer + property real pA: propA % 3 + property real pB: propB % 3 + property real pC: propC % 3 + property real pD: propD % 3 + property real p1: prop1 % 3 + property real p2: prop2 % 3 + property real p3: prop3 % 3 + property real p4: prop4 % 3 + + // Should hit optimizer + property real pE: propA + property real pF: propB + property real pG: propC + property real pH: propD + property real p5: prop1 + property real p6: prop2 + property real p7: prop3 + property real p8: prop4 + + Component.onCompleted: { + methodA() + methodB() + methodC() + methodD() + method1() + method2() + method3() + method4() + } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp b/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp index 94135f9..29e5eac 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp +++ b/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp @@ -113,6 +113,15 @@ void registerTypes() qmlRegisterType("Qt.test", 1,0, "NumberAssignment"); qmlRegisterExtendedType("Qt.test", 1,0, "DefaultPropertyExtendedObject"); qmlRegisterType("Qt.test", 1,0, "OverrideDefaultPropertyObject"); + qmlRegisterType("Qt.test",1,0,"MyRevisionedClass"); + qmlRegisterType("Qt.test",1,1,"MyRevisionedClass"); + + // Register the uncreatable base class + qmlRegisterRevision("Qt.test",1,1); + // MyRevisionedSubclass 1.0 uses MyRevisionedClass revision 0 + qmlRegisterType("Qt.test",1,0,"MyRevisionedSubclass"); + // MyRevisionedSubclass 1.1 uses MyRevisionedClass revision 1 + qmlRegisterType("Qt.test",1,1,"MyRevisionedSubclass"); qmlRegisterExtendedType("Qt.test",1,0,"QWidget"); qmlRegisterType("Qt.test",1,0,"QPlainTextEdit"); diff --git a/tests/auto/declarative/qdeclarativeecmascript/testtypes.h b/tests/auto/declarative/qdeclarativeecmascript/testtypes.h index 15c310f..02a4352 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/testtypes.h +++ b/tests/auto/declarative/qdeclarativeecmascript/testtypes.h @@ -736,6 +736,167 @@ public: OverrideDefaultPropertyObject() {} }; +class MyRevisionedBaseClassRegistered : public QObject +{ +Q_OBJECT + Q_PROPERTY(qreal propA READ propA WRITE setPropA NOTIFY propAChanged) + Q_PROPERTY(qreal propB READ propB WRITE setPropB NOTIFY propBChanged REVISION 1) + +public: + MyRevisionedBaseClassRegistered() : m_pa(1), m_pb(2) {} + + qreal propA() const { return m_pa; } + void setPropA(qreal p) { + if (p != m_pa) { + m_pa = p; + emit propAChanged(); + } + } + qreal propB() const { return m_pb; } + void setPropB(qreal p) { + if (p != m_pb) { + m_pb = p; + emit propBChanged(); + } + } + + Q_INVOKABLE void methodA() { } + Q_INVOKABLE Q_REVISION(1) void methodB() { } + +signals: + void propAChanged(); + void propBChanged(); + + void signalA(); + Q_REVISION(1) void signalB(); + +protected: + qreal m_pa; + qreal m_pb; +}; + +class MyRevisionedBaseClassUnregistered : public MyRevisionedBaseClassRegistered +{ +Q_OBJECT + Q_PROPERTY(qreal propC READ propC WRITE setPropC NOTIFY propCChanged) + Q_PROPERTY(qreal propD READ propD WRITE setPropD NOTIFY propDChanged REVISION 1) + +public: + MyRevisionedBaseClassUnregistered() : m_pc(1), m_pd(2) {} + + qreal propC() const { return m_pc; } + void setPropC(qreal p) { + if (p != m_pc) { + m_pc = p; + emit propCChanged(); + } + } + qreal propD() const { return m_pd; } + void setPropD(qreal p) { + if (p != m_pd) { + m_pd = p; + emit propDChanged(); + } + } + + Q_INVOKABLE void methodC() { } + Q_INVOKABLE Q_REVISION(1) void methodD() { } + +signals: + void propCChanged(); + void propDChanged(); + + void signalC(); + Q_REVISION(1) void signalD(); + +protected: + qreal m_pc; + qreal m_pd; +}; + +class MyRevisionedClass : public MyRevisionedBaseClassUnregistered +{ + Q_OBJECT + Q_PROPERTY(qreal prop1 READ prop1 WRITE setProp1 NOTIFY prop1Changed) + Q_PROPERTY(qreal prop2 READ prop2 WRITE setProp2 NOTIFY prop2Changed REVISION 1) + +public: + MyRevisionedClass() {} + + qreal prop1() const { return m_p1; } + void setProp1(qreal p) { + if (p != m_p1) { + m_p1 = p; + emit prop1Changed(); + } + } + qreal prop2() const { return m_p2; } + void setProp2(qreal p) { + if (p != m_p2) { + m_p2 = p; + emit prop2Changed(); + } + } + + Q_INVOKABLE void method1() { } + Q_INVOKABLE Q_REVISION(1) void method2() { } + +signals: + void prop1Changed(); + void prop2Changed(); + + void signal1(); + Q_REVISION(1) void signal2(); + +protected: + qreal m_p1; + qreal m_p2; +}; + +class MyRevisionedSubclass : public MyRevisionedClass +{ + Q_OBJECT + Q_PROPERTY(qreal prop3 READ prop3 WRITE setProp3 NOTIFY prop3Changed) + Q_PROPERTY(qreal prop4 READ prop4 WRITE setProp4 NOTIFY prop4Changed REVISION 1) + +public: + MyRevisionedSubclass() : m_p3(3), m_p4(4) {} + + qreal prop3() const { return m_p3; } + void setProp3(qreal p) { + if (p != m_p3) { + m_p3 = p; + emit prop3Changed(); + } + } + qreal prop4() const { return m_p4; } + void setProp4(qreal p) { + if (p != m_p4) { + m_p4 = p; + emit prop4Changed(); + } + } + + Q_INVOKABLE void method3() { } + Q_INVOKABLE Q_REVISION(1) void method4() { } + +signals: + void prop3Changed(); + void prop4Changed(); + + void signal3(); + Q_REVISION(1) void signal4(); + +protected: + qreal m_p3; + qreal m_p4; +}; + +QML_DECLARE_TYPE(MyRevisionedBaseClassRegistered) +QML_DECLARE_TYPE(MyRevisionedBaseClassUnregistered) +QML_DECLARE_TYPE(MyRevisionedClass) +QML_DECLARE_TYPE(MyRevisionedSubclass) + void registerTypes(); #endif // TESTTYPES_H diff --git a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp index 4228bc4..a29c459 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp +++ b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp @@ -176,6 +176,9 @@ private slots: void callQtInvokables(); void invokableObjectArg(); void invokableObjectRet(); + + void revisionErrors(); + void revision(); private: QDeclarativeEngine engine; }; @@ -2847,6 +2850,85 @@ void tst_qdeclarativeecmascript::aliasWritesOverrideBindings() } } +void tst_qdeclarativeecmascript::revisionErrors() +{ + { + QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors.qml")); + QString url = component.url().toString(); + + QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2"; + QString warning2 = url + ":11: ReferenceError: Can't find variable: prop2"; + QString warning3 = url + ":13: ReferenceError: Can't find variable: method2"; + + QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData()); + QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData()); + QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData()); + MyRevisionedClass *object = qobject_cast(component.create()); + QVERIFY(object != 0); + } + { + QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors2.qml")); + QString url = component.url().toString(); + + // MyRevisionedSubclass 1.0 uses MyRevisionedClass revision 0 + // method2, prop2 from MyRevisionedClass not available + // method4, prop4 from MyRevisionedSubclass not available + QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2"; + QString warning2 = url + ":14: ReferenceError: Can't find variable: prop2"; + QString warning3 = url + ":10: ReferenceError: Can't find variable: prop4"; + QString warning4 = url + ":16: ReferenceError: Can't find variable: prop4"; + QString warning5 = url + ":20: ReferenceError: Can't find variable: method2"; + + QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData()); + QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData()); + QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData()); + QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData()); + QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData()); + MyRevisionedClass *object = qobject_cast(component.create()); + QVERIFY(object != 0); + } + { + QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors3.qml")); + QString url = component.url().toString(); + + // MyRevisionedSubclass 1.1 uses MyRevisionedClass revision 1 + // All properties/methods available, except MyRevisionedBaseClassUnregistered rev 1 + QString warning1 = url + ":30: ReferenceError: Can't find variable: methodD"; + QString warning2 = url + ":10: ReferenceError: Can't find variable: propD"; + QString warning3 = url + ":20: ReferenceError: Can't find variable: propD"; + QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData()); + QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData()); + QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData()); + MyRevisionedClass *object = qobject_cast(component.create()); + QVERIFY(object != 0); + } +} + +void tst_qdeclarativeecmascript::revision() +{ + { + QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision.qml")); + QString url = component.url().toString(); + + MyRevisionedClass *object = qobject_cast(component.create()); + QVERIFY(object != 0); + } + { + QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision2.qml")); + QString url = component.url().toString(); + + MyRevisionedClass *object = qobject_cast(component.create()); + QVERIFY(object != 0); + } + { + QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision3.qml")); + QString url = component.url().toString(); + + MyRevisionedClass *object = qobject_cast(component.create()); + QVERIFY(object != 0); + } +} + QTEST_MAIN(tst_qdeclarativeecmascript) #include "tst_qdeclarativeecmascript.moc" diff --git a/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.1.errors.txt b/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.1.errors.txt new file mode 100644 index 0000000..6ad6bfa --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.1.errors.txt @@ -0,0 +1 @@ +7:5:Property "prop2" not available in Test/MyRevisionedClass 1.0 diff --git a/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.1.qml b/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.1.qml new file mode 100644 index 0000000..4662d5e --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.1.qml @@ -0,0 +1,8 @@ +import QtQuick 1.0 +import Test 1.0 + +MyRevisionedClass +{ + prop1: 1 + prop2: 2 +} diff --git a/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.2.errors.txt b/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.2.errors.txt new file mode 100644 index 0000000..92ccd9a --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.2.errors.txt @@ -0,0 +1 @@ +6:5:Signal "onSignal2" not available in Test/MyRevisionedClass 1.0 diff --git a/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.2.qml b/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.2.qml new file mode 100644 index 0000000..8da7a25 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.2.qml @@ -0,0 +1,7 @@ +import Test 1.0 + +MyRevisionedClass +{ + onSignal1: prop1 = 2 + onSignal2: prop1 = 3 +} diff --git a/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.3.errors.txt b/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.3.errors.txt new file mode 100644 index 0000000..b3c33c4 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.3.errors.txt @@ -0,0 +1 @@ +9:5:Property "propD" not available in Test/MyRevisionedClass 1.1 diff --git a/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.3.qml b/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.3.qml new file mode 100644 index 0000000..195be21 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.3.qml @@ -0,0 +1,10 @@ +import Test 1.1 + +MyRevisionedClass +{ + propA: 10 + propB: 10 + propC: 10 + // propD is in rev 1 of MyRevisionedClassUnregistered, but not registered in 1.1 + propD: 10 +} diff --git a/tests/auto/declarative/qdeclarativelanguage/data/revisions10.qml b/tests/auto/declarative/qdeclarativelanguage/data/revisions10.qml new file mode 100644 index 0000000..c4974cf --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/revisions10.qml @@ -0,0 +1,8 @@ +import QtQuick 1.0 +import Test 1.0 + +MyRevisionedClass +{ + property real prop2: 10 + prop1: 1 +} diff --git a/tests/auto/declarative/qdeclarativelanguage/data/revisions11.qml b/tests/auto/declarative/qdeclarativelanguage/data/revisions11.qml new file mode 100644 index 0000000..4d3d7d2 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/revisions11.qml @@ -0,0 +1,10 @@ +import QtQuick 1.0 +import Test 1.1 + +MyRevisionedClass +{ + prop1: 1 + prop2: 10 + + onSignal2: prop2 = 3 +} diff --git a/tests/auto/declarative/qdeclarativelanguage/data/revisionsbasesub11.qml b/tests/auto/declarative/qdeclarativelanguage/data/revisionsbasesub11.qml new file mode 100644 index 0000000..57d76b1 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/revisionsbasesub11.qml @@ -0,0 +1,16 @@ +import QtQuick 1.0 +import Test 1.1 + +MyRevisionedSubclass +{ + propA: 10 + propB: 10 + propC: 10 + // propD is not registered in 1.1 + prop1: 10 + prop2: 10 + prop3: 10 + prop4: 10 + + onSignal4: prop4 = 2 +} diff --git a/tests/auto/declarative/qdeclarativelanguage/data/revisionssub10.qml b/tests/auto/declarative/qdeclarativelanguage/data/revisionssub10.qml new file mode 100644 index 0000000..b5de4a3 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/revisionssub10.qml @@ -0,0 +1,10 @@ +import QtQuick 1.0 +import Test 1.0 + +MyRevisionedSubclass +{ + property real prop4: 10 + property real prop2: 10 + prop1: 5 + prop3: 7 +} diff --git a/tests/auto/declarative/qdeclarativelanguage/data/revisionssub11.qml b/tests/auto/declarative/qdeclarativelanguage/data/revisionssub11.qml new file mode 100644 index 0000000..f107356 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/revisionssub11.qml @@ -0,0 +1,12 @@ +import QtQuick 1.0 +import Test 1.1 + +MyRevisionedSubclass +{ + prop1: 10 + prop2: 10 + prop3: 10 + prop4: 10 + + onSignal4: prop4 = 2 +} diff --git a/tests/auto/declarative/qdeclarativelanguage/testtypes.cpp b/tests/auto/declarative/qdeclarativelanguage/testtypes.cpp index e697aeb..217f54a 100644 --- a/tests/auto/declarative/qdeclarativelanguage/testtypes.cpp +++ b/tests/auto/declarative/qdeclarativelanguage/testtypes.cpp @@ -52,6 +52,15 @@ void registerTypes() qmlRegisterType("Test",1,0,"MySecondNamespacedType"); qmlRegisterType("Test",1,0,"MyParserStatus"); qmlRegisterType(); + qmlRegisterType("Test",1,0,"MyRevisionedClass"); + qmlRegisterType("Test",1,1,"MyRevisionedClass"); + + // Register the uncreatable base class + qmlRegisterRevision("Test",1,1); + // MyRevisionedSubclass 1.0 uses MyRevisionedClass revision 0 + qmlRegisterType("Test",1,0,"MyRevisionedSubclass"); + // MyRevisionedSubclass 1.1 uses MyRevisionedClass revision 1 + qmlRegisterType("Test",1,1,"MyRevisionedSubclass"); qmlRegisterCustomType("Test", 1, 0, "MyCustomParserType", new MyCustomParserTypeParser); diff --git a/tests/auto/declarative/qdeclarativelanguage/testtypes.h b/tests/auto/declarative/qdeclarativelanguage/testtypes.h index f8d785c..4508d01 100644 --- a/tests/auto/declarative/qdeclarativelanguage/testtypes.h +++ b/tests/auto/declarative/qdeclarativelanguage/testtypes.h @@ -601,6 +601,169 @@ private: int m_ccc; }; +class MyRevisionedBaseClassRegistered : public QObject +{ + Q_OBJECT + Q_PROPERTY(qreal propA READ propA WRITE setPropA NOTIFY propAChanged) + Q_PROPERTY(qreal propB READ propB WRITE setPropB NOTIFY propBChanged REVISION 1) + +public: + MyRevisionedBaseClassRegistered() : m_pa(1), m_pb(2) {} + + qreal propA() const { return m_pa; } + void setPropA(qreal p) { + if (p != m_pa) { + m_pa = p; + emit propAChanged(); + } + } + qreal propB() const { return m_pb; } + void setPropB(qreal p) { + if (p != m_pb) { + m_pb = p; + emit propBChanged(); + } + } + + Q_INVOKABLE void methodA() { } + Q_INVOKABLE Q_REVISION(1) void methodB() { } + +signals: + void propAChanged(); + void propBChanged(); + + void signalA(); + Q_REVISION(1) void signalB(); + +protected: + qreal m_pa; + qreal m_pb; +}; + +class MyRevisionedBaseClassUnregistered : public MyRevisionedBaseClassRegistered +{ + Q_OBJECT + Q_PROPERTY(qreal propC READ propC WRITE setPropC NOTIFY propCChanged) + Q_PROPERTY(qreal propD READ propD WRITE setPropD NOTIFY propDChanged REVISION 1) + +public: + MyRevisionedBaseClassUnregistered() : m_pc(1), m_pd(2) {} + + qreal propC() const { return m_pc; } + void setPropC(qreal p) { + if (p != m_pc) { + m_pc = p; + emit propCChanged(); + } + } + qreal propD() const { return m_pd; } + void setPropD(qreal p) { + if (p != m_pd) { + m_pd = p; + emit propDChanged(); + } + } + + Q_INVOKABLE void methodC() { } + Q_INVOKABLE Q_REVISION(1) void methodD() { } + +signals: + void propCChanged(); + void propDChanged(); + + void signalC(); + Q_REVISION(1) void signalD(); + +protected: + qreal m_pc; + qreal m_pd; +}; + +class MyRevisionedClass : public MyRevisionedBaseClassUnregistered +{ + Q_OBJECT + Q_PROPERTY(qreal prop1 READ prop1 WRITE setProp1 NOTIFY prop1Changed) + Q_PROPERTY(qreal prop2 READ prop2 WRITE setProp2 NOTIFY prop2Changed REVISION 1) + +public: + MyRevisionedClass() : m_p1(1), m_p2(2) {} + + qreal prop1() const { return m_p1; } + void setProp1(qreal p) { + if (p != m_p1) { + m_p1 = p; + emit prop1Changed(); + } + } + qreal prop2() const { return m_p2; } + void setProp2(qreal p) { + if (p != m_p2) { + m_p2 = p; + emit prop2Changed(); + } + } + + Q_INVOKABLE void method1() { } + Q_INVOKABLE Q_REVISION(1) void method2() { } + +signals: + void prop1Changed(); + void prop2Changed(); + + void signal1(); + Q_REVISION(1) void signal2(); + +protected: + qreal m_p1; + qreal m_p2; +}; + +class MyRevisionedSubclass : public MyRevisionedClass +{ + Q_OBJECT + Q_PROPERTY(qreal prop3 READ prop3 WRITE setProp3 NOTIFY prop3Changed) + Q_PROPERTY(qreal prop4 READ prop4 WRITE setProp4 NOTIFY prop4Changed REVISION 1) + +public: + MyRevisionedSubclass() : m_p3(3), m_p4(4) {} + + qreal prop3() const { return m_p3; } + void setProp3(qreal p) { + if (p != m_p3) { + m_p3 = p; + emit prop3Changed(); + } + } + qreal prop4() const { return m_p4; } + void setProp4(qreal p) { + if (p != m_p4) { + m_p4 = p; + emit prop4Changed(); + } + } + + Q_INVOKABLE void method3() { } + Q_INVOKABLE Q_REVISION(1) void method4() { } + +signals: + void prop3Changed(); + void prop4Changed(); + + void signal3(); + Q_REVISION(1) void signal4(); + +protected: + qreal m_p3; + qreal m_p4; +}; + +QML_DECLARE_TYPE(MyRevisionedBaseClassRegistered) +QML_DECLARE_TYPE(MyRevisionedBaseClassUnregistered) +QML_DECLARE_TYPE(MyRevisionedClass) +QML_DECLARE_TYPE(MyRevisionedSubclass) + + + void registerTypes(); #endif // TESTTYPES_H diff --git a/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp b/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp index 6410853..298d802 100644 --- a/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp +++ b/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp @@ -153,6 +153,8 @@ private slots: void customOnProperty(); void variantNotify(); + void revisions(); + // regression tests for crashes void crash1(); void crash2(); @@ -421,6 +423,10 @@ void tst_qdeclarativelanguage::errors_data() << "incorrectCase.errors.sensitive.txt" #endif << false; + + QTest::newRow("metaobjectRevision.1") << "metaobjectRevision.1.qml" << "metaobjectRevision.1.errors.txt" << false; + QTest::newRow("metaobjectRevision.2") << "metaobjectRevision.2.qml" << "metaobjectRevision.2.errors.txt" << false; + QTest::newRow("metaobjectRevision.3") << "metaobjectRevision.3.qml" << "metaobjectRevision.3.errors.txt" << false; } @@ -1888,6 +1894,62 @@ void tst_qdeclarativelanguage::variantNotify() delete object; } +void tst_qdeclarativelanguage::revisions() +{ + { + QDeclarativeComponent component(&engine, TEST_FILE("revisions10.qml")); + + VERIFY_ERRORS(0); + MyRevisionedClass *object = qobject_cast(component.create()); + QVERIFY(object != 0); + + QCOMPARE(object->prop2(), 2.0); + QCOMPARE(object->property("prop2").toReal(), 10.0); + + delete object; + } + { + QDeclarativeComponent component(&engine, TEST_FILE("revisions11.qml")); + + VERIFY_ERRORS(0); + MyRevisionedClass *object = qobject_cast(component.create()); + QVERIFY(object != 0); + + QCOMPARE(object->prop2(), 10.0); + + delete object; + } + { + QDeclarativeComponent component(&engine, TEST_FILE("revisionssub10.qml")); + + VERIFY_ERRORS(0); + MyRevisionedSubclass *object = qobject_cast(component.create()); + QVERIFY(object != 0); + + QCOMPARE(object->prop2(), 2.0); + QCOMPARE(object->property("prop2").toReal(), 10.0); + + QCOMPARE(object->prop4(), 4.0); + QCOMPARE(object->property("prop4").toReal(), 10.0); + + delete object; + } + { + QDeclarativeComponent component(&engine, TEST_FILE("revisionssub11.qml")); + + VERIFY_ERRORS(0); + MyRevisionedSubclass *object = qobject_cast(component.create()); + QVERIFY(object != 0); + + QCOMPARE(object->prop1(), 10.0); + QCOMPARE(object->prop2(), 10.0); + QCOMPARE(object->prop3(), 10.0); + QCOMPARE(object->prop4(), 10.0); + + delete object; + } +} + void tst_qdeclarativelanguage::initTestCase() { registerTypes(); diff --git a/tests/auto/declarative/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp b/tests/auto/declarative/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp index 0f6d531..a1f938a 100644 --- a/tests/auto/declarative/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp +++ b/tests/auto/declarative/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp @@ -546,7 +546,6 @@ void tst_QMetaObjectBuilder::property() QVERIFY(!nullProp.isUser()); QVERIFY(!nullProp.hasStdCppSet()); QVERIFY(!nullProp.isEnumOrFlag()); - QVERIFY(!nullProp.isDynamic()); QCOMPARE(nullProp.index(), 0); // Add a property and check its attributes. @@ -564,7 +563,6 @@ void tst_QMetaObjectBuilder::property() QVERIFY(!prop1.isUser()); QVERIFY(!prop1.hasStdCppSet()); QVERIFY(!prop1.isEnumOrFlag()); - QVERIFY(!prop1.isDynamic()); QCOMPARE(prop1.index(), 0); QCOMPARE(builder.propertyCount(), 1); @@ -583,7 +581,6 @@ void tst_QMetaObjectBuilder::property() QVERIFY(!prop2.isUser()); QVERIFY(!prop2.hasStdCppSet()); QVERIFY(!prop2.isEnumOrFlag()); - QVERIFY(!prop2.isDynamic()); QCOMPARE(prop2.index(), 1); QCOMPARE(builder.propertyCount(), 2); @@ -605,7 +602,6 @@ void tst_QMetaObjectBuilder::property() prop1.setUser(true); prop1.setStdCppSet(true); prop1.setEnumOrFlag(true); - prop1.setDynamic(true); // Check that prop1 is changed, but prop2 is not. QCOMPARE(prop1.name(), QByteArray("foo")); @@ -620,7 +616,6 @@ void tst_QMetaObjectBuilder::property() QVERIFY(prop1.isUser()); QVERIFY(prop1.hasStdCppSet()); QVERIFY(prop1.isEnumOrFlag()); - QVERIFY(prop1.isDynamic()); QVERIFY(prop2.isReadable()); QVERIFY(prop2.isWritable()); QCOMPARE(prop2.name(), QByteArray("bar")); @@ -633,7 +628,6 @@ void tst_QMetaObjectBuilder::property() QVERIFY(!prop2.isUser()); QVERIFY(!prop2.hasStdCppSet()); QVERIFY(!prop2.isEnumOrFlag()); - QVERIFY(!prop2.isDynamic()); // Remove prop1 and check that prop2 becomes index 0. builder.removeProperty(0); @@ -649,7 +643,6 @@ void tst_QMetaObjectBuilder::property() QVERIFY(!prop2.isUser()); QVERIFY(!prop2.hasStdCppSet()); QVERIFY(!prop2.isEnumOrFlag()); - QVERIFY(!prop2.isDynamic()); QCOMPARE(prop2.index(), 0); // Perform index-based lookup again. @@ -673,7 +666,6 @@ void tst_QMetaObjectBuilder::property() prop2.setUser(false); \ prop2.setStdCppSet(false); \ prop2.setEnumOrFlag(false); \ - prop2.setDynamic(false); \ } while (0) #define COUNT_FLAGS() \ ((prop2.isReadable() ? 1 : 0) + \ @@ -685,8 +677,7 @@ void tst_QMetaObjectBuilder::property() (prop2.isEditable() ? 1 : 0) + \ (prop2.isUser() ? 1 : 0) + \ (prop2.hasStdCppSet() ? 1 : 0) + \ - (prop2.isEnumOrFlag() ? 1 : 0) + \ - (prop2.isDynamic() ? 1 : 0)) + (prop2.isEnumOrFlag() ? 1 : 0)) #define CHECK_FLAG(setFunc,isFunc) \ do { \ CLEAR_FLAGS(); \ @@ -705,7 +696,6 @@ void tst_QMetaObjectBuilder::property() CHECK_FLAG(setUser, isUser); CHECK_FLAG(setStdCppSet, hasStdCppSet); CHECK_FLAG(setEnumOrFlag, isEnumOrFlag); - CHECK_FLAG(setDynamic, isDynamic); // Check that nothing else changed. QVERIFY(checkForSideEffects(builder, QMetaObjectBuilder::Properties)); -- cgit v0.12 From 810eb8e2bf52a30632abc42618b7f9f4352e2dd9 Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Wed, 5 Jan 2011 14:01:44 +1000 Subject: Add missing test data file --- .../auto/declarative/qdeclarativexmllistmodel/data/testtypes.qml | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 tests/auto/declarative/qdeclarativexmllistmodel/data/testtypes.qml diff --git a/tests/auto/declarative/qdeclarativexmllistmodel/data/testtypes.qml b/tests/auto/declarative/qdeclarativexmllistmodel/data/testtypes.qml new file mode 100644 index 0000000..4dbcc02 --- /dev/null +++ b/tests/auto/declarative/qdeclarativexmllistmodel/data/testtypes.qml @@ -0,0 +1,8 @@ +import QtQuick 1.0 + +XmlListModel { + query: "/data" + XmlRole { name: "stringValue"; query: "a-string/string()" } + XmlRole { name: "numberValue"; query: "a-number/number()" } +} + -- cgit v0.12 From c3a4ce70e588620393a9a4189f3e429622103406 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Wed, 5 Jan 2011 17:52:36 +1000 Subject: Test importing version > registered with a matching base class rev. Consieder the case of a BaseClass registered with version 1.1 and the created Class registered with version 1.0. When version 1.1 is imported the Class should be able to use BaseClass properties from version 1.1. This currently fails. Task-number: QTBUG-13451 --- .../qdeclarativelanguage/data/versionedbase.qml | 8 +++++++ .../declarative/qdeclarativelanguage/testtypes.cpp | 3 +++ .../declarative/qdeclarativelanguage/testtypes.h | 26 ++++++++++++++++++++++ .../tst_qdeclarativelanguage.cpp | 17 +++++++++++++- 4 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 tests/auto/declarative/qdeclarativelanguage/data/versionedbase.qml diff --git a/tests/auto/declarative/qdeclarativelanguage/data/versionedbase.qml b/tests/auto/declarative/qdeclarativelanguage/data/versionedbase.qml new file mode 100644 index 0000000..8c74715 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/versionedbase.qml @@ -0,0 +1,8 @@ +import QtQuick 1.0 +import Test 1.1 + +MySubclass +{ + prop1: 10 + prop2: 10 +} diff --git a/tests/auto/declarative/qdeclarativelanguage/testtypes.cpp b/tests/auto/declarative/qdeclarativelanguage/testtypes.cpp index 217f54a..18e3885 100644 --- a/tests/auto/declarative/qdeclarativelanguage/testtypes.cpp +++ b/tests/auto/declarative/qdeclarativelanguage/testtypes.cpp @@ -62,6 +62,9 @@ void registerTypes() // MyRevisionedSubclass 1.1 uses MyRevisionedClass revision 1 qmlRegisterType("Test",1,1,"MyRevisionedSubclass"); + // Only version 1.0, but its super class is registered in version 1.1 also + qmlRegisterType("Test",1,0,"MySubclass"); + qmlRegisterCustomType("Test", 1, 0, "MyCustomParserType", new MyCustomParserTypeParser); qmlRegisterTypeNotAvailable("Test",1,0,"UnavailableType", "UnavailableType is unavailable for testing"); diff --git a/tests/auto/declarative/qdeclarativelanguage/testtypes.h b/tests/auto/declarative/qdeclarativelanguage/testtypes.h index 4508d01..48055e8 100644 --- a/tests/auto/declarative/qdeclarativelanguage/testtypes.h +++ b/tests/auto/declarative/qdeclarativelanguage/testtypes.h @@ -757,10 +757,36 @@ protected: qreal m_p4; }; +class MySubclass : public MyRevisionedClass +{ + Q_OBJECT + Q_PROPERTY(qreal prop5 READ prop5 WRITE setProp5 NOTIFY prop5Changed) + +public: + MySubclass() : m_p5(5) {} + + qreal prop5() const { return m_p5; } + void setProp5(qreal p) { + if (p != m_p5) { + m_p5 = p; + emit prop5Changed(); + } + } + + Q_INVOKABLE void method5() { } + +signals: + void prop5Changed(); + +protected: + qreal m_p5; +}; + QML_DECLARE_TYPE(MyRevisionedBaseClassRegistered) QML_DECLARE_TYPE(MyRevisionedBaseClassUnregistered) QML_DECLARE_TYPE(MyRevisionedClass) QML_DECLARE_TYPE(MyRevisionedSubclass) +QML_DECLARE_TYPE(MySubclass) diff --git a/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp b/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp index 298d802..a139d5e 100644 --- a/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp +++ b/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp @@ -1935,7 +1935,8 @@ void tst_qdeclarativelanguage::revisions() delete object; } { - QDeclarativeComponent component(&engine, TEST_FILE("revisionssub11.qml")); + QDeclarativeEngine myEngine; + QDeclarativeComponent component(&myEngine, TEST_FILE("revisionssub11.qml")); VERIFY_ERRORS(0); MyRevisionedSubclass *object = qobject_cast(component.create()); @@ -1948,6 +1949,20 @@ void tst_qdeclarativelanguage::revisions() delete object; } + { + // If this is uncommented it will work + // qmlRegisterType("Test",1,1,"MySubclass"); + QDeclarativeComponent component(&engine, TEST_FILE("versionedbase.qml")); + QEXPECT_FAIL("", "Class version 1.0 with base class version 1.1 registered", Abort); + VERIFY_ERRORS(0); + MySubclass *object = qobject_cast(component.create()); + QVERIFY(object != 0); + + QCOMPARE(object->prop1(), 10.0); + QCOMPARE(object->prop2(), 10.0); + + delete object; + } } void tst_qdeclarativelanguage::initTestCase() -- cgit v0.12 From 5c11ca38c441dd0e4e105ca0b5372dc917cf31b1 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Thu, 6 Jan 2011 10:56:06 +1000 Subject: Ensure QDeclarativePrivate::RegisterType version is updated and checked. Also exclude from bic check since we expect its size to increase from time to time. Task-number: QTBUG-13451 Reviewed-by: Aaron Kennedy --- src/declarative/qml/qdeclarative.h | 4 ++-- src/declarative/qml/qdeclarativemetatype.cpp | 3 ++- src/declarative/qml/qdeclarativeprivate.h | 1 + tests/auto/bic/tst_bic.cpp | 3 +++ 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/declarative/qml/qdeclarative.h b/src/declarative/qml/qdeclarative.h index 8a6d068..cdd7202 100644 --- a/src/declarative/qml/qdeclarative.h +++ b/src/declarative/qml/qdeclarative.h @@ -199,7 +199,7 @@ int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const c QByteArray listName("QDeclarativeListProperty<" + name + ">"); QDeclarativePrivate::RegisterType type = { - 1, + 2, qRegisterMetaType(pointerName.constData()), qRegisterMetaType >(listName.constData()), @@ -233,7 +233,7 @@ int qmlRegisterRevision(const char *uri, int versionMajor, int versionMinor) QByteArray listName("QDeclarativeListProperty<" + name + ">"); QDeclarativePrivate::RegisterType type = { - 1, + 2, qRegisterMetaType(pointerName.constData()), qRegisterMetaType >(listName.constData()), diff --git a/src/declarative/qml/qdeclarativemetatype.cpp b/src/declarative/qml/qdeclarativemetatype.cpp index 1f387c4..e90fa40 100644 --- a/src/declarative/qml/qdeclarativemetatype.cpp +++ b/src/declarative/qml/qdeclarativemetatype.cpp @@ -200,7 +200,8 @@ QDeclarativeType::QDeclarativeType(int index, const QDeclarativePrivate::Registe d->m_name = name; d->m_version_maj = type.versionMajor; d->m_version_min = type.versionMinor; - d->m_revision = type.revision; + if (type.version > 1) // revisions added in version 2 + d->m_revision = type.revision; d->m_typeId = type.typeId; d->m_listId = type.listId; d->m_allocationSize = type.objectSize; diff --git a/src/declarative/qml/qdeclarativeprivate.h b/src/declarative/qml/qdeclarativeprivate.h index a4fc4c1..981df78 100644 --- a/src/declarative/qml/qdeclarativeprivate.h +++ b/src/declarative/qml/qdeclarativeprivate.h @@ -215,6 +215,7 @@ namespace QDeclarativePrivate QDeclarativeCustomParser *customParser; int revision; + // If this is extended ensure "version" is bumped!!! }; struct RegisterInterface { diff --git a/tests/auto/bic/tst_bic.cpp b/tests/auto/bic/tst_bic.cpp index cd1d5ca..74fa252 100644 --- a/tests/auto/bic/tst_bic.cpp +++ b/tests/auto/bic/tst_bic.cpp @@ -135,6 +135,9 @@ tst_Bic::tst_Bic() /* This structure is semi-private and should never shrink */ bic.addBlacklistedClass(QLatin1String("QVFbHeader")); + + /* This structure has a version field that allows extension */ + bic.addBlacklistedClass(QLatin1String("QDeclarativePrivate::RegisterType")); } void tst_Bic::initTestCase_data() -- cgit v0.12 From fa5c838636a8cf4e483706696d19afef495da994 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Thu, 6 Jan 2011 11:10:38 +1000 Subject: Fix version in previous commit. Had already been bumped. The version had already been bumped from 0 to 1. Only the version check was required. Task-number: QTBUG-13451 Reviewed-by: Aaron Kennedy --- src/declarative/qml/qdeclarative.h | 4 ++-- src/declarative/qml/qdeclarativemetatype.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/declarative/qml/qdeclarative.h b/src/declarative/qml/qdeclarative.h index cdd7202..8a6d068 100644 --- a/src/declarative/qml/qdeclarative.h +++ b/src/declarative/qml/qdeclarative.h @@ -199,7 +199,7 @@ int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const c QByteArray listName("QDeclarativeListProperty<" + name + ">"); QDeclarativePrivate::RegisterType type = { - 2, + 1, qRegisterMetaType(pointerName.constData()), qRegisterMetaType >(listName.constData()), @@ -233,7 +233,7 @@ int qmlRegisterRevision(const char *uri, int versionMajor, int versionMinor) QByteArray listName("QDeclarativeListProperty<" + name + ">"); QDeclarativePrivate::RegisterType type = { - 2, + 1, qRegisterMetaType(pointerName.constData()), qRegisterMetaType >(listName.constData()), diff --git a/src/declarative/qml/qdeclarativemetatype.cpp b/src/declarative/qml/qdeclarativemetatype.cpp index e90fa40..48a63bb 100644 --- a/src/declarative/qml/qdeclarativemetatype.cpp +++ b/src/declarative/qml/qdeclarativemetatype.cpp @@ -200,7 +200,7 @@ QDeclarativeType::QDeclarativeType(int index, const QDeclarativePrivate::Registe d->m_name = name; d->m_version_maj = type.versionMajor; d->m_version_min = type.versionMinor; - if (type.version > 1) // revisions added in version 2 + if (type.version >= 1) // revisions added in version 1 d->m_revision = type.revision; d->m_typeId = type.typeId; d->m_listId = type.listId; -- cgit v0.12 From c1a87921c8a85d5ecee9aba3b3578ae8d042c28a Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Thu, 6 Jan 2011 14:22:35 +1000 Subject: Add Repeater itemAdded(), itemRemoved() signals and itemAt() method Task-number: QTBUG-15161 Reviewed-by: Martin Jones --- doc/src/declarative/qdeclarativemodels.qdoc | 4 +- .../graphicsitems/qdeclarativerepeater.cpp | 123 ++++++++---- .../graphicsitems/qdeclarativerepeater_p.h | 6 + .../tst_qdeclarativerepeater.cpp | 216 +++++++++++++++++++-- 4 files changed, 293 insertions(+), 56 deletions(-) diff --git a/doc/src/declarative/qdeclarativemodels.qdoc b/doc/src/declarative/qdeclarativemodels.qdoc index e11cd56..9fc6696 100644 --- a/doc/src/declarative/qdeclarativemodels.qdoc +++ b/doc/src/declarative/qdeclarativemodels.qdoc @@ -161,7 +161,7 @@ while QAbstractItemModel provides a more flexible solution for more complex models. -\section2 QStringList +\section2 QStringList-based model A model may be a simple QStringList, which provides the contents of the list via the \e modelData role. @@ -182,7 +182,7 @@ have changed. If the QStringList changes, it will be necessary to reset the model by calling QDeclarativeContext::setContextProperty() again. -\section2 QList +\section2 QObjectList-based model A list of QObject* values can also be used as a model. A QList provides the properties of the objects in the list as roles. diff --git a/src/declarative/graphicsitems/qdeclarativerepeater.cpp b/src/declarative/graphicsitems/qdeclarativerepeater.cpp index 6f46c7b..fa684c1 100644 --- a/src/declarative/graphicsitems/qdeclarativerepeater.cpp +++ b/src/declarative/graphicsitems/qdeclarativerepeater.cpp @@ -84,43 +84,23 @@ QDeclarativeRepeaterPrivate::~QDeclarativeRepeaterPrivate() \image repeater-simple.png - The \l model of a Repeater can be any of the supported \l {qmlmodels}{Data Models}. + A Repeater's \l model can be any of the supported \l {qmlmodels}{data models}. + Additionally, like delegates for other views, a Repeater delegate can access + its index within the repeater, as well as the model data relevant to the + delegate. See the \l delegate property documentation for details. Items instantiated by the Repeater are inserted, in order, as children of the Repeater's parent. The insertion starts immediately after the repeater's position in its parent stacking list. This allows a Repeater to be used inside a layout. For example, the following Repeater's items are stacked between a red rectangle and a blue rectangle: - + \snippet doc/src/snippets/declarative/repeaters/repeater.qml layout \image repeater.png - \section2 The \c index and \c modelData properties - - The index of a delegate is exposed as an accessible \c index property in the delegate. - Properties of the model are also available depending upon the type of \l {qmlmodels}{Data Model}. - - Here is a Repeater that uses the \c index property inside the instantiated items: - - \table - \row - \o \snippet doc/src/snippets/declarative/repeaters/repeater.qml index - \o \image repeater-index.png - \endtable - - Here is another Repeater that uses the \c modelData property to reference the data for a - particular index: - - \table - \row - \o \snippet doc/src/snippets/declarative/repeaters/repeater.qml modeldata - \o \image repeater-modeldata.png - \endtable - - - A Repeater item owns all items it instantiates. Removing or dynamically destroying + \note A Repeater item owns all items it instantiates. Removing or dynamically destroying an item created by a Repeater results in unpredictable behavior. @@ -146,6 +126,27 @@ QDeclarativeRepeaterPrivate::~QDeclarativeRepeaterPrivate() \endcode */ +/*! + \qmlsignal Repeater::onItemAdded(int index, Item item) + \since Quick 1.1 + + This handler is called when an item is added to the repeater. The \a index + parameter holds the index at which the item has been inserted within the + repeater, and the \a item parameter holds the \l Item that has been added. +*/ + +/*! + \qmlsignal Repeater::onItemRemoved(int index, Item item) + \since Quick 1.1 + + This handler is called when an item is removed from the repeater. The \a index + parameter holds the index at which the item was removed from the repeater, + and the \a item parameter holds the \l Item that was removed. + + Do not keep a reference to \a item if it was created by this repeater, as + in these cases it will be deleted shortly after the handler is called. +*/ + QDeclarativeRepeater::QDeclarativeRepeater(QDeclarativeItem *parent) : QDeclarativeItem(*(new QDeclarativeRepeaterPrivate), parent) { @@ -160,26 +161,16 @@ QDeclarativeRepeater::~QDeclarativeRepeater() The model providing data for the repeater. - This property can be set to any of the following: + This property can be set to any of the supported \l {qmlmodels}{data models}: \list - \o A number that indicates the number of delegates to be created + \o A number that indicates the number of delegates to be created by the repeater \o A model (e.g. a ListModel item, or a QAbstractItemModel subclass) \o A string list \o An object list \endlist - In each case, the data element and the index is exposed to each instantiated - component. The index is always exposed as an accessible \c index property. - In the case of an object or string list, the data element (of type string - or object) is available as the \c modelData property. In the case of a Qt model, - all roles are available as named properties just like in the view classes. - - As a special case the model can also be merely a number. In this case it will - create that many instances of the component. They will also be assigned an index - based on the order they are created. - - Models can also be created directly in QML, using a \l{ListModel} or \l{XmlListModel}. + The type of model affects the properties that are exposed to the \l delegate. \sa {qmlmodels}{Data Models} */ @@ -243,8 +234,33 @@ void QDeclarativeRepeater::setModel(const QVariant &model) \default The delegate provides a template defining each item instantiated by the repeater. - The index is exposed as an accessible \c index property. Properties of the - model are also available depending upon the type of \l {qmlmodels}{Data Model}. + + Delegates are exposed to a read-only \c index property that indicates the index + of the delegate within the repeater. For example, the following \l Text delegate + displays the index of each repeated item: + + \table + \row + \o \snippet doc/src/snippets/declarative/repeaters/repeater.qml index + \o \image repeater-index.png + \endtable + + If the \l model is a \l{QStringList-based model}{string list} or + \l{QObjectList-based model}{object list}, the delegate is also exposed to + a read-only \c modelData property that holds the string or object data. For + example: + + \table + \row + \o \snippet doc/src/snippets/declarative/repeaters/repeater.qml modeldata + \o \image repeater-modeldata.png + \endtable + + If the \l model is a model object (such as a \l ListModel) the delegate + can access all model roles as named properties, in the same way that delegates + do for view classes like ListView. + + \sa {QML Data Models} */ QDeclarativeComponent *QDeclarativeRepeater::delegate() const { @@ -288,6 +304,21 @@ int QDeclarativeRepeater::count() const return 0; } +/*! + \qmlmethod Item Repeater::itemAt(index) + \since Quick 1.1 + + Returns the \l Item that has been created at the given \a index, or \c null + if no item exists at \a index. +*/ +QDeclarativeItem *QDeclarativeRepeater::itemAt(int index) const +{ + Q_D(const QDeclarativeRepeater); + if (index >= 0 && index < d->deletables.count()) + return d->deletables[index]; + return 0; + +} void QDeclarativeRepeater::componentComplete() { @@ -309,8 +340,13 @@ QVariant QDeclarativeRepeater::itemChange(GraphicsItemChange change, void QDeclarativeRepeater::clear() { Q_D(QDeclarativeRepeater); + bool complete = isComponentComplete(); + if (d->model) { - foreach (QDeclarativeItem *item, d->deletables) { + while (d->deletables.count() > 0) { + QDeclarativeItem *item = d->deletables.takeLast(); + if (complete) + emit itemRemoved(d->deletables.count()-1, item); d->model->release(item); } } @@ -335,6 +371,7 @@ void QDeclarativeRepeater::regenerate() item->setParentItem(parentItem()); item->stackBefore(this); d->deletables << item; + emit itemAdded(ii, item); } } } @@ -355,6 +392,7 @@ void QDeclarativeRepeater::itemsInserted(int index, int count) else item->stackBefore(this); d->deletables.insert(modelIndex, item); + emit itemAdded(modelIndex, item); } } emit countChanged(); @@ -367,6 +405,7 @@ void QDeclarativeRepeater::itemsRemoved(int index, int count) return; while (count--) { QDeclarativeItem *item = d->deletables.takeAt(index); + emit itemRemoved(index, item); if (item) d->model->release(item); else diff --git a/src/declarative/graphicsitems/qdeclarativerepeater_p.h b/src/declarative/graphicsitems/qdeclarativerepeater_p.h index ff58fa0..62552a6 100644 --- a/src/declarative/graphicsitems/qdeclarativerepeater_p.h +++ b/src/declarative/graphicsitems/qdeclarativerepeater_p.h @@ -72,10 +72,16 @@ public: int count() const; + Q_INVOKABLE Q_REVISION(1) QDeclarativeItem *itemAt(int index) const; + Q_SIGNALS: void modelChanged(); void delegateChanged(); void countChanged(); + + Q_REVISION(1) void itemAdded(int index, QDeclarativeItem *item); + Q_REVISION(1) void itemRemoved(int index, QDeclarativeItem *item); + private: void clear(); void regenerate(); diff --git a/tests/auto/declarative/qdeclarativerepeater/tst_qdeclarativerepeater.cpp b/tests/auto/declarative/qdeclarativerepeater/tst_qdeclarativerepeater.cpp index 91a4d68..1b38c11 100644 --- a/tests/auto/declarative/qdeclarativerepeater/tst_qdeclarativerepeater.cpp +++ b/tests/auto/declarative/qdeclarativerepeater/tst_qdeclarativerepeater.cpp @@ -69,8 +69,11 @@ private slots: void numberModel(); void objectList(); void stringList(); - void dataModel(); + void dataModel_adding(); + void dataModel_removing(); + void dataModel_changes(); void itemModel(); + void resetModel(); void properties(); private: @@ -186,6 +189,11 @@ void tst_QDeclarativeRepeater::numberModel() QVERIFY(repeater != 0); QCOMPARE(repeater->parentItem()->childItems().count(), 5+1); + QVERIFY(!repeater->itemAt(-1)); + for (int i=0; icount(); i++) + QCOMPARE(repeater->itemAt(i), repeater->parentItem()->childItems().at(i)); + QVERIFY(!repeater->itemAt(repeater->count())); + QMetaObject::invokeMethod(canvas->rootObject(), "checkProperties"); QVERIFY(testObject->error() == false); @@ -223,6 +231,17 @@ void tst_QDeclarativeRepeater::objectList() QCOMPARE(repeater->property("errors").toInt(), 0);//If this fails either they are out of order or can't find the object's data QCOMPARE(repeater->property("instantiated").toInt(), 100); + QVERIFY(!repeater->itemAt(-1)); + for (int i=0; iitemAt(i), repeater->parentItem()->childItems().at(i)); + QVERIFY(!repeater->itemAt(data.count())); + + QSignalSpy addedSpy(repeater, SIGNAL(itemAdded(int,QDeclarativeItem*))); + QSignalSpy removedSpy(repeater, SIGNAL(itemRemoved(int,QDeclarativeItem*))); + ctxt->setContextProperty("testData", QVariant::fromValue(data)); + QCOMPARE(addedSpy.count(), data.count()); + QCOMPARE(removedSpy.count(), data.count()); + qDeleteAll(data); delete canvas; } @@ -284,7 +303,69 @@ void tst_QDeclarativeRepeater::stringList() delete canvas; } -void tst_QDeclarativeRepeater::dataModel() +void tst_QDeclarativeRepeater::dataModel_adding() +{ + QDeclarativeView *canvas = createView(); + QDeclarativeContext *ctxt = canvas->rootContext(); + TestObject *testObject = new TestObject; + ctxt->setContextProperty("testObject", testObject); + + TestModel testModel; + ctxt->setContextProperty("testData", &testModel); + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/repeater2.qml")); + qApp->processEvents(); + + QDeclarativeRepeater *repeater = findItem(canvas->rootObject(), "repeater"); + QVERIFY(repeater != 0); + QDeclarativeItem *container = findItem(canvas->rootObject(), "container"); + QVERIFY(container != 0); + + QVERIFY(!repeater->itemAt(0)); + + QSignalSpy countSpy(repeater, SIGNAL(countChanged())); + QSignalSpy addedSpy(repeater, SIGNAL(itemAdded(int,QDeclarativeItem*))); + + // add to empty model + testModel.addItem("two", "2"); + QCOMPARE(repeater->itemAt(0), container->childItems().at(0)); + QCOMPARE(countSpy.count(), 1); countSpy.clear(); + QCOMPARE(addedSpy.count(), 1); + QCOMPARE(addedSpy.at(0).at(0).toInt(), 0); + QCOMPARE(addedSpy.at(0).at(1).value(), container->childItems().at(0)); + addedSpy.clear(); + + // insert at start + testModel.insertItem(0, "one", "1"); + QCOMPARE(repeater->itemAt(0), container->childItems().at(0)); + QCOMPARE(countSpy.count(), 1); countSpy.clear(); + QCOMPARE(addedSpy.count(), 1); + QCOMPARE(addedSpy.at(0).at(0).toInt(), 0); + QCOMPARE(addedSpy.at(0).at(1).value(), container->childItems().at(0)); + addedSpy.clear(); + + // insert at end + testModel.insertItem(2, "four", "4"); + QCOMPARE(repeater->itemAt(2), container->childItems().at(2)); + QCOMPARE(countSpy.count(), 1); countSpy.clear(); + QCOMPARE(addedSpy.count(), 1); + QCOMPARE(addedSpy.at(0).at(0).toInt(), 2); + QCOMPARE(addedSpy.at(0).at(1).value(), container->childItems().at(2)); + addedSpy.clear(); + + // insert in middle + testModel.insertItem(2, "three", "3"); + QCOMPARE(repeater->itemAt(2), container->childItems().at(2)); + QCOMPARE(countSpy.count(), 1); countSpy.clear(); + QCOMPARE(addedSpy.count(), 1); + QCOMPARE(addedSpy.at(0).at(0).toInt(), 2); + QCOMPARE(addedSpy.at(0).at(1).value(), container->childItems().at(2)); + addedSpy.clear(); + + delete testObject; + delete canvas; +} + +void tst_QDeclarativeRepeater::dataModel_removing() { QDeclarativeView *canvas = createView(); QDeclarativeContext *ctxt = canvas->rootContext(); @@ -295,28 +376,84 @@ void tst_QDeclarativeRepeater::dataModel() testModel.addItem("one", "1"); testModel.addItem("two", "2"); testModel.addItem("three", "3"); + testModel.addItem("four", "4"); + testModel.addItem("five", "5"); ctxt->setContextProperty("testData", &testModel); - canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/repeater2.qml")); qApp->processEvents(); QDeclarativeRepeater *repeater = findItem(canvas->rootObject(), "repeater"); QVERIFY(repeater != 0); - QDeclarativeItem *container = findItem(canvas->rootObject(), "container"); QVERIFY(container != 0); + QCOMPARE(container->childItems().count(), repeater->count()+1); + + QSignalSpy countSpy(repeater, SIGNAL(countChanged())); + QSignalSpy removedSpy(repeater, SIGNAL(itemRemoved(int,QDeclarativeItem*))); + + // remove at start + QDeclarativeItem *item = repeater->itemAt(0); + QCOMPARE(item, container->childItems().at(0)); + + testModel.removeItem(0); + QVERIFY(repeater->itemAt(0) != item); + QCOMPARE(countSpy.count(), 1); countSpy.clear(); + QCOMPARE(removedSpy.count(), 1); + QCOMPARE(removedSpy.at(0).at(0).toInt(), 0); + QCOMPARE(removedSpy.at(0).at(1).value(), item); + removedSpy.clear(); + + // remove at end + int lastIndex = testModel.count()-1; + item = repeater->itemAt(lastIndex); + QCOMPARE(item, container->childItems().at(lastIndex)); + + testModel.removeItem(lastIndex); + QVERIFY(repeater->itemAt(lastIndex) != item); + QCOMPARE(countSpy.count(), 1); countSpy.clear(); + QCOMPARE(removedSpy.count(), 1); + QCOMPARE(removedSpy.at(0).at(0).toInt(), lastIndex); + QCOMPARE(removedSpy.at(0).at(1).value(), item); + removedSpy.clear(); + + // remove from middle + item = repeater->itemAt(1); + QCOMPARE(item, container->childItems().at(1)); + + testModel.removeItem(1); + QVERIFY(repeater->itemAt(lastIndex) != item); + QCOMPARE(countSpy.count(), 1); countSpy.clear(); + QCOMPARE(removedSpy.count(), 1); + QCOMPARE(removedSpy.at(0).at(0).toInt(), 1); + QCOMPARE(removedSpy.at(0).at(1).value(), item); + removedSpy.clear(); - QCOMPARE(container->childItems().count(), 4); + delete testObject; + delete canvas; +} - QSignalSpy repeaterSpy(repeater, SIGNAL(countChanged())); - testModel.addItem("four", "4"); - QCOMPARE(container->childItems().count(), 5); - QCOMPARE(repeaterSpy.count(),1); +void tst_QDeclarativeRepeater::dataModel_changes() +{ + QDeclarativeView *canvas = createView(); + QDeclarativeContext *ctxt = canvas->rootContext(); + TestObject *testObject = new TestObject; + ctxt->setContextProperty("testObject", testObject); - testModel.removeItem(2); - QCOMPARE(container->childItems().count(), 4); - QCOMPARE(repeaterSpy.count(),2); + TestModel testModel; + testModel.addItem("one", "1"); + testModel.addItem("two", "2"); + testModel.addItem("three", "3"); + + ctxt->setContextProperty("testData", &testModel); + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/repeater2.qml")); + qApp->processEvents(); + + QDeclarativeRepeater *repeater = findItem(canvas->rootObject(), "repeater"); + QVERIFY(repeater != 0); + QDeclarativeItem *container = findItem(canvas->rootObject(), "container"); + QVERIFY(container != 0); + QCOMPARE(container->childItems().count(), repeater->count()+1); // Check that model changes are propagated QDeclarativeText *text = findItem(canvas->rootObject(), "myName", 1); @@ -377,6 +514,61 @@ void tst_QDeclarativeRepeater::itemModel() delete canvas; } +void tst_QDeclarativeRepeater::resetModel() +{ + QDeclarativeView *canvas = createView(); + + QStringList dataA; + for (int i=0; i<10; i++) + dataA << QString::number(i); + + QDeclarativeContext *ctxt = canvas->rootContext(); + ctxt->setContextProperty("testData", dataA); + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/repeater1.qml")); + qApp->processEvents(); + QDeclarativeRepeater *repeater = findItem(canvas->rootObject(), "repeater"); + QVERIFY(repeater != 0); + QDeclarativeItem *container = findItem(canvas->rootObject(), "container"); + QVERIFY(container != 0); + + QCOMPARE(repeater->count(), dataA.count()); + + QSignalSpy countSpy(repeater, SIGNAL(countChanged())); + QSignalSpy addedSpy(repeater, SIGNAL(itemAdded(int,QDeclarativeItem*))); + QSignalSpy removedSpy(repeater, SIGNAL(itemRemoved(int,QDeclarativeItem*))); + + QStringList dataB; + for (int i=0; i<20; i++) + dataB << QString::number(i); + + // reset context property + ctxt->setContextProperty("testData", dataB); + QCOMPARE(repeater->count(), dataB.count()); + + QCOMPARE(countSpy.count(), 1); + QCOMPARE(removedSpy.count(), dataA.count()); + QCOMPARE(addedSpy.count(), dataB.count()); + for (int i=0; i(), repeater->itemAt(i)); + } + countSpy.clear(); + removedSpy.clear(); + addedSpy.clear(); + + // reset via setModel() + repeater->setModel(dataA); + QCOMPARE(repeater->count(), dataA.count()); + + QCOMPARE(countSpy.count(), 1); + QCOMPARE(removedSpy.count(), dataB.count()); + QCOMPARE(addedSpy.count(), dataA.count()); + for (int i=0; i(), repeater->itemAt(i)); + } +} + void tst_QDeclarativeRepeater::properties() { QDeclarativeEngine engine; -- cgit v0.12 From c527a1ee371c4758776217e7d16c75e20fe6f5aa Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Fri, 7 Jan 2011 10:24:54 +1000 Subject: Fix to register Repeater for QtQuick 1.1 Task-number: QTBUG-15161 Reviewed-by: Martin Jones --- .../graphicsitems/qdeclarativeitemsmodule.cpp | 4 ++ .../tst_qdeclarativerepeater.cpp | 46 ++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp b/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp index a462763..f06b256 100644 --- a/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp +++ b/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp @@ -175,6 +175,10 @@ void QDeclarativeItemModule::defineModule() qmlRegisterType(); #endif + // QtQuick 1.1 items + qmlRegisterType("QtQuick",1,1,"Repeater"); + + qmlRegisterUncreatableType("QtQuick",1,0,"KeyNavigation",QDeclarativeKeyNavigationAttached::tr("KeyNavigation is only available via attached properties")); qmlRegisterUncreatableType("QtQuick",1,0,"Keys",QDeclarativeKeysAttached::tr("Keys is only available via attached properties")); diff --git a/tests/auto/declarative/qdeclarativerepeater/tst_qdeclarativerepeater.cpp b/tests/auto/declarative/qdeclarativerepeater/tst_qdeclarativerepeater.cpp index 1b38c11..0629076 100644 --- a/tests/auto/declarative/qdeclarativerepeater/tst_qdeclarativerepeater.cpp +++ b/tests/auto/declarative/qdeclarativerepeater/tst_qdeclarativerepeater.cpp @@ -75,6 +75,8 @@ private slots: void itemModel(); void resetModel(); void properties(); + void testQtQuick11Attributes(); + void testQtQuick11Attributes_data(); private: QDeclarativeView *createView(); @@ -599,6 +601,50 @@ void tst_QDeclarativeRepeater::properties() delete rootObject; } +void tst_QDeclarativeRepeater::testQtQuick11Attributes() +{ + QFETCH(QString, code); + QFETCH(QString, warning); + QFETCH(QString, error); + + QDeclarativeEngine engine; + QObject *obj; + + QDeclarativeComponent invalid(&engine); + invalid.setData("import QtQuick 1.0; Repeater { " + code.toUtf8() + " }", QUrl("")); + QTest::ignoreMessage(QtWarningMsg, warning.toUtf8()); + obj = invalid.create(); + QCOMPARE(invalid.errorString(), error); + delete obj; + + QDeclarativeComponent valid(&engine); + valid.setData("import QtQuick 1.1; Repeater { " + code.toUtf8() + " }", QUrl("")); + obj = valid.create(); + QVERIFY(obj); + QVERIFY(valid.errorString().isEmpty()); + delete obj; +} + +void tst_QDeclarativeRepeater::testQtQuick11Attributes_data() +{ + QTest::addColumn("code"); + QTest::addColumn("warning"); + QTest::addColumn("error"); + + QTest::newRow("itemAdded") << "onItemAdded: count" + << "QDeclarativeComponent: Component is not ready" + << ":1 Signal \"onItemAdded\" not available in QtQuick/Repeater 1.0\n"; + + QTest::newRow("itemRemoved") << "onItemRemoved: count" + << "QDeclarativeComponent: Component is not ready" + << ":1 Signal \"onItemRemoved\" not available in QtQuick/Repeater 1.0\n"; + + QTest::newRow("itemAt") << "Component.onCompleted: itemAt(0)" + << ":1: ReferenceError: Can't find variable: itemAt" + << ""; +} + + QDeclarativeView *tst_QDeclarativeRepeater::createView() { QDeclarativeView *canvas = new QDeclarativeView(0); -- cgit v0.12 From 8b45ca46095020c495b44d764bb439018a87d22a Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Fri, 7 Jan 2011 10:36:01 +1000 Subject: Add linkActivated signal to TextEdit Since TextEdit can also contain rich text with anchors, it should also have a linkActivated signal like Text does. Task-number: QTBUG-15283 Reviewed-by: Martin Jones --- .../graphicsitems/qdeclarativeitemsmodule.cpp | 1 + .../graphicsitems/qdeclarativetextedit.cpp | 16 +- .../graphicsitems/qdeclarativetextedit_p.h | 1 + .../data-X11/linkActivated.0.png | Bin 0 -> 609 bytes .../data-X11/linkActivated.1.png | Bin 0 -> 677 bytes .../data-X11/linkActivated.qml | 191 +++++++++++++++++++++ .../qdeclarativetextedit/data/linkActivated.0.png | Bin 0 -> 609 bytes .../qdeclarativetextedit/data/linkActivated.1.png | Bin 0 -> 677 bytes .../qdeclarativetextedit/data/linkActivated.qml | 191 +++++++++++++++++++++ .../qdeclarativetextedit/linkActivated.qml | 15 ++ 10 files changed, 412 insertions(+), 3 deletions(-) create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetextedit/data-X11/linkActivated.0.png create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetextedit/data-X11/linkActivated.1.png create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetextedit/data-X11/linkActivated.qml create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/linkActivated.0.png create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/linkActivated.1.png create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/linkActivated.qml create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetextedit/linkActivated.qml diff --git a/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp b/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp index a462763..752e239 100644 --- a/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp +++ b/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp @@ -142,6 +142,7 @@ void QDeclarativeItemModule::defineModule() qmlRegisterType("QtQuick",1,0,"Scale"); qmlRegisterType("QtQuick",1,0,"Text"); qmlRegisterType("QtQuick",1,0,"TextEdit"); + qmlRegisterType("QtQuick",1,1,"TextEdit"); #ifndef QT_NO_LINEEDIT qmlRegisterType("QtQuick",1,0,"TextInput"); #endif diff --git a/src/declarative/graphicsitems/qdeclarativetextedit.cpp b/src/declarative/graphicsitems/qdeclarativetextedit.cpp index c1314ff..c71fd98 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextedit.cpp @@ -103,6 +103,14 @@ TextEdit { \sa Text, TextInput, {declarative/text/textselection}{Text Selection example} */ +/*! + \qmlsignal TextEdit::onLinkActivated(string link) + \since Quick 1.1 + + This handler is called when the user clicks on a link embedded in the text. + The link must be in rich text or HTML format and the + \a link string provides access to the particular link. +*/ QDeclarativeTextEdit::QDeclarativeTextEdit(QDeclarativeItem *parent) : QDeclarativePaintedItem(*(new QDeclarativeTextEditPrivate), parent) { @@ -894,11 +902,11 @@ void QDeclarativeTextEdit::setReadOnly(bool r) return; - Qt::TextInteractionFlags flags = Qt::NoTextInteraction; + Qt::TextInteractionFlags flags = Qt::LinksAccessibleByMouse; if (r) { - flags = Qt::TextSelectableByMouse; + flags = flags | Qt::TextSelectableByMouse; } else { - flags = Qt::TextEditorInteraction; + flags = flags | Qt::TextEditorInteraction; } d->control->setTextInteractionFlags(flags); if (!r) @@ -1260,6 +1268,7 @@ void QDeclarativeTextEditPrivate::init() control = new QTextControl(q); control->setIgnoreUnusedNavigationEvents(true); + control->setTextInteractionFlags(control->textInteractionFlags() | Qt::LinksAccessibleByMouse); // QTextControl follows the default text color // defined by the platform, declarative text @@ -1278,6 +1287,7 @@ void QDeclarativeTextEditPrivate::init() QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SLOT(updateSelectionMarkers())); QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SIGNAL(cursorPositionChanged())); QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SIGNAL(cursorRectangleChanged())); + QObject::connect(control, SIGNAL(linkActivated(QString)), q, SIGNAL(linkActivated(QString))); document = control->document(); document->setDefaultFont(font); diff --git a/src/declarative/graphicsitems/qdeclarativetextedit_p.h b/src/declarative/graphicsitems/qdeclarativetextedit_p.h index 691d995..37b24f7 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextedit_p.h @@ -221,6 +221,7 @@ Q_SIGNALS: void persistentSelectionChanged(bool isPersistentSelection); void textMarginChanged(qreal textMargin); void selectByMouseChanged(bool selectByMouse); + Q_REVISION(1) void linkActivated(const QString &link); public Q_SLOTS: void deselect(); diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data-X11/linkActivated.0.png b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data-X11/linkActivated.0.png new file mode 100644 index 0000000..7d0d0ae Binary files /dev/null and b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data-X11/linkActivated.0.png differ diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data-X11/linkActivated.1.png b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data-X11/linkActivated.1.png new file mode 100644 index 0000000..7d612bf Binary files /dev/null and b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data-X11/linkActivated.1.png differ diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data-X11/linkActivated.qml b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data-X11/linkActivated.qml new file mode 100644 index 0000000..8c7e380 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data-X11/linkActivated.qml @@ -0,0 +1,191 @@ +import Qt.VisualTest 4.7 + +VisualTest { + Frame { + msec: 0 + } + Frame { + msec: 16 + image: "linkActivated.0.png" + } + Frame { + msec: 32 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 48 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 64 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 80 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 96 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 112 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 128 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 144 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 160 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 176 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 192 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 208 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 224 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 240 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 256 + hash: "53d97d0966197ea41364511dea13752f" + } + Mouse { + type: 2 + button: 1 + buttons: 1 + x: 21; y: 13 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 272 + hash: "9482227cbc77e9083218c1452e8644d8" + } + Frame { + msec: 288 + hash: "9482227cbc77e9083218c1452e8644d8" + } + Frame { + msec: 304 + hash: "9482227cbc77e9083218c1452e8644d8" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 22; y: 11 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 320 + hash: "9482227cbc77e9083218c1452e8644d8" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 23; y: 10 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 3 + button: 1 + buttons: 0 + x: 23; y: 10 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 336 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 352 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 368 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 384 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 400 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 416 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 432 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 448 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 464 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 480 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 496 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 512 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 528 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 544 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 560 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 576 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 592 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 608 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/linkActivated.0.png b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/linkActivated.0.png new file mode 100644 index 0000000..7d0d0ae Binary files /dev/null and b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/linkActivated.0.png differ diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/linkActivated.1.png b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/linkActivated.1.png new file mode 100644 index 0000000..7d612bf Binary files /dev/null and b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/linkActivated.1.png differ diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/linkActivated.qml b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/linkActivated.qml new file mode 100644 index 0000000..8c7e380 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/data/linkActivated.qml @@ -0,0 +1,191 @@ +import Qt.VisualTest 4.7 + +VisualTest { + Frame { + msec: 0 + } + Frame { + msec: 16 + image: "linkActivated.0.png" + } + Frame { + msec: 32 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 48 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 64 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 80 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 96 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 112 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 128 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 144 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 160 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 176 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 192 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 208 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 224 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 240 + hash: "53d97d0966197ea41364511dea13752f" + } + Frame { + msec: 256 + hash: "53d97d0966197ea41364511dea13752f" + } + Mouse { + type: 2 + button: 1 + buttons: 1 + x: 21; y: 13 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 272 + hash: "9482227cbc77e9083218c1452e8644d8" + } + Frame { + msec: 288 + hash: "9482227cbc77e9083218c1452e8644d8" + } + Frame { + msec: 304 + hash: "9482227cbc77e9083218c1452e8644d8" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 22; y: 11 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 320 + hash: "9482227cbc77e9083218c1452e8644d8" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 23; y: 10 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 3 + button: 1 + buttons: 0 + x: 23; y: 10 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 336 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 352 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 368 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 384 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 400 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 416 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 432 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 448 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 464 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 480 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 496 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 512 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 528 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 544 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 560 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 576 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 592 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } + Frame { + msec: 608 + hash: "29c47cec5d015e6cab0762c3db0fa714" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextedit/linkActivated.qml b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/linkActivated.qml new file mode 100644 index 0000000..177d475 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextedit/linkActivated.qml @@ -0,0 +1,15 @@ +import QtQuick 1.1 + +Rectangle{ + width: 100 + height: 100 + TextEdit{ + text: 'Click Me ' + onLinkActivated: txt.text=link; + } + Text{ + id: txt + y:50 + text: "unknown" + } +} -- cgit v0.12 From 9a186ba66506963b9d88518d5cea0846825ba494 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Fri, 7 Jan 2011 11:27:25 +1000 Subject: Add PinchArea autotests. Task-number: QTBUG-15491 --- tests/auto/declarative/declarative.pro | 1 + .../declarative/qdeclarativepincharea/tst_qdeclarativepincharea.cpp | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/auto/declarative/declarative.pro b/tests/auto/declarative/declarative.pro index f0fcfa9..51597bd 100644 --- a/tests/auto/declarative/declarative.pro +++ b/tests/auto/declarative/declarative.pro @@ -45,6 +45,7 @@ SUBDIRS += \ qdeclarativemousearea \ qdeclarativeparticles \ qdeclarativepathview \ + qdeclarativepincharea \ qdeclarativepixmapcache \ qdeclarativepositioners \ qdeclarativeproperty \ diff --git a/tests/auto/declarative/qdeclarativepincharea/tst_qdeclarativepincharea.cpp b/tests/auto/declarative/qdeclarativepincharea/tst_qdeclarativepincharea.cpp index d1015fc..f175033 100644 --- a/tests/auto/declarative/qdeclarativepincharea/tst_qdeclarativepincharea.cpp +++ b/tests/auto/declarative/qdeclarativepincharea/tst_qdeclarativepincharea.cpp @@ -229,7 +229,7 @@ void tst_QDeclarativePinchArea::scale() QTest::touchEvent(vp).move(0, p1).move(1, p2); QCOMPARE(root->property("scale").toReal(), 1.5); - QCOMPARE(root->property("center").toPointF(), QPointF(90, 90)); + QCOMPARE(root->property("center").toPointF(), QPointF(40, 40)); // blackrect is at 50,50 QCOMPARE(blackRect->scale(), 1.5); // scale beyond bound @@ -283,7 +283,7 @@ void tst_QDeclarativePinchArea::pan() p2 += QPoint(10,10); QTest::touchEvent(vp).move(0, p1).move(1, p2); - QCOMPARE(root->property("center").toPointF(), QPointF(110, 110)); + QCOMPARE(root->property("center").toPointF(), QPointF(60, 60)); // blackrect is at 50,50 QCOMPARE(blackRect->x(), 60.0); QCOMPARE(blackRect->y(), 60.0); -- cgit v0.12 From d57baa9be741e0db90e08cc39ba8d488f58c40f5 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Fri, 7 Jan 2011 14:10:08 +1000 Subject: PinchArea API changes following review. Task-number: QTBUG-15491 Reviewed-by: Michael Brasser --- .../touchinteraction/pincharea/flickresize.qml | 6 ++-- .../graphicsitems/qdeclarativepincharea.cpp | 42 +++++++++++----------- .../graphicsitems/qdeclarativepincharea_p.h | 20 +++++------ .../qdeclarativepincharea/data/pinchproperties.qml | 2 +- 4 files changed, 35 insertions(+), 35 deletions(-) diff --git a/examples/declarative/touchinteraction/pincharea/flickresize.qml b/examples/declarative/touchinteraction/pincharea/flickresize.qml index 8f29d6d..aa426e7 100644 --- a/examples/declarative/touchinteraction/pincharea/flickresize.qml +++ b/examples/declarative/touchinteraction/pincharea/flickresize.qml @@ -56,11 +56,11 @@ Rectangle { height: Math.max(flick.contentHeight, flick.height) onPinchChanged: { // adjust content pos due to drag - flick.contentX += pinch.lastCenter.x - pinch.center.x - flick.contentY += pinch.lastCenter.y - pinch.center.y + flick.contentX += pinch.previousCenter.x - pinch.center.x + flick.contentY += pinch.previousCenter.y - pinch.center.y // resize content - var scale = 1.0 + pinch.scale - pinch.lastScale + var scale = 1.0 + pinch.scale - pinch.previousScale flick.resizeContent(flick.contentWidth * scale, flick.contentHeight * scale, pinch.center) } diff --git a/src/declarative/graphicsitems/qdeclarativepincharea.cpp b/src/declarative/graphicsitems/qdeclarativepincharea.cpp index 998c30d..436099e 100644 --- a/src/declarative/graphicsitems/qdeclarativepincharea.cpp +++ b/src/declarative/graphicsitems/qdeclarativepincharea.cpp @@ -58,11 +58,11 @@ QT_BEGIN_NAMESPACE \bold {The PinchEvent element was added in QtQuick 1.1} - The \c center, \c startCenter, \c lastCenter properties provide the center position between the two touch points. + The \c center, \c startCenter, \c previousCenter properties provide the center position between the two touch points. - The \c scale and \c lastScale properties provide the scale factor. + The \c scale and \c previousScale properties provide the scale factor. - The \c angle, \c lastAngle and \c rotation properties provide the angle between the two points and the amount of rotation. + The \c angle, \c previousAngle and \c rotation properties provide the angle between the two points and the amount of rotation. The \c point1, \c point2, \c startPoint1, \c startPoint2 properties provide the positions of the touch points. @@ -75,26 +75,26 @@ QT_BEGIN_NAMESPACE /*! \qmlproperty QPointF PinchEvent::center \qmlproperty QPointF PinchEvent::startCenter - \qmlproperty QPointF PinchEvent::lastCenter + \qmlproperty QPointF PinchEvent::previousCenter These properties hold the position of the center point between the two touch points. \list \o \c center is the current center point - \o \c lastCenter is the center point of the previous event. + \o \c previousCenter is the center point of the previous event. \o \c startCenter is the center point when the gesture began \endlist */ /*! \qmlproperty real PinchEvent::scale - \qmlproperty real PinchEvent::lastScale + \qmlproperty real PinchEvent::previousScale These properties hold the scale factor determined by the change in distance between the two touch points. \list \o \c scale is the current scale factor. - \o \c lastScale is the scale factor of the previous event. + \o \c previousScale is the scale factor of the previous event. \endlist When a pinch gesture is started, the scale is 1.0. @@ -102,14 +102,14 @@ QT_BEGIN_NAMESPACE /*! \qmlproperty real PinchEvent::angle - \qmlproperty real PinchEvent::lastAngle + \qmlproperty real PinchEvent::previousAngle \qmlproperty real PinchEvent::rotation These properties hold the angle between the two touch points. \list \o \c angle is the current angle between the two points in the range -180 to 180. - \o \c lastAngle is the angle of the previous event. + \o \c previousAngle is the angle of the previous event. \o \c rotation is the total rotation since the pinch gesture started. \endlist @@ -169,7 +169,7 @@ QDeclarativePinchAreaPrivate::~QDeclarativePinchAreaPrivate() \list \o setting a \c pinch.target to provide automatic interaction with an element - \o using the onPinchStarted, onPinchChanged and onPinchFinished handlers + \o using the onPinchStarted, onPinchUpdated and onPinchFinished handlers \endlist \sa PinchEvent @@ -188,7 +188,7 @@ QDeclarativePinchAreaPrivate::~QDeclarativePinchAreaPrivate() */ /*! - \qmlsignal PinchArea::onPinchChanged() + \qmlsignal PinchArea::onPinchUpdated() This handler is called when the pinch area detects that a pinch gesture has changed. @@ -304,9 +304,9 @@ void QDeclarativePinchArea::updatePinch() QPointF pinchCenter = mapFromScene(d->sceneLastCenter); QDeclarativePinchEvent pe(pinchCenter, d->pinchLastScale, d->pinchLastAngle, rotationAngle); pe.setStartCenter(d->pinchStartCenter); - pe.setLastCenter(pinchCenter); - pe.setLastAngle(d->pinchLastAngle); - pe.setLastScale(d->pinchLastScale); + pe.setPreviousCenter(pinchCenter); + pe.setPreviousAngle(d->pinchLastAngle); + pe.setPreviousScale(d->pinchLastScale); pe.setStartPoint1(mapFromScene(d->sceneStartPoint1)); pe.setStartPoint2(mapFromScene(d->sceneStartPoint2)); pe.setPoint1(d->lastPoint1); @@ -352,9 +352,9 @@ void QDeclarativePinchArea::updatePinch() d->lastPoint2 = d->touchPoints.at(1).pos(); QDeclarativePinchEvent pe(d->pinchStartCenter, 1.0, angle, 0.0); pe.setStartCenter(d->pinchStartCenter); - pe.setLastCenter(d->pinchStartCenter); - pe.setLastAngle(d->pinchLastAngle); - pe.setLastScale(d->pinchLastScale); + pe.setPreviousCenter(d->pinchStartCenter); + pe.setPreviousAngle(d->pinchLastAngle); + pe.setPreviousScale(d->pinchLastScale); pe.setStartPoint1(mapFromScene(d->sceneStartPoint1)); pe.setStartPoint2(mapFromScene(d->sceneStartPoint2)); pe.setPoint1(d->lastPoint1); @@ -383,9 +383,9 @@ void QDeclarativePinchArea::updatePinch() QPointF pinchCenter = mapFromScene(sceneCenter); QDeclarativePinchEvent pe(pinchCenter, scale, angle, rotationAngle); pe.setStartCenter(d->pinchStartCenter); - pe.setLastCenter(mapFromScene(d->sceneLastCenter)); - pe.setLastAngle(d->pinchLastAngle); - pe.setLastScale(d->pinchLastScale); + pe.setPreviousCenter(mapFromScene(d->sceneLastCenter)); + pe.setPreviousAngle(d->pinchLastAngle); + pe.setPreviousScale(d->pinchLastScale); pe.setStartPoint1(mapFromScene(d->sceneStartPoint1)); pe.setStartPoint2(mapFromScene(d->sceneStartPoint2)); pe.setPoint1(d->touchPoints.at(0).pos()); @@ -395,7 +395,7 @@ void QDeclarativePinchArea::updatePinch() d->pinchLastAngle = angle; d->lastPoint1 = d->touchPoints.at(0).pos(); d->lastPoint2 = d->touchPoints.at(1).pos(); - emit pinchChanged(&pe); + emit pinchUpdated(&pe); if (d->pinch && d->pinch->target()) { qreal s = d->pinchStartScale * scale; s = qMin(qMax(pinch()->minimumScale(),s), pinch()->maximumScale()); diff --git a/src/declarative/graphicsitems/qdeclarativepincharea_p.h b/src/declarative/graphicsitems/qdeclarativepincharea_p.h index 9a73a17..cd5423d 100644 --- a/src/declarative/graphicsitems/qdeclarativepincharea_p.h +++ b/src/declarative/graphicsitems/qdeclarativepincharea_p.h @@ -193,11 +193,11 @@ class Q_AUTOTEST_EXPORT QDeclarativePinchEvent : public QObject Q_PROPERTY(QPointF center READ center) Q_PROPERTY(QPointF startCenter READ startCenter) - Q_PROPERTY(QPointF lastCenter READ lastCenter) + Q_PROPERTY(QPointF previousCenter READ previousCenter) Q_PROPERTY(qreal scale READ scale) - Q_PROPERTY(qreal lastScale READ lastScale) + Q_PROPERTY(qreal previousScale READ previousScale) Q_PROPERTY(qreal angle READ angle) - Q_PROPERTY(qreal lastAngle READ lastAngle) + Q_PROPERTY(qreal previousAngle READ previousAngle) Q_PROPERTY(qreal rotation READ rotation) Q_PROPERTY(QPointF point1 READ point1) Q_PROPERTY(QPointF startPoint1 READ startPoint1) @@ -212,14 +212,14 @@ public: QPointF center() const { return m_center; } QPointF startCenter() const { return m_startCenter; } void setStartCenter(QPointF c) { m_startCenter = c; } - QPointF lastCenter() const { return m_lastCenter; } - void setLastCenter(QPointF c) { m_lastCenter = c; } + QPointF previousCenter() const { return m_lastCenter; } + void setPreviousCenter(QPointF c) { m_lastCenter = c; } qreal scale() const { return m_scale; } - qreal lastScale() const { return m_lastScale; } - void setLastScale(qreal s) { m_lastScale = s; } + qreal previousScale() const { return m_lastScale; } + void setPreviousScale(qreal s) { m_lastScale = s; } qreal angle() const { return m_angle; } - qreal lastAngle() const { return m_lastAngle; } - void setLastAngle(qreal a) { m_lastAngle = a; } + qreal previousAngle() const { return m_lastAngle; } + void setPreviousAngle(qreal a) { m_lastAngle = a; } qreal rotation() const { return m_rotation; } QPointF point1() const { return m_point1; } void setPoint1(QPointF p) { m_point1 = p; } @@ -271,7 +271,7 @@ public: Q_SIGNALS: void enabledChanged(); void pinchStarted(QDeclarativePinchEvent *pinch); - void pinchChanged(QDeclarativePinchEvent *pinch); + void pinchUpdated(QDeclarativePinchEvent *pinch); void pinchFinished(QDeclarativePinchEvent *pinch); protected: diff --git a/tests/auto/declarative/qdeclarativepincharea/data/pinchproperties.qml b/tests/auto/declarative/qdeclarativepincharea/data/pinchproperties.qml index f39ea06..0b59d9d 100644 --- a/tests/auto/declarative/qdeclarativepincharea/data/pinchproperties.qml +++ b/tests/auto/declarative/qdeclarativepincharea/data/pinchproperties.qml @@ -33,7 +33,7 @@ Rectangle { whiteRect.center = pinch.center whiteRect.scale = pinch.scale } - onPinchChanged: { + onPinchUpdated: { whiteRect.center = pinch.center whiteRect.scale = pinch.scale } -- cgit v0.12 From 5f4bf308ac7d4c81374f651103f85d45e0065d05 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Fri, 7 Jan 2011 14:11:43 +1000 Subject: Group all QtQuick 1.1 registrations together Task-number: QTBUG-15279 --- src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp b/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp index 5e04168..7db4d85 100644 --- a/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp +++ b/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp @@ -142,20 +142,16 @@ void QDeclarativeItemModule::defineModule() qmlRegisterType("QtQuick",1,0,"Scale"); qmlRegisterType("QtQuick",1,0,"Text"); qmlRegisterType("QtQuick",1,0,"TextEdit"); - qmlRegisterType("QtQuick",1,1,"TextEdit"); #ifndef QT_NO_LINEEDIT qmlRegisterType("QtQuick",1,0,"TextInput"); #endif qmlRegisterType("QtQuick",1,0,"ViewSection"); qmlRegisterType("QtQuick",1,0,"VisualDataModel"); qmlRegisterType("QtQuick",1,0,"VisualItemModel"); - qmlRegisterType("QtQuick",1,1,"PinchArea"); - qmlRegisterType(); qmlRegisterType(); qmlRegisterType(); qmlRegisterType(); - qmlRegisterType(); qmlRegisterType(); qmlRegisterType("QtQuick",1,0,"QGraphicsWidget"); qmlRegisterExtendedType("QtQuick",1,0,"QGraphicsWidget"); @@ -176,13 +172,16 @@ void QDeclarativeItemModule::defineModule() qmlRegisterType(); #endif - // QtQuick 1.1 items - qmlRegisterType("QtQuick",1,1,"Repeater"); - - qmlRegisterUncreatableType("QtQuick",1,0,"KeyNavigation",QDeclarativeKeyNavigationAttached::tr("KeyNavigation is only available via attached properties")); qmlRegisterUncreatableType("QtQuick",1,0,"Keys",QDeclarativeKeysAttached::tr("Keys is only available via attached properties")); + // QtQuick 1.1 items + qmlRegisterType("QtQuick",1,1,"PinchArea"); + qmlRegisterType("QtQuick",1,1,"Pinch"); + qmlRegisterType(); + qmlRegisterType("QtQuick",1,1,"Repeater"); + qmlRegisterType("QtQuick",1,1,"TextEdit"); + #ifndef QT_NO_IMPORT_QT47_QML #ifdef QT_NO_MOVIE qmlRegisterTypeNotAvailable("Qt",4,7,"AnimatedImage", -- cgit v0.12 From d3a6fcd9174b893aaac9db7d5e541ceb54b12402 Mon Sep 17 00:00:00 2001 From: Joona Petrell Date: Thu, 23 Dec 2010 12:24:47 +1000 Subject: Introduce Qt.application.active property Replaces qmlviewer's runtime.activeWindow property. Task-number: QTBUG-13351 Reviewed-by: Martin Jones --- demos/declarative/snake/snake.qml | 2 +- doc/src/snippets/declarative/application.qml | 53 +++++++++ src/declarative/qml/qdeclarativeengine.cpp | 4 + src/declarative/util/qdeclarativeapplication.cpp | 118 +++++++++++++++++++++ src/declarative/util/qdeclarativeapplication_p.h | 83 +++++++++++++++ src/declarative/util/qdeclarativeutilmodule.cpp | 3 + src/declarative/util/util.pri | 2 + tests/auto/declarative/declarative.pro | 1 + .../qdeclarativeapplication.pro | 5 + .../tst_qdeclarativeapplication.cpp | 96 +++++++++++++++++ 10 files changed, 366 insertions(+), 1 deletion(-) create mode 100644 doc/src/snippets/declarative/application.qml create mode 100644 src/declarative/util/qdeclarativeapplication.cpp create mode 100644 src/declarative/util/qdeclarativeapplication_p.h create mode 100644 tests/auto/declarative/qdeclarativeapplication/qdeclarativeapplication.pro create mode 100644 tests/auto/declarative/qdeclarativeapplication/tst_qdeclarativeapplication.cpp diff --git a/demos/declarative/snake/snake.qml b/demos/declarative/snake/snake.qml index af86aac..366c172 100644 --- a/demos/declarative/snake/snake.qml +++ b/demos/declarative/snake/snake.qml @@ -105,7 +105,7 @@ Rectangle { source: "content/pics/pause.png" anchors.centerIn: parent; //opacity is deliberately not animated - opacity: activeGame && !runtime.isActiveWindow + opacity: activeGame && !Qt.application.active } Image { diff --git a/doc/src/snippets/declarative/application.qml b/doc/src/snippets/declarative/application.qml new file mode 100644 index 0000000..2820ff2 --- /dev/null +++ b/doc/src/snippets/declarative/application.qml @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** 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 documentation 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$ +** +****************************************************************************/ + +//! [document] +import QtQuick 1.1 + +Rectangle { + width: 300; height: 55 + color: Qt.application.active ? "white" : "lightgray" + Text { + text: "Application " + (Qt.application.active ? "active" : "inactive") + opacity: Qt.application.active ? 1.0 : 0.5 + anchors.centerIn: parent + } +} +//! [document] diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp index 0a008ff..b940457 100644 --- a/src/declarative/qml/qdeclarativeengine.cpp +++ b/src/declarative/qml/qdeclarativeengine.cpp @@ -70,6 +70,7 @@ #include "private/qdeclarativeinclude_p.h" #include "private/qdeclarativenotifier_p.h" #include "private/qdeclarativedebugtrace_p.h" +#include "private/qdeclarativeapplication_p.h" #include #include @@ -521,6 +522,9 @@ void QDeclarativeEnginePrivate::init() listClass = new QDeclarativeListScriptClass(q); rootContext = new QDeclarativeContext(q,true); + QScriptValue applicationObject = objectClass->newQObject(new QDeclarativeApplication(q)); + scriptEngine.globalObject().property(QLatin1String("Qt")).setProperty(QLatin1String("application"), applicationObject); + if (QCoreApplication::instance()->thread() == q->thread() && QDeclarativeEngineDebugServer::isDebuggingEnabled()) { isDebugging = true; diff --git a/src/declarative/util/qdeclarativeapplication.cpp b/src/declarative/util/qdeclarativeapplication.cpp new file mode 100644 index 0000000..53d196f --- /dev/null +++ b/src/declarative/util/qdeclarativeapplication.cpp @@ -0,0 +1,118 @@ +/**************************************************************************** +** +** 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 "qdeclarativeapplication_p.h" +#include +#include + +class QDeclarativeApplicationPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QDeclarativeApplication) +public: + QDeclarativeApplicationPrivate() : active(QApplication::activeWindow() != 0) {} + bool active; +}; + +/*! + \qmlclass Application QDeclarativeApplication + \since QtQuick 1.1 + \ingroup qml-utility-elements + \brief The Application element provides access to global application + state properties shared by many QML components. + + These properties include application activity property \c active. + + \section1 Example Usage + + The following example shows the simplest usage of the Application element. + + \snippet doc/src/snippets/declarative/application.qml document + +*/ + +QDeclarativeApplication::QDeclarativeApplication(QObject *parent) : QObject(*new QDeclarativeApplicationPrivate(), parent) +{ + if (qApp) + qApp->installEventFilter(this); +} + +QDeclarativeApplication::~QDeclarativeApplication() +{ +} + +/*! + \qmlproperty bool Application::active + + This property indicates whether the application is the top-most and focused + application, and user is able to interact with the application. The property + is false when the application is on the background, device keylock or screen + saver is active, the screen backlight is turned off, or global system dialog + is being displayed on top of the application. It can be used for stopping and + pausing animations, timers, active processing of data to save device battery + and free device memory and processor load when the application is not active. + This property is readonly. + +*/ +bool QDeclarativeApplication::active() const +{ + Q_D(const QDeclarativeApplication); + return d->active; +} + +bool QDeclarativeApplication::eventFilter(QObject *obj, QEvent *event) +{ + Q_UNUSED(obj) + Q_D(QDeclarativeApplication); + if (event->type() == QEvent::ApplicationActivate + || event->type() == QEvent::ApplicationDeactivate) { + bool active = d->active; + if (event->type() == QEvent::ApplicationActivate) + active = true; + else if (event->type() == QEvent::ApplicationDeactivate) + active = false; + + if (d->active != active) { + d->active = active; + emit activeChanged(); + } + } + return false; +} diff --git a/src/declarative/util/qdeclarativeapplication_p.h b/src/declarative/util/qdeclarativeapplication_p.h new file mode 100644 index 0000000..59ea7fe --- /dev/null +++ b/src/declarative/util/qdeclarativeapplication_p.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** 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 QDECLARATIVEAPPLICATION_P_H +#define QDECLARATIVEAPPLICATION_P_H + +#include +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class QDeclarativeApplicationPrivate; +class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeApplication : public QObject +{ + Q_OBJECT + Q_PROPERTY(bool active READ active NOTIFY activeChanged) + +public: + explicit QDeclarativeApplication(QObject *parent = 0); + virtual ~QDeclarativeApplication(); + bool active() const; + +protected: + bool eventFilter(QObject *obj, QEvent *event); + +Q_SIGNALS: + void activeChanged(); + +private: + Q_DISABLE_COPY(QDeclarativeApplication) + Q_DECLARE_PRIVATE(QDeclarativeApplication) +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QDeclarativeApplication) + +QT_END_HEADER + +#endif // QDECLARATIVEAPPLICATION_P_H diff --git a/src/declarative/util/qdeclarativeutilmodule.cpp b/src/declarative/util/qdeclarativeutilmodule.cpp index 0544f22..5abf085 100644 --- a/src/declarative/util/qdeclarativeutilmodule.cpp +++ b/src/declarative/util/qdeclarativeutilmodule.cpp @@ -66,6 +66,7 @@ #include "private/qdeclarativetimer_p.h" #include "private/qdeclarativetransitionmanager_p_p.h" #include "private/qdeclarativetransition_p.h" +#include "private/qdeclarativeapplication_p.h" #include "qdeclarativeview.h" #include "qdeclarativeinfo.h" #include "private/qdeclarativetypenotavailable_p.h" @@ -75,6 +76,8 @@ void QDeclarativeUtilModule::defineModule() { + qmlRegisterUncreatableType("QtQuick",1,1,"Application", "Application is an abstract class"); + qmlRegisterType("QtQuick",1,0,"AnchorAnimation"); qmlRegisterType("QtQuick",1,0,"AnchorChanges"); qmlRegisterType("QtQuick",1,0,"Behavior"); diff --git a/src/declarative/util/util.pri b/src/declarative/util/util.pri index fd57144..62fa8f1 100644 --- a/src/declarative/util/util.pri +++ b/src/declarative/util/util.pri @@ -1,6 +1,7 @@ INCLUDEPATH += $$PWD SOURCES += \ + $$PWD/qdeclarativeapplication.cpp \ $$PWD/qdeclarativeutilmodule.cpp\ $$PWD/qdeclarativeview.cpp \ $$PWD/qdeclarativeconnections.cpp \ @@ -30,6 +31,7 @@ SOURCES += \ $$PWD/qlistmodelinterface.cpp HEADERS += \ + $$PWD/qdeclarativeapplication_p.h \ $$PWD/qdeclarativeutilmodule_p.h\ $$PWD/qdeclarativeview.h \ $$PWD/qdeclarativeconnections_p.h \ diff --git a/tests/auto/declarative/declarative.pro b/tests/auto/declarative/declarative.pro index 51597bd..1f0d32a 100644 --- a/tests/auto/declarative/declarative.pro +++ b/tests/auto/declarative/declarative.pro @@ -11,6 +11,7 @@ SUBDIRS += \ qdeclarativeanchors \ qdeclarativeanimatedimage \ qdeclarativeanimations \ + qdeclarativeapplication \ qdeclarativebehaviors \ qdeclarativebinding \ qdeclarativeborderimage \ diff --git a/tests/auto/declarative/qdeclarativeapplication/qdeclarativeapplication.pro b/tests/auto/declarative/qdeclarativeapplication/qdeclarativeapplication.pro new file mode 100644 index 0000000..91e5468 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeapplication/qdeclarativeapplication.pro @@ -0,0 +1,5 @@ +load(qttest_p4) +contains(QT_CONFIG,declarative): QT += declarative gui +macx:CONFIG -= app_bundle + +SOURCES += tst_qdeclarativeapplication.cpp diff --git a/tests/auto/declarative/qdeclarativeapplication/tst_qdeclarativeapplication.cpp b/tests/auto/declarative/qdeclarativeapplication/tst_qdeclarativeapplication.cpp new file mode 100644 index 0000000..0d069dc --- /dev/null +++ b/tests/auto/declarative/qdeclarativeapplication/tst_qdeclarativeapplication.cpp @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** 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 test suite 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 +#include "../../../shared/util.h" +#include +#include +#include +#include +#include + +class tst_qdeclarativeapplication : public QObject +{ + Q_OBJECT +public: + tst_qdeclarativeapplication(); + +private slots: + void active(); + +private: + QDeclarativeEngine engine; +}; + +tst_qdeclarativeapplication::tst_qdeclarativeapplication() +{ +} + +void tst_qdeclarativeapplication::active() +{ + QDeclarativeComponent component(&engine); + component.setData("import QtQuick 1.0; Item { property bool active: Qt.application.active }", QUrl::fromLocalFile("")); + QDeclarativeItem *item = qobject_cast(component.create()); + QVERIFY(item); + QGraphicsScene scene; + QGraphicsView view(&scene); + scene.addItem(item); + + // not active + QVERIFY(!item->property("active").toBool()); + QCOMPARE(item->property("active").toBool(), QApplication::activeWindow() != 0); + + // active + view.show(); + QApplication::setActiveWindow(&view); + QTest::qWaitForWindowShown(&view); + QTRY_COMPARE(QApplication::activeWindow(), static_cast(&view)); + QCOMPARE(item->property("active").toBool(), QApplication::activeWindow() != 0); + + // not active again + QApplication::setActiveWindow(0); + QVERIFY(!item->property("active").toBool()); + QCOMPARE(item->property("active").toBool(), QApplication::activeWindow() != 0); +} + +QTEST_MAIN(tst_qdeclarativeapplication) + +#include "tst_qdeclarativeapplication.moc" -- cgit v0.12 From 0371e80ba76b7dcaf1809ba9345fd96610390222 Mon Sep 17 00:00:00 2001 From: Joona Petrell Date: Tue, 4 Jan 2011 17:25:48 +1000 Subject: Add layoutDirection property to Qt.application element Task-number: QTBUG-16424 Reviewed-by: Martin Jones --- src/declarative/util/qdeclarativeapplication.cpp | 32 ++++++++++++++++++++-- src/declarative/util/qdeclarativeapplication_p.h | 3 ++ .../tst_qdeclarativeapplication.cpp | 23 ++++++++++++++++ 3 files changed, 56 insertions(+), 2 deletions(-) diff --git a/src/declarative/util/qdeclarativeapplication.cpp b/src/declarative/util/qdeclarativeapplication.cpp index 53d196f..f724c16 100644 --- a/src/declarative/util/qdeclarativeapplication.cpp +++ b/src/declarative/util/qdeclarativeapplication.cpp @@ -47,8 +47,10 @@ class QDeclarativeApplicationPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QDeclarativeApplication) public: - QDeclarativeApplicationPrivate() : active(QApplication::activeWindow() != 0) {} + QDeclarativeApplicationPrivate() : active(QApplication::activeWindow() != 0), + layoutDirection(QApplication::layoutDirection()) {} bool active; + Qt::LayoutDirection layoutDirection; }; /*! @@ -58,7 +60,8 @@ public: \brief The Application element provides access to global application state properties shared by many QML components. - These properties include application activity property \c active. + These properties include application activity property \c active, + and default layout direction property \c layoutDirection. \section1 Example Usage @@ -97,6 +100,24 @@ bool QDeclarativeApplication::active() const return d->active; } +/*! + \qmlproperty bool Application::layoutDirection + + This property can be used to query the default layout direction of the + application. On system start-up, the default layout direction depends on the + application's language. The property has a value Qt.RightToLeft in locales + where text and graphic elements are read from right to left, and Qt.LeftToRight + where the reading direction flows from left to right. You can bind to the + property to customize your application layouts to support both layout + directions. This property is readonly. + +*/ +bool QDeclarativeApplication::layoutDirection() const +{ + Q_D(const QDeclarativeApplication); + return d->layoutDirection; +} + bool QDeclarativeApplication::eventFilter(QObject *obj, QEvent *event) { Q_UNUSED(obj) @@ -114,5 +135,12 @@ bool QDeclarativeApplication::eventFilter(QObject *obj, QEvent *event) emit activeChanged(); } } + if (event->type() == QEvent::LayoutDirectionChange) { + Qt::LayoutDirection direction = QApplication::layoutDirection(); + if (d->layoutDirection != direction) { + d->layoutDirection = direction; + emit layoutDirectionChanged(); + } + } return false; } diff --git a/src/declarative/util/qdeclarativeapplication_p.h b/src/declarative/util/qdeclarativeapplication_p.h index 59ea7fe..c5cd227 100644 --- a/src/declarative/util/qdeclarativeapplication_p.h +++ b/src/declarative/util/qdeclarativeapplication_p.h @@ -57,17 +57,20 @@ class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeApplication : public QObject { Q_OBJECT Q_PROPERTY(bool active READ active NOTIFY activeChanged) + Q_PROPERTY(bool layoutDirection READ layoutDirection NOTIFY layoutDirectionChanged) public: explicit QDeclarativeApplication(QObject *parent = 0); virtual ~QDeclarativeApplication(); bool active() const; + bool layoutDirection() const; protected: bool eventFilter(QObject *obj, QEvent *event); Q_SIGNALS: void activeChanged(); + void layoutDirectionChanged(); private: Q_DISABLE_COPY(QDeclarativeApplication) diff --git a/tests/auto/declarative/qdeclarativeapplication/tst_qdeclarativeapplication.cpp b/tests/auto/declarative/qdeclarativeapplication/tst_qdeclarativeapplication.cpp index 0d069dc..3011257 100644 --- a/tests/auto/declarative/qdeclarativeapplication/tst_qdeclarativeapplication.cpp +++ b/tests/auto/declarative/qdeclarativeapplication/tst_qdeclarativeapplication.cpp @@ -55,6 +55,7 @@ public: private slots: void active(); + void layoutDirection(); private: QDeclarativeEngine engine; @@ -91,6 +92,28 @@ void tst_qdeclarativeapplication::active() QCOMPARE(item->property("active").toBool(), QApplication::activeWindow() != 0); } +void tst_qdeclarativeapplication::layoutDirection() +{ + QDeclarativeComponent component(&engine); + component.setData("import QtQuick 1.0; Item { property bool layoutDirection: Qt.application.layoutDirection }", QUrl::fromLocalFile("")); + QDeclarativeItem *item = qobject_cast(component.create()); + QVERIFY(item); + QGraphicsScene scene; + QGraphicsView view(&scene); + scene.addItem(item); + + // not mirrored + QCOMPARE(Qt::LayoutDirection(item->property("layoutDirection").toInt()), Qt::LeftToRight); + + // mirrored + QApplication::setLayoutDirection(Qt::RightToLeft); + QCOMPARE(Qt::LayoutDirection(item->property("layoutDirection").toInt()), Qt::RightToLeft); + + // not mirrored again + QApplication::setLayoutDirection(Qt::LeftToRight); + QCOMPARE(Qt::LayoutDirection(item->property("layoutDirection").toInt()), Qt::LeftToRight); +} + QTEST_MAIN(tst_qdeclarativeapplication) #include "tst_qdeclarativeapplication.moc" -- cgit v0.12 From eea1c1a0d12920e3c0a0ffe5339e33055ffe0fdd Mon Sep 17 00:00:00 2001 From: Joona Petrell Date: Fri, 7 Jan 2011 18:37:47 +1000 Subject: Add missing Qt namespaces macros to qdeclarativeapplication.cpp source file Task-number: Reviewed-by: Aaron Kennedy --- src/declarative/util/qdeclarativeapplication.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/declarative/util/qdeclarativeapplication.cpp b/src/declarative/util/qdeclarativeapplication.cpp index f724c16..7559aa9 100644 --- a/src/declarative/util/qdeclarativeapplication.cpp +++ b/src/declarative/util/qdeclarativeapplication.cpp @@ -43,6 +43,8 @@ #include #include +QT_BEGIN_NAMESPACE + class QDeclarativeApplicationPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QDeclarativeApplication) @@ -144,3 +146,5 @@ bool QDeclarativeApplication::eventFilter(QObject *obj, QEvent *event) } return false; } + +QT_END_NAMESPACE -- cgit v0.12 From 6db61ce39aa2fefaa9e22ca84edd8d140a5c6449 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Mon, 10 Jan 2011 13:00:54 +1000 Subject: Document property/method versioning in QML. Task-number: QTBUG-13451 Reviewed-by: Bea Lam --- doc/src/declarative/extending.qdoc | 69 ++++++++++++++++++++++++++++++++++ doc/src/declarative/qtdeclarative.qdoc | 15 ++++++++ 2 files changed, 84 insertions(+) diff --git a/doc/src/declarative/extending.qdoc b/doc/src/declarative/extending.qdoc index ff519f6..429997f 100644 --- a/doc/src/declarative/extending.qdoc +++ b/doc/src/declarative/extending.qdoc @@ -112,6 +112,75 @@ Person { \l {Extending QML - Adding Types Example} shows the complete code used to create the \c Person type. +\section1 QML Type Versioning + +In C++ adding a new method or property cannot break old applications. +In QML, however, new methods and properties can change what a name previously +resolved to to within a scope chain. + +For example, consider these two QML files + +\code +// main.qml +import QtQuick 1.0 +Item { + id: root + MyComponent {} +} +\endcode + +\code +// MyComponent.qml +import MyModule 1.0 +CppItem { + value: root.x +} +\endcode + +where CppItem maps to the C++ class QCppItem. + +If the author of QCppItem adds a "root" property to QCppItem in a new version of the module, +it will break the above program as \c root.x now resolves to a different value. +The solution is to allow the author of QCppItem to state that the new \c root property is +only available from a particular version of QCppItem onwards. This permits new properties +and features to be added to existing elements without breaking existing programs. + +QML enables this by allowing the properties, methods and signals of a class to be tagged with +a particular \e revision, so that they are only accessible if the relevant module version +is imported. In this case, the author can tag the \c root property as being added in +\e {revision 1} of the class, and register that revision in version 1.1 of the module. + +The REVISION tag is used to mark the \c root property as added in revision 1 of the class. +Methods such as Q_INVOKABLE's, signals and slots can also be tagged for a +revision using the \c Q_REVISION(x) macro: + +\code +class CppItem : public QObject +{ + Q_OBJECT + Q_PROPERTY(int root READ root WRITE setRoot NOTIFY rootChanged REVISION 1) + +signals: + Q_REVISION(1) void rootChanged(); +}; +\endcode + +To register the new class revision to a particular version the following function is used: + +\code +template +int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const char *qmlName) +\endcode + +To register \c CppItem version 1 for \c {MyModule 1.1}: + +\code +qmlRegisterType("MyModule", 1, 1, "CppItem") +\endcode + +\c root is only available when MyModule 1.1 is imported. + + \section1 Object and List Property Types \snippet examples/declarative/cppextensions/referenceexamples/properties/example.qml 0 diff --git a/doc/src/declarative/qtdeclarative.qdoc b/doc/src/declarative/qtdeclarative.qdoc index b0c6e06..5ab4319 100644 --- a/doc/src/declarative/qtdeclarative.qdoc +++ b/doc/src/declarative/qtdeclarative.qdoc @@ -85,6 +85,21 @@ Returns the QML type id. + There are two forms of this template function: + + \code + template + int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const char *qmlName); + + template + int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const char *qmlName); + \endcode + + The former is the standard form which registers the type \e T as a new type. + The latter allows a particular revision of a class to be registered in + a specified version (see \l {QML Type Versioning}). + + For example, this registers a C++ class \c MySliderItem as a QML type named \c Slider for version 1.0 of a \l{QML Modules}{module} called "com.mycompany.qmlcomponents": -- cgit v0.12 From cbf6bfbff8c0643bc82bb2456214994931052bd6 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Fri, 7 Jan 2011 17:42:12 +1000 Subject: Add selection modes to TextEdit and TextInput. Add an overload for moveCursorSelection which takes a parameter specifying whether to update the selection with individual characters or whole words. Task-number: QTBUG-16283 Reviewed-by: Martin Jones --- .../graphicsitems/qdeclarativetextedit.cpp | 89 +++++++++-- .../graphicsitems/qdeclarativetextedit_p.h | 7 + .../graphicsitems/qdeclarativetextinput.cpp | 101 ++++++++++++- .../graphicsitems/qdeclarativetextinput_p.h | 7 + .../tst_qdeclarativetextedit.cpp | 164 ++++++++++++++++++++- .../tst_qdeclarativetextinput.cpp | 163 +++++++++++++++++++- 6 files changed, 512 insertions(+), 19 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativetextedit.cpp b/src/declarative/graphicsitems/qdeclarativetextedit.cpp index 6a51a3c..7ea3dec 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextedit.cpp @@ -579,37 +579,108 @@ int QDeclarativeTextEdit::positionAt(int x, int y) const return r; } +void QDeclarativeTextEdit::moveCursorSelection(int pos) +{ + //Note that this is the same as setCursorPosition but with the KeepAnchor flag set + Q_D(QDeclarativeTextEdit); + QTextCursor cursor = d->control->textCursor(); + if (cursor.position() == pos) + return; + cursor.setPosition(pos, QTextCursor::KeepAnchor); + d->control->setTextCursor(cursor); +} + /*! - \qmlmethod int TextEdit::moveCursorSelection(int pos) + \qmlmethod void TextEdit::moveCursorSelection(int position, SelectionMode mode = TextEdit.SelectCharacters) + \since Quick 1.1 - Moves the cursor to \a position and updates the selection accordingly. - (To only move the cursor, set the \l cursorPosition property.) + Moves the cursor to \a position and updates the selection according to the optional \a mode + parameter. (To only move the cursor, set the \l cursorPosition property.) When this method is called it additionally sets either the selectionStart or the selectionEnd (whichever was at the previous cursor position) to the specified position. This allows you to easily extend and contract the selected text range. + The selection mode specifies whether the selection is updated on a per character or a per word + basis. If not specified the selection mode will default to TextEdit.SelectCharacters. + + \list + \o TextEdit.SelectCharacters - Sets either the selectionStart or selectionEnd (whichever was at + the previous cursor position) to the specified position. + \o TextEdit.SelectWords - Sets the selectionStart and selectionEnd to include all + words between the specified postion and the previous cursor position. Words partially in the + range are included. + \endlist + For example, take this sequence of calls: \code cursorPosition = 5 - moveCursorSelection(9) - moveCursorSelection(7) + moveCursorSelection(9, TextEdit.SelectCharacters) + moveCursorSelection(7, TextEdit.SelectCharacters) \endcode This moves the cursor to position 5, extend the selection end from 5 to 9 and then retract the selection end from 9 to 7, leaving the text from position 5 to 7 selected (the 6th and 7th characters). + + The same sequence with TextEdit.SelectWords will extend the selection start to a word boundary + before or on position 5 and extend the selection end to a word boundary past position 9, and + then if there is a word boundary between position 7 and 8 retract the selection end to that + boundary. If there is whitespace at position 7 the selection will be retracted further. */ -void QDeclarativeTextEdit::moveCursorSelection(int pos) +void QDeclarativeTextEdit::moveCursorSelection(int pos, SelectionMode mode) { - //Note that this is the same as setCursorPosition but with the KeepAnchor flag set Q_D(QDeclarativeTextEdit); QTextCursor cursor = d->control->textCursor(); if (cursor.position() == pos) return; - cursor.setPosition(pos, QTextCursor::KeepAnchor); + if (mode == SelectCharacters) { + cursor.setPosition(pos, QTextCursor::KeepAnchor); + } else if (cursor.anchor() < pos) { + cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor); + cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor); + if (cursor.position() == cursor.anchor()) { + cursor.movePosition(QTextCursor::NextWord, QTextCursor::MoveAnchor); + } else { + cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::MoveAnchor); + cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::MoveAnchor); + } + cursor.setPosition(pos, QTextCursor::KeepAnchor); + cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::KeepAnchor); + if (cursor.position() == pos) { + cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::KeepAnchor); + cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor); + + if (cursor.anchor() > cursor.position()) + cursor.setPosition(pos, QTextCursor::MoveAnchor); + } else { + cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor); + } + } else if (cursor.anchor() > pos) { + cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor); + cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::KeepAnchor); + if (cursor.position() == cursor.anchor()) { + cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::MoveAnchor); + cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::MoveAnchor); + } else { + cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::MoveAnchor); + } + cursor.setPosition(pos, QTextCursor::KeepAnchor); + cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor); + if (cursor.position() == pos) { + cursor.movePosition(QTextCursor::NextWord, QTextCursor::KeepAnchor); + + if (cursor.anchor() < cursor.position()) + cursor.setPosition(pos, QTextCursor::MoveAnchor); + } else { + cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor); + cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::KeepAnchor); + } + } else { + cursor.setPosition(pos, QTextCursor::MoveAnchor); + } d->control->setTextCursor(cursor); } @@ -655,7 +726,7 @@ void QDeclarativeTextEdit::setCursorPosition(int pos) if (pos < 0 || pos > d->text.length()) return; QTextCursor cursor = d->control->textCursor(); - if (cursor.position() == pos) + if (cursor.position() == pos && cursor.anchor() == pos) return; cursor.setPosition(pos); d->control->setTextCursor(cursor); diff --git a/src/declarative/graphicsitems/qdeclarativetextedit_p.h b/src/declarative/graphicsitems/qdeclarativetextedit_p.h index 37b24f7..6a05aa8 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextedit_p.h @@ -65,6 +65,7 @@ class Q_AUTOTEST_EXPORT QDeclarativeTextEdit : public QDeclarativePaintedItem Q_ENUMS(HAlignment) Q_ENUMS(TextFormat) Q_ENUMS(WrapMode) + Q_ENUMS(SelectionMode) Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged) Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) @@ -120,6 +121,11 @@ public: Wrap = QTextOption::WrapAtWordBoundaryOrAnywhere }; + enum SelectionMode { + SelectCharacters, + SelectWords + }; + Q_INVOKABLE void openSoftwareInputPanel(); Q_INVOKABLE void closeSoftwareInputPanel(); @@ -195,6 +201,7 @@ public: Q_INVOKABLE QRectF positionToRectangle(int) const; Q_INVOKABLE int positionAt(int x, int y) const; Q_INVOKABLE void moveCursorSelection(int pos); + Q_INVOKABLE Q_REVISION(1) void moveCursorSelection(int pos, SelectionMode mode); QRectF boundingRect() const; diff --git a/src/declarative/graphicsitems/qdeclarativetextinput.cpp b/src/declarative/graphicsitems/qdeclarativetextinput.cpp index ac07d4b..491d219c4 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextinput.cpp @@ -50,6 +50,7 @@ #include #include #include +#include #ifndef QT_NO_LINEEDIT @@ -1320,35 +1321,119 @@ void QDeclarativeTextInput::setSelectByMouse(bool on) } } +void QDeclarativeTextInput::moveCursorSelection(int position) +{ + Q_D(QDeclarativeTextInput); + d->control->moveCursor(position, true); + d->updateHorizontalScroll(); +} /*! - \qmlmethod void TextInput::moveCursorSelection(int position) + \qmlmethod void TextInput::moveCursorSelection(int position, SelectionMode mode = TextInput.SelectCharacters) + \since Quick 1.1 - Moves the cursor to \a position and updates the selection accordingly. - (To only move the cursor, set the \l cursorPosition property.) + Moves the cursor to \a position and updates the selection according to the optional \a mode + parameter. (To only move the cursor, set the \l cursorPosition property.) When this method is called it additionally sets either the selectionStart or the selectionEnd (whichever was at the previous cursor position) to the specified position. This allows you to easily extend and contract the selected text range. + The selection mode specifies whether the selection is updated on a per character or a per word + basis. If not specified the selection mode will default to TextInput.SelectCharacters. + + \list + \o TextEdit.SelectCharacters - Sets either the selectionStart or selectionEnd (whichever was at + the previous cursor position) to the specified position. + \o TextEdit.SelectWords - Sets the selectionStart and selectionEnd to include all + words between the specified postion and the previous cursor position. Words partially in the + range are included. + \endlist + For example, take this sequence of calls: \code cursorPosition = 5 - moveCursorSelection(9) - moveCursorSelection(7) + moveCursorSelection(9, TextInput.SelectCharacters) + moveCursorSelection(7, TextInput.SelectCharacters) \endcode This moves the cursor to position 5, extend the selection end from 5 to 9 and then retract the selection end from 9 to 7, leaving the text from position 5 to 7 selected (the 6th and 7th characters). + + The same sequence with TextInput.SelectWords will extend the selection start to a word boundary + before or on position 5 and extend the selection end to a word boundary past position 9, and + then if there is a word boundary between position 7 and 8 retract the selection end to that + boundary. If there is whitespace at position 7 the selection will be retracted further. */ -void QDeclarativeTextInput::moveCursorSelection(int position) +void QDeclarativeTextInput::moveCursorSelection(int pos, SelectionMode mode) { Q_D(QDeclarativeTextInput); - d->control->moveCursor(position, true); - d->updateHorizontalScroll(); + + if (mode == SelectCharacters) { + d->control->moveCursor(pos, true); + } else if (pos != d->control->cursor()){ + int anchor; + if (!d->control->hasSelectedText()) + anchor = d->control->cursor(); + else if (d->control->selectionStart() == d->control->cursor()) + anchor = d->control->selectionEnd(); + else + anchor = d->control->selectionStart(); + + if (anchor < pos) { + QTextBoundaryFinder finder(QTextBoundaryFinder::Word, d->control->text()); + finder.setPosition(anchor); + + if (!(finder.boundaryReasons() & QTextBoundaryFinder::StartWord)) { + finder.toNextBoundary(); + if (finder.boundaryReasons() != QTextBoundaryFinder::StartWord) + finder.toPreviousBoundary(); + } + anchor = finder.position(); + + finder.setPosition(pos); + if (!(finder.boundaryReasons() & QTextBoundaryFinder::EndWord)) { + finder.toPreviousBoundary(); + if (finder.boundaryReasons() != QTextBoundaryFinder::EndWord) + finder.toNextBoundary(); + } + int cursor = finder.position(); + + if (anchor < cursor) + d->control->setSelection(anchor, cursor - anchor); + else + d->control->moveCursor(pos, false); + + } else if (anchor > pos) { + QTextBoundaryFinder finder(QTextBoundaryFinder::Word, d->control->text()); + + finder.setPosition(anchor); + if (!(finder.boundaryReasons() & QTextBoundaryFinder::EndWord)) { + finder.toPreviousBoundary(); + if (finder.boundaryReasons() != QTextBoundaryFinder::EndWord) + finder.toNextBoundary(); + } + anchor = finder.position(); + + finder.setPosition(pos); + if (!(finder.boundaryReasons() & QTextBoundaryFinder::StartWord)) { + finder.toNextBoundary(); + if (finder.boundaryReasons() != QTextBoundaryFinder::StartWord) + finder.toPreviousBoundary(); + } + int cursor = finder.position(); + + if (anchor > cursor) + d->control->setSelection(anchor, cursor - anchor); + else + d->control->moveCursor(pos, false); + } else { + d->control->moveCursor(pos, false); + } + } } /*! diff --git a/src/declarative/graphicsitems/qdeclarativetextinput_p.h b/src/declarative/graphicsitems/qdeclarativetextinput_p.h index 878f040..25b8e66 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextinput_p.h @@ -63,6 +63,7 @@ class Q_AUTOTEST_EXPORT QDeclarativeTextInput : public QDeclarativePaintedItem Q_OBJECT Q_ENUMS(HAlignment) Q_ENUMS(EchoMode) + Q_ENUMS(SelectionMode) Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged) Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) @@ -112,10 +113,16 @@ public: AlignHCenter = Qt::AlignHCenter }; + enum SelectionMode { + SelectCharacters, + SelectWords + }; + //Auxilliary functions needed to control the TextInput from QML Q_INVOKABLE int positionAt(int x) const; Q_INVOKABLE QRectF positionToRectangle(int pos) const; Q_INVOKABLE void moveCursorSelection(int pos); + Q_INVOKABLE Q_REVISION(1) void moveCursorSelection(int pos, SelectionMode mode); Q_INVOKABLE void openSoftwareInputPanel(); Q_INVOKABLE void closeSoftwareInputPanel(); diff --git a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp index 23c8a1b..7af008f 100644 --- a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp +++ b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp @@ -66,6 +66,8 @@ #define SRCDIR "." #endif +Q_DECLARE_METATYPE(QDeclarativeTextEdit::SelectionMode) + QString createExpectedFileIfNotFound(const QString& filebasename, const QImage& actual) { // XXX This will be replaced by some clever persistent platform image store. @@ -107,6 +109,8 @@ private slots: void persistentSelection(); void focusOnPress(); void selection(); + void moveCursorSelection_data(); + void moveCursorSelection(); void mouseSelection_data(); void mouseSelection(); void inputMethodHints(); @@ -144,7 +148,9 @@ private: tst_qdeclarativetextedit::tst_qdeclarativetextedit() { standard << "the quick brown fox jumped over the lazy dog" - << "the quick brown fox\n jumped over the lazy dog"; + << "the quick brown fox\n jumped over the lazy dog" + << "Hello, world!" + << "!dlrow ,olleH"; richText << "the quick brown fox jumped over the lazy dog" << "the quick brown fox
jumped over the lazy dog
"; @@ -711,6 +717,162 @@ void tst_qdeclarativetextedit::selection() QVERIFY(textEditObject->selectedText().isNull()); } +void tst_qdeclarativetextedit::moveCursorSelection_data() +{ + QTest::addColumn("testStr"); + QTest::addColumn("cursorPosition"); + QTest::addColumn("movePosition"); + QTest::addColumn("mode"); + QTest::addColumn("selectionStart"); + QTest::addColumn("selectionEnd"); + QTest::addColumn("reversible"); + + QTest::newRow("(t)he|characters") + << standard[0] << 0 << 1 << QDeclarativeTextEdit::SelectCharacters << 0 << 1 << true; + QTest::newRow("do(g)|characters") + << standard[0] << 43 << 44 << QDeclarativeTextEdit::SelectCharacters << 43 << 44 << true; + QTest::newRow("jum(p)ed|characters") + << standard[0] << 23 << 24 << QDeclarativeTextEdit::SelectCharacters << 23 << 24 << true; + QTest::newRow("jumped( )over|characters") + << standard[0] << 26 << 27 << QDeclarativeTextEdit::SelectCharacters << 26 << 27 << true; + QTest::newRow("(the )|characters") + << standard[0] << 0 << 4 << QDeclarativeTextEdit::SelectCharacters << 0 << 4 << true; + QTest::newRow("( dog)|characters") + << standard[0] << 40 << 44 << QDeclarativeTextEdit::SelectCharacters << 40 << 44 << true; + QTest::newRow("( jumped )|characters") + << standard[0] << 19 << 27 << QDeclarativeTextEdit::SelectCharacters << 19 << 27 << true; + QTest::newRow("th(e qu)ick|characters") + << standard[0] << 2 << 6 << QDeclarativeTextEdit::SelectCharacters << 2 << 6 << true; + QTest::newRow("la(zy d)og|characters") + << standard[0] << 38 << 42 << QDeclarativeTextEdit::SelectCharacters << 38 << 42 << true; + QTest::newRow("jum(ped ov)er|characters") + << standard[0] << 23 << 29 << QDeclarativeTextEdit::SelectCharacters << 23 << 29 << true; + QTest::newRow("()the|characters") + << standard[0] << 0 << 0 << QDeclarativeTextEdit::SelectCharacters << 0 << 0 << true; + QTest::newRow("dog()|characters") + << standard[0] << 44 << 44 << QDeclarativeTextEdit::SelectCharacters << 44 << 44 << true; + QTest::newRow("jum()ped|characters") + << standard[0] << 23 << 23 << QDeclarativeTextEdit::SelectCharacters << 23 << 23 << true; + + QTest::newRow("(t)he|words") + << standard[0] << 0 << 1 << QDeclarativeTextEdit::SelectWords << 0 << 3 << true; + QTest::newRow("do(g)|words") + << standard[0] << 43 << 44 << QDeclarativeTextEdit::SelectWords << 41 << 44 << true; + QTest::newRow("jum(p)ed|words") + << standard[0] << 23 << 24 << QDeclarativeTextEdit::SelectWords << 20 << 26 << true; + QTest::newRow("jumped( )over|words") + << standard[0] << 26 << 27 << QDeclarativeTextEdit::SelectWords << 27 << 27 << false; + QTest::newRow("jumped( )over|words,reversed") + << standard[0] << 27 << 26 << QDeclarativeTextEdit::SelectWords << 26 << 26 << false; + QTest::newRow("(the )|words") + << standard[0] << 0 << 4 << QDeclarativeTextEdit::SelectWords << 0 << 3 << true; + QTest::newRow("( dog)|words") + << standard[0] << 40 << 44 << QDeclarativeTextEdit::SelectWords << 41 << 44 << true; + QTest::newRow("( jumped )|words") + << standard[0] << 19 << 27 << QDeclarativeTextEdit::SelectWords << 20 << 26 << true; + QTest::newRow("th(e qu)ick|words") + << standard[0] << 2 << 6 << QDeclarativeTextEdit::SelectWords << 0 << 9 << true; + QTest::newRow("la(zy d)og|words") + << standard[0] << 38 << 42 << QDeclarativeTextEdit::SelectWords << 36 << 44 << true; + QTest::newRow("jum(ped ov)er|words") + << standard[0] << 23 << 29 << QDeclarativeTextEdit::SelectWords << 20 << 31 << true; + QTest::newRow("()the|words") + << standard[0] << 0 << 0 << QDeclarativeTextEdit::SelectWords << 0 << 0 << true; + QTest::newRow("dog()|words") + << standard[0] << 44 << 44 << QDeclarativeTextEdit::SelectWords << 44 << 44 << true; + QTest::newRow("jum()ped|words") + << standard[0] << 23 << 23 << QDeclarativeTextEdit::SelectWords << 23 << 23 << true; + + QTest::newRow("Hello(,) |words") + << standard[2] << 5 << 6 << QDeclarativeTextEdit::SelectWords << 5 << 6 << true; + QTest::newRow("Hello(, )|words") + << standard[2] << 5 << 7 << QDeclarativeTextEdit::SelectWords << 5 << 6 << true; + QTest::newRow("Hel(lo, )|words") + << standard[2] << 3 << 7 << QDeclarativeTextEdit::SelectWords << 0 << 6 << true; + QTest::newRow("Hel(lo),|words") + << standard[2] << 3 << 5 << QDeclarativeTextEdit::SelectWords << 0 << 5 << true; + QTest::newRow("Hello(),|words") + << standard[2] << 5 << 5 << QDeclarativeTextEdit::SelectWords << 5 << 5 << true; + QTest::newRow("Hello,()|words") + << standard[2] << 6 << 6 << QDeclarativeTextEdit::SelectWords << 6 << 6 << true; + QTest::newRow("Hello,( )|words") + << standard[2] << 6 << 7 << QDeclarativeTextEdit::SelectWords << 7 << 7 << false; + QTest::newRow("Hello,( )|words") + << standard[2] << 7 << 6 << QDeclarativeTextEdit::SelectWords << 6 << 6 << false; + QTest::newRow("Hello,( world)|words") + << standard[2] << 6 << 12 << QDeclarativeTextEdit::SelectWords << 7 << 12 << true; + QTest::newRow("Hello,( world!)|words") + << standard[2] << 6 << 13 << QDeclarativeTextEdit::SelectWords << 7 << 13 << true; + QTest::newRow("Hello(, world!)|words") + << standard[2] << 5 << 13 << QDeclarativeTextEdit::SelectWords << 5 << 13 << true; + QTest::newRow("world(!)|words") + << standard[2] << 12 << 13 << QDeclarativeTextEdit::SelectWords << 12 << 13 << true; + QTest::newRow("world!())|words") + << standard[2] << 13 << 13 << QDeclarativeTextEdit::SelectWords << 13 << 13 << true; + QTest::newRow("world()!)|words") + << standard[2] << 12 << 12 << QDeclarativeTextEdit::SelectWords << 12 << 12 << true; + + QTest::newRow("(,)olleH |words") + << standard[3] << 7 << 8 << QDeclarativeTextEdit::SelectWords << 7 << 8 << true; + QTest::newRow("( ,)olleH|words") + << standard[3] << 6 << 8 << QDeclarativeTextEdit::SelectWords << 7 << 8 << true; + QTest::newRow("( ,ol)leH|words") + << standard[3] << 6 << 10 << QDeclarativeTextEdit::SelectWords << 7 << 13 << true; + QTest::newRow(",(ol)leH,|words") + << standard[3] << 8 << 10 << QDeclarativeTextEdit::SelectWords << 8 << 13 << true; + QTest::newRow(",()olleH|words") + << standard[3] << 8 << 8 << QDeclarativeTextEdit::SelectWords << 8 << 8 << true; + QTest::newRow("(),olleH|words") + << standard[3] << 7 << 7 << QDeclarativeTextEdit::SelectWords << 7 << 7 << true; + QTest::newRow("( ),olleH|words") + << standard[3] << 6 << 7 << QDeclarativeTextEdit::SelectWords << 7 << 7 << false; + QTest::newRow("( ),olleH|words,reversed") + << standard[3] << 7 << 6 << QDeclarativeTextEdit::SelectWords << 6 << 6 << false; + QTest::newRow("(dlrow ),olleH|words") + << standard[3] << 1 << 7 << QDeclarativeTextEdit::SelectWords << 1 << 6 << true; + QTest::newRow("(!dlrow ),olleH|words") + << standard[3] << 0 << 7 << QDeclarativeTextEdit::SelectWords << 0 << 6 << true; + QTest::newRow("(!dlrow ,)olleH|words") + << standard[3] << 0 << 8 << QDeclarativeTextEdit::SelectWords << 0 << 8 << true; + QTest::newRow("(!)dlrow|words") + << standard[3] << 0 << 1 << QDeclarativeTextEdit::SelectWords << 0 << 1 << true; + QTest::newRow("()!dlrow|words") + << standard[3] << 0 << 0 << QDeclarativeTextEdit::SelectWords << 0 << 0 << true; + QTest::newRow("!()dlrow|words") + << standard[3] << 1 << 1 << QDeclarativeTextEdit::SelectWords << 1 << 1 << true; +} + +void tst_qdeclarativetextedit::moveCursorSelection() +{ + QFETCH(QString, testStr); + QFETCH(int, cursorPosition); + QFETCH(int, movePosition); + QFETCH(QDeclarativeTextEdit::SelectionMode, mode); + QFETCH(int, selectionStart); + QFETCH(int, selectionEnd); + QFETCH(bool, reversible); + + QString componentStr = "import QtQuick 1.1\nTextEdit { text: \""+ testStr +"\"; }"; + QDeclarativeComponent textinputComponent(&engine); + textinputComponent.setData(componentStr.toLatin1(), QUrl()); + QDeclarativeTextEdit *texteditObject = qobject_cast(textinputComponent.create()); + QVERIFY(texteditObject != 0); + + texteditObject->setCursorPosition(cursorPosition); + texteditObject->moveCursorSelection(movePosition, mode); + + QCOMPARE(texteditObject->selectionStart(), selectionStart); + QCOMPARE(texteditObject->selectionEnd(), selectionEnd); + + if (reversible) { + texteditObject->setCursorPosition(movePosition); + texteditObject->moveCursorSelection(cursorPosition, mode); + + QCOMPARE(texteditObject->selectionStart(), selectionStart); + QCOMPARE(texteditObject->selectionEnd(), selectionEnd); + } +} + void tst_qdeclarativetextedit::mouseSelection_data() { QTest::addColumn("qmlfile"); diff --git a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp index 160c3b6..1de695e 100644 --- a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp +++ b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp @@ -57,6 +57,8 @@ #define SRCDIR "." #endif +Q_DECLARE_METATYPE(QDeclarativeTextInput::SelectionMode) + QString createExpectedFileIfNotFound(const QString& filebasename, const QImage& actual) { // XXX This will be replaced by some clever persistent platform image store. @@ -87,6 +89,8 @@ private slots: void font(); void color(); void selection(); + void moveCursorSelection_data(); + void moveCursorSelection(); void horizontalAlignment_data(); void horizontalAlignment(); @@ -124,7 +128,8 @@ tst_qdeclarativetextinput::tst_qdeclarativetextinput() { standard << "the quick brown fox jumped over the lazy dog" << "It's supercalifragisiticexpialidocious!" - << "Hello, world!"; + << "Hello, world!" + << "!dlrow ,olleH"; colorStrings << "aliceblue" << "antiquewhite" @@ -415,6 +420,162 @@ void tst_qdeclarativetextinput::selection() delete textinputObject; } +void tst_qdeclarativetextinput::moveCursorSelection_data() +{ + QTest::addColumn("testStr"); + QTest::addColumn("cursorPosition"); + QTest::addColumn("movePosition"); + QTest::addColumn("mode"); + QTest::addColumn("selectionStart"); + QTest::addColumn("selectionEnd"); + QTest::addColumn("reversible"); + + QTest::newRow("(t)he|characters") + << standard[0] << 0 << 1 << QDeclarativeTextInput::SelectCharacters << 0 << 1 << true; + QTest::newRow("do(g)|characters") + << standard[0] << 43 << 44 << QDeclarativeTextInput::SelectCharacters << 43 << 44 << true; + QTest::newRow("jum(p)ed|characters") + << standard[0] << 23 << 24 << QDeclarativeTextInput::SelectCharacters << 23 << 24 << true; + QTest::newRow("jumped( )over|characters") + << standard[0] << 26 << 27 << QDeclarativeTextInput::SelectCharacters << 26 << 27 << true; + QTest::newRow("(the )|characters") + << standard[0] << 0 << 4 << QDeclarativeTextInput::SelectCharacters << 0 << 4 << true; + QTest::newRow("( dog)|characters") + << standard[0] << 40 << 44 << QDeclarativeTextInput::SelectCharacters << 40 << 44 << true; + QTest::newRow("( jumped )|characters") + << standard[0] << 19 << 27 << QDeclarativeTextInput::SelectCharacters << 19 << 27 << true; + QTest::newRow("th(e qu)ick|characters") + << standard[0] << 2 << 6 << QDeclarativeTextInput::SelectCharacters << 2 << 6 << true; + QTest::newRow("la(zy d)og|characters") + << standard[0] << 38 << 42 << QDeclarativeTextInput::SelectCharacters << 38 << 42 << true; + QTest::newRow("jum(ped ov)er|characters") + << standard[0] << 23 << 29 << QDeclarativeTextInput::SelectCharacters << 23 << 29 << true; + QTest::newRow("()the|characters") + << standard[0] << 0 << 0 << QDeclarativeTextInput::SelectCharacters << 0 << 0 << true; + QTest::newRow("dog()|characters") + << standard[0] << 44 << 44 << QDeclarativeTextInput::SelectCharacters << 44 << 44 << true; + QTest::newRow("jum()ped|characters") + << standard[0] << 23 << 23 << QDeclarativeTextInput::SelectCharacters << 23 << 23 << true; + + QTest::newRow("(t)he|words") + << standard[0] << 0 << 1 << QDeclarativeTextInput::SelectWords << 0 << 3 << true; + QTest::newRow("do(g)|words") + << standard[0] << 43 << 44 << QDeclarativeTextInput::SelectWords << 41 << 44 << true; + QTest::newRow("jum(p)ed|words") + << standard[0] << 23 << 24 << QDeclarativeTextInput::SelectWords << 20 << 26 << true; + QTest::newRow("jumped( )over|words") + << standard[0] << 26 << 27 << QDeclarativeTextInput::SelectWords << 27 << 27 << false; + QTest::newRow("jumped( )over|words,reversed") + << standard[0] << 27 << 26 << QDeclarativeTextInput::SelectWords << 26 << 26 << false; + QTest::newRow("(the )|words") + << standard[0] << 0 << 4 << QDeclarativeTextInput::SelectWords << 0 << 3 << true; + QTest::newRow("( dog)|words") + << standard[0] << 40 << 44 << QDeclarativeTextInput::SelectWords << 41 << 44 << true; + QTest::newRow("( jumped )|words") + << standard[0] << 19 << 27 << QDeclarativeTextInput::SelectWords << 20 << 26 << true; + QTest::newRow("th(e qu)ick|words") + << standard[0] << 2 << 6 << QDeclarativeTextInput::SelectWords << 0 << 9 << true; + QTest::newRow("la(zy d)og|words") + << standard[0] << 38 << 42 << QDeclarativeTextInput::SelectWords << 36 << 44 << true; + QTest::newRow("jum(ped ov)er|words") + << standard[0] << 23 << 29 << QDeclarativeTextInput::SelectWords << 20 << 31 << true; + QTest::newRow("()the|words") + << standard[0] << 0 << 0 << QDeclarativeTextInput::SelectWords << 0 << 0 << true; + QTest::newRow("dog()|words") + << standard[0] << 44 << 44 << QDeclarativeTextInput::SelectWords << 44 << 44 << true; + QTest::newRow("jum()ped|words") + << standard[0] << 23 << 23 << QDeclarativeTextInput::SelectWords << 23 << 23 << true; + + QTest::newRow("Hello(,) |words") + << standard[2] << 5 << 6 << QDeclarativeTextInput::SelectWords << 5 << 6 << true; + QTest::newRow("Hello(, )|words") + << standard[2] << 5 << 7 << QDeclarativeTextInput::SelectWords << 5 << 6 << true; + QTest::newRow("Hel(lo, )|words") + << standard[2] << 3 << 7 << QDeclarativeTextInput::SelectWords << 0 << 6 << true; + QTest::newRow("Hel(lo),|words") + << standard[2] << 3 << 5 << QDeclarativeTextInput::SelectWords << 0 << 5 << true; + QTest::newRow("Hello(),|words") + << standard[2] << 5 << 5 << QDeclarativeTextInput::SelectWords << 5 << 5 << true; + QTest::newRow("Hello,()|words") + << standard[2] << 6 << 6 << QDeclarativeTextInput::SelectWords << 6 << 6 << true; + QTest::newRow("Hello,( )|words") + << standard[2] << 6 << 7 << QDeclarativeTextInput::SelectWords << 7 << 7 << false; + QTest::newRow("Hello,( )|words,reversed") + << standard[2] << 7 << 6 << QDeclarativeTextInput::SelectWords << 6 << 6 << false; + QTest::newRow("Hello,( world)|words") + << standard[2] << 6 << 12 << QDeclarativeTextInput::SelectWords << 7 << 12 << true; + QTest::newRow("Hello,( world!)|words") + << standard[2] << 6 << 13 << QDeclarativeTextInput::SelectWords << 7 << 13 << true; + QTest::newRow("Hello(, world!)|words") + << standard[2] << 5 << 13 << QDeclarativeTextInput::SelectWords << 5 << 13 << true; + QTest::newRow("world(!)|words") + << standard[2] << 12 << 13 << QDeclarativeTextInput::SelectWords << 12 << 13 << true; + QTest::newRow("world!())|words") + << standard[2] << 13 << 13 << QDeclarativeTextInput::SelectWords << 13 << 13 << true; + QTest::newRow("world()!)|words") + << standard[2] << 12 << 12 << QDeclarativeTextInput::SelectWords << 12 << 12 << true; + + QTest::newRow("(,)olleH |words") + << standard[3] << 7 << 8 << QDeclarativeTextInput::SelectWords << 7 << 8 << true; + QTest::newRow("( ,)olleH|words") + << standard[3] << 6 << 8 << QDeclarativeTextInput::SelectWords << 7 << 8 << true; + QTest::newRow("( ,ol)leH|words") + << standard[3] << 6 << 10 << QDeclarativeTextInput::SelectWords << 7 << 13 << true; + QTest::newRow(",(ol)leH,|words") + << standard[3] << 8 << 10 << QDeclarativeTextInput::SelectWords << 8 << 13 << true; + QTest::newRow(",()olleH|words") + << standard[3] << 8 << 8 << QDeclarativeTextInput::SelectWords << 8 << 8 << true; + QTest::newRow("(),olleH|words") + << standard[3] << 7 << 7 << QDeclarativeTextInput::SelectWords << 7 << 7 << true; + QTest::newRow("( ),olleH|words") + << standard[3] << 6 << 7 << QDeclarativeTextInput::SelectWords << 7 << 7 << false; + QTest::newRow("( ),olleH|words,reversed") + << standard[3] << 7 << 6 << QDeclarativeTextInput::SelectWords << 6 << 6 << false; + QTest::newRow("(dlrow ),olleH|words") + << standard[3] << 1 << 7 << QDeclarativeTextInput::SelectWords << 1 << 6 << true; + QTest::newRow("(!dlrow ),olleH|words") + << standard[3] << 0 << 7 << QDeclarativeTextInput::SelectWords << 0 << 6 << true; + QTest::newRow("(!dlrow ,)olleH|words") + << standard[3] << 0 << 8 << QDeclarativeTextInput::SelectWords << 0 << 8 << true; + QTest::newRow("(!)dlrow|words") + << standard[3] << 0 << 1 << QDeclarativeTextInput::SelectWords << 0 << 1 << true; + QTest::newRow("()!dlrow|words") + << standard[3] << 0 << 0 << QDeclarativeTextInput::SelectWords << 0 << 0 << true; + QTest::newRow("!()dlrow|words") + << standard[3] << 1 << 1 << QDeclarativeTextInput::SelectWords << 1 << 1 << true; +} + +void tst_qdeclarativetextinput::moveCursorSelection() +{ + QFETCH(QString, testStr); + QFETCH(int, cursorPosition); + QFETCH(int, movePosition); + QFETCH(QDeclarativeTextInput::SelectionMode, mode); + QFETCH(int, selectionStart); + QFETCH(int, selectionEnd); + QFETCH(bool, reversible); + + QString componentStr = "import QtQuick 1.1\nTextInput { text: \""+ testStr +"\"; }"; + QDeclarativeComponent textinputComponent(&engine); + textinputComponent.setData(componentStr.toLatin1(), QUrl()); + QDeclarativeTextInput *textinputObject = qobject_cast(textinputComponent.create()); + QVERIFY(textinputObject != 0); + + textinputObject->setCursorPosition(cursorPosition); + textinputObject->moveCursorSelection(movePosition, mode); + + QCOMPARE(textinputObject->selectionStart(), selectionStart); + QCOMPARE(textinputObject->selectionEnd(), selectionEnd); + + if (reversible) { + textinputObject->setCursorPosition(movePosition); + textinputObject->moveCursorSelection(cursorPosition, mode); + + QCOMPARE(textinputObject->selectionStart(), selectionStart); + QCOMPARE(textinputObject->selectionEnd(), selectionEnd); + } +} + void tst_qdeclarativetextinput::horizontalAlignment_data() { QTest::addColumn("hAlign"); -- cgit v0.12 From 77cba04c244c47c77af04777de3b3172c309b541 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Mon, 10 Jan 2011 15:01:11 +1000 Subject: Fix word selection in QLineControl Word selection occasionally selected the word beforehand as well, in both QLineEdit and TextInput. Visual Test included to verify behavior. Task-number: QTBUG-15818 Reviewed-by: Martin Jones --- src/gui/widgets/qlinecontrol.cpp | 4 +- .../data-X11/qtbug-15818.0.png | Bin 0 -> 573 bytes .../data-X11/qtbug-15818.1.png | Bin 0 -> 573 bytes .../data-X11/qtbug-15818.2.png | Bin 0 -> 573 bytes .../data-X11/qtbug-15818.3.png | Bin 0 -> 647 bytes .../data-X11/qtbug-15818.4.png | Bin 0 -> 647 bytes .../data-X11/qtbug-15818.5.png | Bin 0 -> 625 bytes .../qdeclarativetextinput/data-X11/qtbug-15818.qml | 1039 ++++++++++++++++++++ .../qdeclarativetextinput/qtbug-15818.qml | 13 + 9 files changed, 1054 insertions(+), 2 deletions(-) create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.0.png create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.1.png create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.2.png create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.3.png create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.4.png create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.5.png create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.qml create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetextinput/qtbug-15818.qml diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index 5ea9dc4..12607c1 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -541,10 +541,10 @@ void QLineControl::draw(QPainter *painter, const QPoint &offset, const QRect &cl */ void QLineControl::selectWordAtPos(int cursor) { - int c = m_textLayout.previousCursorPosition(cursor, QTextLayout::SkipWords); + int c = m_textLayout.previousCursorPosition(cursor+1, QTextLayout::SkipWords); moveCursor(c, false); // ## text layout should support end of words. - int end = m_textLayout.nextCursorPosition(cursor, QTextLayout::SkipWords); + int end = m_textLayout.nextCursorPosition(c, QTextLayout::SkipWords); while (end > cursor && m_text[end-1].isSpace()) --end; moveCursor(end, true); diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.0.png b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.0.png new file mode 100644 index 0000000..fc34b1a Binary files /dev/null and b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.0.png differ diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.1.png b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.1.png new file mode 100644 index 0000000..fc34b1a Binary files /dev/null and b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.1.png differ diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.2.png b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.2.png new file mode 100644 index 0000000..fc34b1a Binary files /dev/null and b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.2.png differ diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.3.png b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.3.png new file mode 100644 index 0000000..fb2c90b Binary files /dev/null and b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.3.png differ diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.4.png b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.4.png new file mode 100644 index 0000000..fb2c90b Binary files /dev/null and b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.4.png differ diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.5.png b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.5.png new file mode 100644 index 0000000..e2231ff Binary files /dev/null and b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.5.png differ diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.qml b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.qml new file mode 100644 index 0000000..790dffa --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/data-X11/qtbug-15818.qml @@ -0,0 +1,1039 @@ +import Qt.VisualTest 4.7 + +VisualTest { + Frame { + msec: 0 + } + Frame { + msec: 16 + image: "qtbug-15818.0.png" + } + Frame { + msec: 32 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 48 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 64 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 80 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 96 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 112 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 128 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 144 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 160 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 176 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 192 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 208 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 224 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 240 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 256 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 272 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 288 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 304 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 320 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 336 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 352 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 368 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 384 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 400 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 416 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 432 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 448 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 464 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 480 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 496 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 512 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 528 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 544 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 560 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 576 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 592 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 608 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 624 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 640 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 656 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 672 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 688 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 704 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 720 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 736 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 752 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 768 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 784 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 800 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 816 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 832 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 848 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 864 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 880 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Mouse { + type: 2 + button: 1 + buttons: 1 + x: 26; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 896 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 912 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 928 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 27; y: 9 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 3 + button: 1 + buttons: 0 + x: 27; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 944 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 960 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 976 + image: "qtbug-15818.1.png" + } + Frame { + msec: 992 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Mouse { + type: 4 + button: 1 + buttons: 1 + x: 27; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1008 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1024 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1040 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1056 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1072 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1088 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1104 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Mouse { + type: 3 + button: 1 + buttons: 0 + x: 27; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1120 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1136 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1152 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1168 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1184 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1200 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1216 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1232 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1248 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1264 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1280 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1296 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1312 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1328 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1344 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1360 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1376 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1392 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1408 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1424 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1440 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1456 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1472 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1488 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1504 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1520 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1536 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1552 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1568 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1584 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1600 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1616 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1632 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1648 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1664 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1680 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1696 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1712 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1728 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1744 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1760 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1776 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Frame { + msec: 1792 + hash: "8833dfac6aae78ce1309222cc4438e6f" + } + Mouse { + type: 2 + button: 1 + buttons: 1 + x: 43; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1808 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 1824 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 1840 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 1856 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 1872 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 1888 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Mouse { + type: 3 + button: 1 + buttons: 0 + x: 43; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1904 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 1920 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 1936 + image: "qtbug-15818.2.png" + } + Frame { + msec: 1952 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Mouse { + type: 4 + button: 1 + buttons: 1 + x: 43; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 1968 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 1984 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2000 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2016 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2032 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2048 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2064 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Mouse { + type: 3 + button: 1 + buttons: 0 + x: 43; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2080 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2096 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2112 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2128 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2144 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2160 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2176 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2192 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2208 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2224 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2240 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2256 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2272 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2288 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2304 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2320 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2336 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2352 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2368 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2384 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2400 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2416 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2432 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2448 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2464 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2480 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2496 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2512 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2528 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2544 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2560 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2576 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2592 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2608 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2624 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2640 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2656 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2672 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2688 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Mouse { + type: 2 + button: 1 + buttons: 1 + x: 54; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2704 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 2720 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 2736 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 2752 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 2768 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 2784 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Mouse { + type: 5 + button: 0 + buttons: 1 + x: 55; y: 9 + modifiers: 0 + sendToViewport: true + } + Mouse { + type: 3 + button: 1 + buttons: 0 + x: 55; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2800 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 2816 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 2832 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Frame { + msec: 2848 + hash: "0a63463fc1004efffd15f9524bcf3a29" + } + Mouse { + type: 4 + button: 1 + buttons: 1 + x: 55; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2864 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2880 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2896 + image: "qtbug-15818.3.png" + } + Frame { + msec: 2912 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2928 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2944 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2960 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 2976 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Mouse { + type: 3 + button: 1 + buttons: 0 + x: 55; y: 9 + modifiers: 0 + sendToViewport: true + } + Frame { + msec: 2992 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3008 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3024 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3040 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3056 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3072 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3088 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3104 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3120 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3136 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3152 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3168 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3184 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3200 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3216 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3232 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3248 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3264 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3280 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3296 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3312 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3328 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3344 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3360 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3376 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3392 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3408 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3424 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3440 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3456 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3472 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3488 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3504 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3520 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3536 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3552 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3568 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3584 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3600 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3616 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3632 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3648 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3664 + hash: "270462ec02bce658757e0ea4fb2136b1" + } + Frame { + msec: 3680 + hash: "270462ec02bce658757e0ea4fb2136b1" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetextinput/qtbug-15818.qml b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/qtbug-15818.qml new file mode 100644 index 0000000..59710a4 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetextinput/qtbug-15818.qml @@ -0,0 +1,13 @@ +import QtQuick 1.1 +//Test that doubleclicking on the front of a word only selects that word, and not the word in front + +Item{ + width: 200 + height: 100 + TextInput{ + anchors.fill: parent + readOnly: true + selectByMouse: true + text: "abc a cba test" + } +} -- cgit v0.12 From 7aae8a569809208318ad06017eda39c860c1b2a9 Mon Sep 17 00:00:00 2001 From: Joona Petrell Date: Mon, 10 Jan 2011 15:29:03 +1000 Subject: Add no warnings label to qmlviewer warnings window Small developer usability improvement Task-number: Reviewed-by: Bea Lam --- tools/qml/loggerwidget.cpp | 15 +++++++++++++++ tools/qml/loggerwidget.h | 4 +++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/tools/qml/loggerwidget.cpp b/tools/qml/loggerwidget.cpp index f601d95..fb4fedc 100644 --- a/tools/qml/loggerwidget.cpp +++ b/tools/qml/loggerwidget.cpp @@ -45,6 +45,8 @@ #include #include #include +#include +#include #ifdef Q_WS_MAEMO_5 # include # include @@ -83,6 +85,14 @@ LoggerWidget::LoggerWidget(QWidget *parent) : setCentralWidget(m_plainTextEdit); #endif + m_noWarningsLabel = new QLabel(m_plainTextEdit); + m_noWarningsLabel->setText(tr("(No warnings)")); + m_noWarningsLabel->setAlignment(Qt::AlignVCenter | Qt::AlignHCenter); + QVBoxLayout *layout = new QVBoxLayout; + layout->addWidget(m_noWarningsLabel); + m_plainTextEdit->setLayout(layout); + connect(m_plainTextEdit, SIGNAL(textChanged()), this, SLOT(updateNoWarningsLabel())); + readSettings(); setupPreferencesMenu(); } @@ -207,4 +217,9 @@ void LoggerWidget::setupPreferencesMenu() } } +void LoggerWidget::updateNoWarningsLabel() +{ + m_noWarningsLabel->setVisible(m_plainTextEdit->toPlainText().length() == 0); +} + QT_END_NAMESPACE diff --git a/tools/qml/loggerwidget.h b/tools/qml/loggerwidget.h index 13c319f..27d4d0b 100644 --- a/tools/qml/loggerwidget.h +++ b/tools/qml/loggerwidget.h @@ -48,6 +48,7 @@ QT_BEGIN_NAMESPACE class QPlainTextEdit; +class QLabel; class QMenu; class QAction; @@ -66,6 +67,7 @@ public: public slots: void append(const QString &msg); + void updateNoWarningsLabel(); private slots: void warningsPreferenceChanged(QAction *action); @@ -86,7 +88,7 @@ private: QMenu *m_preferencesMenu; QAction *m_showWidgetAction; QPlainTextEdit *m_plainTextEdit; - + QLabel *m_noWarningsLabel; enum ConfigOrigin { CommandLineOrigin, SettingsOrigin }; ConfigOrigin m_visibilityOrigin; Visibility m_visibility; -- cgit v0.12 From 6a36f1f6299980cd0338009cb31e2a36cd40e44f Mon Sep 17 00:00:00 2001 From: Joona Petrell Date: Mon, 10 Jan 2011 15:40:11 +1000 Subject: Add property versioning checks for QtQuick 1.1 deselect() function Task-number: QTBUG-16059 Reviewed-by: Martin Jones --- src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp | 5 ++++- src/declarative/graphicsitems/qdeclarativetextedit_p.h | 2 +- src/declarative/graphicsitems/qdeclarativetextinput_p.h | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp b/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp index 7db4d85..0d386c6 100644 --- a/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp +++ b/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp @@ -179,8 +179,11 @@ void QDeclarativeItemModule::defineModule() qmlRegisterType("QtQuick",1,1,"PinchArea"); qmlRegisterType("QtQuick",1,1,"Pinch"); qmlRegisterType(); - qmlRegisterType("QtQuick",1,1,"Repeater"); + qmlRegisterType("QtQuick",1,1,"Repeater"); qmlRegisterType("QtQuick",1,1,"TextEdit"); +#ifndef QT_NO_LINEEDIT + qmlRegisterType("QtQuick",1,1,"TextInput"); +#endif #ifndef QT_NO_IMPORT_QT47_QML #ifdef QT_NO_MOVIE diff --git a/src/declarative/graphicsitems/qdeclarativetextedit_p.h b/src/declarative/graphicsitems/qdeclarativetextedit_p.h index 6a05aa8..3e86a05 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextedit_p.h @@ -231,10 +231,10 @@ Q_SIGNALS: Q_REVISION(1) void linkActivated(const QString &link); public Q_SLOTS: - void deselect(); void selectAll(); void selectWord(); void select(int start, int end); + Q_REVISION(1) void deselect(); #ifndef QT_NO_CLIPBOARD void cut(); void copy(); diff --git a/src/declarative/graphicsitems/qdeclarativetextinput_p.h b/src/declarative/graphicsitems/qdeclarativetextinput_p.h index 25b8e66..5bff2ea 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextinput_p.h @@ -238,10 +238,10 @@ protected: void focusInEvent(QFocusEvent *event); public Q_SLOTS: - void deselect(); void selectAll(); void selectWord(); void select(int start, int end); + Q_REVISION(1) void deselect(); #ifndef QT_NO_CLIPBOARD void cut(); void copy(); -- cgit v0.12 From 7d43a31902ca6d2132004c45db313194c9669bb6 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Mon, 10 Jan 2011 18:11:19 +1000 Subject: Disable dragging text in TextEdit. Add a dragEnabled property to QTextControl so text dragging can optionally be disabled. Task-number: QTBUG-16248 Reviewed-by: Martin Jones --- .../graphicsitems/qdeclarativetextedit.cpp | 1 + src/gui/text/qtextcontrol.cpp | 17 +++++++- src/gui/text/qtextcontrol_p.h | 3 ++ src/gui/text/qtextcontrol_p_p.h | 2 + .../tst_qdeclarativetextedit.cpp | 46 ++++++++++++++++++++++ .../data/mouseselection_true.qml | 7 ++++ .../tst_qdeclarativetextinput.cpp | 45 +++++++++++++++++++++ 7 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 tests/auto/declarative/qdeclarativetextinput/data/mouseselection_true.qml diff --git a/src/declarative/graphicsitems/qdeclarativetextedit.cpp b/src/declarative/graphicsitems/qdeclarativetextedit.cpp index 7ea3dec..c1c7a0c 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextedit.cpp @@ -1342,6 +1342,7 @@ void QDeclarativeTextEditPrivate::init() control = new QTextControl(q); control->setIgnoreUnusedNavigationEvents(true); control->setTextInteractionFlags(control->textInteractionFlags() | Qt::LinksAccessibleByMouse); + control->setDragEnabled(false); // QTextControl follows the default text color // defined by the platform, declarative text diff --git a/src/gui/text/qtextcontrol.cpp b/src/gui/text/qtextcontrol.cpp index 7f2c4e9..548d81e 100644 --- a/src/gui/text/qtextcontrol.cpp +++ b/src/gui/text/qtextcontrol.cpp @@ -114,6 +114,7 @@ static QTextLine currentTextLine(const QTextCursor &cursor) QTextControlPrivate::QTextControlPrivate() : doc(0), cursorOn(false), cursorIsFocusIndicator(false), interactionFlags(Qt::TextEditorInteraction), + dragEnabled(true), #ifndef QT_NO_DRAGANDDROP mousePressed(false), mightStartDrag(false), #endif @@ -1551,7 +1552,8 @@ void QTextControlPrivate::mousePressEvent(QEvent *e, Qt::MouseButton button, con setCursorPosition(cursorPos, QTextCursor::KeepAnchor); } else { - if (cursor.hasSelection() + if (dragEnabled + && cursor.hasSelection() && !cursorIsFocusIndicator && cursorPos >= cursor.selectionStart() && cursorPos <= cursor.selectionEnd() @@ -2328,6 +2330,19 @@ bool QTextControl::cursorIsFocusIndicator() const return d->cursorIsFocusIndicator; } + +void QTextControl::setDragEnabled(bool enabled) +{ + Q_D(QTextControl); + d->dragEnabled = enabled; +} + +bool QTextControl::isDragEnabled() const +{ + Q_D(const QTextControl); + return d->dragEnabled; +} + #ifndef QT_NO_PRINTER void QTextControl::print(QPrinter *printer) const { diff --git a/src/gui/text/qtextcontrol_p.h b/src/gui/text/qtextcontrol_p.h index 8399d50..2af442f 100644 --- a/src/gui/text/qtextcontrol_p.h +++ b/src/gui/text/qtextcontrol_p.h @@ -175,6 +175,9 @@ public: void setCursorIsFocusIndicator(bool b); bool cursorIsFocusIndicator() const; + void setDragEnabled(bool enabled); + bool isDragEnabled() const; + #ifndef QT_NO_PRINTER void print(QPrinter *printer) const; #endif diff --git a/src/gui/text/qtextcontrol_p_p.h b/src/gui/text/qtextcontrol_p_p.h index c103103..29c04a7 100644 --- a/src/gui/text/qtextcontrol_p_p.h +++ b/src/gui/text/qtextcontrol_p_p.h @@ -174,6 +174,8 @@ public: QBasicTimer trippleClickTimer; QPointF trippleClickPoint; + bool dragEnabled; + bool mousePressed; bool mightStartDrag; diff --git a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp index 7af008f..649d34f 100644 --- a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp +++ b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp @@ -113,6 +113,7 @@ private slots: void moveCursorSelection(); void mouseSelection_data(); void mouseSelection(); + void dragMouseSelection(); void inputMethodHints(); void cursorDelegate(); @@ -916,6 +917,51 @@ void tst_qdeclarativetextedit::mouseSelection() QVERIFY(str.isEmpty()); } +void tst_qdeclarativetextedit::dragMouseSelection() +{ + QString qmlfile = SRCDIR "/data/mouseselection_true.qml"; + + QDeclarativeView *canvas = createView(qmlfile); + + canvas->show(); + QApplication::setActiveWindow(canvas); + QTest::qWaitForWindowShown(canvas); + QTRY_COMPARE(QApplication::activeWindow(), static_cast(canvas)); + + QVERIFY(canvas->rootObject() != 0); + QDeclarativeTextEdit *textEditObject = qobject_cast(canvas->rootObject()); + QVERIFY(textEditObject != 0); + + textEditObject->setAcceptDrops(true); + + // press-and-drag-and-release from x1 to x2 + int x1 = 10; + int x2 = 70; + int y = textEditObject->height()/2; + QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y))); + { + QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(canvas->viewport(), &mv); + } + QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y))); + QString str1 = textEditObject->selectedText(); + QVERIFY(str1.length() > 3); + + // press and drag the current selection. + x1 = 40; + x2 = 100; + QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y))); + { + QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(canvas->viewport(), &mv); + } + QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y))); + QString str2 = textEditObject->selectedText(); + QVERIFY(str2.length() > 3); + + QVERIFY(str1 != str2); // Verify the second press and drag is a new selection and doesn't not the first moved. +} + void tst_qdeclarativetextedit::inputMethodHints() { QDeclarativeView *canvas = createView(SRCDIR "/data/inputmethodhints.qml"); diff --git a/tests/auto/declarative/qdeclarativetextinput/data/mouseselection_true.qml b/tests/auto/declarative/qdeclarativetextinput/data/mouseselection_true.qml new file mode 100644 index 0000000..8115ba0 --- /dev/null +++ b/tests/auto/declarative/qdeclarativetextinput/data/mouseselection_true.qml @@ -0,0 +1,7 @@ +import QtQuick 1.0 + +TextInput { + focus: true + text: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + selectByMouse: true +} diff --git a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp index 1de695e..964125f 100644 --- a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp +++ b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp @@ -91,6 +91,7 @@ private slots: void selection(); void moveCursorSelection_data(); void moveCursorSelection(); + void dragMouseSelection(); void horizontalAlignment_data(); void horizontalAlignment(); @@ -576,6 +577,50 @@ void tst_qdeclarativetextinput::moveCursorSelection() } } +void tst_qdeclarativetextinput::dragMouseSelection() +{ + QString qmlfile = SRCDIR "/data/mouseselection_true.qml"; + + QDeclarativeView *canvas = createView(qmlfile); + + canvas->show(); + QApplication::setActiveWindow(canvas); + QTest::qWaitForWindowShown(canvas); + QTRY_COMPARE(QApplication::activeWindow(), static_cast(canvas)); + + QVERIFY(canvas->rootObject() != 0); + QDeclarativeTextInput *textInputObject = qobject_cast(canvas->rootObject()); + QVERIFY(textInputObject != 0); + + // press-and-drag-and-release from x1 to x2 + int x1 = 10; + int x2 = 70; + int y = textInputObject->height()/2; + QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y))); + { + QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(canvas->viewport(), &mv); + } + QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y))); + + QString str1 = textInputObject->selectedText(); + QVERIFY(str1.length() > 3); + + // press and drag the current selection. + x1 = 40; + x2 = 100; + QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y))); + { + QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(canvas->viewport(), &mv); + } + QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y))); + QString str2 = textInputObject->selectedText(); + QVERIFY(str2.length() > 3); + + QVERIFY(str1 != str2); // Verify the second press and drag is a new selection and doesn't not the first moved. +} + void tst_qdeclarativetextinput::horizontalAlignment_data() { QTest::addColumn("hAlign"); -- cgit v0.12 From 7ca750fad4e74929c9c34a98c19bde37747a9dc5 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Tue, 11 Jan 2011 10:55:14 +1000 Subject: Add versioning for new Flickable methods. Task-number: QTBUG-15148 --- .../graphicsitems/qdeclarativeflickable_p.h | 5 +-- .../graphicsitems/qdeclarativeitemsmodule.cpp | 1 + .../tst_qdeclarativeflickable.cpp | 43 ++++++++++++++++++++++ 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativeflickable_p.h b/src/declarative/graphicsitems/qdeclarativeflickable_p.h index ece2db7..4d3da92 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable_p.h +++ b/src/declarative/graphicsitems/qdeclarativeflickable_p.h @@ -149,9 +149,8 @@ public: FlickableDirection flickableDirection() const; void setFlickableDirection(FlickableDirection); - //XXX Added in QtQuick 1.1 - Q_INVOKABLE void resizeContent(qreal w, qreal h, QPointF center); - Q_INVOKABLE void returnToBounds(); + Q_INVOKABLE Q_REVISION(1) void resizeContent(qreal w, qreal h, QPointF center); + Q_INVOKABLE Q_REVISION(1) void returnToBounds(); Q_SIGNALS: void contentWidthChanged(); diff --git a/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp b/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp index 0d386c6..ddbde0b 100644 --- a/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp +++ b/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp @@ -179,6 +179,7 @@ void QDeclarativeItemModule::defineModule() qmlRegisterType("QtQuick",1,1,"PinchArea"); qmlRegisterType("QtQuick",1,1,"Pinch"); qmlRegisterType(); + qmlRegisterType("QtQuick",1,1,"Flickable"); qmlRegisterType("QtQuick",1,1,"Repeater"); qmlRegisterType("QtQuick",1,1,"TextEdit"); #ifndef QT_NO_LINEEDIT diff --git a/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp b/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp index c1564bc..10ab467 100644 --- a/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp +++ b/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp @@ -72,6 +72,8 @@ private slots: void qgraphicswidget(); void resizeContent(); void returnToBounds(); + void testQtQuick11Attributes(); + void testQtQuick11Attributes_data(); private: QDeclarativeEngine engine; @@ -331,6 +333,47 @@ void tst_qdeclarativeflickable::returnToBounds() delete root; } +void tst_qdeclarativeflickable::testQtQuick11Attributes() +{ + QFETCH(QString, code); + QFETCH(QString, warning); + QFETCH(QString, error); + + QDeclarativeEngine engine; + QObject *obj; + + QDeclarativeComponent invalid(&engine); + invalid.setData("import QtQuick 1.0; Flickable { " + code.toUtf8() + " }", QUrl("")); + QTest::ignoreMessage(QtWarningMsg, warning.toUtf8()); + obj = invalid.create(); + QCOMPARE(invalid.errorString(), error); + delete obj; + + QDeclarativeComponent valid(&engine); + valid.setData("import QtQuick 1.1; Flickable { " + code.toUtf8() + " }", QUrl("")); + obj = valid.create(); + QVERIFY(obj); + QVERIFY(valid.errorString().isEmpty()); + delete obj; +} + +void tst_qdeclarativeflickable::testQtQuick11Attributes_data() +{ + QTest::addColumn("code"); + QTest::addColumn("warning"); + QTest::addColumn("error"); + + QTest::newRow("resizeContent") << "Component.onCompleted: resizeContent(100,100,Qt.point(50,50))" + << ":1: ReferenceError: Can't find variable: resizeContent" + << ""; + + QTest::newRow("returnToBounds") << "Component.onCompleted: returnToBounds()" + << ":1: ReferenceError: Can't find variable: returnToBounds" + << ""; + +} + + template T *tst_qdeclarativeflickable::findItem(QGraphicsObject *parent, const QString &objectName) { -- cgit v0.12 From 9fbe02cf8a76d4cca0a28d9fb92a2b181494c82d Mon Sep 17 00:00:00 2001 From: Joona Petrell Date: Mon, 10 Jan 2011 15:54:54 +1000 Subject: Fix examples autotest failure Task-number: Reviewed-by: Martin Jones --- examples/declarative/touchinteraction/pincharea/flickresize.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/declarative/touchinteraction/pincharea/flickresize.qml b/examples/declarative/touchinteraction/pincharea/flickresize.qml index aa426e7..a2f81ff 100644 --- a/examples/declarative/touchinteraction/pincharea/flickresize.qml +++ b/examples/declarative/touchinteraction/pincharea/flickresize.qml @@ -54,7 +54,7 @@ Rectangle { PinchArea { width: Math.max(flick.contentWidth, flick.width) height: Math.max(flick.contentHeight, flick.height) - onPinchChanged: { + onPinchUpdated: { // adjust content pos due to drag flick.contentX += pinch.previousCenter.x - pinch.center.x flick.contentY += pinch.previousCenter.y - pinch.center.y -- cgit v0.12 From aca9a8d95f1fa9c29a7650d528616a0962732db3 Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Mon, 10 Jan 2011 14:08:44 +1000 Subject: set() and setProperty() should not always trigger change signals Fix set() and setProperty() to only trigger itemsChanged(), and the the Changed signals for items returned by get(), if the new value is different from the old one. The exception to this are list values, as it is inefficient to check the sublists and also the model classes are due to be revised. This also fixes models used with a WorkerScript to emit itemsChanged() with the correct roles. Task-number: QTBUG-14620 Reviewed-by: Michael Brasser --- src/declarative/util/qdeclarativelistmodel.cpp | 83 +++++++---- src/declarative/util/qdeclarativelistmodel_p.h | 3 + src/declarative/util/qdeclarativelistmodel_p_p.h | 6 +- .../util/qdeclarativelistmodelworkeragent.cpp | 28 ++-- .../util/qdeclarativelistmodelworkeragent_p.h | 5 +- .../tst_qdeclarativelistmodel.cpp | 159 ++++++++++++++++++++- 6 files changed, 238 insertions(+), 46 deletions(-) diff --git a/src/declarative/util/qdeclarativelistmodel.cpp b/src/declarative/util/qdeclarativelistmodel.cpp index 538e8af..8290665 100644 --- a/src/declarative/util/qdeclarativelistmodel.cpp +++ b/src/declarative/util/qdeclarativelistmodel.cpp @@ -559,6 +559,14 @@ QScriptValue QDeclarativeListModel::get(int index) const */ void QDeclarativeListModel::set(int index, const QScriptValue& valuemap) { + QList roles; + set(index, valuemap, &roles); + if (!roles.isEmpty() && !inWorkerThread()) + emit itemsChanged(index, 1, roles); +} + +void QDeclarativeListModel::set(int index, const QScriptValue& valuemap, QList *roles) +{ if (!valuemap.isObject() || valuemap.isArray()) { qmlInfo(this) << tr("set: value is not an object"); return; @@ -571,14 +579,10 @@ void QDeclarativeListModel::set(int index, const QScriptValue& valuemap) if (index == count()) { append(valuemap); } else { - QList roles; if (m_flat) - m_flat->set(index, valuemap, &roles); + m_flat->set(index, valuemap, roles); else - m_nested->set(index, valuemap, &roles); - - if (!inWorkerThread()) - emit itemsChanged(index, 1, roles); + m_nested->set(index, valuemap, roles); } } @@ -597,19 +601,23 @@ void QDeclarativeListModel::set(int index, const QScriptValue& valuemap) */ void QDeclarativeListModel::setProperty(int index, const QString& property, const QVariant& value) { + QList roles; + setProperty(index, property, value, &roles); + if (!roles.isEmpty() && !inWorkerThread()) + emit itemsChanged(index, 1, roles); +} + +void QDeclarativeListModel::setProperty(int index, const QString& property, const QVariant& value, QList *roles) +{ if (count() == 0 || index >= count() || index < 0) { qmlInfo(this) << tr("set: index %1 out of range").arg(index); return; } - QList roles; if (m_flat) - m_flat->setProperty(index, property, value, &roles); + m_flat->setProperty(index, property, value, roles); else - m_nested->setProperty(index, property, value, &roles); - - if (!inWorkerThread()) - emit itemsChanged(index, 1, roles); + m_nested->setProperty(index, property, value, roles); } /*! @@ -1011,9 +1019,11 @@ void FlatListModel::setProperty(int index, const QString& property, const QVaria } else { role = iter.value(); } - roles->append(role); - m_values[index][role] = value; + if (m_values[index][role] != value) { + roles->append(role); + m_values[index][role] = value; + } } void FlatListModel::move(int from, int to, int n) @@ -1043,6 +1053,10 @@ bool FlatListModel::addValue(const QScriptValue &value, QHash *ro iter = m_strings.insert(name, role); if (roles) roles->append(role); + } else { + int role = iter.value(); + if (roles && row->contains(role) && row->value(role) != v) + roles->append(role); } row->insert(*iter, v); } @@ -1151,14 +1165,14 @@ void FlatListScriptClass::setProperty(Object *obj, const Identifier &name, const QHash &row = m_model->m_values[index]; row[role] = value.toVariant(); + QList roles; + roles << role; if (m_model->m_parentAgent) { // This is the list in the worker thread, so tell the agent to // emit itemsChanged() later - m_model->m_parentAgent->changedData(index, 1); + m_model->m_parentAgent->changedData(index, 1, roles); } else { // This is the list in the main thread, so emit itemsChanged() - QList roles; - roles << role; emit m_model->m_listModel->itemsChanged(index, 1, roles); } } @@ -1350,7 +1364,9 @@ void NestedListModel::set(int index, const QScriptValue& valuemap, QList *r Q_ASSERT(index >=0 && index < count()); ModelNode *node = qvariant_cast(_root->values.at(index)); - node->setObjectValue(valuemap); + bool emitItemsChanged = node->setObjectValue(valuemap); + if (!emitItemsChanged) + return; QScriptValueIterator it(valuemap); while (it.hasNext()) { @@ -1369,7 +1385,9 @@ void NestedListModel::setProperty(int index, const QString& property, const QVar Q_ASSERT(index >=0 && index < count()); ModelNode *node = qvariant_cast(_root->values.at(index)); - node->setProperty(property, value); + bool emitItemsChanged = node->setProperty(property, value); + if (!emitItemsChanged) + return; int r = roleStrings.indexOf(property); if (r < 0) { @@ -1441,26 +1459,37 @@ void ModelNode::clear() properties.clear(); } -void ModelNode::setObjectValue(const QScriptValue& valuemap, bool writeToCache) { +bool ModelNode::setObjectValue(const QScriptValue& valuemap, bool writeToCache) +{ + bool emitItemsChanged = false; + QScriptValueIterator it(valuemap); while (it.hasNext()) { it.next(); + ModelNode *prev = properties.value(it.name()); ModelNode *value = new ModelNode(m_model); QScriptValue v = it.value(); + if (v.isArray()) { value->isArray = true; value->setListValue(v); if (writeToCache && objectCache) objectCache->setValue(it.name().toUtf8(), QVariant::fromValue(value->model(m_model))); + emitItemsChanged = true; // for now, too inefficient to check whether list and sublists have changed } else { value->values << v.toVariant(); if (writeToCache && objectCache) objectCache->setValue(it.name().toUtf8(), value->values.last()); + if (!emitItemsChanged && prev && prev->values.count() == 1 + && prev->values[0] != value->values.last()) { + emitItemsChanged = true; + } } if (properties.contains(it.name())) delete properties[it.name()]; properties.insert(it.name(), value); } + return emitItemsChanged; } void ModelNode::setListValue(const QScriptValue& valuelist) { @@ -1483,9 +1512,12 @@ void ModelNode::setListValue(const QScriptValue& valuelist) { } } -void ModelNode::setProperty(const QString& prop, const QVariant& val) { +bool ModelNode::setProperty(const QString& prop, const QVariant& val) { QHash::const_iterator it = properties.find(prop); + bool emitItemsChanged = false; if (it != properties.end()) { + if (val != (*it)->values[0]) + emitItemsChanged = true; (*it)->values[0] = val; } else { ModelNode *n = new ModelNode(m_model); @@ -1494,6 +1526,7 @@ void ModelNode::setProperty(const QString& prop, const QVariant& val) { } if (objectCache) objectCache->setValue(prop.toUtf8(), val); + return emitItemsChanged; } void ModelNode::updateListIndexes() @@ -1561,7 +1594,7 @@ ModelObject::ModelObject(ModelNode *node, NestedListModel *model, QScriptEngine void ModelObject::setValue(const QByteArray &name, const QVariant &val) { m_meta->setValue(name, val); - setProperty(name.constData(), val); + //setProperty(name.constData(), val); } void ModelObject::setNodeUpdatesEnabled(bool enable) @@ -1588,9 +1621,9 @@ void ModelNodeMetaObject::propertyWritten(int index) QScriptValue sv = m_seng->newObject(); sv.setProperty(propName, m_seng->newVariant(value)); - m_obj->m_node->setObjectValue(sv, false); - - m_obj->m_node->changedProperty(propName); + bool changed = m_obj->m_node->setObjectValue(sv, false); + if (changed) + m_obj->m_node->changedProperty(propName); } diff --git a/src/declarative/util/qdeclarativelistmodel_p.h b/src/declarative/util/qdeclarativelistmodel_p.h index 90036f9..0b4becd 100644 --- a/src/declarative/util/qdeclarativelistmodel_p.h +++ b/src/declarative/util/qdeclarativelistmodel_p.h @@ -103,6 +103,9 @@ private: // Constructs a flat list model for a worker agent QDeclarativeListModel(const QDeclarativeListModel *orig, QDeclarativeListModelWorkerAgent *parent); + void set(int index, const QScriptValue&, QList *roles); + void setProperty(int index, const QString& property, const QVariant& value, QList *roles); + bool flatten(); bool inWorkerThread() const; diff --git a/src/declarative/util/qdeclarativelistmodel_p_p.h b/src/declarative/util/qdeclarativelistmodel_p_p.h index 43a0a9b..ec1b538 100644 --- a/src/declarative/util/qdeclarativelistmodel_p_p.h +++ b/src/declarative/util/qdeclarativelistmodel_p_p.h @@ -190,7 +190,7 @@ public: bool insert(int index, const QScriptValue&); QScriptValue get(int index) const; void set(int index, const QScriptValue&, QList *roles); - void setProperty(int index, const QString& property, const QVariant& value, QList *role); + void setProperty(int index, const QString& property, const QVariant& value, QList *roles); void move(int from, int to, int count); QVariant valueForNode(ModelNode *, bool *hasNested = 0) const; @@ -255,9 +255,9 @@ struct ModelNode QDeclarativeListModel *model(const NestedListModel *model); ModelObject *object(const NestedListModel *model); - void setObjectValue(const QScriptValue& valuemap, bool writeToCache = true); + bool setObjectValue(const QScriptValue& valuemap, bool writeToCache = true); void setListValue(const QScriptValue& valuelist); - void setProperty(const QString& prop, const QVariant& val); + bool setProperty(const QString& prop, const QVariant& val); void changedProperty(const QString &name) const; void updateListIndexes(); static void dump(ModelNode *node, int ind); diff --git a/src/declarative/util/qdeclarativelistmodelworkeragent.cpp b/src/declarative/util/qdeclarativelistmodelworkeragent.cpp index 852b055..76d3048 100644 --- a/src/declarative/util/qdeclarativelistmodelworkeragent.cpp +++ b/src/declarative/util/qdeclarativelistmodelworkeragent.cpp @@ -60,25 +60,25 @@ void QDeclarativeListModelWorkerAgent::Data::clearChange() void QDeclarativeListModelWorkerAgent::Data::insertChange(int index, int count) { - Change c = { Change::Inserted, index, count, 0 }; + Change c = { Change::Inserted, index, count, 0, QList() }; changes << c; } void QDeclarativeListModelWorkerAgent::Data::removeChange(int index, int count) { - Change c = { Change::Removed, index, count, 0 }; + Change c = { Change::Removed, index, count, 0, QList() }; changes << c; } void QDeclarativeListModelWorkerAgent::Data::moveChange(int index, int count, int to) { - Change c = { Change::Moved, index, count, to }; + Change c = { Change::Moved, index, count, to, QList() }; changes << c; } -void QDeclarativeListModelWorkerAgent::Data::changedChange(int index, int count) +void QDeclarativeListModelWorkerAgent::Data::changedChange(int index, int count, const QList &roles) { - Change c = { Change::Changed, index, count, 0 }; + Change c = { Change::Changed, index, count, 0, roles }; changes << c; } @@ -165,14 +165,18 @@ QScriptValue QDeclarativeListModelWorkerAgent::get(int index) const void QDeclarativeListModelWorkerAgent::set(int index, const QScriptValue &value) { - m_copy->set(index, value); - data.changedChange(index, 1); + QList roles; + m_copy->set(index, value, &roles); + if (!roles.isEmpty()) + data.changedChange(index, 1, roles); } void QDeclarativeListModelWorkerAgent::setProperty(int index, const QString& property, const QVariant& value) { - m_copy->setProperty(index, property, value); - data.changedChange(index, 1); + QList roles; + m_copy->setProperty(index, property, value, &roles); + if (!roles.isEmpty()) + data.changedChange(index, 1, roles); } void QDeclarativeListModelWorkerAgent::move(int from, int to, int count) @@ -194,9 +198,9 @@ void QDeclarativeListModelWorkerAgent::sync() mutex.unlock(); } -void QDeclarativeListModelWorkerAgent::changedData(int index, int count) +void QDeclarativeListModelWorkerAgent::changedData(int index, int count, const QList &roles) { - data.changedChange(index, count); + data.changedChange(index, count, roles); } bool QDeclarativeListModelWorkerAgent::event(QEvent *e) @@ -255,7 +259,7 @@ bool QDeclarativeListModelWorkerAgent::event(QEvent *e) emit m_orig->itemsMoved(change.index, change.to, change.count); break; case Change::Changed: - emit m_orig->itemsChanged(change.index, change.count, orig->m_roles.keys()); + emit m_orig->itemsChanged(change.index, change.count, change.roles); break; } } diff --git a/src/declarative/util/qdeclarativelistmodelworkeragent_p.h b/src/declarative/util/qdeclarativelistmodelworkeragent_p.h index 10c3bca..0823b7e 100644 --- a/src/declarative/util/qdeclarativelistmodelworkeragent_p.h +++ b/src/declarative/util/qdeclarativelistmodelworkeragent_p.h @@ -124,6 +124,7 @@ private: int index; // Inserted/Removed/Moved/Changed int count; // Inserted/Removed/Moved/Changed int to; // Moved + QList roles; }; struct Data { @@ -133,7 +134,7 @@ private: void insertChange(int index, int count); void removeChange(int index, int count); void moveChange(int index, int count, int to); - void changedChange(int index, int count); + void changedChange(int index, int count, const QList &roles); }; Data data; @@ -143,7 +144,7 @@ private: QDeclarativeListModel *list; }; - void changedData(int index, int count); + void changedData(int index, int count, const QList &roles); QAtomicInt m_ref; QDeclarativeListModel *m_orig; diff --git a/tests/auto/declarative/qdeclarativelistmodel/tst_qdeclarativelistmodel.cpp b/tests/auto/declarative/qdeclarativelistmodel/tst_qdeclarativelistmodel.cpp index 55f7421..bdc5988 100644 --- a/tests/auto/declarative/qdeclarativelistmodel/tst_qdeclarativelistmodel.cpp +++ b/tests/auto/declarative/qdeclarativelistmodel/tst_qdeclarativelistmodel.cpp @@ -59,6 +59,7 @@ #endif Q_DECLARE_METATYPE(QList) +Q_DECLARE_METATYPE(QList) class tst_qdeclarativelistmodel : public QObject { @@ -101,6 +102,10 @@ private slots: void get_nested_data(); void crash_model_with_multiple_roles(); void set_model_cache(); + void property_changes(); + void property_changes_data(); + void property_changes_worker(); + void property_changes_worker_data(); }; int tst_qdeclarativelistmodel::roleFromName(const QDeclarativeListModel *model, const QString &roleName) { @@ -298,13 +303,10 @@ void tst_qdeclarativelistmodel::dynamic_data() QTest::newRow("nested-append3") << "{append({'foo':123,'bars':[{'a':1},{'a':2},{'a':3}]});get(0).bars.append({'a':4});get(0).bars.get(3).a}" << 4 << ""; QTest::newRow("nested-insert") << "{append({'foo':123});insert(0,{'bars':[{'a':1},{'b':2},{'c':3}]});get(0).bars.get(0).a}" << 1 << ""; - QTest::newRow("nested-set") << "{append({'foo':123});set(0,{'foo':[{'x':123}]});get(0).foo.get(0).x}" << 123 << ""; + QTest::newRow("nested-set") << "{append({'foo':[{'x':1}]});set(0,{'foo':[{'x':123}]});get(0).foo.get(0).x}" << 123 << ""; QTest::newRow("nested-count") << "{append({'foo':123,'bars':[{'a':1},{'a':2},{'a':3}]}); get(0).bars.count}" << 3 << ""; QTest::newRow("nested-clear") << "{append({'foo':123,'bars':[{'a':1},{'a':2},{'a':3}]}); get(0).bars.clear(); get(0).bars.count}" << 0 << ""; - - // XXX - //QTest::newRow("nested-setprop") << "{append({'foo':123});setProperty(0,'foo',[{'x':123}]);get(0).foo.get(0).x}" << 123 << ""; } void tst_qdeclarativelistmodel::dynamic() @@ -421,6 +423,9 @@ void tst_qdeclarativelistmodel::dynamic_worker_sync() if (QByteArray(QTest::currentDataTag()).startsWith("nested")) QTest::ignoreMessage(QtWarningMsg, ": QML ListModel: Cannot add list-type data when modifying or after modification from a worker script"); + if (QByteArray(QTest::currentDataTag()).startsWith("nested-set")) + QTest::ignoreMessage(QtWarningMsg, ": QML ListModel: Cannot add list-type data when modifying or after modification from a worker script"); + QVERIFY(QMetaObject::invokeMethod(item, "evalExpressionViaWorker", Q_ARG(QVariant, operations.mid(0, operations.length()-1)))); waitForWorker(item); @@ -940,6 +945,152 @@ void tst_qdeclarativelistmodel::set_model_cache() QVERIFY(model->property("ok").toBool()); } +void tst_qdeclarativelistmodel::property_changes() +{ + QFETCH(QString, script_setup); + QFETCH(QString, script_change); + QFETCH(QString, roleName); + QFETCH(int, listIndex); + QFETCH(bool, itemsChanged); + QFETCH(QString, testExpression); + + QDeclarativeEngine engine; + QDeclarativeListModel model; + QDeclarativeEngine::setContextForObject(&model, engine.rootContext()); + engine.rootContext()->setContextObject(&model); + + QDeclarativeExpression expr(engine.rootContext(), &model, script_setup); + expr.evaluate(); + QVERIFY2(!expr.hasError(), QTest::toString(expr.error().toString())); + + QString signalHandler = "on" + QString(roleName[0].toUpper()) + roleName.mid(1, roleName.length()) + "Changed:"; + QString qml = "import QtQuick 1.0\n" + "Connections {\n" + "property bool gotSignal: false\n" + "target: model.get(0)\n" + + signalHandler + " gotSignal = true\n" + "}\n"; + QDeclarativeComponent component(&engine); + component.setData(qml.toUtf8(), QUrl::fromLocalFile("")); + engine.rootContext()->setContextProperty("model", &model); + QObject *connectionsObject = component.create(); + QVERIFY2(component.errorString().isEmpty(), QTest::toString(component.errorString())); + + QSignalSpy spyItemsChanged(&model, SIGNAL(itemsChanged(int, int, QList))); + + expr.setExpression(script_change); + expr.evaluate(); + QVERIFY2(!expr.hasError(), QTest::toString(expr.error())); + + // test the object returned by get() emits the correct signals + QCOMPARE(connectionsObject->property("gotSignal").toBool(), itemsChanged); + + // test itemsChanged() is emitted correctly + if (itemsChanged) { + QCOMPARE(spyItemsChanged.count(), 1); + QCOMPARE(spyItemsChanged.at(0).at(0).toInt(), listIndex); + QCOMPARE(spyItemsChanged.at(0).at(1).toInt(), 1); + } else { + QCOMPARE(spyItemsChanged.count(), 0); + } + + expr.setExpression(testExpression); + QCOMPARE(expr.evaluate().toBool(), true); + + delete connectionsObject; +} + +void tst_qdeclarativelistmodel::property_changes_data() +{ + QTest::addColumn("script_setup"); + QTest::addColumn("script_change"); + QTest::addColumn("roleName"); + QTest::addColumn("listIndex"); + QTest::addColumn("itemsChanged"); + QTest::addColumn("testExpression"); + + QTest::newRow("set: plain") << "append({'a':123, 'b':456, 'c':789});" << "set(0,{'b':123});" + << "b" << 0 << true << "get(0).b == 123"; + QTest::newRow("setProperty: plain") << "append({'a':123, 'b':456, 'c':789});" << "setProperty(0, 'b', 123);" + << "b" << 0 << true << "get(0).b == 123"; + + QTest::newRow("set: plain, no changes") << "append({'a':123, 'b':456, 'c':789});" << "set(0,{'b':456});" + << "b" << 0 << false << "get(0).b == 456"; + QTest::newRow("setProperty: plain, no changes") << "append({'a':123, 'b':456, 'c':789});" << "setProperty(0, 'b', 456);" + << "b" << 0 << false << "get(0).b == 456"; + + // Following tests only call set() since setProperty() only allows plain + // values, not lists, as the argument. + // Note that when a list is changed, itemsChanged() is currently always + // emitted regardless of whether it actually changed or not. + + QTest::newRow("nested-set: list, new size") << "append({'a':123, 'b':[{'a':1},{'a':2},{'a':3}], 'c':789});" << "set(0,{'b':[{'a':1},{'a':2}]});" + << "b" << 0 << true << "get(0).b.get(0).a == 1 && get(0).b.get(1).a == 2"; + + QTest::newRow("nested-set: list, empty -> non-empty") << "append({'a':123, 'b':[], 'c':789});" << "set(0,{'b':[{'a':1},{'a':2},{'a':3}]});" + << "b" << 0 << true << "get(0).b.get(0).a == 1 && get(0).b.get(1).a == 2 && get(0).b.get(2).a == 3"; + + QTest::newRow("nested-set: list, non-empty -> empty") << "append({'a':123, 'b':[{'a':1},{'a':2},{'a':3}], 'c':789});" << "set(0,{'b':[]});" + << "b" << 0 << true << "get(0).b.count == 0"; + + QTest::newRow("nested-set: list, same size, different values") << "append({'a':123, 'b':[{'a':1},{'a':2},{'a':3}], 'c':789});" << "set(0,{'b':[{'a':1},{'a':222},{'a':3}]});" + << "b" << 0 << true << "get(0).b.get(0).a == 1 && get(0).b.get(1).a == 222 && get(0).b.get(2).a == 3"; + + QTest::newRow("nested-set: list, no changes") << "append({'a':123, 'b':[{'a':1},{'a':2},{'a':3}], 'c':789});" << "set(0,{'b':[{'a':1},{'a':2},{'a':3}]});" + << "b" << 0 << true << "get(0).b.get(0).a == 1 && get(0).b.get(1).a == 2 && get(0).b.get(2).a == 3"; + + QTest::newRow("nested-set: list, no changes, empty") << "append({'a':123, 'b':[], 'c':789});" << "set(0,{'b':[]});" + << "b" << 0 << true << "get(0).b.count == 0"; +} + + +void tst_qdeclarativelistmodel::property_changes_worker() +{ + // nested models are not supported when WorkerScript is involved + if (QByteArray(QTest::currentDataTag()).startsWith("nested-")) + return; + + QFETCH(QString, script_setup); + QFETCH(QString, script_change); + QFETCH(QString, roleName); + QFETCH(int, listIndex); + QFETCH(bool, itemsChanged); + + QDeclarativeListModel model; + QDeclarativeEngine engine; + QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/model.qml")); + QVERIFY2(component.errorString().isEmpty(), component.errorString().toUtf8()); + QDeclarativeItem *item = createWorkerTest(&engine, &component, &model); + QVERIFY(item != 0); + + QDeclarativeExpression expr(engine.rootContext(), &model, script_setup); + expr.evaluate(); + QVERIFY2(!expr.hasError(), QTest::toString(expr.error().toString())); + + QSignalSpy spyItemsChanged(&model, SIGNAL(itemsChanged(int, int, QList))); + + QVERIFY(QMetaObject::invokeMethod(item, "evalExpressionViaWorker", + Q_ARG(QVariant, QStringList(script_change)))); + waitForWorker(item); + + // test itemsChanged() is emitted correctly + if (itemsChanged) { + QCOMPARE(spyItemsChanged.count(), 1); + QCOMPARE(spyItemsChanged.at(0).at(0).toInt(), listIndex); + QCOMPARE(spyItemsChanged.at(0).at(1).toInt(), 1); + } else { + QCOMPARE(spyItemsChanged.count(), 0); + } + + delete item; + qApp->processEvents(); +} + +void tst_qdeclarativelistmodel::property_changes_worker_data() +{ + property_changes_data(); +} + QTEST_MAIN(tst_qdeclarativelistmodel) #include "tst_qdeclarativelistmodel.moc" -- cgit v0.12 From 39d2f837f5d5ac67d0cfcc3710aa23d22a84d3c1 Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Tue, 11 Jan 2011 11:42:37 +1000 Subject: Fix Qt.formatTime() to accept QTime values QScriptValue::toDateTime() does not work for QTime values. Task-number: QTBUG-16492 Reviewed-by: Michael Brasser --- src/declarative/qml/qdeclarativeengine.cpp | 86 ++++++++++++----- .../declarative/qdeclarativeqt/data/formatting.qml | 53 ++++++---- .../declarative/qdeclarativeqt/qdeclarativeqt.pro | 2 +- .../qdeclarativeqt/tst_qdeclarativeqt.cpp | 107 ++++++++++++++------- 4 files changed, 173 insertions(+), 75 deletions(-) diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp index b940457..52df518 100644 --- a/src/declarative/qml/qdeclarativeengine.cpp +++ b/src/declarative/qml/qdeclarativeengine.cpp @@ -1379,7 +1379,17 @@ QScriptValue QDeclarativeEnginePrivate::vector3d(QScriptContext *ctxt, QScriptEn /*! \qmlmethod string Qt::formatDate(datetime date, variant format) -Returns the string representation of \c date, formatted according to \c format. + +Returns a string representation of \c date, optionally formatted according +to \c format. + +The \a date parameter may be a JavaScript \c Date object, a \l{date}{date} +property, a QDate, or QDateTime value. The \a format parameter may be any of +the possible format values as described for +\l{QML:Qt::formatDateTime()}{Qt.formatDateTime()}. + +If \a format is not specified, \a date is formatted using +\l {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}. */ #ifndef QT_NO_DATESTRING QScriptValue QDeclarativeEnginePrivate::formatDate(QScriptContext*ctxt, QScriptEngine*engine) @@ -1406,9 +1416,16 @@ QScriptValue QDeclarativeEnginePrivate::formatDate(QScriptContext*ctxt, QScriptE /*! \qmlmethod string Qt::formatTime(datetime time, variant format) -Returns the string representation of \c time, formatted according to \c format. -See Qt::formatDateTime for how to define \c format. +Returns a string representation of \c time, optionally formatted according to +\c format. + +The \a time parameter may be a JavaScript \c Date object, a QTime, or QDateTime +value. The \a format parameter may be any of the possible format values as +described for \l{QML:Qt::formatDateTime()}{Qt.formatDateTime()}. + +If \a format is not specified, \a time is formatted using +\l {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}. */ QScriptValue QDeclarativeEnginePrivate::formatTime(QScriptContext*ctxt, QScriptEngine*engine) { @@ -1416,29 +1433,49 @@ QScriptValue QDeclarativeEnginePrivate::formatTime(QScriptContext*ctxt, QScriptE if(argCount == 0 || argCount > 2) return ctxt->throwError(QLatin1String("Qt.formatTime(): Invalid arguments")); - QTime date = ctxt->argument(0).toDateTime().time(); + QTime time; + QScriptValue sv = ctxt->argument(0); + if (sv.isDate()) + time = sv.toDateTime().time(); + else if (sv.toVariant().type() == QVariant::Time) + time = sv.toVariant().toTime(); + Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate; if (argCount == 2) { QScriptValue formatArg = ctxt->argument(1); if (formatArg.isString()) { QString format = formatArg.toString(); - return engine->newVariant(qVariantFromValue(date.toString(format))); + return engine->newVariant(qVariantFromValue(time.toString(format))); } else if (formatArg.isNumber()) { enumFormat = Qt::DateFormat(formatArg.toUInt32()); } else { return ctxt->throwError(QLatin1String("Qt.formatTime(): Invalid time format")); } } - return engine->newVariant(qVariantFromValue(date.toString(enumFormat))); + return engine->newVariant(qVariantFromValue(time.toString(enumFormat))); } /*! \qmlmethod string Qt::formatDateTime(datetime dateTime, variant format) -Returns the string representation of \c dateTime, formatted according to \c format. -\c format for the date/time formatting functions is be specified as follows. +Returns a string representation of \c datetime, optionally formatted according to +\c format. + +The \a date parameter may be a JavaScript \c Date object, a \l{date}{date} +property, a QDate, QTime, or QDateTime value. - These expressions may be used for the date: +If \a format is not provided, \a dateTime is formatted using +\l {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}. Otherwise, +\a format should be either. + +\list +\o One of the Qt::DateFormat enumeration values, such as + \c Qt.DefaultLocaleShortDate or \c Qt.ISODate +\o A string that specifies the format of the returned string, as detailed below. +\endlist + +If \a format specifies a format string, it should use the following expressions +to specify the date: \table \header \i Expression \i Output @@ -1462,7 +1499,7 @@ Returns the string representation of \c dateTime, formatted according to \c form \row \i yyyy \i the year as four digit number \endtable - These expressions may be used for the time: +In addition the following expressions can be used to specify the time: \table \header \i Expression \i Output @@ -1483,23 +1520,28 @@ Returns the string representation of \c dateTime, formatted according to \c form \endtable All other input characters will be ignored. Any sequence of characters that - are enclosed in singlequotes will be treated as text and not be used as an - expression. Two consecutive singlequotes ("''") are replaced by a singlequote + are enclosed in single quotes will be treated as text and not be used as an + expression. Two consecutive single quotes ("''") are replaced by a single quote in the output. - Example format strings (assumed that the date and time is 21 May 2001 - 14:13:09): +For example, if the following date/time value was specified: + + \code + // 21 May 2001 14:13:09 + var dateTime = new Date(2001, 5, 21, 14, 13, 09) + \endcode + +This \a dateTime value could be passed to \c Qt.formatDateTime(), +\l {QML:Qt::formatDate()}{Qt.formatDate()} or \l {QML:Qt::formatTime()}{Qt.formatTime()} +with the \a format values below to produce the following results: \table - \header \i Format \i Result - \row \i dd.MM.yyyy \i 21.05.2001 - \row \i ddd MMMM d yy \i Tue May 21 01 - \row \i hh:mm:ss.zzz \i 14:13:09.042 - \row \i h:m:s ap \i 2:13:9 pm + \header \i Format \i Result + \row \i "dd.MM.yyyy" \i 21.05.2001 + \row \i "ddd MMMM d yy" \i Tue May 21 01 + \row \i "hh:mm:ss.zzz" \i 14:13:09.042 + \row \i "h:m:s ap" \i 2:13:9 pm \endtable - -If no format is specified the locale's short format is used. Alternatively, you can specify -\c Qt.DefaultLocaleLongDate to get the locale's long format. */ QScriptValue QDeclarativeEnginePrivate::formatDateTime(QScriptContext*ctxt, QScriptEngine*engine) { diff --git a/tests/auto/declarative/qdeclarativeqt/data/formatting.qml b/tests/auto/declarative/qdeclarativeqt/data/formatting.qml index 35c6a29..f520aeb 100644 --- a/tests/auto/declarative/qdeclarativeqt/data/formatting.qml +++ b/tests/auto/declarative/qdeclarativeqt/data/formatting.qml @@ -1,29 +1,44 @@ import QtQuick 1.0 QtObject { - property date date1: "2008-12-24" - property string test1: Qt.formatDate(date1) - property string test2: Qt.formatDate(date1, Qt.DefaultLocaleLongDate) - property string test3: Qt.formatDate(date1, "ddd MMMM d yy") + property date dateFromString: "2008-12-24" + property variant jsdate: new Date(2008,11,24,14,15,38,200) // months are 0-based - property variant time1: new Date(0,0,0,14,15,38,200) - property string test4: Qt.formatTime(time1) - property string test5: Qt.formatTime(time1, Qt.DefaultLocaleLongDate) - property string test6: Qt.formatTime(time1, "H:m:s a") - property string test7: Qt.formatTime(time1, "hh:mm:ss.zzz") + function formatDate(prop) { + var v = eval(prop) + return [ + Qt.formatDate(v), + Qt.formatDate(v, Qt.DefaultLocaleLongDate), + Qt.formatDate(v, "ddd MMMM d yy") + ] + } - property variant dateTime1: new Date(1978,2,4,9,13,54) - property string test8: Qt.formatDateTime(dateTime1) - property string test9: Qt.formatDateTime(dateTime1, Qt.DefaultLocaleLongDate) - property string test10: Qt.formatDateTime(dateTime1, "M/d/yy H:m:s a") + function formatTime(prop) { + var v = eval(prop) + return [ + Qt.formatTime(v), + Qt.formatTime(v, Qt.DefaultLocaleLongDate), + Qt.formatTime(v, "H:m:s a"), + Qt.formatTime(v, "hh:mm:ss.zzz") + ] + } + + function formatDateTime(prop) { + var v = eval(prop) + return [ + Qt.formatDateTime(v), + Qt.formatDateTime(v, Qt.DefaultLocaleLongDate), + Qt.formatDateTime(v, "M/d/yy H:m:s a") + ] + } // Error cases - property string test11: Qt.formatDate() - property string test12: Qt.formatDate(new Date, new Object) + property string err_date1: Qt.formatDate() + property string err_date2: Qt.formatDate(new Date, new Object) - property string test13: Qt.formatTime() - property string test14: Qt.formatTime(new Date, new Object) + property string err_time1: Qt.formatTime() + property string err_time2: Qt.formatTime(new Date, new Object) - property string test15: Qt.formatDateTime() - property string test16: Qt.formatDateTime(new Date, new Object) + property string err_dateTime1: Qt.formatDateTime() + property string err_dateTime2: Qt.formatDateTime(new Date, new Object) } diff --git a/tests/auto/declarative/qdeclarativeqt/qdeclarativeqt.pro b/tests/auto/declarative/qdeclarativeqt/qdeclarativeqt.pro index 6af6500..9e698fe 100644 --- a/tests/auto/declarative/qdeclarativeqt/qdeclarativeqt.pro +++ b/tests/auto/declarative/qdeclarativeqt/qdeclarativeqt.pro @@ -1,5 +1,5 @@ load(qttest_p4) -contains(QT_CONFIG,declarative): QT += declarative +contains(QT_CONFIG,declarative): QT += declarative script SOURCES += tst_qdeclarativeqt.cpp macx:CONFIG -= app_bundle diff --git a/tests/auto/declarative/qdeclarativeqt/tst_qdeclarativeqt.cpp b/tests/auto/declarative/qdeclarativeqt/tst_qdeclarativeqt.cpp index 9f45d74..c8c1a22 100644 --- a/tests/auto/declarative/qdeclarativeqt/tst_qdeclarativeqt.cpp +++ b/tests/auto/declarative/qdeclarativeqt/tst_qdeclarativeqt.cpp @@ -38,6 +38,7 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#include #include #include @@ -81,7 +82,8 @@ private slots: void createComponent_pragmaLibrary(); void createQmlObject(); void consoleLog(); - void formatting(); + void dateTimeFormatting(); + void dateTimeFormatting_data(); void isQtObject(); void btoa(); void atob(); @@ -446,49 +448,88 @@ void tst_qdeclarativeqt::consoleLog() delete object; } -void tst_qdeclarativeqt::formatting() +void tst_qdeclarativeqt::dateTimeFormatting() { - QDeclarativeComponent component(&engine, TEST_FILE("formatting.qml")); + QFETCH(QString, method); + QFETCH(QStringList, inputProperties); + QFETCH(QStringList, expectedResults); - QString warning1 = component.url().toString() + ":22: Error: Qt.formatDate(): Invalid date format"; - QString warning2 = component.url().toString() + ":21: Error: Qt.formatDate(): Invalid arguments"; - QString warning3 = component.url().toString() + ":28: Error: Qt.formatDateTime(): Invalid datetime format"; - QString warning4 = component.url().toString() + ":27: Error: Qt.formatDateTime(): Invalid arguments"; - QString warning5 = component.url().toString() + ":25: Error: Qt.formatTime(): Invalid time format"; - QString warning6 = component.url().toString() + ":24: Error: Qt.formatTime(): Invalid arguments"; + QDate date(2008,12,24); + QTime time(14,15,38,200); + QDateTime dateTime(date, time); - QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1)); - QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2)); - QTest::ignoreMessage(QtWarningMsg, qPrintable(warning3)); - QTest::ignoreMessage(QtWarningMsg, qPrintable(warning4)); - QTest::ignoreMessage(QtWarningMsg, qPrintable(warning5)); - QTest::ignoreMessage(QtWarningMsg, qPrintable(warning6)); + QDeclarativeEngine eng; + + eng.rootContext()->setContextProperty("qdate", date); + eng.rootContext()->setContextProperty("qtime", time); + eng.rootContext()->setContextProperty("qdatetime", dateTime); + + QDeclarativeComponent component(&eng, TEST_FILE("formatting.qml")); + + QStringList warnings; + warnings << component.url().toString() + ":37: Error: Qt.formatDate(): Invalid date format" + << component.url().toString() + ":36: Error: Qt.formatDate(): Invalid arguments" + << component.url().toString() + ":40: Error: Qt.formatTime(): Invalid time format" + << component.url().toString() + ":39: Error: Qt.formatTime(): Invalid arguments" + << component.url().toString() + ":43: Error: Qt.formatDateTime(): Invalid datetime format" + << component.url().toString() + ":42: Error: Qt.formatDateTime(): Invalid arguments"; + + foreach (const QString &warning, warnings) + QTest::ignoreMessage(QtWarningMsg, qPrintable(warning)); QObject *object = component.create(); + QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString())); QVERIFY(object != 0); - QDate date1(2008,12,24); - QCOMPARE(object->property("date1").toDate(), date1); - QCOMPARE(object->property("test1").toString(), date1.toString(Qt::DefaultLocaleShortDate)); - QCOMPARE(object->property("test2").toString(), date1.toString(Qt::DefaultLocaleLongDate)); - QCOMPARE(object->property("test3").toString(), date1.toString("ddd MMMM d yy")); - - QTime time1(14,15,38,200); - QCOMPARE(object->property("time1").toTime(), time1); - QCOMPARE(object->property("test4").toString(), time1.toString(Qt::DefaultLocaleShortDate)); - QCOMPARE(object->property("test5").toString(), time1.toString(Qt::DefaultLocaleLongDate)); - QCOMPARE(object->property("test6").toString(), time1.toString("H:m:s a")); - QCOMPARE(object->property("test7").toString(), time1.toString("hh:mm:ss.zzz")); - - QDateTime dateTime1(QDate(1978,03,04),QTime(9,13,54)); - QCOMPARE(object->property("dateTime1").toDateTime(),dateTime1); - QCOMPARE(object->property("test8").toString(), dateTime1.toString(Qt::DefaultLocaleShortDate)); - QCOMPARE(object->property("test9").toString(), dateTime1.toString(Qt::DefaultLocaleLongDate)); - QCOMPARE(object->property("test10").toString(), dateTime1.toString("M/d/yy H:m:s a")); + QVERIFY(inputProperties.count() > 0); + + QVariant result; + foreach(const QString &prop, inputProperties) { + QVERIFY(QMetaObject::invokeMethod(object, method.toUtf8().constData(), + Q_RETURN_ARG(QVariant, result), + Q_ARG(QVariant, prop))); + + QStringList output = result.toStringList(); + for (int i=0; i("method"); + QTest::addColumn("inputProperties"); + QTest::addColumn("expectedResults"); + + QDate date(2008,12,24); + QTime time(14,15,38,200); + QDateTime dateTime(date, time); + + QTest::newRow("formatDate") + << "formatDate" + << (QStringList() << "dateFromString" << "jsdate" << "qdate" << "qdatetime") + << (QStringList() << date.toString(Qt::DefaultLocaleShortDate) + << date.toString(Qt::DefaultLocaleLongDate) + << date.toString("ddd MMMM d yy")); + + QTest::newRow("formatTime") + << "formatTime" + << (QStringList() << "jsdate" << "qtime" << "qdatetime") + << (QStringList() << time.toString(Qt::DefaultLocaleShortDate) + << time.toString(Qt::DefaultLocaleLongDate) + << time.toString("H:m:s a") + << time.toString("hh:mm:ss.zzz")); + + QTest::newRow("formatDateTime") + << "formatDateTime" + << (QStringList() << "jsdate" << "qdatetime") + << (QStringList() << dateTime.toString(Qt::DefaultLocaleShortDate) + << dateTime.toString(Qt::DefaultLocaleLongDate) + << dateTime.toString("M/d/yy H:m:s a")); +} + void tst_qdeclarativeqt::isQtObject() { QDeclarativeComponent component(&engine, TEST_FILE("isQtObject.qml")); -- cgit v0.12 From 11347a267125ecd0eaa5b022547297082954eb86 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Tue, 11 Jan 2011 13:09:01 +1000 Subject: Add methods to position view at beginning or end. Takes into account header/footer. Task-number: QTBUG-16213 Reviewed-by: Michael Brasser --- .../graphicsitems/qdeclarativegridview.cpp | 156 ++++++++++++------- .../graphicsitems/qdeclarativegridview_p.h | 2 + .../graphicsitems/qdeclarativeitemsmodule.cpp | 2 + .../graphicsitems/qdeclarativelistview.cpp | 166 ++++++++++++++------- .../graphicsitems/qdeclarativelistview_p.h | 2 + .../qdeclarativegridview/data/gridview1.qml | 8 + .../tst_qdeclarativegridview.cpp | 59 ++++++++ .../qdeclarativelistview/data/listviewtest.qml | 9 ++ .../tst_qdeclarativelistview.cpp | 59 ++++++++ 9 files changed, 355 insertions(+), 108 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativegridview.cpp b/src/declarative/graphicsitems/qdeclarativegridview.cpp index c2c28c2..6e6e8c1 100644 --- a/src/declarative/graphicsitems/qdeclarativegridview.cpp +++ b/src/declarative/graphicsitems/qdeclarativegridview.cpp @@ -336,6 +336,7 @@ public: } } + void positionViewAtIndex(int index, int mode); virtual void fixup(AxisData &data, qreal minExtent, qreal maxExtent); virtual void flick(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize, QDeclarativeTimeLineCallback::Callback fixupCallback, qreal velocity); @@ -2124,6 +2125,77 @@ void QDeclarativeGridView::moveCurrentIndexRight() } } +void QDeclarativeGridViewPrivate::positionViewAtIndex(int index, int mode) +{ + Q_Q(QDeclarativeGridView); + if (!isValid()) + return; + if (mode < QDeclarativeGridView::Beginning || mode > QDeclarativeGridView::Contain) + return; + + int idx = qMax(qMin(index, model->count()-1), 0); + + if (layoutScheduled) + layout(); + qreal pos = position(); + FxGridItem *item = visibleItem(idx); + if (!item) { + int itemPos = rowPosAt(idx); + // save the currently visible items in case any of them end up visible again + QList oldVisible = visibleItems; + visibleItems.clear(); + visibleIndex = idx - idx % columns; + setPosition(itemPos); + // now release the reference to all the old visible items. + for (int i = 0; i < oldVisible.count(); ++i) + releaseItem(oldVisible.at(i)); + item = visibleItem(idx); + } + if (item) { + qreal itemPos = item->rowPos(); + switch (mode) { + case QDeclarativeGridView::Beginning: + pos = itemPos; + if (index < 0 && header) { + pos -= flow == QDeclarativeGridView::LeftToRight + ? header->item->height() + : header->item->width(); + } + break; + case QDeclarativeGridView::Center: + pos = itemPos - (size() - rowSize())/2; + break; + case QDeclarativeGridView::End: + pos = itemPos - size() + rowSize(); + if (index >= model->count() && footer) { + pos += flow == QDeclarativeGridView::LeftToRight + ? footer->item->height() + : footer->item->width(); + } + break; + case QDeclarativeGridView::Visible: + if (itemPos > pos + size()) + pos = itemPos - size() + rowSize(); + else if (item->endRowPos() < pos) + pos = itemPos; + break; + case QDeclarativeGridView::Contain: + if (item->endRowPos() > pos + size()) + pos = itemPos - size() + rowSize(); + if (itemPos < pos) + pos = itemPos; + } + qreal maxExtent = flow == QDeclarativeGridView::LeftToRight ? -q->maxYExtent() : -q->maxXExtent(); + pos = qMin(pos, maxExtent); + qreal minExtent = flow == QDeclarativeGridView::LeftToRight ? -q->minYExtent() : -q->minXExtent(); + pos = qMax(pos, minExtent); + moveReason = QDeclarativeGridViewPrivate::Other; + q->cancelFlick(); + setPosition(pos); + } + fixupPosition(); +} + /*! \qmlmethod GridView::positionViewAtIndex(int index, PositionMode mode) @@ -2161,58 +2233,42 @@ void QDeclarativeGridView::positionViewAtIndex(int index, int mode) Q_D(QDeclarativeGridView); if (!d->isValid() || index < 0 || index >= d->model->count()) return; - if (mode < Beginning || mode > Contain) + d->positionViewAtIndex(index, mode); +} + +/*! + \qmlmethod GridView::positionViewAtBeginning() + \qmlmethod GridView::positionViewAtEnd() + + Positions the view at the beginning or end, taking into account any header or footer. + + It is not recommended to use \l {Flickable::}{contentX} or \l {Flickable::}{contentY} to position the view + at a particular index. This is unreliable since removing items from the start + of the list does not cause all other items to be repositioned, and because + the actual start of the view can vary based on the size of the delegates. + + \bold Note: methods should only be called after the Component has completed. To position + the view at startup, this method should be called by Component.onCompleted. For + example, to position the view at the end on startup: + + \code + Component.onCompleted: positionViewAtEnd() + \endcode +*/ +void QDeclarativeGridView::positionViewAtBeginning() +{ + Q_D(QDeclarativeGridView); + if (!d->isValid()) return; + d->positionViewAtIndex(-1, Beginning); +} - if (d->layoutScheduled) - d->layout(); - qreal pos = d->position(); - FxGridItem *item = d->visibleItem(index); - if (!item) { - int itemPos = d->rowPosAt(index); - // save the currently visible items in case any of them end up visible again - QList oldVisible = d->visibleItems; - d->visibleItems.clear(); - d->visibleIndex = index - index % d->columns; - d->setPosition(itemPos); - // now release the reference to all the old visible items. - for (int i = 0; i < oldVisible.count(); ++i) - d->releaseItem(oldVisible.at(i)); - item = d->visibleItem(index); - } - if (item) { - qreal itemPos = item->rowPos(); - switch (mode) { - case Beginning: - pos = itemPos; - break; - case Center: - pos = itemPos - (d->size() - d->rowSize())/2; - break; - case End: - pos = itemPos - d->size() + d->rowSize(); - break; - case Visible: - if (itemPos > pos + d->size()) - pos = itemPos - d->size() + d->rowSize(); - else if (item->endRowPos() < pos) - pos = itemPos; - break; - case Contain: - if (item->endRowPos() > pos + d->size()) - pos = itemPos - d->size() + d->rowSize(); - if (itemPos < pos) - pos = itemPos; - } - qreal maxExtent = d->flow == QDeclarativeGridView::LeftToRight ? -maxYExtent() : -maxXExtent(); - pos = qMin(pos, maxExtent); - qreal minExtent = d->flow == QDeclarativeGridView::LeftToRight ? -minYExtent() : -minXExtent(); - pos = qMax(pos, minExtent); - d->moveReason = QDeclarativeGridViewPrivate::Other; - cancelFlick(); - d->setPosition(pos); - } - d->fixupPosition(); +void QDeclarativeGridView::positionViewAtEnd() +{ + Q_D(QDeclarativeGridView); + if (!d->isValid()) + return; + d->positionViewAtIndex(d->model->count(), End); } /*! diff --git a/src/declarative/graphicsitems/qdeclarativegridview_p.h b/src/declarative/graphicsitems/qdeclarativegridview_p.h index ee632b1..e41537c 100644 --- a/src/declarative/graphicsitems/qdeclarativegridview_p.h +++ b/src/declarative/graphicsitems/qdeclarativegridview_p.h @@ -159,6 +159,8 @@ public: Q_INVOKABLE void positionViewAtIndex(int index, int mode); Q_INVOKABLE int indexAt(int x, int y) const; + Q_INVOKABLE Q_REVISION(1) void positionViewAtBeginning(); + Q_INVOKABLE Q_REVISION(1) void positionViewAtEnd(); static QDeclarativeGridViewAttached *qmlAttachedProperties(QObject *); diff --git a/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp b/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp index ddbde0b..529686e 100644 --- a/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp +++ b/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp @@ -180,6 +180,8 @@ void QDeclarativeItemModule::defineModule() qmlRegisterType("QtQuick",1,1,"Pinch"); qmlRegisterType(); qmlRegisterType("QtQuick",1,1,"Flickable"); + qmlRegisterType("QtQuick",1,1,"ListView"); + qmlRegisterType("QtQuick",1,1,"GridView"); qmlRegisterType("QtQuick",1,1,"Repeater"); qmlRegisterType("QtQuick",1,1,"TextEdit"); #ifndef QT_NO_LINEEDIT diff --git a/src/declarative/graphicsitems/qdeclarativelistview.cpp b/src/declarative/graphicsitems/qdeclarativelistview.cpp index 702442b..470f947 100644 --- a/src/declarative/graphicsitems/qdeclarativelistview.cpp +++ b/src/declarative/graphicsitems/qdeclarativelistview.cpp @@ -451,6 +451,7 @@ public: void updateHeader(); void updateFooter(); void fixupPosition(); + void positionViewAtIndex(int index, int mode); virtual void fixup(AxisData &data, qreal minExtent, qreal maxExtent); virtual void flick(QDeclarativeFlickablePrivate::AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize, QDeclarativeTimeLineCallback::Callback fixupCallback, qreal velocity); @@ -2558,6 +2559,79 @@ void QDeclarativeListView::decrementCurrentIndex() } } +void QDeclarativeListViewPrivate::positionViewAtIndex(int index, int mode) +{ + Q_Q(QDeclarativeListView); + if (!isValid()) + return; + if (mode < QDeclarativeListView::Beginning || mode > QDeclarativeListView::Contain) + return; +qDebug() << "positionViewAtIndex"; + int idx = qMax(qMin(index, model->count()-1), 0); + + if (layoutScheduled) + layout(); + qreal pos = position(); + FxListItem *item = visibleItem(idx); + if (!item) { + int itemPos = positionAt(idx); + // save the currently visible items in case any of them end up visible again + QList oldVisible = visibleItems; + visibleItems.clear(); + visiblePos = itemPos; + visibleIndex = idx; + setPosition(itemPos); + // now release the reference to all the old visible items. + for (int i = 0; i < oldVisible.count(); ++i) + releaseItem(oldVisible.at(i)); + item = visibleItem(idx); + } + if (item) { + const qreal itemPos = item->position(); + switch (mode) { + case QDeclarativeListView::Beginning: + pos = itemPos; + if (index < 0 && header) + pos -= header->size(); + break; + case QDeclarativeListView::Center: + pos = itemPos - (size() - item->size())/2; + break; + case QDeclarativeListView::End: + pos = itemPos - size() + item->size(); + if (index >= model->count() && footer) + pos += footer->size(); + break; + case QDeclarativeListView::Visible: + if (itemPos > pos + size()) + pos = itemPos - size() + item->size(); + else if (item->endPosition() < pos) + pos = itemPos; + break; + case QDeclarativeListView::Contain: + if (item->endPosition() > pos + size()) + pos = itemPos - size() + item->size(); + if (itemPos < pos) + pos = itemPos; + } + qreal maxExtent = orient == QDeclarativeListView::Vertical ? -q->maxYExtent() : -q->maxXExtent(); + pos = qMin(pos, maxExtent); + qreal minExtent = orient == QDeclarativeListView::Vertical ? -q->minYExtent() : -q->minXExtent(); + pos = qMax(pos, minExtent); + moveReason = QDeclarativeListViewPrivate::Other; + q->cancelFlick(); + setPosition(pos); + if (highlight) { + if (autoHighlight) { + highlight->setPosition(currentItem->itemPosition()); + highlight->setSize(currentItem->itemSize()); + } + updateHighlight(); + } + } + fixupPosition(); +} + /*! \qmlmethod ListView::positionViewAtIndex(int index, PositionMode mode) @@ -2596,66 +2670,42 @@ void QDeclarativeListView::positionViewAtIndex(int index, int mode) Q_D(QDeclarativeListView); if (!d->isValid() || index < 0 || index >= d->model->count()) return; - if (mode < Beginning || mode > Contain) + d->positionViewAtIndex(index, mode); +} + +/*! + \qmlmethod ListView::positionViewAtBeginning() + \qmlmethod ListView::positionViewAtEnd() + + Positions the view at the beginning or end, taking into account any header or footer. + + It is not recommended to use \l {Flickable::}{contentX} or \l {Flickable::}{contentY} to position the view + at a particular index. This is unreliable since removing items from the start + of the list does not cause all other items to be repositioned, and because + the actual start of the view can vary based on the size of the delegates. + + \bold Note: methods should only be called after the Component has completed. To position + the view at startup, this method should be called by Component.onCompleted. For + example, to position the view at the end on startup: + + \code + Component.onCompleted: positionViewAtEnd() + \endcode +*/ +void QDeclarativeListView::positionViewAtBeginning() +{ + Q_D(QDeclarativeListView); + if (!d->isValid()) return; + d->positionViewAtIndex(-1, Beginning); +} - if (d->layoutScheduled) - d->layout(); - qreal pos = d->position(); - FxListItem *item = d->visibleItem(index); - if (!item) { - int itemPos = d->positionAt(index); - // save the currently visible items in case any of them end up visible again - QList oldVisible = d->visibleItems; - d->visibleItems.clear(); - d->visiblePos = itemPos; - d->visibleIndex = index; - d->setPosition(itemPos); - // now release the reference to all the old visible items. - for (int i = 0; i < oldVisible.count(); ++i) - d->releaseItem(oldVisible.at(i)); - item = d->visibleItem(index); - } - if (item) { - const qreal itemPos = item->position(); - switch (mode) { - case Beginning: - pos = itemPos; - break; - case Center: - pos = itemPos - (d->size() - item->size())/2; - break; - case End: - pos = itemPos - d->size() + item->size(); - break; - case Visible: - if (itemPos > pos + d->size()) - pos = itemPos - d->size() + item->size(); - else if (item->endPosition() < pos) - pos = itemPos; - break; - case Contain: - if (item->endPosition() > pos + d->size()) - pos = itemPos - d->size() + item->size(); - if (itemPos < pos) - pos = itemPos; - } - qreal maxExtent = d->orient == QDeclarativeListView::Vertical ? -maxYExtent() : -maxXExtent(); - pos = qMin(pos, maxExtent); - qreal minExtent = d->orient == QDeclarativeListView::Vertical ? -minYExtent() : -minXExtent(); - pos = qMax(pos, minExtent); - d->moveReason = QDeclarativeListViewPrivate::Other; - cancelFlick(); - d->setPosition(pos); - if (d->highlight) { - if (d->autoHighlight) { - d->highlight->setPosition(d->currentItem->itemPosition()); - d->highlight->setSize(d->currentItem->itemSize()); - } - d->updateHighlight(); - } - } - d->fixupPosition(); +void QDeclarativeListView::positionViewAtEnd() +{ + Q_D(QDeclarativeListView); + if (!d->isValid()) + return; + d->positionViewAtIndex(d->model->count(), End); } /*! diff --git a/src/declarative/graphicsitems/qdeclarativelistview_p.h b/src/declarative/graphicsitems/qdeclarativelistview_p.h index 2678b90..2f7f6da 100644 --- a/src/declarative/graphicsitems/qdeclarativelistview_p.h +++ b/src/declarative/graphicsitems/qdeclarativelistview_p.h @@ -209,6 +209,8 @@ public: Q_INVOKABLE void positionViewAtIndex(int index, int mode); Q_INVOKABLE int indexAt(int x, int y) const; + Q_INVOKABLE Q_REVISION(1) void positionViewAtBeginning(); + Q_INVOKABLE Q_REVISION(1) void positionViewAtEnd(); public Q_SLOTS: void incrementCurrentIndex(); diff --git a/tests/auto/declarative/qdeclarativegridview/data/gridview1.qml b/tests/auto/declarative/qdeclarativegridview/data/gridview1.qml index 77c94ba..e4e699c 100644 --- a/tests/auto/declarative/qdeclarativegridview/data/gridview1.qml +++ b/tests/auto/declarative/qdeclarativegridview/data/gridview1.qml @@ -2,6 +2,8 @@ import QtQuick 1.0 Rectangle { id: root + property bool showHeader: false + property bool showFooter: false property int added: -1 property variant removed @@ -40,6 +42,10 @@ Rectangle { GridView.onAdd: root.added = index GridView.onRemove: root.removed = name } + }, + Component { + id: headerFooter + Rectangle { width: 30; height: 320; color: "blue" } } ] GridView { @@ -52,5 +58,7 @@ Rectangle { flow: (testTopToBottom == false) ? "LeftToRight" : "TopToBottom" model: testModel delegate: myDelegate + header: root.showHeader ? headerFooter : null + footer: root.showFooter ? headerFooter : null } } diff --git a/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp b/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp index bb06c3c..ab80b56 100644 --- a/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp +++ b/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp @@ -86,6 +86,8 @@ private slots: void footer(); void header(); void indexAt(); + void testQtQuick11Attributes(); + void testQtQuick11Attributes_data(); private: QDeclarativeView *createView(); @@ -1133,6 +1135,24 @@ void tst_QDeclarativeGridView::positionViewAtIndex() gridview->positionViewAtIndex(25, QDeclarativeGridView::Contain); QTRY_COMPARE(gridview->contentX(), 240.); + // positionViewAtBeginning + gridview->positionViewAtBeginning(); + QTRY_COMPARE(gridview->contentX(), 0.); + + gridview->setContentX(80); + canvas->rootObject()->setProperty("showHeader", true); + gridview->positionViewAtBeginning(); + QTRY_COMPARE(gridview->contentX(), -30.); + + // positionViewAtEnd + gridview->positionViewAtEnd(); + QTRY_COMPARE(gridview->contentX(), 430.); + + gridview->setContentX(80); + canvas->rootObject()->setProperty("showFooter", true); + gridview->positionViewAtEnd(); + QTRY_COMPARE(gridview->contentX(), 460.); + delete canvas; } @@ -1429,6 +1449,45 @@ void tst_QDeclarativeGridView::indexAt() delete canvas; } +void tst_QDeclarativeGridView::testQtQuick11Attributes() +{ + QFETCH(QString, code); + QFETCH(QString, warning); + QFETCH(QString, error); + + QDeclarativeEngine engine; + QObject *obj; + + QDeclarativeComponent valid(&engine); + valid.setData("import QtQuick 1.1; GridView { " + code.toUtf8() + " }", QUrl("")); + obj = valid.create(); + QVERIFY(obj); + QVERIFY(valid.errorString().isEmpty()); + delete obj; + + QDeclarativeComponent invalid(&engine); + invalid.setData("import QtQuick 1.0; GridView { " + code.toUtf8() + " }", QUrl("")); + QTest::ignoreMessage(QtWarningMsg, warning.toUtf8()); + obj = invalid.create(); + QCOMPARE(invalid.errorString(), error); + delete obj; +} + +void tst_QDeclarativeGridView::testQtQuick11Attributes_data() +{ + QTest::addColumn("code"); + QTest::addColumn("warning"); + QTest::addColumn("error"); + + QTest::newRow("positionViewAtBeginning") << "Component.onCompleted: positionViewAtBeginning()" + << ":1: ReferenceError: Can't find variable: positionViewAtBeginning" + << ""; + + QTest::newRow("positionViewAtEnd") << "Component.onCompleted: positionViewAtEnd()" + << ":1: ReferenceError: Can't find variable: positionViewAtEnd" + << ""; +} + QDeclarativeView *tst_QDeclarativeGridView::createView() { QDeclarativeView *canvas = new QDeclarativeView(0); diff --git a/tests/auto/declarative/qdeclarativelistview/data/listviewtest.qml b/tests/auto/declarative/qdeclarativelistview/data/listviewtest.qml index 534540f..3cd6f42 100644 --- a/tests/auto/declarative/qdeclarativelistview/data/listviewtest.qml +++ b/tests/auto/declarative/qdeclarativelistview/data/listviewtest.qml @@ -1,10 +1,13 @@ import QtQuick 1.0 Rectangle { + id: root width: 240 height: 320 color: "#ffffff" + property bool showHeader: false + property bool showFooter: false property real hr: list.visibleArea.heightRatio function heightRatio() { return list.visibleArea.heightRatio @@ -105,6 +108,10 @@ Rectangle { Component { id: invalidHl SmoothedAnimation {} + }, + Component { + id: headerFooter + Rectangle { height: 30; width: 240; color: "blue" } } ] ListView { @@ -119,5 +126,7 @@ Rectangle { highlightMoveSpeed: 1000 highlightResizeSpeed: 1000 cacheBuffer: testObject.cacheBuffer + header: root.showHeader ? headerFooter : null + footer: root.showFooter ? headerFooter : null } } diff --git a/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp b/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp index e76cb15..80c0118 100644 --- a/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp +++ b/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp @@ -108,6 +108,8 @@ private slots: void QTBUG_16037(); void indexAt(); void incrementalModel(); + void testQtQuick11Attributes(); + void testQtQuick11Attributes_data(); private: template void items(); @@ -1370,6 +1372,24 @@ void tst_QDeclarativeListView::positionViewAtIndex() listview->positionViewAtIndex(20, QDeclarativeListView::Contain); QTRY_COMPARE(listview->contentY(), 100.); + // positionAtBeginnging + listview->positionViewAtBeginning(); + QTRY_COMPARE(listview->contentY(), 0.); + + listview->setContentY(80); + canvas->rootObject()->setProperty("showHeader", true); + listview->positionViewAtBeginning(); + QTRY_COMPARE(listview->contentY(), -30.); + + // positionAtEnd + listview->positionViewAtEnd(); + QTRY_COMPARE(listview->contentY(), 480.); // 40*20 - 320 + + listview->setContentY(80); + canvas->rootObject()->setProperty("showFooter", true); + listview->positionViewAtEnd(); + QTRY_COMPARE(listview->contentY(), 510.); + delete canvas; } @@ -2026,6 +2046,45 @@ void tst_QDeclarativeListView::incrementalModel() delete canvas; } +void tst_QDeclarativeListView::testQtQuick11Attributes() +{ + QFETCH(QString, code); + QFETCH(QString, warning); + QFETCH(QString, error); + + QDeclarativeEngine engine; + QObject *obj; + + QDeclarativeComponent valid(&engine); + valid.setData("import QtQuick 1.1; ListView { " + code.toUtf8() + " }", QUrl("")); + obj = valid.create(); + QVERIFY(obj); + QVERIFY(valid.errorString().isEmpty()); + delete obj; + + QDeclarativeComponent invalid(&engine); + invalid.setData("import QtQuick 1.0; ListView { " + code.toUtf8() + " }", QUrl("")); + QTest::ignoreMessage(QtWarningMsg, warning.toUtf8()); + obj = invalid.create(); + QCOMPARE(invalid.errorString(), error); + delete obj; +} + +void tst_QDeclarativeListView::testQtQuick11Attributes_data() +{ + QTest::addColumn("code"); + QTest::addColumn("warning"); + QTest::addColumn("error"); + + QTest::newRow("positionViewAtBeginning") << "Component.onCompleted: positionViewAtBeginning()" + << ":1: ReferenceError: Can't find variable: positionViewAtBeginning" + << ""; + + QTest::newRow("positionViewAtEnd") << "Component.onCompleted: positionViewAtEnd()" + << ":1: ReferenceError: Can't find variable: positionViewAtEnd" + << ""; +} + void tst_QDeclarativeListView::qListModelInterface_items() { items(); -- cgit v0.12 From 7393fa902a62e53558ffb56769d31b4d5ba77161 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Tue, 11 Jan 2011 14:10:18 +1000 Subject: Don't crash if cursor at the end. 77cba04c2 assumed a level of bounds checking in QTextLayout that does not exist. Task-number: qtbug-15818 Reviewed-by: Michael Brasser --- src/gui/widgets/qlinecontrol.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index 12607c1..9abbfac 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -541,7 +541,10 @@ void QLineControl::draw(QPainter *painter, const QPoint &offset, const QRect &cl */ void QLineControl::selectWordAtPos(int cursor) { - int c = m_textLayout.previousCursorPosition(cursor+1, QTextLayout::SkipWords); + int next = cursor + 1; + if(next > end()) + --next; + int c = m_textLayout.previousCursorPosition(next, QTextLayout::SkipWords); moveCursor(c, false); // ## text layout should support end of words. int end = m_textLayout.nextCursorPosition(c, QTextLayout::SkipWords); -- cgit v0.12 From 78d6465a6db7e99720adef8e24803e75cbd8dd65 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Tue, 11 Jan 2011 11:19:38 +0100 Subject: QDeclarativeDebug: Extend autotest Check that sendMessage doesn't crash if service isn't connected. --- .../qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/auto/declarative/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp b/tests/auto/declarative/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp index 30629f9..14efc57 100644 --- a/tests/auto/declarative/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp +++ b/tests/auto/declarative/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp @@ -133,6 +133,10 @@ void tst_QDeclarativeDebugService::sendMessage() client.sendMessage(msg); QByteArray resp = client.waitForResponse(); QCOMPARE(resp, msg); + + QTest::ignoreMessage(QtWarningMsg, "QDeclarativeDebugService: Conflicting plugin name \"tst_QDeclarativeDebugService::sendMessage()\" "); + QDeclarativeDebugService duplicate("tst_QDeclarativeDebugService::sendMessage()"); + duplicate.sendMessage("msg"); } void tst_QDeclarativeDebugService::idForObject() -- cgit v0.12 From 619cb18022baaea3020dd15369c67b2bc07f5f86 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Mon, 10 Jan 2011 13:16:00 +0100 Subject: QDeclarativeDebug: Hardcode version when serializing Qt types Make sure that e.g. QtCreator compiled with 4.7 can debug a program compiled with 4.8. Reviewed-by: Christiaan Janssen --- src/declarative/debugger/qpacketprotocol.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/declarative/debugger/qpacketprotocol.cpp b/src/declarative/debugger/qpacketprotocol.cpp index ad1e767..1d056e4 100644 --- a/src/declarative/debugger/qpacketprotocol.cpp +++ b/src/declarative/debugger/qpacketprotocol.cpp @@ -407,6 +407,7 @@ QPacket::QPacket() buf = new QBuffer(&b); buf->open(QIODevice::WriteOnly); setDevice(buf); + setVersion(QDataStream::Qt_4_7); } /*! -- cgit v0.12 From d91eb7728beea99eb347293c89500cfa03814208 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Wed, 12 Jan 2011 14:21:59 +1000 Subject: Don't use implicitSize when calculating implicit size Width/height ended up getting trapped at <0 in this fillMode if only one of witdh/height was explicit. Task-number: QTBUG-16389 Reviewed-by: Michael Brasser --- src/declarative/graphicsitems/qdeclarativeimage.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativeimage.cpp b/src/declarative/graphicsitems/qdeclarativeimage.cpp index 68a1ecb..af9fc0b 100644 --- a/src/declarative/graphicsitems/qdeclarativeimage.cpp +++ b/src/declarative/graphicsitems/qdeclarativeimage.cpp @@ -386,14 +386,16 @@ void QDeclarativeImage::updatePaintedGeometry() if (d->fillMode == PreserveAspectFit) { if (!d->pix.width() || !d->pix.height()) return; - qreal widthScale = width() / qreal(d->pix.width()); - qreal heightScale = height() / qreal(d->pix.height()); + int effectiveHeight = heightValid() ? height() : d->pix.height(); + int effectiveWidth = widthValid() ? width() : d->pix.width(); + qreal widthScale = effectiveWidth / qreal(d->pix.width()); + qreal heightScale = effectiveHeight / qreal(d->pix.height()); if (widthScale <= heightScale) { - d->paintedWidth = width(); + d->paintedWidth = effectiveWidth; d->paintedHeight = widthScale * qreal(d->pix.height()); } else if(heightScale < widthScale) { d->paintedWidth = heightScale * qreal(d->pix.width()); - d->paintedHeight = height(); + d->paintedHeight = effectiveHeight; } if (widthValid() && !heightValid()) { setImplicitHeight(d->paintedHeight); -- cgit v0.12 From 51a09036d2c7fdefa82698d5f096efd604f4e364 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Wed, 12 Jan 2011 15:08:53 +1000 Subject: Revert "Don't use implicitSize when calculating implicit size" This reverts commit d91eb7728beea99eb347293c89500cfa03814208. Need to consult on the expected behavior before fixing this one. --- src/declarative/graphicsitems/qdeclarativeimage.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativeimage.cpp b/src/declarative/graphicsitems/qdeclarativeimage.cpp index af9fc0b..68a1ecb 100644 --- a/src/declarative/graphicsitems/qdeclarativeimage.cpp +++ b/src/declarative/graphicsitems/qdeclarativeimage.cpp @@ -386,16 +386,14 @@ void QDeclarativeImage::updatePaintedGeometry() if (d->fillMode == PreserveAspectFit) { if (!d->pix.width() || !d->pix.height()) return; - int effectiveHeight = heightValid() ? height() : d->pix.height(); - int effectiveWidth = widthValid() ? width() : d->pix.width(); - qreal widthScale = effectiveWidth / qreal(d->pix.width()); - qreal heightScale = effectiveHeight / qreal(d->pix.height()); + qreal widthScale = width() / qreal(d->pix.width()); + qreal heightScale = height() / qreal(d->pix.height()); if (widthScale <= heightScale) { - d->paintedWidth = effectiveWidth; + d->paintedWidth = width(); d->paintedHeight = widthScale * qreal(d->pix.height()); } else if(heightScale < widthScale) { d->paintedWidth = heightScale * qreal(d->pix.width()); - d->paintedHeight = effectiveHeight; + d->paintedHeight = height(); } if (widthValid() && !heightValid()) { setImplicitHeight(d->paintedHeight); -- cgit v0.12 From a750cf02225e46063161a1352451d46eb2df5491 Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Thu, 13 Jan 2011 13:29:02 +1000 Subject: Add NOTIFY signals to Flipable 'front' and 'back' properties Although the change notifications themselves may not be that useful, as these properties are write-once, adding the NOTIFY signals allows the properties to be used in bindings. Task-number: QTBUG-16580, QTBUG-14551 Reviewed-by: Martin Jones --- src/declarative/graphicsitems/qdeclarativeflipable.cpp | 2 ++ src/declarative/graphicsitems/qdeclarativeflipable_p.h | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativeflipable.cpp b/src/declarative/graphicsitems/qdeclarativeflipable.cpp index f118a85..b7c4063 100644 --- a/src/declarative/graphicsitems/qdeclarativeflipable.cpp +++ b/src/declarative/graphicsitems/qdeclarativeflipable.cpp @@ -142,6 +142,7 @@ void QDeclarativeFlipable::setFront(QGraphicsObject *front) d->front->setParentItem(this); if (Back == d->current) d->front->setOpacity(0.); + emit frontChanged(); } QGraphicsObject *QDeclarativeFlipable::back() @@ -165,6 +166,7 @@ void QDeclarativeFlipable::setBack(QGraphicsObject *back) this, SLOT(retransformBack())); connect(back, SIGNAL(heightChanged()), this, SLOT(retransformBack())); + emit backChanged(); } void QDeclarativeFlipable::retransformBack() diff --git a/src/declarative/graphicsitems/qdeclarativeflipable_p.h b/src/declarative/graphicsitems/qdeclarativeflipable_p.h index 78eaf53..b8fa8a4 100644 --- a/src/declarative/graphicsitems/qdeclarativeflipable_p.h +++ b/src/declarative/graphicsitems/qdeclarativeflipable_p.h @@ -60,8 +60,8 @@ class Q_AUTOTEST_EXPORT QDeclarativeFlipable : public QDeclarativeItem Q_OBJECT Q_ENUMS(Side) - Q_PROPERTY(QGraphicsObject *front READ front WRITE setFront) - Q_PROPERTY(QGraphicsObject *back READ back WRITE setBack) + Q_PROPERTY(QGraphicsObject *front READ front WRITE setFront NOTIFY frontChanged) + Q_PROPERTY(QGraphicsObject *back READ back WRITE setBack NOTIFY backChanged) Q_PROPERTY(Side side READ side NOTIFY sideChanged) //### flipAxis //### flipRotation @@ -79,6 +79,8 @@ public: Side side() const; Q_SIGNALS: + void frontChanged(); + void backChanged(); void sideChanged(); private Q_SLOTS: -- cgit v0.12 From 08bd83f5f1b738713e80bbfbd06468d27c5d3694 Mon Sep 17 00:00:00 2001 From: Christopher Ham Date: Fri, 14 Jan 2011 14:57:10 +1000 Subject: QDeclarativeText has new multiline properties LineCount should return the number of lines currently being displayed. Setting maximumLineCount limits the number of lines that will be shown Truncated will return true if the text has been elided normally, or if the lines have been limited due to maximumLineCount. Task-number: QTBUG-12305 Reviewed-by: Michael Brasser --- src/declarative/graphicsitems/qdeclarativetext.cpp | 179 +++++++++++++++++++-- src/declarative/graphicsitems/qdeclarativetext_p.h | 14 ++ .../graphicsitems/qdeclarativetext_p_p.h | 7 + .../qdeclarativetext/data/lineCount.qml | 15 ++ .../qdeclarativetext/tst_qdeclarativetext.cpp | 30 ++++ 5 files changed, 230 insertions(+), 15 deletions(-) create mode 100644 tests/auto/declarative/qdeclarativetext/data/lineCount.qml diff --git a/src/declarative/graphicsitems/qdeclarativetext.cpp b/src/declarative/graphicsitems/qdeclarativetext.cpp index cf11be6..d61342e 100644 --- a/src/declarative/graphicsitems/qdeclarativetext.cpp +++ b/src/declarative/graphicsitems/qdeclarativetext.cpp @@ -54,6 +54,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -84,12 +85,14 @@ private: DEFINE_BOOL_CONFIG_OPTION(enableImageCache, QML_ENABLE_TEXT_IMAGE_CACHE); +QString QDeclarativeTextPrivate::elideChar = QString(0x2026); + QDeclarativeTextPrivate::QDeclarativeTextPrivate() : color((QRgb)0), style(QDeclarativeText::Normal), hAlign(QDeclarativeText::AlignLeft), vAlign(QDeclarativeText::AlignTop), elideMode(QDeclarativeText::ElideNone), - format(QDeclarativeText::AutoText), wrapMode(QDeclarativeText::NoWrap), imageCacheDirty(true), - updateOnComponentComplete(true), richText(false), singleline(false), cacheAllTextAsImage(true), - internalWidthUpdate(false), doc(0) + format(QDeclarativeText::AutoText), wrapMode(QDeclarativeText::NoWrap), lineCount(1), truncated(false), maximumLineCount(INT_MAX), + maximumLineCountValid(false), imageCacheDirty(true), updateOnComponentComplete(true), richText(false), singleline(false), + cacheAllTextAsImage(true), internalWidthUpdate(false), doc(0) { cacheAllTextAsImage = enableImageCache(); QGraphicsItemPrivate::acceptedMouseButtons = Qt::LeftButton; @@ -192,9 +195,13 @@ void QDeclarativeTextPrivate::updateLayout() QString tmp = text; tmp.replace(QLatin1Char('\n'), QChar::LineSeparator); singleline = !tmp.contains(QChar::LineSeparator); - if (singleline && elideMode != QDeclarativeText::ElideNone && q->widthValid()) { + if (singleline && !maximumLineCountValid && elideMode != QDeclarativeText::ElideNone && q->widthValid()) { QFontMetrics fm(font); tmp = fm.elidedText(tmp,(Qt::TextElideMode)elideMode,q->width()); // XXX still worth layout...? + if (tmp != text && !truncated) { + truncated = true; + emit q->truncatedChanged(); + } } layout.setText(tmp); } else { @@ -291,6 +298,8 @@ QSize QDeclarativeTextPrivate::setupTextLayout() qreal height = 0; qreal widthUsed = 0; qreal lineWidth = 0; + int visibleTextLength = 0; + int visibleCount = 0; //set manual width if ((wrapMode != QDeclarativeText::NoWrap || elideMode != QDeclarativeText::ElideNone) && q->widthValid()) @@ -302,16 +311,71 @@ QSize QDeclarativeTextPrivate::setupTextLayout() textOption.setWrapMode(QTextOption::WrapMode(wrapMode)); layout.setTextOption(textOption); - layout.beginLayout(); - forever { - QTextLine line = layout.createLine(); - if (!line.isValid()) - break; + bool elideText = false; + bool truncate = false; + + QFontMetrics fm(layout.font()); + qreal elideWidth = fm.width(elideChar); + elidePos = QPointF(); + + if (maximumLineCountValid) { + layout.beginLayout(); + int y = 0; + int linesLeft = maximumLineCount; + while (linesLeft > 0) { + QTextLine line = layout.createLine(); + if (!line.isValid()) + break; + + visibleCount++; + + if (lineWidth) { + if (--linesLeft == 0) { + line.setLineWidth(q->width()*2); // Set out more than is required, but not too much. + if (line.naturalTextWidth() > lineWidth) + line.setLineWidth(lineWidth - elideWidth); + visibleTextLength += line.textLength(); // Used to catch new lines that are shorter than the layout width. + + if (visibleTextLength < text.length()) { + truncate = true; + if (elideMode==QDeclarativeText::ElideRight) { + // Need to correct for alignment + int x = line.naturalTextWidth(); + if (hAlign == QDeclarativeText::AlignRight) { + x = q->width()-elideWidth; + } else if (hAlign == QDeclarativeText::AlignHCenter) { + x = (q->width()+line.naturalTextWidth()-elideWidth)/2; + } + elidePos = QPointF(x, y + fm.ascent()); + } + } + } else { + line.setLineWidth(lineWidth); + visibleTextLength += line.textLength(); + } + + y += line.height(); + } + } + layout.endLayout(); - if (lineWidth) - line.setLineWidth(lineWidth); + //Update truncated + if (truncated != truncate) { + truncated = truncate; + emit q->truncatedChanged(); + } + } else { + layout.beginLayout(); + forever { + QTextLine line = layout.createLine(); + if (!line.isValid()) + break; + visibleCount++; + if (lineWidth) + line.setLineWidth(lineWidth); + } + layout.endLayout(); } - layout.endLayout(); for (int i = 0; i < layout.lineCount(); ++i) { QTextLine line = layout.lineAt(i); @@ -331,13 +395,23 @@ QSize QDeclarativeTextPrivate::setupTextLayout() x = 0; } else if (hAlign == QDeclarativeText::AlignRight) { x = layoutWidth - line.naturalTextWidth(); + if (elideText && i == layout.lineCount()-1) + x -= elideWidth; // Correct for when eliding multilines } else if (hAlign == QDeclarativeText::AlignHCenter) { x = (layoutWidth - line.naturalTextWidth()) / 2; + if (elideText && i == layout.lineCount()-1) + x -= elideWidth/2; // Correct for when eliding multilines } line.setPosition(QPointF(x, line.y())); } } + //Update the number of visible lines + if (lineCount != visibleCount) { + lineCount = visibleCount; + emit q->lineCountChanged(); + } + return layout.boundingRect().toAlignedRect().size(); } @@ -391,7 +465,9 @@ void QDeclarativeTextPrivate::drawTextLayout(QPainter *painter, const QPointF &p else painter->setPen(color); painter->setFont(font); - layout.draw(painter, pos); + layout.draw(painter, pos); + if (!elidePos.isNull()) + painter->drawText(elidePos, elideChar); } /*! @@ -979,6 +1055,76 @@ void QDeclarativeText::setWrapMode(WrapMode mode) emit wrapModeChanged(); } +/*! + \qmlproperty int Text::lineCount + + Returns the number of lines visible in the text item. + + This property is not supported for rich text. + + \sa maximumLineCount +*/ +int QDeclarativeText::lineCount() const +{ + Q_D(const QDeclarativeText); + return d->lineCount; +} + +/*! + \qmlproperty bool Text::truncated + + Returns if the text has been truncated due to \l maximumLineCount + or \l elide. + + This property is not supported for rich text. + + \sa maximumLineCount, elide +*/ +bool QDeclarativeText::truncated() const +{ + Q_D(const QDeclarativeText); + return d->truncated; +} + +/*! + \qmlproperty int Text::maximumLineCount + + Set this property to limit the number of lines that the text item will show. + If elide is set to Text.ElideRight, the text will be elided appropriately. + By default, this is the value of the largest possible integer. + + This property is not supported for rich text. + + \sa lineCount, elide +*/ +int QDeclarativeText::maximumLineCount() const +{ + Q_D(const QDeclarativeText); + return d->maximumLineCount; +} + +void QDeclarativeText::setMaximumLineCount(int lines) +{ + Q_D(QDeclarativeText); + + d->maximumLineCountValid = lines==INT_MAX ? false : true; + if (d->maximumLineCount != lines) { + d->maximumLineCount = lines; + d->updateLayout(); + emit maximumLineCountChanged(); + } +} + +void QDeclarativeText::resetMaximumLineCount() +{ + Q_D(QDeclarativeText); + setMaximumLineCount(INT_MAX); + d->elidePos = QPointF(); + if (d->truncated != false) { + d->truncated = false; + emit truncatedChanged(); + } +} /*! \qmlproperty enumeration Text::textFormat @@ -1066,7 +1212,7 @@ void QDeclarativeText::setTextFormat(TextFormat format) Set this property to elide parts of the text fit to the Text item's width. The text will only elide if an explicit width has been set. - This property cannot be used with multi-line text or with rich text. + This property cannot be used with rich text. Eliding can be: \list @@ -1076,6 +1222,9 @@ void QDeclarativeText::setTextFormat(TextFormat format) \o Text.ElideRight \endlist + If this property is set to Text.ElideRight, it can be used with multiline + text. The text will only elide if maximumLineCount has been set. + If the text is a multi-length string, and the mode is not \c Text.ElideNone, the first string that fits will be used, otherwise the last will be elided. @@ -1153,7 +1302,7 @@ void QDeclarativeText::geometryChanged(const QRectF &newGeometry, const QRectF & && (d->wrapMode != QDeclarativeText::NoWrap || d->elideMode != QDeclarativeText::ElideNone || d->hAlign != QDeclarativeText::AlignLeft)) { - if (d->singleline && d->elideMode != QDeclarativeText::ElideNone && widthValid()) { + if ((d->singleline || d->maximumLineCountValid) && d->elideMode != QDeclarativeText::ElideNone && widthValid()) { // We need to re-elide d->updateLayout(); } else { diff --git a/src/declarative/graphicsitems/qdeclarativetext_p.h b/src/declarative/graphicsitems/qdeclarativetext_p.h index 49bff14..2e19910 100644 --- a/src/declarative/graphicsitems/qdeclarativetext_p.h +++ b/src/declarative/graphicsitems/qdeclarativetext_p.h @@ -71,6 +71,10 @@ class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeText : public QDeclarativeItem Q_PROPERTY(HAlignment horizontalAlignment READ hAlign WRITE setHAlign NOTIFY horizontalAlignmentChanged) Q_PROPERTY(VAlignment verticalAlignment READ vAlign WRITE setVAlign NOTIFY verticalAlignmentChanged) Q_PROPERTY(WrapMode wrapMode READ wrapMode WRITE setWrapMode NOTIFY wrapModeChanged) + Q_PROPERTY(int lineCount READ lineCount NOTIFY lineCountChanged) + Q_PROPERTY(bool truncated READ truncated NOTIFY truncatedChanged) + Q_PROPERTY(int maximumLineCount READ maximumLineCount WRITE setMaximumLineCount NOTIFY maximumLineCountChanged RESET resetMaximumLineCount) + Q_PROPERTY(TextFormat textFormat READ textFormat WRITE setTextFormat NOTIFY textFormatChanged) Q_PROPERTY(TextElideMode elide READ elideMode WRITE setElideMode NOTIFY elideModeChanged) //### elideMode? Q_PROPERTY(qreal paintedWidth READ paintedWidth NOTIFY paintedSizeChanged) @@ -131,6 +135,13 @@ public: WrapMode wrapMode() const; void setWrapMode(WrapMode w); + int lineCount() const; + bool truncated() const; + + int maximumLineCount() const; + void setMaximumLineCount(int lines); + void resetMaximumLineCount(); + TextFormat textFormat() const; void setTextFormat(TextFormat format); @@ -158,6 +169,9 @@ Q_SIGNALS: void horizontalAlignmentChanged(HAlignment alignment); void verticalAlignmentChanged(VAlignment alignment); void wrapModeChanged(); + void lineCountChanged(); + void truncatedChanged(); + void maximumLineCountChanged(); void textFormatChanged(TextFormat textFormat); void elideModeChanged(TextElideMode mode); void paintedSizeChanged(); diff --git a/src/declarative/graphicsitems/qdeclarativetext_p_p.h b/src/declarative/graphicsitems/qdeclarativetext_p_p.h index e37f477..42c815b 100644 --- a/src/declarative/graphicsitems/qdeclarativetext_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativetext_p_p.h @@ -88,6 +88,13 @@ public: QDeclarativeText::TextElideMode elideMode; QDeclarativeText::TextFormat format; QDeclarativeText::WrapMode wrapMode; + int lineCount; + bool truncated; + int maximumLineCount; + int maximumLineCountValid; + QPointF elidePos; + + static QString elideChar; void invalidateImageCache(); void checkImageCache(); diff --git a/tests/auto/declarative/qdeclarativetext/data/lineCount.qml b/tests/auto/declarative/qdeclarativetext/data/lineCount.qml new file mode 100644 index 0000000..b3d7bc1 --- /dev/null +++ b/tests/auto/declarative/qdeclarativetext/data/lineCount.qml @@ -0,0 +1,15 @@ +import QtQuick 1.0 + +Item { + width: 200 + height: 200 + + Text { + id: myText + objectName: "myText" + width: 200 + wrapMode: Text.WordWrap + maximumLineCount: undefined + text: "Testing that maximumLines, visibleLines, and totalLines works properly in the autotests. The quick brown fox jumped over the lazy anything with the letter 'g'." + } +} diff --git a/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp b/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp index d6c37ae..ca23c9f 100644 --- a/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp +++ b/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp @@ -49,6 +49,7 @@ #include #include #include +#include #include "../../../shared/util.h" #include "testhttpserver.h" @@ -78,6 +79,8 @@ private slots: void embeddedImages_data(); void embeddedImages(); + void lineCount(); + // ### these tests may be trivial void horizontalAlignment(); void verticalAlignment(); @@ -1020,6 +1023,33 @@ void tst_qdeclarativetext::embeddedImages() } } +void tst_qdeclarativetext::lineCount() +{ + QDeclarativeView *canvas = createView(SRCDIR "/data/lineCount.qml"); + + QDeclarativeText *myText = canvas->rootObject()->findChild("myText"); + QVERIFY(myText != 0); + + QVERIFY(myText->lineCount() > 1); + QVERIFY(!myText->truncated()); + QCOMPARE(myText->maximumLineCount(), INT_MAX); + + myText->setMaximumLineCount(2); + QCOMPARE(myText->lineCount(), 2); + QCOMPARE(myText->truncated(), true); + QCOMPARE(myText->maximumLineCount(), 2); + + myText->resetMaximumLineCount(); + QCOMPARE(myText->maximumLineCount(), INT_MAX); + QCOMPARE(myText->truncated(), false); + + myText->setElideMode(QDeclarativeText::ElideRight); + myText->setMaximumLineCount(2); + QCOMPARE(myText->lineCount(), 2); + QCOMPARE(myText->truncated(), true); + QCOMPARE(myText->maximumLineCount(), 2); +} + QTEST_MAIN(tst_qdeclarativetext) #include "tst_qdeclarativetext.moc" -- cgit v0.12 From 82c0594ef35dbe9520da2f5e0900385c68f1cba5 Mon Sep 17 00:00:00 2001 From: Christopher Ham Date: Fri, 14 Jan 2011 15:05:35 +1000 Subject: Add lineCount property to QDeclarativeTextEdit The lineCount property should return the number of lines contained in textEdit. Also corrected minor documentation in Text Task-number: QTBUG-12305 Reviewed-by: Michael Brasser --- src/declarative/graphicsitems/qdeclarativetext.cpp | 2 +- .../graphicsitems/qdeclarativetextedit.cpp | 33 ++++++++++++++++++++++ .../graphicsitems/qdeclarativetextedit_p.h | 5 ++++ .../graphicsitems/qdeclarativetextedit_p_p.h | 1 + 4 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/declarative/graphicsitems/qdeclarativetext.cpp b/src/declarative/graphicsitems/qdeclarativetext.cpp index d61342e..3911d65 100644 --- a/src/declarative/graphicsitems/qdeclarativetext.cpp +++ b/src/declarative/graphicsitems/qdeclarativetext.cpp @@ -1073,7 +1073,7 @@ int QDeclarativeText::lineCount() const /*! \qmlproperty bool Text::truncated - Returns if the text has been truncated due to \l maximumLineCount + Returns true if the text has been truncated due to \l maximumLineCount or \l elide. This property is not supported for rich text. diff --git a/src/declarative/graphicsitems/qdeclarativetextedit.cpp b/src/declarative/graphicsitems/qdeclarativetextedit.cpp index c1c7a0c..1539998 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextedit.cpp @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -527,6 +528,17 @@ void QDeclarativeTextEdit::setWrapMode(WrapMode mode) } /*! + \qmlproperty int TextEdit::lineCount + + Returns the total number of lines in the textEdit item. +*/ +int QDeclarativeTextEdit::lineCount() const +{ + Q_D(const QDeclarativeTextEdit); + return d->lineCount; +} + +/*! \qmlproperty real TextEdit::paintedWidth Returns the width of the text, including the width past the width @@ -1376,6 +1388,7 @@ void QDeclarativeTextEdit::q_textChanged() Q_D(QDeclarativeTextEdit); d->text = text(); updateSize(); + updateTotalLines(); updateMicroFocus(); emit textChanged(d->text); } @@ -1487,6 +1500,26 @@ void QDeclarativeTextEdit::updateSize() emit update(); } +void QDeclarativeTextEdit::updateTotalLines() +{ + Q_D(QDeclarativeTextEdit); + + int subLines = 0; + + for (QTextBlock it = d->document->begin(); it != d->document->end(); it = it.next()) { + QTextLayout *layout = it.layout(); + if (!layout) + continue; + subLines += layout->lineCount()-1; + } + + int newTotalLines = d->document->lineCount() + subLines; + if (d->lineCount != newTotalLines) { + d->lineCount = newTotalLines; + emit lineCountChanged(); + } +} + void QDeclarativeTextEditPrivate::updateDefaultTextOption() { QTextOption opt = document->defaultTextOption(); diff --git a/src/declarative/graphicsitems/qdeclarativetextedit_p.h b/src/declarative/graphicsitems/qdeclarativetextedit_p.h index 3e86a05..928d100 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextedit_p.h @@ -75,6 +75,7 @@ class Q_AUTOTEST_EXPORT QDeclarativeTextEdit : public QDeclarativePaintedItem Q_PROPERTY(HAlignment horizontalAlignment READ hAlign WRITE setHAlign NOTIFY horizontalAlignmentChanged) Q_PROPERTY(VAlignment verticalAlignment READ vAlign WRITE setVAlign NOTIFY verticalAlignmentChanged) Q_PROPERTY(WrapMode wrapMode READ wrapMode WRITE setWrapMode NOTIFY wrapModeChanged) + Q_PROPERTY(int lineCount READ lineCount NOTIFY lineCountChanged) Q_PROPERTY(qreal paintedWidth READ paintedWidth NOTIFY paintedSizeChanged) Q_PROPERTY(qreal paintedHeight READ paintedHeight NOTIFY paintedSizeChanged) Q_PROPERTY(TextFormat textFormat READ textFormat WRITE setTextFormat NOTIFY textFormatChanged) @@ -156,6 +157,8 @@ public: WrapMode wrapMode() const; void setWrapMode(WrapMode w); + int lineCount() const; + bool isCursorVisible() const; void setCursorVisible(bool on); @@ -220,6 +223,7 @@ Q_SIGNALS: void horizontalAlignmentChanged(HAlignment alignment); void verticalAlignmentChanged(VAlignment alignment); void wrapModeChanged(); + void lineCountChanged(); void textFormatChanged(TextFormat textFormat); void readOnlyChanged(bool isReadOnly); void cursorVisibleChanged(bool isCursorVisible); @@ -250,6 +254,7 @@ private Q_SLOTS: private: void updateSize(); + void updateTotalLines(); protected: virtual void geometryChanged(const QRectF &newGeometry, diff --git a/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h b/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h index 4092e65..45d342f 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h @@ -118,6 +118,7 @@ public: QTextDocument *document; QTextControl *control; QDeclarativeTextEdit::WrapMode wrapMode; + int lineCount; bool selectByMouse; int yoff; }; -- cgit v0.12 From 0dbb193973aa25f61bc541f4e7938deeaade2e75 Mon Sep 17 00:00:00 2001 From: Joona Petrell Date: Mon, 17 Jan 2011 11:03:34 +1000 Subject: Remove unnecessary debug traces from declarative classes Task-number: Reviewed-by: Martin Jones --- src/declarative/graphicsitems/qdeclarativelistview.cpp | 1 - tools/qml/qmlruntime.cpp | 1 - 2 files changed, 2 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativelistview.cpp b/src/declarative/graphicsitems/qdeclarativelistview.cpp index 470f947..0fe5fb4 100644 --- a/src/declarative/graphicsitems/qdeclarativelistview.cpp +++ b/src/declarative/graphicsitems/qdeclarativelistview.cpp @@ -2566,7 +2566,6 @@ void QDeclarativeListViewPrivate::positionViewAtIndex(int index, int mode) return; if (mode < QDeclarativeListView::Beginning || mode > QDeclarativeListView::Contain) return; -qDebug() << "positionViewAtIndex"; int idx = qMax(qMin(index, model->count()-1), 0); if (layoutScheduled) diff --git a/tools/qml/qmlruntime.cpp b/tools/qml/qmlruntime.cpp index b829528..31bb73b 100644 --- a/tools/qml/qmlruntime.cpp +++ b/tools/qml/qmlruntime.cpp @@ -586,7 +586,6 @@ QNetworkAccessManager *NetworkAccessManagerFactory::create(QObject *parent) } connect(manager, SIGNAL(destroyed(QObject*)), this, SLOT(managerDestroyed(QObject*))); namList.append(manager); - qDebug() << "created new network access manager for" << parent; return manager; } -- cgit v0.12 From 62087b2ec0afad240d61a61c7a2972d021e01695 Mon Sep 17 00:00:00 2001 From: Joona Petrell Date: Mon, 17 Jan 2011 11:04:51 +1000 Subject: Add a warning when translating QML application in qmlviewer fails Task-number: Reviewed-by: Martin Jones --- tools/qml/main.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/qml/main.cpp b/tools/qml/main.cpp index b5a4fd0..89f2f5e 100644 --- a/tools/qml/main.cpp +++ b/tools/qml/main.cpp @@ -550,8 +550,11 @@ int main(int argc, char ** argv) QTranslator qmlTranslator; if (!opts.translationFile.isEmpty()) { - qmlTranslator.load(opts.translationFile); - app.installTranslator(&qmlTranslator); + if (qmlTranslator.load(opts.translationFile)) { + app.installTranslator(&qmlTranslator); + } else { + qWarning() << "Could not load the translation file" << opts.translationFile; + } } if (opts.fullScreen && opts.maximized) -- cgit v0.12 From 8b6674e55118896dfecbcdc1960418dc2064f632 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Mon, 17 Jan 2011 14:07:33 +1000 Subject: Add canPaste property to TextInput and TextEdit Task-number: QTBUG-16190 Reviewed-by: Martin Jones --- .../graphicsitems/qdeclarativetextedit.cpp | 28 ++++++++++++++++++++++ .../graphicsitems/qdeclarativetextedit_p.h | 5 ++++ .../graphicsitems/qdeclarativetextedit_p_p.h | 3 ++- .../graphicsitems/qdeclarativetextinput.cpp | 26 +++++++++++++++++++- .../graphicsitems/qdeclarativetextinput_p.h | 4 ++++ .../graphicsitems/qdeclarativetextinput_p_p.h | 3 ++- .../tst_qdeclarativetextedit.cpp | 8 +++++++ .../tst_qdeclarativetextinput.cpp | 9 +++++++ 8 files changed, 83 insertions(+), 3 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativetextedit.cpp b/src/declarative/graphicsitems/qdeclarativetextedit.cpp index 1539998..4a421b4 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextedit.cpp @@ -1342,6 +1342,21 @@ void QDeclarativeTextEdit::updateImgCache(const QRectF &rf) filtering at the beginning of the animation and reenable it at the conclusion. */ +/*! + \qmlproperty bool TextEdit::canPaste + + Returns true if the TextEdit is writable and the content of the clipboard is + suitable for pasting into the TextEdit. + + \since QtQuick 1.1 +*/ + +bool QDeclarativeTextEdit::canPaste() const +{ + Q_D(const QDeclarativeTextEdit); + return d->canPaste; +} + void QDeclarativeTextEditPrivate::init() { Q_Q(QDeclarativeTextEdit); @@ -1374,6 +1389,10 @@ void QDeclarativeTextEditPrivate::init() QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SIGNAL(cursorPositionChanged())); QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SIGNAL(cursorRectangleChanged())); QObject::connect(control, SIGNAL(linkActivated(QString)), q, SIGNAL(linkActivated(QString))); +#ifndef QT_NO_CLIPBOARD + QObject::connect(q, SIGNAL(readOnlyChanged(bool)), q, SLOT(q_canPasteChanged())); + QObject::connect(QApplication::clipboard(), SIGNAL(dataChanged()), q, SLOT(q_canPasteChanged())); +#endif document = control->document(); document->setDefaultFont(font); @@ -1648,4 +1667,13 @@ void QDeclarativeTextEdit::focusInEvent(QFocusEvent *event) QDeclarativePaintedItem::focusInEvent(event); } +void QDeclarativeTextEdit::q_canPasteChanged() +{ + Q_D(QDeclarativeTextEdit); + bool old = d->canPaste; + d->canPaste = d->control->canPaste(); + if(old!=d->canPaste) + emit canPasteChanged(); +} + QT_END_NAMESPACE diff --git a/src/declarative/graphicsitems/qdeclarativetextedit_p.h b/src/declarative/graphicsitems/qdeclarativetextedit_p.h index 928d100..f28763e 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextedit_p.h @@ -92,6 +92,7 @@ class Q_AUTOTEST_EXPORT QDeclarativeTextEdit : public QDeclarativePaintedItem Q_PROPERTY(qreal textMargin READ textMargin WRITE setTextMargin NOTIFY textMarginChanged) Q_PROPERTY(Qt::InputMethodHints inputMethodHints READ inputMethodHints WRITE setInputMethodHints) Q_PROPERTY(bool selectByMouse READ selectByMouse WRITE setSelectByMouse NOTIFY selectByMouseChanged) + Q_REVISION(1) Q_PROPERTY(bool canPaste READ canPaste NOTIFY canPasteChanged) public: QDeclarativeTextEdit(QDeclarativeItem *parent=0); @@ -185,6 +186,8 @@ public: bool selectByMouse() const; void setSelectByMouse(bool); + bool canPaste() const; + virtual void componentComplete(); /* FROM EDIT */ @@ -233,6 +236,7 @@ Q_SIGNALS: void textMarginChanged(qreal textMargin); void selectByMouseChanged(bool selectByMouse); Q_REVISION(1) void linkActivated(const QString &link); + Q_REVISION(1) void canPasteChanged(); public Q_SLOTS: void selectAll(); @@ -251,6 +255,7 @@ private Q_SLOTS: void updateSelectionMarkers(); void moveCursorDelegate(); void loadCursorDelegate(); + void q_canPasteChanged(); private: void updateSize(); diff --git a/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h b/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h index 45d342f..6da91df 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h @@ -73,7 +73,7 @@ public: showInputPanelOnFocus(true), clickCausedFocus(false), persistentSelection(true), textMargin(0.0), lastSelectionStart(0), lastSelectionEnd(0), cursorComponent(0), cursor(0), format(QDeclarativeTextEdit::AutoText), document(0), wrapMode(QDeclarativeTextEdit::NoWrap), - selectByMouse(false), + selectByMouse(false), canPaste(false), yoff(0) { #ifdef Q_OS_SYMBIAN @@ -120,6 +120,7 @@ public: QDeclarativeTextEdit::WrapMode wrapMode; int lineCount; bool selectByMouse; + bool canPaste; int yoff; }; diff --git a/src/declarative/graphicsitems/qdeclarativetextinput.cpp b/src/declarative/graphicsitems/qdeclarativetextinput.cpp index 491d219c4..bfdcc9b 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextinput.cpp @@ -1222,7 +1222,8 @@ void QDeclarativeTextInput::copy() void QDeclarativeTextInput::paste() { Q_D(QDeclarativeTextInput); - d->control->paste(); + if(!d->control->isReadOnly()) + d->control->paste(); } #endif // QT_NO_CLIPBOARD @@ -1321,6 +1322,12 @@ void QDeclarativeTextInput::setSelectByMouse(bool on) } } +bool QDeclarativeTextInput::canPaste() const +{ + Q_D(const QDeclarativeTextInput); + return d->canPaste; +} + void QDeclarativeTextInput::moveCursorSelection(int position) { Q_D(QDeclarativeTextInput); @@ -1569,6 +1576,12 @@ void QDeclarativeTextInputPrivate::init() q, SIGNAL(accepted())); q->connect(control, SIGNAL(updateNeeded(QRect)), q, SLOT(updateRect(QRect))); +#ifndef QT_NO_CLIPBOARD + q->connect(q, SIGNAL(readOnlyChanged(bool)), + q, SLOT(q_canPasteChanged())); + q->connect(QApplication::clipboard(), SIGNAL(dataChanged()), + q, SLOT(q_canPasteChanged())); +#endif // QT_NO_CLIPBOARD q->updateSize(); oldValidity = control->hasAcceptableInput(); lastSelectionStart = 0; @@ -1670,6 +1683,17 @@ void QDeclarativeTextInput::updateSize(bool needsRedraw) } } +void QDeclarativeTextInput::q_canPasteChanged() +{ + Q_D(QDeclarativeTextInput); + bool old = d->canPaste; +#ifndef QT_NO_CLIPBOARD + d->canPaste = !d->control->isReadOnly() && QApplication::clipboard()->text().length() != 0; +#endif + if(d->canPaste != old) + emit canPasteChanged(); +} + QT_END_NAMESPACE #endif // QT_NO_LINEEDIT diff --git a/src/declarative/graphicsitems/qdeclarativetextinput_p.h b/src/declarative/graphicsitems/qdeclarativetextinput_p.h index 5bff2ea..582e626 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextinput_p.h @@ -95,6 +95,7 @@ class Q_AUTOTEST_EXPORT QDeclarativeTextInput : public QDeclarativePaintedItem Q_PROPERTY(QString displayText READ displayText NOTIFY displayTextChanged) Q_PROPERTY(bool autoScroll READ autoScroll WRITE setAutoScroll NOTIFY autoScrollChanged) Q_PROPERTY(bool selectByMouse READ selectByMouse WRITE setSelectByMouse NOTIFY selectByMouseChanged) + Q_REVISION(1) Q_PROPERTY(bool canPaste READ canPaste NOTIFY canPasteChanged) public: QDeclarativeTextInput(QDeclarativeItem* parent=0); @@ -197,6 +198,7 @@ public: QVariant inputMethodQuery(Qt::InputMethodQuery property) const; QRectF boundingRect() const; + bool canPaste() const; Q_SIGNALS: void textChanged(); @@ -223,6 +225,7 @@ Q_SIGNALS: void activeFocusOnPressChanged(bool activeFocusOnPress); void autoScrollChanged(bool autoScroll); void selectByMouseChanged(bool selectByMouse); + Q_REVISION(1) void canPasteChanged(); protected: virtual void geometryChanged(const QRectF &newGeometry, @@ -256,6 +259,7 @@ private Q_SLOTS: void moveCursor(); void cursorPosChanged(); void updateRect(const QRect &r = QRect()); + void q_canPasteChanged(); private: Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarativeTextInput) diff --git a/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h b/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h index 5ad6a3b..a3853c3 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h @@ -75,7 +75,7 @@ public: styleColor((QRgb)0), hAlign(QDeclarativeTextInput::AlignLeft), hscroll(0), oldScroll(0), focused(false), focusOnPress(true), showInputPanelOnFocus(true), clickCausedFocus(false), cursorVisible(false), - autoScroll(true), selectByMouse(false) + autoScroll(true), selectByMouse(false), canPaste(false) { #ifdef Q_OS_SYMBIAN if (QSysInfo::symbianVersion() == QSysInfo::SV_SF_1 || QSysInfo::symbianVersion() == QSysInfo::SV_SF_3) { @@ -130,6 +130,7 @@ public: bool cursorVisible; bool autoScroll; bool selectByMouse; + bool canPaste; }; QT_END_NAMESPACE diff --git a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp index 649d34f..7578042 100644 --- a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp +++ b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp @@ -1111,10 +1111,18 @@ void tst_qdeclarativetextedit::copyAndPaste() { QCOMPARE(textEdit->selectedText(), QString("Hello world!")); QCOMPARE(textEdit->selectedText().length(), 12); textEdit->setCursorPosition(0); + QVERIFY(textEdit->canPaste()); textEdit->paste(); QCOMPARE(textEdit->text(), QString("Hello world!Hello world!")); QCOMPARE(textEdit->text().length(), 24); + // canPaste + QVERIFY(textEdit->canPaste()); + textEdit->setReadOnly(true); + QVERIFY(!textEdit->canPaste()); + textEdit->setReadOnly(false); + QVERIFY(textEdit->canPaste()); + // QTBUG-12339 // test that document and internal text attribute are in sync QDeclarativeItemPrivate* pri = QDeclarativeItemPrivate::get(textEdit); diff --git a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp index 964125f..d7e6a60 100644 --- a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp +++ b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp @@ -952,10 +952,18 @@ void tst_qdeclarativetextinput::copyAndPaste() { QCOMPARE(textInput->selectedText(), QString("Hello world!")); QCOMPARE(textInput->selectedText().length(), 12); textInput->setCursorPosition(0); + QVERIFY(textInput->canPaste()); textInput->paste(); QCOMPARE(textInput->text(), QString("Hello world!Hello world!")); QCOMPARE(textInput->text().length(), 24); + // can paste + QVERIFY(textInput->canPaste()); + textInput->setReadOnly(true); + QVERIFY(!textInput->canPaste()); + textInput->setReadOnly(false); + QVERIFY(textInput->canPaste()); + // select word textInput->setCursorPosition(0); textInput->selectWord(); @@ -973,6 +981,7 @@ void tst_qdeclarativetextinput::copyAndPaste() { QClipboard *clipboard = QApplication::clipboard(); QVERIFY(clipboard); clipboard->clear(); + QVERIFY(!textInput->canPaste()); // test that copy functionality is disabled // when echo mode is set to hide text/password mode -- cgit v0.12 From dd4243b62379d9a1d6e8a7f13b1f7c4fa3de2984 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Mon, 17 Jan 2011 14:18:39 +1000 Subject: Fix memory leak Introduced by 488e616b50707e5b37162e6d0cfc71a1ffdf9bef --- src/declarative/qml/qdeclarativebinding.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/declarative/qml/qdeclarativebinding.cpp b/src/declarative/qml/qdeclarativebinding.cpp index 223d057..2092087 100644 --- a/src/declarative/qml/qdeclarativebinding.cpp +++ b/src/declarative/qml/qdeclarativebinding.cpp @@ -247,9 +247,15 @@ QDeclarativeBinding::createBinding(Identifier id, QObject *obj, QDeclarativeCont QDeclarativeEnginePrivate *engine = QDeclarativeEnginePrivate::get(qmlEngine(obj)); QDeclarativeCompiledData *cdata = 0; - if (engine && ctxtdata && !ctxtdata->url.isEmpty()) - cdata = engine->typeLoader.get(ctxtdata->url)->compiledData(); - return cdata ? new QDeclarativeBinding((void*)cdata->datas.at(id).constData(), cdata, obj, ctxtdata, url, lineNumber, parent) : 0; + QDeclarativeTypeData *typeData = 0; + if (engine && ctxtdata && !ctxtdata->url.isEmpty()) { + typeData = engine->typeLoader.get(ctxtdata->url); + cdata = typeData->compiledData(); + } + QDeclarativeBinding *rv = cdata ? new QDeclarativeBinding((void*)cdata->datas.at(id).constData(), cdata, obj, ctxtdata, url, lineNumber, parent) : 0; + if (typeData) + typeData->release(); + return rv; } QDeclarativeBinding::QDeclarativeBinding(const QString &str, QObject *obj, QDeclarativeContext *ctxt, -- cgit v0.12 From 5100cfbd888301d0dd040e8959a56353fa72573a Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Tue, 18 Jan 2011 10:42:22 +1000 Subject: Proper versioning for canPaste --- src/declarative/graphicsitems/qdeclarativetextedit_p.h | 2 +- src/declarative/graphicsitems/qdeclarativetextinput_p.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativetextedit_p.h b/src/declarative/graphicsitems/qdeclarativetextedit_p.h index f28763e..7c6e999 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextedit_p.h @@ -92,7 +92,7 @@ class Q_AUTOTEST_EXPORT QDeclarativeTextEdit : public QDeclarativePaintedItem Q_PROPERTY(qreal textMargin READ textMargin WRITE setTextMargin NOTIFY textMarginChanged) Q_PROPERTY(Qt::InputMethodHints inputMethodHints READ inputMethodHints WRITE setInputMethodHints) Q_PROPERTY(bool selectByMouse READ selectByMouse WRITE setSelectByMouse NOTIFY selectByMouseChanged) - Q_REVISION(1) Q_PROPERTY(bool canPaste READ canPaste NOTIFY canPasteChanged) + Q_PROPERTY(bool canPaste READ canPaste NOTIFY canPasteChanged REVISION 1) public: QDeclarativeTextEdit(QDeclarativeItem *parent=0); diff --git a/src/declarative/graphicsitems/qdeclarativetextinput_p.h b/src/declarative/graphicsitems/qdeclarativetextinput_p.h index 582e626..ec260d5 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextinput_p.h @@ -95,7 +95,7 @@ class Q_AUTOTEST_EXPORT QDeclarativeTextInput : public QDeclarativePaintedItem Q_PROPERTY(QString displayText READ displayText NOTIFY displayTextChanged) Q_PROPERTY(bool autoScroll READ autoScroll WRITE setAutoScroll NOTIFY autoScrollChanged) Q_PROPERTY(bool selectByMouse READ selectByMouse WRITE setSelectByMouse NOTIFY selectByMouseChanged) - Q_REVISION(1) Q_PROPERTY(bool canPaste READ canPaste NOTIFY canPasteChanged) + Q_PROPERTY(bool canPaste READ canPaste NOTIFY canPasteChanged REVISION 1) public: QDeclarativeTextInput(QDeclarativeItem* parent=0); -- cgit v0.12 From ac2df91cf83918d1b247382fe75a30fafc1a896f Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Tue, 18 Jan 2011 11:51:55 +1000 Subject: Document TextInput::readOnly --- src/declarative/graphicsitems/qdeclarativetextinput.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/declarative/graphicsitems/qdeclarativetextinput.cpp b/src/declarative/graphicsitems/qdeclarativetextinput.cpp index bfdcc9b..e35032b 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextinput.cpp @@ -345,6 +345,16 @@ void QDeclarativeTextInput::setHAlign(HAlignment align) emit horizontalAlignmentChanged(d->hAlign); } +/*! + \qmlproperty bool TextInput::readOnly + + Sets whether user input can modify the contents of the TextInput. + + If readOnly is set to true, then user input will not affect the text + property. Any bindings or attempts to set the text property will still + work. +*/ + bool QDeclarativeTextInput::isReadOnly() const { Q_D(const QDeclarativeTextInput); -- cgit v0.12 From f503dc25886e556983fc1bf3efb2e15669f3507c Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Tue, 18 Jan 2011 13:47:17 +1000 Subject: Cleanup view at end of auto test. --- .../declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp index d7e6a60..88bff8a 100644 --- a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp +++ b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp @@ -619,6 +619,7 @@ void tst_qdeclarativetextinput::dragMouseSelection() QVERIFY(str2.length() > 3); QVERIFY(str1 != str2); // Verify the second press and drag is a new selection and doesn't not the first moved. + delete canvas; } void tst_qdeclarativetextinput::horizontalAlignment_data() @@ -1129,6 +1130,8 @@ void tst_qdeclarativetextinput::echoMode() input->setFocus(false); QVERIFY(input->hasActiveFocus() == false); QCOMPARE(input->displayText(), QLatin1String("Q")); + + delete canvas; } void tst_qdeclarativetextinput::simulateKey(QDeclarativeView *view, int key) -- cgit v0.12 From 9ef953a65a96b511aae2a4ba6db9579b5d23cc29 Mon Sep 17 00:00:00 2001 From: Joona Petrell Date: Tue, 18 Jan 2011 13:37:56 +1000 Subject: Add a way to clear warnings in qmlviewer warnings window on Symbian Basically by adding a clear soft key to the currently empty right soft key in warninng window in qmlviewer. Task-number: Reviewed-by: Martin Jones --- tools/qml/loggerwidget.cpp | 5 +++++ tools/qml/qmlruntime.cpp | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/tools/qml/loggerwidget.cpp b/tools/qml/loggerwidget.cpp index fb4fedc..e167c94 100644 --- a/tools/qml/loggerwidget.cpp +++ b/tools/qml/loggerwidget.cpp @@ -67,6 +67,11 @@ LoggerWidget::LoggerWidget(QWidget *parent) : m_plainTextEdit = new QPlainTextEdit(); #if defined(Q_OS_SYMBIAN) + QAction* clearAction = new QAction(tr("Clear"), this); + clearAction->setSoftKeyRole(QAction::PositiveSoftKey); + connect(clearAction, SIGNAL(triggered()), m_plainTextEdit, SLOT(clear())); + addAction(clearAction); + m_plainTextEdit->setReadOnly(true); QAction* backAction = new QAction( tr("Back"), this ); backAction->setSoftKeyRole( QAction::NegativeSoftKey ); diff --git a/tools/qml/qmlruntime.cpp b/tools/qml/qmlruntime.cpp index 31bb73b..586eaa5 100644 --- a/tools/qml/qmlruntime.cpp +++ b/tools/qml/qmlruntime.cpp @@ -781,9 +781,11 @@ void QDeclarativeViewer::createMenu() aboutAction->setMenuRole(QAction::AboutQtRole); connect(aboutAction, SIGNAL(triggered()), qApp, SLOT(aboutQt())); +#if !defined(Q_OS_SYMBIAN) QAction *closeAction = new QAction(tr("&Close"), this); closeAction->setShortcuts(QKeySequence::Close); connect(closeAction, SIGNAL(triggered()), this, SLOT(close())); +#endif QAction *quitAction = new QAction(tr("&Quit"), this); quitAction->setMenuRole(QAction::QuitRole); @@ -819,9 +821,9 @@ void QDeclarativeViewer::createMenu() fileMenu->addAction(openAction); fileMenu->addAction(openUrlAction); fileMenu->addAction(reloadAction); +#if !defined(Q_OS_SYMBIAN) fileMenu->addSeparator(); fileMenu->addAction(closeAction); -#if !defined(Q_OS_SYMBIAN) fileMenu->addAction(quitAction); QMenu *recordMenu = menu->addMenu(tr("&Recording")); -- cgit v0.12 From 9f6fd23fda43a5668d3fad398eb3e9d80cee9c44 Mon Sep 17 00:00:00 2001 From: Joona Petrell Date: Tue, 18 Jan 2011 13:42:48 +1000 Subject: Fix QtDeclarative compilation warnings Task-number: Reviewed-by: Martin Jones --- src/declarative/graphicsitems/qdeclarativegridview.cpp | 8 -------- src/declarative/qml/qdeclarativeboundsignal.cpp | 2 +- src/declarative/qml/qdeclarativeenginedebug.cpp | 13 ++++++------- src/declarative/qml/qdeclarativescriptparser.cpp | 6 ------ src/declarative/util/qdeclarativeutilmodule.cpp | 2 +- 5 files changed, 8 insertions(+), 23 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativegridview.cpp b/src/declarative/graphicsitems/qdeclarativegridview.cpp index 6e6e8c1..0bea638 100644 --- a/src/declarative/graphicsitems/qdeclarativegridview.cpp +++ b/src/declarative/graphicsitems/qdeclarativegridview.cpp @@ -2618,12 +2618,8 @@ void QDeclarativeGridView::itemsMoved(int from, int to, int count) return; QHash moved; - bool removedBeforeVisible = false; FxGridItem *firstItem = d->firstVisibleItem(); - if (from < to && from < d->visibleIndex && to > d->visibleIndex) - removedBeforeVisible = true; - QList::Iterator it = d->visibleItems.begin(); while (it != d->visibleItems.end()) { FxGridItem *item = *it; @@ -2632,16 +2628,12 @@ void QDeclarativeGridView::itemsMoved(int from, int to, int count) item->index += (to-from); moved.insert(item->index, item); it = d->visibleItems.erase(it); - if (item->rowPos() < firstItem->rowPos()) - removedBeforeVisible = true; } else { if (item->index > from && item->index != -1) { // move everything after the moved items. item->index -= count; if (item->index < d->visibleIndex) d->visibleIndex = item->index; - } else if (item->index != -1) { - removedBeforeVisible = true; } ++it; } diff --git a/src/declarative/qml/qdeclarativeboundsignal.cpp b/src/declarative/qml/qdeclarativeboundsignal.cpp index 030fb2c..0ac3f64 100644 --- a/src/declarative/qml/qdeclarativeboundsignal.cpp +++ b/src/declarative/qml/qdeclarativeboundsignal.cpp @@ -167,7 +167,7 @@ int QDeclarativeBoundSignal::qt_metacall(QMetaObject::Call c, int id, void **a) { if (c == QMetaObject::InvokeMetaMethod && id == evaluateIdx) { QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::HandlingSignal); - QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::HandlingSignal, QLatin1String(m_signal.signature()) + QLatin1String(": ") + (m_expression ? m_expression->expression() : "")); + QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::HandlingSignal, QLatin1String(m_signal.signature()) + QLatin1String(": ") + (m_expression ? m_expression->expression() : QLatin1String(""))); m_isEvaluating = true; if (!m_paramsValid) { if (!m_signal.parameterTypes().isEmpty()) diff --git a/src/declarative/qml/qdeclarativeenginedebug.cpp b/src/declarative/qml/qdeclarativeenginedebug.cpp index b6b4b49..0881003 100644 --- a/src/declarative/qml/qdeclarativeenginedebug.cpp +++ b/src/declarative/qml/qdeclarativeenginedebug.cpp @@ -539,7 +539,6 @@ void QDeclarativeEngineDebugServer::setBinding(int objectId, { QObject *object = objectForId(objectId); QDeclarativeContext *context = qmlContext(object); - QByteArray propertyNameArray = propertyName.toUtf8(); if (object && context) { QDeclarativeProperty property(object, propertyName, context); @@ -550,7 +549,7 @@ void QDeclarativeEngineDebugServer::setBinding(int objectId, foreach(QWeakPointer statePointer, m_allStates) { if (QDeclarativeState *state = statePointer.data()) { // here we assume that the revert list on itself defines the base state - if ( state->isStateActive() && state->containsPropertyInRevertList(object, propertyNameArray) ) { + if (state->isStateActive() && state->containsPropertyInRevertList(object, propertyName)) { inBaseState = false; QDeclarativeBinding *newBinding = 0; @@ -560,10 +559,10 @@ void QDeclarativeEngineDebugServer::setBinding(int objectId, newBinding->setNotifyOnValueChanged(true); } - state->changeBindingInRevertList(object,propertyNameArray, newBinding); + state->changeBindingInRevertList(object, propertyName, newBinding); if (isLiteralValue) - state->changeValueInRevertList(object, propertyNameArray, expression); + state->changeValueInRevertList(object, propertyName, expression); } } } @@ -592,9 +591,9 @@ void QDeclarativeEngineDebugServer::setBinding(int objectId, // not a valid property if (QDeclarativePropertyChanges *propertyChanges = dynamic_cast(object)) { if (isLiteralValue) { - propertyChanges->changeValue(propertyName.toUtf8(),expression); + propertyChanges->changeValue(propertyName, expression); } else { - propertyChanges->changeExpression(propertyName.toUtf8(),expression.toString()); + propertyChanges->changeExpression(propertyName, expression.toString()); } } else { qWarning() << "QDeclarativeEngineDebugServer::setBinding: unable to set property" << propertyName << "on object" << object; @@ -639,7 +638,7 @@ void QDeclarativeEngineDebugServer::resetBinding(int objectId, const QString &pr } } else { if (QDeclarativePropertyChanges *propertyChanges = dynamic_cast(object)) { - propertyChanges->removeProperty(propertyName.toUtf8()); + propertyChanges->removeProperty(propertyName); } } } diff --git a/src/declarative/qml/qdeclarativescriptparser.cpp b/src/declarative/qml/qdeclarativescriptparser.cpp index e32a3d2..ce6f943 100644 --- a/src/declarative/qml/qdeclarativescriptparser.cpp +++ b/src/declarative/qml/qdeclarativescriptparser.cpp @@ -170,12 +170,6 @@ private: StateStack _stateStack; QStringList _scope; QString _contents; - - inline bool isSignalProperty(const QByteArray &propertyName) const { - return (propertyName.length() >= 3 && propertyName.startsWith("on") && - ('A' <= propertyName.at(2) && 'Z' >= propertyName.at(2))); - } - }; ProcessAST::ProcessAST(QDeclarativeScriptParser *parser) diff --git a/src/declarative/util/qdeclarativeutilmodule.cpp b/src/declarative/util/qdeclarativeutilmodule.cpp index 5abf085..f32f390 100644 --- a/src/declarative/util/qdeclarativeutilmodule.cpp +++ b/src/declarative/util/qdeclarativeutilmodule.cpp @@ -76,7 +76,7 @@ void QDeclarativeUtilModule::defineModule() { - qmlRegisterUncreatableType("QtQuick",1,1,"Application", "Application is an abstract class"); + qmlRegisterUncreatableType("QtQuick",1,1,"Application", QDeclarativeApplication::tr("Application is an abstract class")); qmlRegisterType("QtQuick",1,0,"AnchorAnimation"); qmlRegisterType("QtQuick",1,0,"AnchorChanges"); -- cgit v0.12 From e46c44f9538dbe5b44ce61d3a42403cfa471ae8b Mon Sep 17 00:00:00 2001 From: Joona Petrell Date: Tue, 18 Jan 2011 14:16:47 +1000 Subject: Fix declarative autotest compilation on Symbian Task-number: Reviewed-by: Martin Jones --- src/declarative/qml/qdeclarativeglobal_p.h | 2 +- .../tst_qdeclarativepixmapcache.cpp | 12 ++++++++++++ tests/auto/declarative/qmlvisual/qmlvisual.pro | 2 +- tools/qml/qml.pri | 17 +++++++++++++---- tools/qml/qml.pro | 6 ------ 5 files changed, 27 insertions(+), 12 deletions(-) diff --git a/src/declarative/qml/qdeclarativeglobal_p.h b/src/declarative/qml/qdeclarativeglobal_p.h index 31fbb1e..b8428b8 100644 --- a/src/declarative/qml/qdeclarativeglobal_p.h +++ b/src/declarative/qml/qdeclarativeglobal_p.h @@ -65,7 +65,7 @@ QT_MODULE(Declarative) } #ifdef Q_OS_SYMBIAN -#define Q_DECLARATIVE_PRIVATE_EXPORT +#define Q_DECLARATIVE_PRIVATE_EXPORT Q_AUTOTEST_EXPORT #else #define Q_DECLARATIVE_PRIVATE_EXPORT Q_DECLARATIVE_EXPORT #endif diff --git a/tests/auto/declarative/qdeclarativepixmapcache/tst_qdeclarativepixmapcache.cpp b/tests/auto/declarative/qdeclarativepixmapcache/tst_qdeclarativepixmapcache.cpp index 50d0731..df7c694 100644 --- a/tests/auto/declarative/qdeclarativepixmapcache/tst_qdeclarativepixmapcache.cpp +++ b/tests/auto/declarative/qdeclarativepixmapcache/tst_qdeclarativepixmapcache.cpp @@ -47,6 +47,11 @@ #include "testhttpserver.h" #include "../../../shared/util.h" +#ifndef QT_NO_CONCURRENT +#include +#include +#endif + // These don't let normal people run tests! //#include "../network-settings.h" @@ -74,7 +79,10 @@ private slots: void massive(); void cancelcrash(); void shrinkcache(); +#ifndef QT_NO_CONCURRENT void networkCrash(); +#endif + private: QDeclarativeEngine engine; QUrl thisfile; @@ -354,6 +362,8 @@ void tst_qdeclarativepixmapcache::shrinkcache() } } +#ifndef QT_NO_CONCURRENT + void createNetworkServer() { QEventLoop eventLoop; @@ -378,6 +388,8 @@ void tst_qdeclarativepixmapcache::networkCrash() future.cancel(); } +#endif + QTEST_MAIN(tst_qdeclarativepixmapcache) #include "tst_qdeclarativepixmapcache.moc" diff --git a/tests/auto/declarative/qmlvisual/qmlvisual.pro b/tests/auto/declarative/qmlvisual/qmlvisual.pro index cb7e5d7..b2c5b4f 100644 --- a/tests/auto/declarative/qmlvisual/qmlvisual.pro +++ b/tests/auto/declarative/qmlvisual/qmlvisual.pro @@ -19,7 +19,7 @@ symbian: { qdeclarativepathview \ qdeclarativepositioners \ qdeclarativesmoothedanimation \ - qdeclarativespringfollow \ + qdeclarativespringanimation \ qdeclarativetext \ qdeclarativetextedit \ qdeclarativetextinput \ diff --git a/tools/qml/qml.pri b/tools/qml/qml.pri index 5db7678..08cd506 100644 --- a/tools/qml/qml.pri +++ b/tools/qml/qml.pri @@ -19,10 +19,18 @@ SOURCES += $$PWD/qmlruntime.cpp \ RESOURCES = $$PWD/browser/browser.qrc \ $$PWD/startup/startup.qrc -symbian:!contains(S60_VERSION, 3.1):!contains(S60_VERSION, 3.2) { - SOURCES += $$PWD/deviceorientation_symbian.cpp - FORMS = $$PWD/recopts.ui \ - $$PWD/proxysettings.ui +symbian: { + contains(QT_CONFIG, s60): { + LIBS += -lavkon -lcone + } + !contains(S60_VERSION, 3.1):!contains(S60_VERSION, 3.2) { + LIBS += -lsensrvclient -lsensrvutil + } + !contains(S60_VERSION, 3.1):!contains(S60_VERSION, 3.2): { + SOURCES += $$PWD/deviceorientation_symbian.cpp + FORMS = $$PWD/recopts.ui \ + $$PWD/proxysettings.ui + } } else:maemo5 { QT += dbus HEADERS += $$PWD/texteditautoresizer_maemo5.h @@ -39,3 +47,4 @@ symbian:!contains(S60_VERSION, 3.1):!contains(S60_VERSION, 3.2) { FORMS = $$PWD/recopts.ui \ $$PWD/proxysettings.ui } + diff --git a/tools/qml/qml.pro b/tools/qml/qml.pro index 9b07ebe..5d6192d 100644 --- a/tools/qml/qml.pro +++ b/tools/qml/qml.pro @@ -37,12 +37,6 @@ symbian { 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) { - LIBS += -lsensrvclient -lsensrvutil - } - contains(QT_CONFIG, s60): { - LIBS += -lavkon -lcone - } # Deploy plugin for remote debugging qmldebuggingplugin.sources = $$QT_BUILD_TREE/plugins/qmldebugging/tcpserver$${QT_LIBINFIX}.dll -- cgit v0.12 From ec6a1c33a930e38cb22efd9fa268d80329745062 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Tue, 18 Jan 2011 14:52:01 +1000 Subject: Implement layoutDirection property on Row, Grid, Flow Task-number: QTBUG-11042 Reviewed-by: Joona Petrell --- .../graphicsitems/qdeclarativeitemsmodule.cpp | 3 + .../graphicsitems/qdeclarativepositioners.cpp | 214 ++++++++++-- .../graphicsitems/qdeclarativepositioners_p.h | 20 ++ .../data/flow-testimplicitsize.qml | 9 +- .../data/flowtest-toptobottom.qml | 44 +++ .../qdeclarativepositioners/data/flowtest.qml | 5 +- .../qdeclarativepositioners/data/grid-animated.qml | 5 +- .../data/grid-righttoleft.qml | 41 +++ .../data/horizontal-animated.qml | 5 +- .../data/horizontal-spacing.qml | 5 +- .../qdeclarativepositioners/data/horizontal.qml | 5 +- .../tst_qdeclarativepositioners.cpp | 380 ++++++++++++++++++++- 12 files changed, 705 insertions(+), 31 deletions(-) create mode 100644 tests/auto/declarative/qdeclarativepositioners/data/flowtest-toptobottom.qml create mode 100644 tests/auto/declarative/qdeclarativepositioners/data/grid-righttoleft.qml diff --git a/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp b/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp index 529686e..32c71dd 100644 --- a/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp +++ b/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp @@ -182,6 +182,9 @@ void QDeclarativeItemModule::defineModule() qmlRegisterType("QtQuick",1,1,"Flickable"); qmlRegisterType("QtQuick",1,1,"ListView"); qmlRegisterType("QtQuick",1,1,"GridView"); + qmlRegisterType("QtQuick",1,1,"Row"); + qmlRegisterType("QtQuick",1,1,"Grid"); + qmlRegisterType("QtQuick",1,1,"Flow"); qmlRegisterType("QtQuick",1,1,"Repeater"); qmlRegisterType("QtQuick",1,1,"TextEdit"); #ifndef QT_NO_LINEEDIT diff --git a/src/declarative/graphicsitems/qdeclarativepositioners.cpp b/src/declarative/graphicsitems/qdeclarativepositioners.cpp index e2a373f..c4b35a8 100644 --- a/src/declarative/graphicsitems/qdeclarativepositioners.cpp +++ b/src/declarative/graphicsitems/qdeclarativepositioners.cpp @@ -574,21 +574,55 @@ void QDeclarativeColumn::reportConflictingAnchors() \sa Grid::spacing */ QDeclarativeRow::QDeclarativeRow(QDeclarativeItem *parent) -: QDeclarativeBasePositioner(Horizontal, parent) +: QDeclarativeBasePositioner(Horizontal, parent), m_layoutDirection(Qt::LeftToRight) { } +/*! + \qmlproperty enumeration Row::layoutDirection + This property holds the layoutDirection of the row. + + Possible values: + + \list + \o Qt.LeftToRight (default) - Items are laid out from left to right. If the width of the row is explicitly set, + the left anchor remains to the left of the row. + \o Qt.RightToLeft - Items are laid out from right to left. If the width of the row is explicitly set, + the right anchor remains to the right of the row. + \endlist + + \sa Grid::layoutDirection, Flow::layoutDirection +*/ +Qt::LayoutDirection QDeclarativeRow::layoutDirection() const +{ + return m_layoutDirection; +} + +void QDeclarativeRow::setLayoutDirection(Qt::LayoutDirection layoutDirection) +{ + if (m_layoutDirection != layoutDirection) { + m_layoutDirection = layoutDirection; + prePositioning(); + emit layoutDirectionChanged(); + } +} + void QDeclarativeRow::doPositioning(QSizeF *contentSize) { int hoffset = 0; + int hoffsets[positionedItems.count()]; for (int ii = 0; ii < positionedItems.count(); ++ii) { const PositionedItem &child = positionedItems.at(ii); if (!child.item || !child.isVisible) continue; - if(child.item->x() != hoffset) - positionX(hoffset, child); + if(m_layoutDirection == Qt::LeftToRight){ + if(child.item->x() != hoffset) + positionX(hoffset, child); + }else{ + hoffsets[ii] = hoffset; + } contentSize->setHeight(qMax(contentSize->height(), QGraphicsItemPrivate::get(child.item)->height())); @@ -597,6 +631,25 @@ void QDeclarativeRow::doPositioning(QSizeF *contentSize) } contentSize->setWidth(hoffset - spacing()); + + if(m_layoutDirection == Qt::LeftToRight) + return; + + //Right to Left layout + int end = 0; + if(!widthValid()) + end = contentSize->width(); + else + end = width(); + + for (int ii = 0; ii < positionedItems.count(); ++ii) { + const PositionedItem &child = positionedItems.at(ii); + if (!child.item || !child.isVisible) + continue; + hoffset = end - hoffsets[ii] - QGraphicsItemPrivate::get(child.item)->width(); + if(child.item->x() != hoffset) + positionX(hoffset, child); + } } void QDeclarativeRow::reportConflictingAnchors() @@ -732,7 +785,7 @@ void QDeclarativeRow::reportConflictingAnchors() \sa rows, columns */ QDeclarativeGrid::QDeclarativeGrid(QDeclarativeItem *parent) : - QDeclarativeBasePositioner(Both, parent), m_rows(-1), m_columns(-1), m_flow(LeftToRight) + QDeclarativeBasePositioner(Both, parent), m_rows(-1), m_columns(-1), m_flow(LeftToRight), m_layoutDirection(Qt::LeftToRight) { } @@ -780,7 +833,7 @@ void QDeclarativeGrid::setRows(const int rows) \list \o Grid.LeftToRight (default) - Items are positioned next to - to each other from left to right, then wrapped to the next line. + each other in the \l layoutDirection, then wrapped to the next line. \o Grid.TopToBottom - Items are positioned next to each other from top to bottom, then wrapped to the next column. \endlist @@ -799,6 +852,37 @@ void QDeclarativeGrid::setFlow(Flow flow) } } +/*! + \qmlproperty enumeration Grid::layoutDirection + This property holds the layout direction of the layout. + + Possible values are: + + \list + \o Qt.LeftToRight (default) - Items are positioned beginning + from the top, left anchor. The flow direction is dependent + on the \l Grid::flow property. + \o Qt.RightToLeft - Items are positioned beginning from the + top, right anchor. The flow direction is dependent on the + \l Grid::flow property. + \endlist + + \sa Flow::layoutDirection, Row::layoutDirection +*/ +Qt::LayoutDirection QDeclarativeGrid::layoutDirection() const +{ + return m_layoutDirection; +} + +void QDeclarativeGrid::setLayoutDirection(Qt::LayoutDirection layoutDirection) +{ + if (m_layoutDirection != layoutDirection) { + m_layoutDirection = layoutDirection; + prePositioning(); + emit layoutDirectionChanged(); + } +} + void QDeclarativeGrid::doPositioning(QSizeF *contentSize) { @@ -864,40 +948,71 @@ void QDeclarativeGrid::doPositioning(QSizeF *contentSize) } } + int widthSum = 0; + for(int j=0; j < c; j++){ + if(j) + widthSum += spacing(); + widthSum += maxColWidth[j]; + } + + int heightSum = 0; + for(int i=0; i < r; i++){ + if(i) + heightSum += spacing(); + heightSum += maxRowHeight[i]; + } + + contentSize->setHeight(heightSum); + contentSize->setWidth(widthSum); + + int end = 0; + if(widthValid()) + end = width(); + else + end = widthSum; + int xoffset=0; + if(m_layoutDirection == Qt::RightToLeft) + xoffset=end; int yoffset=0; int curRow =0; int curCol =0; for (int i = 0; i < visibleItems.count(); ++i) { const PositionedItem &child = visibleItems.at(i); - if((child.item->x()!=xoffset)||(child.item->y()!=yoffset)){ - positionX(xoffset, child); + int childXOffset = xoffset; + if(m_layoutDirection == Qt::RightToLeft) + childXOffset -= QGraphicsItemPrivate::get(child.item)->width(); + if((child.item->x()!=childXOffset)||(child.item->y()!=yoffset)){ + positionX(childXOffset, child); positionY(yoffset, child); } if (m_flow == LeftToRight) { - contentSize->setWidth(qMax(contentSize->width(), xoffset + QGraphicsItemPrivate::get(child.item)->width())); - contentSize->setHeight(yoffset + maxRowHeight[curRow]); - - xoffset+=maxColWidth[curCol]+spacing(); + if(m_layoutDirection == Qt::LeftToRight) + xoffset+=maxColWidth[curCol]+spacing(); + else + xoffset-=maxColWidth[curCol]+spacing(); curCol++; curCol%=c; if (!curCol){ yoffset+=maxRowHeight[curRow]+spacing(); - xoffset=0; + if(m_layoutDirection == Qt::LeftToRight) + xoffset=0; + else + xoffset=end; curRow++; if (curRow>=r) break; } } else { - contentSize->setHeight(qMax(contentSize->height(), yoffset + QGraphicsItemPrivate::get(child.item)->height())); - contentSize->setWidth(xoffset + maxColWidth[curCol]); - yoffset+=maxRowHeight[curRow]+spacing(); curRow++; curRow%=r; if (!curRow){ - xoffset+=maxColWidth[curCol]+spacing(); + if(m_layoutDirection == Qt::LeftToRight) + xoffset+=maxColWidth[curCol]+spacing(); + else + xoffset-=maxColWidth[curCol]+spacing(); yoffset=0; curCol++; if (curCol>=c) @@ -1029,10 +1144,12 @@ class QDeclarativeFlowPrivate : public QDeclarativeBasePositionerPrivate public: QDeclarativeFlowPrivate() - : QDeclarativeBasePositionerPrivate(), flow(QDeclarativeFlow::LeftToRight) + : QDeclarativeBasePositionerPrivate(), flow(QDeclarativeFlow::LeftToRight), + layoutDirection(Qt::LeftToRight) {} QDeclarativeFlow::Flow flow; + Qt::LayoutDirection layoutDirection; }; QDeclarativeFlow::QDeclarativeFlow(QDeclarativeItem *parent) @@ -1051,7 +1168,7 @@ QDeclarativeFlow::QDeclarativeFlow(QDeclarativeItem *parent) \list \o Flow.LeftToRight (default) - Items are positioned next to - to each other from left to right until the width of the Flow + to each other according to the \l layoutDirection until the width of the Flow is exceeded, then wrapped to the next line. \o Flow.TopToBottom - Items are positioned next to each other from top to bottom until the height of the Flow is exceeded, @@ -1074,6 +1191,39 @@ void QDeclarativeFlow::setFlow(Flow flow) } } +/*! + \qmlproperty enumeration Flow::layoutDirection + This property holds the layout direction of the layout. + + Possible values are: + + \list + \o Qt.LeftToRight (default) - Items are positioned beginning + from the top, left anchor. The flow direction is dependent + on the \l Flow::flow property. + \o Qt.RightToLeft - Items are positioned beginning from the + top, right anchor. The flow direction is dependent on the + \l Flow::flow property. + \endlist + + \sa Grid::layoutDirection, Row::layoutDirection +*/ +Qt::LayoutDirection QDeclarativeFlow::layoutDirection() const +{ + Q_D(const QDeclarativeFlow); + return d->layoutDirection; +} + +void QDeclarativeFlow::setLayoutDirection(Qt::LayoutDirection layoutDirection) +{ + Q_D(QDeclarativeFlow); + if (d->layoutDirection != layoutDirection) { + d->layoutDirection = layoutDirection; + prePositioning(); + emit layoutDirectionChanged(); + } +} + void QDeclarativeFlow::doPositioning(QSizeF *contentSize) { Q_D(QDeclarativeFlow); @@ -1081,6 +1231,7 @@ void QDeclarativeFlow::doPositioning(QSizeF *contentSize) int hoffset = 0; int voffset = 0; int linemax = 0; + int hoffsets[positionedItems.count()]; for (int i = 0; i < positionedItems.count(); ++i) { const PositionedItem &child = positionedItems.at(i); @@ -1102,10 +1253,14 @@ void QDeclarativeFlow::doPositioning(QSizeF *contentSize) } } - if(child.item->x() != hoffset || child.item->y() != voffset){ - positionX(hoffset, child); - positionY(voffset, child); + if(d->layoutDirection == Qt::LeftToRight){ + if(child.item->x() != hoffset) + positionX(hoffset, child); + }else{ + hoffsets[i] = hoffset; } + if(child.item->y() != voffset) + positionY(voffset, child); contentSize->setWidth(qMax(contentSize->width(), hoffset + childPrivate->width())); contentSize->setHeight(qMax(contentSize->height(), voffset + childPrivate->height())); @@ -1120,6 +1275,23 @@ void QDeclarativeFlow::doPositioning(QSizeF *contentSize) linemax = qMax(linemax, qCeil(childPrivate->width())); } } + + if(d->layoutDirection == Qt::LeftToRight) + return; + + int end; + if(widthValid()) + end = width(); + else + end = contentSize->width(); + for (int i = 0; i < positionedItems.count(); ++i) { + const PositionedItem &child = positionedItems.at(i); + if (!child.item || !child.isVisible) + continue; + hoffset = end - hoffsets[i] - QGraphicsItemPrivate::get(child.item)->width(); + if(child.item->x() != hoffset) + positionX(hoffset, child); + } } void QDeclarativeFlow::reportConflictingAnchors() diff --git a/src/declarative/graphicsitems/qdeclarativepositioners_p.h b/src/declarative/graphicsitems/qdeclarativepositioners_p.h index d3ae926..e3358fa 100644 --- a/src/declarative/graphicsitems/qdeclarativepositioners_p.h +++ b/src/declarative/graphicsitems/qdeclarativepositioners_p.h @@ -129,12 +129,21 @@ private: class Q_AUTOTEST_EXPORT QDeclarativeRow: public QDeclarativeBasePositioner { Q_OBJECT + Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged REVISION 1); public: QDeclarativeRow(QDeclarativeItem *parent=0); + + Qt::LayoutDirection layoutDirection() const; + void setLayoutDirection (Qt::LayoutDirection); + +Q_SIGNALS: + Q_REVISION(1) void layoutDirectionChanged(); + protected: virtual void doPositioning(QSizeF *contentSize); virtual void reportConflictingAnchors(); private: + Qt::LayoutDirection m_layoutDirection; Q_DISABLE_COPY(QDeclarativeRow) }; @@ -144,6 +153,7 @@ class Q_AUTOTEST_EXPORT QDeclarativeGrid : public QDeclarativeBasePositioner Q_PROPERTY(int rows READ rows WRITE setRows NOTIFY rowsChanged) Q_PROPERTY(int columns READ columns WRITE setColumns NOTIFY columnsChanged) Q_PROPERTY(Flow flow READ flow WRITE setFlow NOTIFY flowChanged) + Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged REVISION 1); public: QDeclarativeGrid(QDeclarativeItem *parent=0); @@ -159,10 +169,14 @@ public: Flow flow() const; void setFlow(Flow); + Qt::LayoutDirection layoutDirection() const; + void setLayoutDirection (Qt::LayoutDirection); + Q_SIGNALS: void rowsChanged(); void columnsChanged(); void flowChanged(); + Q_REVISION(1) void layoutDirectionChanged(); protected: virtual void doPositioning(QSizeF *contentSize); @@ -172,6 +186,7 @@ private: int m_rows; int m_columns; Flow m_flow; + Qt::LayoutDirection m_layoutDirection; Q_DISABLE_COPY(QDeclarativeGrid) }; @@ -179,6 +194,7 @@ class QDeclarativeFlowPrivate; class Q_AUTOTEST_EXPORT QDeclarativeFlow: public QDeclarativeBasePositioner { Q_OBJECT + Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged REVISION 1); Q_PROPERTY(Flow flow READ flow WRITE setFlow NOTIFY flowChanged) public: QDeclarativeFlow(QDeclarativeItem *parent=0); @@ -188,8 +204,12 @@ public: Flow flow() const; void setFlow(Flow); + Qt::LayoutDirection layoutDirection() const; + void setLayoutDirection (Qt::LayoutDirection); + Q_SIGNALS: void flowChanged(); + Q_REVISION(1) void layoutDirectionChanged(); protected: virtual void doPositioning(QSizeF *contentSize); diff --git a/tests/auto/declarative/qdeclarativepositioners/data/flow-testimplicitsize.qml b/tests/auto/declarative/qdeclarativepositioners/data/flow-testimplicitsize.qml index 51c8134..ee4e104 100644 --- a/tests/auto/declarative/qdeclarativepositioners/data/flow-testimplicitsize.qml +++ b/tests/auto/declarative/qdeclarativepositioners/data/flow-testimplicitsize.qml @@ -1,16 +1,19 @@ -import QtQuick 1.0 +import QtQuick 1.1 Rectangle { width: 300; height: 200; - property bool leftToRight: false + property int flowLayout: 1 Flow { objectName: "flow" - flow: leftToRight ? Flow.LeftToRight : Flow.TopToBottom + layoutDirection: (flowLayout == 2) ? Qt.RightToLeft : Qt.LeftToRight + flow: (flowLayout == 1) ? Flow.TopToBottom : Flow.LeftToRight; + spacing: 20 anchors.horizontalCenter: parent.horizontalCenter Rectangle { color: "red"; width: 100; height: 50 } Rectangle { color: "blue"; width: 100; height: 50 } } } + diff --git a/tests/auto/declarative/qdeclarativepositioners/data/flowtest-toptobottom.qml b/tests/auto/declarative/qdeclarativepositioners/data/flowtest-toptobottom.qml new file mode 100644 index 0000000..ec1d666 --- /dev/null +++ b/tests/auto/declarative/qdeclarativepositioners/data/flowtest-toptobottom.qml @@ -0,0 +1,44 @@ +import QtQuick 1.1 + +Item { + height: 90 + width: 480 + property bool testRightToLeft: false + + Flow { + objectName: "flow" + height: parent.height + layoutDirection: testRightToLeft ? Qt.RightToLeft : Qt.LeftToRight + flow: Flow.TopToBottom + Rectangle { + objectName: "one" + color: "red" + width: 50 + height: 50 + } + Rectangle { + objectName: "two" + color: "green" + width: 20 + height: 50 + } + Rectangle { + objectName: "three" + color: "blue" + width: 50 + height: 20 + } + Rectangle { + objectName: "four" + color: "cyan" + width: 50 + height: 50 + } + Rectangle { + objectName: "five" + color: "magenta" + width: 10 + height: 10 + } + } +} diff --git a/tests/auto/declarative/qdeclarativepositioners/data/flowtest.qml b/tests/auto/declarative/qdeclarativepositioners/data/flowtest.qml index 2810234..7c124a3 100644 --- a/tests/auto/declarative/qdeclarativepositioners/data/flowtest.qml +++ b/tests/auto/declarative/qdeclarativepositioners/data/flowtest.qml @@ -1,11 +1,14 @@ -import QtQuick 1.0 +import QtQuick 1.1 Item { width: 90 height: 480 + property bool testRightToLeft: false + Flow { objectName: "flow" width: parent.width + layoutDirection: testRightToLeft ? Qt.RightToLeft : Qt.LeftToRight Rectangle { objectName: "one" color: "red" diff --git a/tests/auto/declarative/qdeclarativepositioners/data/grid-animated.qml b/tests/auto/declarative/qdeclarativepositioners/data/grid-animated.qml index e13f078..3dcbed1 100644 --- a/tests/auto/declarative/qdeclarativepositioners/data/grid-animated.qml +++ b/tests/auto/declarative/qdeclarativepositioners/data/grid-animated.qml @@ -1,11 +1,14 @@ -import QtQuick 1.0 +import QtQuick 1.1 Item { width: 640 height: 480 + property bool testRightToLeft: true + Grid { objectName: "grid" columns: 3 + layoutDirection: testRightToLeft ? Qt.RightToLeft : Qt.LeftToRight add: Transition { NumberAnimation { properties: "x,y"; diff --git a/tests/auto/declarative/qdeclarativepositioners/data/grid-righttoleft.qml b/tests/auto/declarative/qdeclarativepositioners/data/grid-righttoleft.qml new file mode 100644 index 0000000..0ec1f37 --- /dev/null +++ b/tests/auto/declarative/qdeclarativepositioners/data/grid-righttoleft.qml @@ -0,0 +1,41 @@ +import QtQuick 1.1 + +Item { + width: 640 + height: 480 + Grid { + objectName: "grid" + columns: 3 + layoutDirection: Qt.RightToLeft + Rectangle { + objectName: "one" + color: "red" + width: 50 + height: 50 + } + Rectangle { + objectName: "two" + color: "green" + width: 20 + height: 50 + } + Rectangle { + objectName: "three" + color: "blue" + width: 50 + height: 20 + } + Rectangle { + objectName: "four" + color: "cyan" + width: 50 + height: 50 + } + Rectangle { + objectName: "five" + color: "magenta" + width: 10 + height: 10 + } + } +} diff --git a/tests/auto/declarative/qdeclarativepositioners/data/horizontal-animated.qml b/tests/auto/declarative/qdeclarativepositioners/data/horizontal-animated.qml index 5b064cd..3c95f53 100644 --- a/tests/auto/declarative/qdeclarativepositioners/data/horizontal-animated.qml +++ b/tests/auto/declarative/qdeclarativepositioners/data/horizontal-animated.qml @@ -1,10 +1,13 @@ -import QtQuick 1.0 +import QtQuick 1.1 Item { width: 640 height: 480 + property bool testRightToLeft: false + Row { objectName: "row" + layoutDirection: testRightToLeft ? Qt.RightToLeft : Qt.LeftToRight add: Transition { NumberAnimation { properties: "x"; diff --git a/tests/auto/declarative/qdeclarativepositioners/data/horizontal-spacing.qml b/tests/auto/declarative/qdeclarativepositioners/data/horizontal-spacing.qml index 2b46bca..64bedb0 100644 --- a/tests/auto/declarative/qdeclarativepositioners/data/horizontal-spacing.qml +++ b/tests/auto/declarative/qdeclarativepositioners/data/horizontal-spacing.qml @@ -1,11 +1,14 @@ -import QtQuick 1.0 +import QtQuick 1.1 Item { width: 640 height: 480 + property bool testRightToLeft: false + Row { objectName: "row" spacing: 10 + layoutDirection: testRightToLeft ? Qt.RightToLeft : Qt.LeftToRight Rectangle { objectName: "one" color: "red" diff --git a/tests/auto/declarative/qdeclarativepositioners/data/horizontal.qml b/tests/auto/declarative/qdeclarativepositioners/data/horizontal.qml index 919cecc..e1a9652 100644 --- a/tests/auto/declarative/qdeclarativepositioners/data/horizontal.qml +++ b/tests/auto/declarative/qdeclarativepositioners/data/horizontal.qml @@ -1,10 +1,13 @@ -import QtQuick 1.0 +import QtQuick 1.1 Item { width: 640 height: 480 + property bool testRightToLeft: false + Row { objectName: "row" + layoutDirection: testRightToLeft ? Qt.RightToLeft : Qt.LeftToRight Rectangle { objectName: "one" color: "red" diff --git a/tests/auto/declarative/qdeclarativepositioners/tst_qdeclarativepositioners.cpp b/tests/auto/declarative/qdeclarativepositioners/tst_qdeclarativepositioners.cpp index 254349f..cdf6933 100644 --- a/tests/auto/declarative/qdeclarativepositioners/tst_qdeclarativepositioners.cpp +++ b/tests/auto/declarative/qdeclarativepositioners/tst_qdeclarativepositioners.cpp @@ -62,20 +62,28 @@ public: private slots: void test_horizontal(); + void test_horizontal_rtl(); void test_horizontal_spacing(); + void test_horizontal_spacing_rightToLeft(); void test_horizontal_animated(); + void test_horizontal_animated_rightToLeft(); void test_vertical(); void test_vertical_spacing(); void test_vertical_animated(); void test_grid(); void test_grid_topToBottom(); + void test_grid_rightToLeft(); void test_grid_spacing(); void test_grid_animated(); + void test_grid_animated_rightToLeft(); void test_grid_zero_columns(); void test_propertychanges(); void test_repeater(); void test_flow(); + void test_flow_rightToLeft(); + void test_flow_topToBottom(); void test_flow_resize(); + void test_flow_resize_rightToLeft(); void test_flow_implicit_resize(); void test_conflictinganchors(); void test_vertical_qgraphicswidget(); @@ -91,6 +99,8 @@ void tst_QDeclarativePositioners::test_horizontal() { QDeclarativeView *canvas = createView(SRCDIR "/data/horizontal.qml"); + canvas->rootObject()->setProperty("testRightToLeft", false); + QDeclarativeRectangle *one = canvas->rootObject()->findChild("one"); QVERIFY(one != 0); @@ -114,10 +124,41 @@ void tst_QDeclarativePositioners::test_horizontal() delete canvas; } +void tst_QDeclarativePositioners::test_horizontal_rtl() +{ + QDeclarativeView *canvas = createView(SRCDIR "/data/horizontal.qml"); + + canvas->rootObject()->setProperty("testRightToLeft", true); + + QDeclarativeRectangle *one = canvas->rootObject()->findChild("one"); + QVERIFY(one != 0); + + QDeclarativeRectangle *two = canvas->rootObject()->findChild("two"); + QVERIFY(two != 0); + + QDeclarativeRectangle *three = canvas->rootObject()->findChild("three"); + QVERIFY(three != 0); + + QCOMPARE(one->x(), 60.0); + QCOMPARE(one->y(), 0.0); + QCOMPARE(two->x(), 40.0); + QCOMPARE(two->y(), 0.0); + QCOMPARE(three->x(), 0.0); + QCOMPARE(three->y(), 0.0); + + QDeclarativeItem *row = canvas->rootObject()->findChild("row"); + QCOMPARE(row->width(), 110.0); + QCOMPARE(row->height(), 50.0); + + delete canvas; +} + void tst_QDeclarativePositioners::test_horizontal_spacing() { QDeclarativeView *canvas = createView(SRCDIR "/data/horizontal-spacing.qml"); + canvas->rootObject()->setProperty("testRightToLeft", false); + QDeclarativeRectangle *one = canvas->rootObject()->findChild("one"); QVERIFY(one != 0); @@ -141,10 +182,41 @@ void tst_QDeclarativePositioners::test_horizontal_spacing() delete canvas; } +void tst_QDeclarativePositioners::test_horizontal_spacing_rightToLeft() +{ + QDeclarativeView *canvas = createView(SRCDIR "/data/horizontal-spacing.qml"); + + canvas->rootObject()->setProperty("testRightToLeft", true); + + QDeclarativeRectangle *one = canvas->rootObject()->findChild("one"); + QVERIFY(one != 0); + + QDeclarativeRectangle *two = canvas->rootObject()->findChild("two"); + QVERIFY(two != 0); + + QDeclarativeRectangle *three = canvas->rootObject()->findChild("three"); + QVERIFY(three != 0); + + QCOMPARE(one->x(), 80.0); + QCOMPARE(one->y(), 0.0); + QCOMPARE(two->x(), 50.0); + QCOMPARE(two->y(), 0.0); + QCOMPARE(three->x(), 00.0); + QCOMPARE(three->y(), 0.0); + + QDeclarativeItem *row = canvas->rootObject()->findChild("row"); + QCOMPARE(row->width(), 130.0); + QCOMPARE(row->height(), 50.0); + + delete canvas; +} + void tst_QDeclarativePositioners::test_horizontal_animated() { QDeclarativeView *canvas = createView(SRCDIR "/data/horizontal-animated.qml"); + canvas->rootObject()->setProperty("testRightToLeft", false); + QDeclarativeRectangle *one = canvas->rootObject()->findChild("one"); QVERIFY(one != 0); @@ -193,6 +265,60 @@ void tst_QDeclarativePositioners::test_horizontal_animated() delete canvas; } +void tst_QDeclarativePositioners::test_horizontal_animated_rightToLeft() +{ + QDeclarativeView *canvas = createView(SRCDIR "/data/horizontal-animated.qml"); + + canvas->rootObject()->setProperty("testRightToLeft", true); + + QDeclarativeRectangle *one = canvas->rootObject()->findChild("one"); + QVERIFY(one != 0); + + QDeclarativeRectangle *two = canvas->rootObject()->findChild("two"); + QVERIFY(two != 0); + + QDeclarativeRectangle *three = canvas->rootObject()->findChild("three"); + QVERIFY(three != 0); + + //Note that they animate in + QCOMPARE(one->x(), -100.0); + QCOMPARE(two->x(), -100.0); + QCOMPARE(three->x(), -100.0); + + QDeclarativeItem *row = canvas->rootObject()->findChild("row"); + QVERIFY(row); + QCOMPARE(row->width(), 100.0); + QCOMPARE(row->height(), 50.0); + + //QTRY_COMPARE used instead of waiting for the expected time of animation completion + //Note that this means the duration of the animation is NOT tested + + QTRY_COMPARE(one->x(), 50.0); + QTRY_COMPARE(one->y(), 0.0); + QTRY_COMPARE(two->opacity(), 0.0); + QTRY_COMPARE(two->x(), -100.0);//Not 'in' yet + QTRY_COMPARE(two->y(), 0.0); + QTRY_COMPARE(three->x(), 0.0); + QTRY_COMPARE(three->y(), 0.0); + + //Add 'two' + two->setOpacity(1.0); + QCOMPARE(two->opacity(), 1.0); + + // New size should be immediate + QCOMPARE(row->width(), 150.0); + QCOMPARE(row->height(), 50.0); + + QTest::qWait(0);//Let the animation start + QCOMPARE(one->x(), 50.0); + QCOMPARE(two->x(), -100.0); + + QTRY_COMPARE(one->x(), 100.0); + QTRY_COMPARE(two->x(), 50.0); + + delete canvas; +} + void tst_QDeclarativePositioners::test_vertical() { QDeclarativeView *canvas = createView(SRCDIR "/data/vertical.qml"); @@ -364,6 +490,40 @@ void tst_QDeclarativePositioners::test_grid_topToBottom() delete canvas; } +void tst_QDeclarativePositioners::test_grid_rightToLeft() +{ + QDeclarativeView *canvas = createView(SRCDIR "/data/grid-righttoleft.qml"); + + QDeclarativeRectangle *one = canvas->rootObject()->findChild("one"); + QVERIFY(one != 0); + QDeclarativeRectangle *two = canvas->rootObject()->findChild("two"); + QVERIFY(two != 0); + QDeclarativeRectangle *three = canvas->rootObject()->findChild("three"); + QVERIFY(three != 0); + QDeclarativeRectangle *four = canvas->rootObject()->findChild("four"); + QVERIFY(four != 0); + QDeclarativeRectangle *five = canvas->rootObject()->findChild("five"); + QVERIFY(five != 0); + + QCOMPARE(one->x(), 70.0); + QCOMPARE(one->y(), 0.0); + QCOMPARE(two->x(), 50.0); + QCOMPARE(two->y(), 0.0); + QCOMPARE(three->x(), 0.0); + QCOMPARE(three->y(), 0.0); + QCOMPARE(four->x(), 70.0); + QCOMPARE(four->y(), 50.0); + QCOMPARE(five->x(), 60.0); + QCOMPARE(five->y(), 50.0); + + QDeclarativeGrid *grid = canvas->rootObject()->findChild("grid"); + QCOMPARE(grid->layoutDirection(), Qt::RightToLeft); + QCOMPARE(grid->width(), 120.0); + QCOMPARE(grid->height(), 100.0); + + delete canvas; +} + void tst_QDeclarativePositioners::test_grid_spacing() { QDeclarativeView *canvas = createView(SRCDIR "/data/grid-spacing.qml"); @@ -401,6 +561,8 @@ void tst_QDeclarativePositioners::test_grid_animated() { QDeclarativeView *canvas = createView(SRCDIR "/data/grid-animated.qml"); + canvas->rootObject()->setProperty("testRightToLeft", false); + //Note that all animate in QDeclarativeRectangle *one = canvas->rootObject()->findChild("one"); QVERIFY(one != 0); @@ -478,6 +640,89 @@ void tst_QDeclarativePositioners::test_grid_animated() delete canvas; } +void tst_QDeclarativePositioners::test_grid_animated_rightToLeft() +{ + QDeclarativeView *canvas = createView(SRCDIR "/data/grid-animated.qml"); + + canvas->rootObject()->setProperty("testRightToLeft", true); + + //Note that all animate in + QDeclarativeRectangle *one = canvas->rootObject()->findChild("one"); + QVERIFY(one != 0); + QCOMPARE(one->x(), -100.0); + QCOMPARE(one->y(), -100.0); + + QDeclarativeRectangle *two = canvas->rootObject()->findChild("two"); + QVERIFY(two != 0); + QCOMPARE(two->x(), -100.0); + QCOMPARE(two->y(), -100.0); + + QDeclarativeRectangle *three = canvas->rootObject()->findChild("three"); + QVERIFY(three != 0); + QCOMPARE(three->x(), -100.0); + QCOMPARE(three->y(), -100.0); + + QDeclarativeRectangle *four = canvas->rootObject()->findChild("four"); + QVERIFY(four != 0); + QCOMPARE(four->x(), -100.0); + QCOMPARE(four->y(), -100.0); + + QDeclarativeRectangle *five = canvas->rootObject()->findChild("five"); + QVERIFY(five != 0); + QCOMPARE(five->x(), -100.0); + QCOMPARE(five->y(), -100.0); + + QDeclarativeItem *grid = canvas->rootObject()->findChild("grid"); + QVERIFY(grid); + QCOMPARE(grid->width(), 150.0); + QCOMPARE(grid->height(), 100.0); + + //QTRY_COMPARE used instead of waiting for the expected time of animation completion + //Note that this means the duration of the animation is NOT tested + + QTRY_COMPARE(one->y(), 0.0); + QTRY_COMPARE(one->x(), 100.0); + QTRY_COMPARE(two->opacity(), 0.0); + QTRY_COMPARE(two->y(), -100.0); + QTRY_COMPARE(two->x(), -100.0); + QTRY_COMPARE(three->y(), 0.0); + QTRY_COMPARE(three->x(), 50.0); + QTRY_COMPARE(four->y(), 0.0); + QTRY_COMPARE(four->x(), 0.0); + QTRY_COMPARE(five->y(), 50.0); + QTRY_COMPARE(five->x(), 100.0); + + //Add 'two' + two->setOpacity(1.0); + QCOMPARE(two->opacity(), 1.0); + QCOMPARE(grid->width(), 150.0); + QCOMPARE(grid->height(), 100.0); + QTest::qWait(0);//Let the animation start + QCOMPARE(two->x(), -100.0); + QCOMPARE(two->y(), -100.0); + QCOMPARE(one->x(), 100.0); + QCOMPARE(one->y(), 0.0); + QCOMPARE(three->x(), 50.0); + QCOMPARE(three->y(), 0.0); + QCOMPARE(four->x(), 0.0); + QCOMPARE(four->y(), 0.0); + QCOMPARE(five->x(), 100.0); + QCOMPARE(five->y(), 50.0); + //Let the animation complete + QTRY_COMPARE(two->x(), 50.0); + QTRY_COMPARE(two->y(), 0.0); + QTRY_COMPARE(one->x(), 100.0); + QTRY_COMPARE(one->y(), 0.0); + QTRY_COMPARE(three->x(), 0.0); + QTRY_COMPARE(three->y(), 0.0); + QTRY_COMPARE(four->x(), 100.0); + QTRY_COMPARE(four->y(), 50.0); + QTRY_COMPARE(five->x(), 50.0); + QTRY_COMPARE(five->y(), 50.0); + + delete canvas; +} + void tst_QDeclarativePositioners::test_grid_zero_columns() { QDeclarativeView *canvas = createView(SRCDIR "/data/gridzerocolumns.qml"); @@ -597,6 +842,8 @@ void tst_QDeclarativePositioners::test_flow() { QDeclarativeView *canvas = createView(SRCDIR "/data/flowtest.qml"); + canvas->rootObject()->setProperty("testRightToLeft", false); + QDeclarativeRectangle *one = canvas->rootObject()->findChild("one"); QVERIFY(one != 0); QDeclarativeRectangle *two = canvas->rootObject()->findChild("two"); @@ -627,6 +874,95 @@ void tst_QDeclarativePositioners::test_flow() delete canvas; } +void tst_QDeclarativePositioners::test_flow_rightToLeft() +{ + QDeclarativeView *canvas = createView(SRCDIR "/data/flowtest.qml"); + + canvas->rootObject()->setProperty("testRightToLeft", true); + + QDeclarativeRectangle *one = canvas->rootObject()->findChild("one"); + QVERIFY(one != 0); + QDeclarativeRectangle *two = canvas->rootObject()->findChild("two"); + QVERIFY(two != 0); + QDeclarativeRectangle *three = canvas->rootObject()->findChild("three"); + QVERIFY(three != 0); + QDeclarativeRectangle *four = canvas->rootObject()->findChild("four"); + QVERIFY(four != 0); + QDeclarativeRectangle *five = canvas->rootObject()->findChild("five"); + QVERIFY(five != 0); + + QCOMPARE(one->x(), 40.0); + QCOMPARE(one->y(), 0.0); + QCOMPARE(two->x(), 20.0); + QCOMPARE(two->y(), 0.0); + QCOMPARE(three->x(), 40.0); + QCOMPARE(three->y(), 50.0); + QCOMPARE(four->x(), 40.0); + QCOMPARE(four->y(), 70.0); + QCOMPARE(five->x(), 30.0); + QCOMPARE(five->y(), 70.0); + + QDeclarativeItem *flow = canvas->rootObject()->findChild("flow"); + QVERIFY(flow); + QCOMPARE(flow->width(), 90.0); + QCOMPARE(flow->height(), 120.0); + + delete canvas; +} + +void tst_QDeclarativePositioners::test_flow_topToBottom() +{ + QDeclarativeView *canvas = createView(SRCDIR "/data/flowtest-toptobottom.qml"); + + canvas->rootObject()->setProperty("testRightToLeft", false); + + QDeclarativeRectangle *one = canvas->rootObject()->findChild("one"); + QVERIFY(one != 0); + QDeclarativeRectangle *two = canvas->rootObject()->findChild("two"); + QVERIFY(two != 0); + QDeclarativeRectangle *three = canvas->rootObject()->findChild("three"); + QVERIFY(three != 0); + QDeclarativeRectangle *four = canvas->rootObject()->findChild("four"); + QVERIFY(four != 0); + QDeclarativeRectangle *five = canvas->rootObject()->findChild("five"); + QVERIFY(five != 0); + + QCOMPARE(one->x(), 0.0); + QCOMPARE(one->y(), 0.0); + QCOMPARE(two->x(), 50.0); + QCOMPARE(two->y(), 0.0); + QCOMPARE(three->x(), 50.0); + QCOMPARE(three->y(), 50.0); + QCOMPARE(four->x(), 100.0); + QCOMPARE(four->y(), 00.0); + QCOMPARE(five->x(), 100.0); + QCOMPARE(five->y(), 50.0); + + QDeclarativeItem *flow = canvas->rootObject()->findChild("flow"); + QVERIFY(flow); + QCOMPARE(flow->height(), 90.0); + QCOMPARE(flow->width(), 150.0); + + canvas->rootObject()->setProperty("testRightToLeft", true); + + QVERIFY(flow); + QCOMPARE(flow->height(), 90.0); + QCOMPARE(flow->width(), 150.0); + + QCOMPARE(one->x(), 100.0); + QCOMPARE(one->y(), 0.0); + QCOMPARE(two->x(), 80.0); + QCOMPARE(two->y(), 0.0); + QCOMPARE(three->x(), 50.0); + QCOMPARE(three->y(), 50.0); + QCOMPARE(four->x(), 0.0); + QCOMPARE(four->y(), 0.0); + QCOMPARE(five->x(), 40.0); + QCOMPARE(five->y(), 50.0); + + delete canvas; +} + void tst_QDeclarativePositioners::test_flow_resize() { QDeclarativeView *canvas = createView(SRCDIR "/data/flowtest.qml"); @@ -634,6 +970,7 @@ void tst_QDeclarativePositioners::test_flow_resize() QDeclarativeItem *root = qobject_cast(canvas->rootObject()); QVERIFY(root); root->setWidth(125); + root->setProperty("testRightToLeft", false); QDeclarativeRectangle *one = canvas->rootObject()->findChild("one"); QVERIFY(one != 0); @@ -660,6 +997,40 @@ void tst_QDeclarativePositioners::test_flow_resize() delete canvas; } +void tst_QDeclarativePositioners::test_flow_resize_rightToLeft() +{ + QDeclarativeView *canvas = createView(SRCDIR "/data/flowtest.qml"); + + QDeclarativeItem *root = qobject_cast(canvas->rootObject()); + QVERIFY(root); + root->setWidth(125); + root->setProperty("testRightToLeft", true); + + QDeclarativeRectangle *one = canvas->rootObject()->findChild("one"); + QVERIFY(one != 0); + QDeclarativeRectangle *two = canvas->rootObject()->findChild("two"); + QVERIFY(two != 0); + QDeclarativeRectangle *three = canvas->rootObject()->findChild("three"); + QVERIFY(three != 0); + QDeclarativeRectangle *four = canvas->rootObject()->findChild("four"); + QVERIFY(four != 0); + QDeclarativeRectangle *five = canvas->rootObject()->findChild("five"); + QVERIFY(five != 0); + + QCOMPARE(one->x(), 75.0); + QCOMPARE(one->y(), 0.0); + QCOMPARE(two->x(), 55.0); + QCOMPARE(two->y(), 0.0); + QCOMPARE(three->x(), 5.0); + QCOMPARE(three->y(), 0.0); + QCOMPARE(four->x(), 75.0); + QCOMPARE(four->y(), 50.0); + QCOMPARE(five->x(), 65.0); + QCOMPARE(five->y(), 50.0); + + delete canvas; +} + void tst_QDeclarativePositioners::test_flow_implicit_resize() { QDeclarativeView *canvas = createView(SRCDIR "/data/flow-testimplicitsize.qml"); @@ -671,16 +1042,21 @@ void tst_QDeclarativePositioners::test_flow_implicit_resize() QCOMPARE(flow->width(), 100.0); QCOMPARE(flow->height(), 120.0); - canvas->rootObject()->setProperty("leftToRight", true); + canvas->rootObject()->setProperty("flowLayout", 0); QCOMPARE(flow->flow(), QDeclarativeFlow::LeftToRight); QCOMPARE(flow->width(), 220.0); QCOMPARE(flow->height(), 50.0); - canvas->rootObject()->setProperty("leftToRight", false); + canvas->rootObject()->setProperty("flowLayout", 1); QCOMPARE(flow->flow(), QDeclarativeFlow::TopToBottom); QCOMPARE(flow->width(), 100.0); QCOMPARE(flow->height(), 120.0); + canvas->rootObject()->setProperty("flowLayout", 2); + QCOMPARE(flow->layoutDirection(), Qt::RightToLeft); + QCOMPARE(flow->width(), 220.0); + QCOMPARE(flow->height(), 50.0); + delete canvas; } -- cgit v0.12 From 28951758263e1512b00ca8e2e91a0cc95d176512 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Tue, 18 Jan 2011 17:00:49 +1000 Subject: Avoid index out of bounds array accesses --- src/declarative/graphicsitems/qdeclarativepositioners.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativepositioners.cpp b/src/declarative/graphicsitems/qdeclarativepositioners.cpp index c4b35a8..b3383ab 100644 --- a/src/declarative/graphicsitems/qdeclarativepositioners.cpp +++ b/src/declarative/graphicsitems/qdeclarativepositioners.cpp @@ -905,6 +905,9 @@ void QDeclarativeGrid::doPositioning(QSizeF *contentSize) c = (numVisible+(m_rows-1))/m_rows; } + if(r==0 || c==0) + return; //Nothing to do + QList maxColWidth; QList maxRowHeight; int childIndex =0; @@ -949,14 +952,14 @@ void QDeclarativeGrid::doPositioning(QSizeF *contentSize) } int widthSum = 0; - for(int j=0; j < c; j++){ + for(int j=0; j < maxColWidth.size(); j++){ if(j) widthSum += spacing(); widthSum += maxColWidth[j]; } int heightSum = 0; - for(int i=0; i < r; i++){ + for(int i=0; i < maxRowHeight.size(); i++){ if(i) heightSum += spacing(); heightSum += maxRowHeight[i]; -- cgit v0.12 From 9c1e67d83f6175f339e6771be05ee60ba72426b3 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Wed, 19 Jan 2011 08:38:49 +1000 Subject: Compile on windows --- src/declarative/graphicsitems/qdeclarativepositioners.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativepositioners.cpp b/src/declarative/graphicsitems/qdeclarativepositioners.cpp index b3383ab..ee9181d 100644 --- a/src/declarative/graphicsitems/qdeclarativepositioners.cpp +++ b/src/declarative/graphicsitems/qdeclarativepositioners.cpp @@ -611,7 +611,7 @@ void QDeclarativeRow::doPositioning(QSizeF *contentSize) { int hoffset = 0; - int hoffsets[positionedItems.count()]; + QList hoffsets; for (int ii = 0; ii < positionedItems.count(); ++ii) { const PositionedItem &child = positionedItems.at(ii); if (!child.item || !child.isVisible) @@ -621,7 +621,7 @@ void QDeclarativeRow::doPositioning(QSizeF *contentSize) if(child.item->x() != hoffset) positionX(hoffset, child); }else{ - hoffsets[ii] = hoffset; + hoffsets << hoffset; } contentSize->setHeight(qMax(contentSize->height(), QGraphicsItemPrivate::get(child.item)->height())); @@ -642,11 +642,12 @@ void QDeclarativeRow::doPositioning(QSizeF *contentSize) else end = width(); + int acc = 0; for (int ii = 0; ii < positionedItems.count(); ++ii) { const PositionedItem &child = positionedItems.at(ii); if (!child.item || !child.isVisible) continue; - hoffset = end - hoffsets[ii] - QGraphicsItemPrivate::get(child.item)->width(); + hoffset = end - hoffsets[acc++] - QGraphicsItemPrivate::get(child.item)->width(); if(child.item->x() != hoffset) positionX(hoffset, child); } @@ -1234,7 +1235,7 @@ void QDeclarativeFlow::doPositioning(QSizeF *contentSize) int hoffset = 0; int voffset = 0; int linemax = 0; - int hoffsets[positionedItems.count()]; + QList hoffsets; for (int i = 0; i < positionedItems.count(); ++i) { const PositionedItem &child = positionedItems.at(i); @@ -1260,7 +1261,7 @@ void QDeclarativeFlow::doPositioning(QSizeF *contentSize) if(child.item->x() != hoffset) positionX(hoffset, child); }else{ - hoffsets[i] = hoffset; + hoffsets << hoffset; } if(child.item->y() != voffset) positionY(voffset, child); @@ -1287,11 +1288,12 @@ void QDeclarativeFlow::doPositioning(QSizeF *contentSize) end = width(); else end = contentSize->width(); + int acc = 0; for (int i = 0; i < positionedItems.count(); ++i) { const PositionedItem &child = positionedItems.at(i); if (!child.item || !child.isVisible) continue; - hoffset = end - hoffsets[i] - QGraphicsItemPrivate::get(child.item)->width(); + hoffset = end - hoffsets[acc++] - QGraphicsItemPrivate::get(child.item)->width(); if(child.item->x() != hoffset) positionX(hoffset, child); } -- cgit v0.12 From 5ddfe819e93462eff396c24d10c0446c4cd9b0ac Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Tue, 18 Jan 2011 10:40:26 +1000 Subject: Rename Image::cached to 'cached' (and QDeclarativePixmap::Cached also) This is to keep consistent property naming consistent. E.g. Image has 'smooth', 'mirror' properties rather than 'smoothed', 'mirrored'. For consistency QDeclarativePixmap::Cached was renamed as well. Reviewed-by: Martin Jones --- .../graphicsitems/qdeclarativeborderimage.cpp | 8 ++++---- src/declarative/graphicsitems/qdeclarativeimage.cpp | 6 +++--- src/declarative/graphicsitems/qdeclarativeimagebase.cpp | 16 ++++++++-------- src/declarative/graphicsitems/qdeclarativeimagebase_p.h | 8 ++++---- .../graphicsitems/qdeclarativeimagebase_p_p.h | 4 ++-- src/declarative/util/qdeclarativepixmapcache.cpp | 8 ++++---- src/declarative/util/qdeclarativepixmapcache_p.h | 2 +- .../qdeclarativeimage/tst_qdeclarativeimage.cpp | 14 +++++++------- 8 files changed, 33 insertions(+), 33 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativeborderimage.cpp b/src/declarative/graphicsitems/qdeclarativeborderimage.cpp index 49ee357..3832813 100644 --- a/src/declarative/graphicsitems/qdeclarativeborderimage.cpp +++ b/src/declarative/graphicsitems/qdeclarativeborderimage.cpp @@ -313,8 +313,8 @@ void QDeclarativeBorderImage::load() QDeclarativePixmap::Options options; if (d->async) options |= QDeclarativePixmap::Asynchronous; - if (d->cached) - options |= QDeclarativePixmap::Cached; + if (d->cache) + options |= QDeclarativePixmap::Cache; d->pix.load(qmlEngine(this), d->url, options); if (d->pix.isLoading()) { @@ -442,8 +442,8 @@ void QDeclarativeBorderImage::setGridScaledImage(const QDeclarativeGridScaledIma QDeclarativePixmap::Options options; if (d->async) options |= QDeclarativePixmap::Asynchronous; - if (d->cached) - options |= QDeclarativePixmap::Cached; + if (d->cache) + options |= QDeclarativePixmap::Cache; d->pix.load(qmlEngine(this), d->sciurl, options); if (d->pix.isLoading()) { diff --git a/src/declarative/graphicsitems/qdeclarativeimage.cpp b/src/declarative/graphicsitems/qdeclarativeimage.cpp index 71a4f0c..2c9bde5 100644 --- a/src/declarative/graphicsitems/qdeclarativeimage.cpp +++ b/src/declarative/graphicsitems/qdeclarativeimage.cpp @@ -459,11 +459,11 @@ QRectF QDeclarativeImage::boundingRect() const */ /*! - \qmlproperty bool Image::cached + \qmlproperty bool Image::cache \since Quick 1.1 - Specifies that the image should be cached. The default value is - true. Setting \a cached to false is useful when dealing with large images, + Specifies whether the image should be cached. The default value is + true. Setting \a cache to false is useful when dealing with large images, to make sure that they aren't cached at the expense of small 'ui element' images. */ diff --git a/src/declarative/graphicsitems/qdeclarativeimagebase.cpp b/src/declarative/graphicsitems/qdeclarativeimagebase.cpp index b99ed4b..7ce357b 100644 --- a/src/declarative/graphicsitems/qdeclarativeimagebase.cpp +++ b/src/declarative/graphicsitems/qdeclarativeimagebase.cpp @@ -128,20 +128,20 @@ QSize QDeclarativeImageBase::sourceSize() const return QSize(width != -1 ? width : implicitWidth(), height != -1 ? height : implicitHeight()); } -bool QDeclarativeImageBase::cached() const +bool QDeclarativeImageBase::cache() const { Q_D(const QDeclarativeImageBase); - return d->cached; + return d->cache; } -void QDeclarativeImageBase::setCached(bool cached) +void QDeclarativeImageBase::setCache(bool cache) { Q_D(QDeclarativeImageBase); - if (d->cached == cached) + if (d->cache == cache) return; - d->cached = cached; - emit cachedChanged(); + d->cache = cache; + emit cacheChanged(); if (isComponentComplete()) load(); } @@ -184,8 +184,8 @@ void QDeclarativeImageBase::load() QDeclarativePixmap::Options options; if (d->async) options |= QDeclarativePixmap::Asynchronous; - if (d->cached) - options |= QDeclarativePixmap::Cached; + if (d->cache) + options |= QDeclarativePixmap::Cache; d->pix.load(qmlEngine(this), d->url, d->explicitSourceSize ? sourceSize() : QSize(), options); if (d->pix.isLoading()) { diff --git a/src/declarative/graphicsitems/qdeclarativeimagebase_p.h b/src/declarative/graphicsitems/qdeclarativeimagebase_p.h index ad2e370..4d2aa04 100644 --- a/src/declarative/graphicsitems/qdeclarativeimagebase_p.h +++ b/src/declarative/graphicsitems/qdeclarativeimagebase_p.h @@ -58,7 +58,7 @@ class Q_AUTOTEST_EXPORT QDeclarativeImageBase : public QDeclarativeItem Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged) Q_PROPERTY(qreal progress READ progress NOTIFY progressChanged) Q_PROPERTY(bool asynchronous READ asynchronous WRITE setAsynchronous NOTIFY asynchronousChanged) - Q_PROPERTY(bool cached READ cached WRITE setCached NOTIFY cachedChanged) // ### VERSIONING: Only in QtQuick 1.1 + Q_PROPERTY(bool cache READ cache WRITE setCache NOTIFY cacheChanged) // ### VERSIONING: Only in QtQuick 1.1 Q_PROPERTY(QSize sourceSize READ sourceSize WRITE setSourceSize NOTIFY sourceSizeChanged) Q_PROPERTY(bool mirror READ mirror WRITE setMirror NOTIFY mirrorChanged) // ### VERSIONING: Only in QtQuick 1.1 @@ -74,8 +74,8 @@ public: bool asynchronous() const; void setAsynchronous(bool); - bool cached() const; - void setCached(bool); + bool cache() const; + void setCache(bool); virtual void setSourceSize(const QSize&); QSize sourceSize() const; @@ -89,7 +89,7 @@ Q_SIGNALS: void statusChanged(QDeclarativeImageBase::Status); void progressChanged(qreal progress); void asynchronousChanged(); - void cachedChanged(); + void cacheChanged(); void mirrorChanged(); protected: diff --git a/src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h b/src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h index 475e7cd..39cf44e 100644 --- a/src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h @@ -71,7 +71,7 @@ public: progress(0.0), explicitSourceSize(false), async(false), - cached(true), + cache(true), mirror(false) { QGraphicsItemPrivate::flags = QGraphicsItemPrivate::flags & ~QGraphicsItem::ItemHasNoContents; @@ -84,7 +84,7 @@ public: QSize sourcesize; bool explicitSourceSize : 1; bool async : 1; - bool cached : 1; + bool cache : 1; bool mirror: 1; }; diff --git a/src/declarative/util/qdeclarativepixmapcache.cpp b/src/declarative/util/qdeclarativepixmapcache.cpp index aef24c6..5190eab 100644 --- a/src/declarative/util/qdeclarativepixmapcache.cpp +++ b/src/declarative/util/qdeclarativepixmapcache.cpp @@ -959,7 +959,7 @@ QRect QDeclarativePixmap::rect() const void QDeclarativePixmap::load(QDeclarativeEngine *engine, const QUrl &url) { - load(engine, url, QSize(), QDeclarativePixmap::Cached); + load(engine, url, QSize(), QDeclarativePixmap::Cache); } void QDeclarativePixmap::load(QDeclarativeEngine *engine, const QUrl &url, QDeclarativePixmap::Options options) @@ -969,7 +969,7 @@ void QDeclarativePixmap::load(QDeclarativeEngine *engine, const QUrl &url, QDecl void QDeclarativePixmap::load(QDeclarativeEngine *engine, const QUrl &url, const QSize &size) { - load(engine, url, size, QDeclarativePixmap::Cached); + load(engine, url, size, QDeclarativePixmap::Cache); } void QDeclarativePixmap::load(QDeclarativeEngine *engine, const QUrl &url, const QSize &requestSize, QDeclarativePixmap::Options options) @@ -994,7 +994,7 @@ void QDeclarativePixmap::load(QDeclarativeEngine *engine, const QUrl &url, const bool ok = false; d = createPixmapDataSync(engine, url, requestSize, &ok); if (ok) { - if (options & QDeclarativePixmap::Cached) + if (options & QDeclarativePixmap::Cache) d->addToCache(); return; } @@ -1008,7 +1008,7 @@ void QDeclarativePixmap::load(QDeclarativeEngine *engine, const QUrl &url, const QDeclarativePixmapReader *reader = QDeclarativePixmapReader::instance(engine); d = new QDeclarativePixmapData(url, requestSize); - if (options & QDeclarativePixmap::Cached) + if (options & QDeclarativePixmap::Cache) d->addToCache(); d->reply = reader->getImage(d); diff --git a/src/declarative/util/qdeclarativepixmapcache_p.h b/src/declarative/util/qdeclarativepixmapcache_p.h index b16f1bf..1cf76dd 100644 --- a/src/declarative/util/qdeclarativepixmapcache_p.h +++ b/src/declarative/util/qdeclarativepixmapcache_p.h @@ -68,7 +68,7 @@ public: enum Option { Asynchronous = 0x00000001, - Cached = 0x00000002 + Cache = 0x00000002 }; Q_DECLARE_FLAGS(Options, Option) diff --git a/tests/auto/declarative/qdeclarativeimage/tst_qdeclarativeimage.cpp b/tests/auto/declarative/qdeclarativeimage/tst_qdeclarativeimage.cpp index 7bb629e..c277eb7 100644 --- a/tests/auto/declarative/qdeclarativeimage/tst_qdeclarativeimage.cpp +++ b/tests/auto/declarative/qdeclarativeimage/tst_qdeclarativeimage.cpp @@ -126,7 +126,7 @@ void tst_qdeclarativeimage::imageSource_data() QTest::addColumn("height"); QTest::addColumn("remote"); QTest::addColumn("async"); - QTest::addColumn("cached"); + QTest::addColumn("cache"); QTest::addColumn("error"); QTest::newRow("local") << QUrl::fromLocalFile(SRCDIR "/data/colors.png").toString() << 120.0 << 120.0 << false << false << true << ""; @@ -151,7 +151,7 @@ void tst_qdeclarativeimage::imageSource() QFETCH(double, height); QFETCH(bool, remote); QFETCH(bool, async); - QFETCH(bool, cached); + QFETCH(bool, cache); QFETCH(QString, error); TestHTTPServer server(SERVER_PORT); @@ -165,8 +165,8 @@ void tst_qdeclarativeimage::imageSource() QTest::ignoreMessage(QtWarningMsg, error.toUtf8()); QString componentStr = "import QtQuick 1.0\nImage { source: \"" + source + "\"; asynchronous: " - + (async ? QLatin1String("true") : QLatin1String("false")) + "; cached: " - + (cached ? QLatin1String("true") : QLatin1String("false")) + " }"; + + (async ? QLatin1String("true") : QLatin1String("false")) + "; cache: " + + (cache ? QLatin1String("true") : QLatin1String("false")) + " }"; QDeclarativeComponent component(&engine); component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); QDeclarativeImage *obj = qobject_cast(component.create()); @@ -177,10 +177,10 @@ void tst_qdeclarativeimage::imageSource() else QVERIFY(obj->asynchronous() == false); - if (cached) - QVERIFY(obj->cached() == true); + if (cache) + QVERIFY(obj->cache() == true); else - QVERIFY(obj->cached() == false); + QVERIFY(obj->cache() == false); if (remote || async) QTRY_VERIFY(obj->status() == QDeclarativeImage::Loading); -- cgit v0.12 From eaacbac00bbd65cc6b12de9db4556dd2bdd18a5c Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Wed, 19 Jan 2011 15:44:28 +1000 Subject: Update demos following renaming of Image::cached --- demos/declarative/photoviewer/PhotoViewerCore/PhotoDelegate.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/demos/declarative/photoviewer/PhotoViewerCore/PhotoDelegate.qml b/demos/declarative/photoviewer/PhotoViewerCore/PhotoDelegate.qml index e0c1363..bfc8756 100644 --- a/demos/declarative/photoviewer/PhotoViewerCore/PhotoDelegate.qml +++ b/demos/declarative/photoviewer/PhotoViewerCore/PhotoDelegate.qml @@ -88,11 +88,11 @@ Package { } BusyIndicator { anchors.centerIn: parent; on: originalImage.status != Image.Ready } Image { - id: originalImage; smooth: true; source: "http://" + Script.getImagePath(content); cached: false + id: originalImage; smooth: true; source: "http://" + Script.getImagePath(content); cache: false fillMode: Image.PreserveAspectFit; width: photoWrapper.width; height: photoWrapper.height } Image { - id: hqImage; smooth: true; source: ""; visible: false; cached: false + id: hqImage; smooth: true; source: ""; visible: false; cache: false fillMode: Image.PreserveAspectFit; width: photoWrapper.width; height: photoWrapper.height } Binding { -- cgit v0.12 From eead12e91799c766dd3913687156a37f245ee20e Mon Sep 17 00:00:00 2001 From: Joona Petrell Date: Tue, 18 Jan 2011 15:35:55 +1000 Subject: Add a layout direction example to positioners Task-number: Reviewed-by: Alan Alpert --- doc/src/declarative/examples.qdoc | 3 +- doc/src/examples/qml-examples.qdoc | 18 +- .../qml-positioners-layoutdirection-example.png | Bin 0 -> 13019 bytes examples/declarative/positioners/Button.qml | 78 ------- examples/declarative/positioners/add.png | Bin 810 -> 0 bytes .../positioners/addandremove/Button.qml | 78 +++++++ .../declarative/positioners/addandremove/add.png | Bin 0 -> 810 bytes .../positioners/addandremove/addandremove.qml | 253 +++++++++++++++++++++ .../addandremove/addandremove.qmlproject | 18 ++ .../declarative/positioners/addandremove/del.png | Bin 0 -> 488 bytes examples/declarative/positioners/del.png | Bin 488 -> 0 bytes .../layoutdirection/layoutdirection.qml | 151 ++++++++++++ .../layoutdirection/layoutdirection.qmlproject | 18 ++ examples/declarative/positioners/positioners.qml | 253 --------------------- .../declarative/positioners/positioners.qmlproject | 18 -- .../graphicsitems/qdeclarativepositioners.cpp | 23 +- 16 files changed, 546 insertions(+), 365 deletions(-) create mode 100644 doc/src/images/qml-positioners-layoutdirection-example.png delete mode 100644 examples/declarative/positioners/Button.qml delete mode 100644 examples/declarative/positioners/add.png create mode 100644 examples/declarative/positioners/addandremove/Button.qml create mode 100644 examples/declarative/positioners/addandremove/add.png create mode 100644 examples/declarative/positioners/addandremove/addandremove.qml create mode 100644 examples/declarative/positioners/addandremove/addandremove.qmlproject create mode 100644 examples/declarative/positioners/addandremove/del.png delete mode 100644 examples/declarative/positioners/del.png create mode 100644 examples/declarative/positioners/layoutdirection/layoutdirection.qml create mode 100644 examples/declarative/positioners/layoutdirection/layoutdirection.qmlproject delete mode 100644 examples/declarative/positioners/positioners.qml delete mode 100644 examples/declarative/positioners/positioners.qmlproject diff --git a/doc/src/declarative/examples.qdoc b/doc/src/declarative/examples.qdoc index e03557b..be2d0c7 100644 --- a/doc/src/declarative/examples.qdoc +++ b/doc/src/declarative/examples.qdoc @@ -136,7 +136,8 @@ The examples can be found in Qt's \c examples/declarative directory. \section2 Positioners \list -\o \l{declarative/positioners}{Example} +\o \l{declarative/positioners/addandremove}{Adding and Removing Items} +\o \l{declarative/positioners/layoutdirection}{Layout Direction} \endlist \section2 Key Interaction diff --git a/doc/src/examples/qml-examples.qdoc b/doc/src/examples/qml-examples.qdoc index 46af110..2dc45e3 100644 --- a/doc/src/examples/qml-examples.qdoc +++ b/doc/src/examples/qml-examples.qdoc @@ -270,16 +270,26 @@ */ /*! - \title Positioners Example - \example declarative/positioners + \title Positioners: Adding and Removing Items Example + \example declarative/positioners/addandremove - This example shows how to use positioner elements such as \l Row, \l Column, - \l Grid and \l Flow. + This example shows how to use the positioner elements such as \l Row, \l Column, + \l Grid and \l Flow, in particular how to add and remove items with appropriate transitions. \image qml-positioners-example.png */ /*! + \title Positioners: Layout Direction Example + \example declarative/positioners/layoutdirection + + This example shows how to control the horizontal layout direction of + \l Row, \l Grid and \l Flow positioners. + + \image qml-positioners-layoutdirection-example.png +*/ + +/*! \title Key Interaction: Focus Example \example declarative/keyinteraction/focus diff --git a/doc/src/images/qml-positioners-layoutdirection-example.png b/doc/src/images/qml-positioners-layoutdirection-example.png new file mode 100644 index 0000000..2c42b09 Binary files /dev/null and b/doc/src/images/qml-positioners-layoutdirection-example.png differ diff --git a/examples/declarative/positioners/Button.qml b/examples/declarative/positioners/Button.qml deleted file mode 100644 index 25907c0..0000000 --- a/examples/declarative/positioners/Button.qml +++ /dev/null @@ -1,78 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the examples 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 QtQuick 1.0 - -Rectangle { - id: page - - property string text - property string icon - signal clicked - - border.color: "black"; color: "steelblue"; radius: 5 - width: pix.width + textelement.width + 13 - height: pix.height + 10 - - Image { id: pix; x: 5; y:5; source: parent.icon } - - Text { - id: textelement - text: page.text; color: "white" - x: pix.width + pix.x + 3 - anchors.verticalCenter: pix.verticalCenter - } - - MouseArea { - id: mr - anchors.fill: parent - onClicked: { parent.focus = true; page.clicked() } - } - - states: State { - name: "pressed"; when: mr.pressed - PropertyChanges { target: textelement; x: 5 } - PropertyChanges { target: pix; x: textelement.x + textelement.width + 3 } - } - - transitions: Transition { - NumberAnimation { properties: "x,left"; easing.type: Easing.InOutQuad; duration: 200 } - } -} diff --git a/examples/declarative/positioners/add.png b/examples/declarative/positioners/add.png deleted file mode 100644 index 1ee4542..0000000 Binary files a/examples/declarative/positioners/add.png and /dev/null differ diff --git a/examples/declarative/positioners/addandremove/Button.qml b/examples/declarative/positioners/addandremove/Button.qml new file mode 100644 index 0000000..25907c0 --- /dev/null +++ b/examples/declarative/positioners/addandremove/Button.qml @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples 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 QtQuick 1.0 + +Rectangle { + id: page + + property string text + property string icon + signal clicked + + border.color: "black"; color: "steelblue"; radius: 5 + width: pix.width + textelement.width + 13 + height: pix.height + 10 + + Image { id: pix; x: 5; y:5; source: parent.icon } + + Text { + id: textelement + text: page.text; color: "white" + x: pix.width + pix.x + 3 + anchors.verticalCenter: pix.verticalCenter + } + + MouseArea { + id: mr + anchors.fill: parent + onClicked: { parent.focus = true; page.clicked() } + } + + states: State { + name: "pressed"; when: mr.pressed + PropertyChanges { target: textelement; x: 5 } + PropertyChanges { target: pix; x: textelement.x + textelement.width + 3 } + } + + transitions: Transition { + NumberAnimation { properties: "x,left"; easing.type: Easing.InOutQuad; duration: 200 } + } +} diff --git a/examples/declarative/positioners/addandremove/add.png b/examples/declarative/positioners/addandremove/add.png new file mode 100644 index 0000000..1ee4542 Binary files /dev/null and b/examples/declarative/positioners/addandremove/add.png differ diff --git a/examples/declarative/positioners/addandremove/addandremove.qml b/examples/declarative/positioners/addandremove/addandremove.qml new file mode 100644 index 0000000..7d6d8fe --- /dev/null +++ b/examples/declarative/positioners/addandremove/addandremove.qml @@ -0,0 +1,253 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples 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 QtQuick 1.0 + +Rectangle { + id: page + width: 420; height: 420 + + Column { + id: layout1 + y: 0 + move: Transition { + NumberAnimation { properties: "y"; easing.type: Easing.OutBounce } + } + add: Transition { + NumberAnimation { properties: "y"; easing.type: Easing.OutQuad } + } + + Rectangle { color: "red"; width: 100; height: 50; border.color: "black"; radius: 15 } + + Rectangle { + id: blueV1 + width: 100; height: 50 + color: "lightsteelblue" + border.color: "black" + radius: 15 + Behavior on opacity { NumberAnimation {} } + } + + Rectangle { color: "green"; width: 100; height: 50; border.color: "black"; radius: 15 } + + Rectangle { + id: blueV2 + width: 100; height: 50 + color: "lightsteelblue" + border.color: "black" + radius: 15 + Behavior on opacity { NumberAnimation {} } + } + + Rectangle { color: "orange"; width: 100; height: 50; border.color: "black"; radius: 15 } + } + + Row { + id: layout2 + y: 300 + move: Transition { + NumberAnimation { properties: "x"; easing.type: Easing.OutBounce } + } + add: Transition { + NumberAnimation { properties: "x"; easing.type: Easing.OutQuad } + } + + Rectangle { color: "red"; width: 50; height: 100; border.color: "black"; radius: 15 } + + Rectangle { + id: blueH1 + width: 50; height: 100 + color: "lightsteelblue" + border.color: "black" + radius: 15 + Behavior on opacity { NumberAnimation {} } + } + + Rectangle { color: "green"; width: 50; height: 100; border.color: "black"; radius: 15 } + + Rectangle { + id: blueH2 + width: 50; height: 100 + color: "lightsteelblue" + border.color: "black" + radius: 15 + Behavior on opacity { NumberAnimation {} } + } + + Rectangle { color: "orange"; width: 50; height: 100; border.color: "black"; radius: 15 } + } + + Button { + x: 135; y: 90 + text: "Remove" + icon: "del.png" + + onClicked: { + blueH2.opacity = 0 + blueH1.opacity = 0 + blueV1.opacity = 0 + blueV2.opacity = 0 + blueG1.opacity = 0 + blueG2.opacity = 0 + blueG3.opacity = 0 + blueF1.opacity = 0 + blueF2.opacity = 0 + blueF3.opacity = 0 + } + } + + Button { + x: 145; y: 140 + text: "Add" + icon: "add.png" + + onClicked: { + blueH2.opacity = 1 + blueH1.opacity = 1 + blueV1.opacity = 1 + blueV2.opacity = 1 + blueG1.opacity = 1 + blueG2.opacity = 1 + blueG3.opacity = 1 + blueF1.opacity = 1 + blueF2.opacity = 1 + blueF3.opacity = 1 + } + } + + Grid { + x: 260; y: 0 + columns: 3 + + move: Transition { + NumberAnimation { properties: "x,y"; easing.type: Easing.OutBounce } + } + + add: Transition { + NumberAnimation { properties: "x,y"; easing.type: Easing.OutBounce } + } + + Rectangle { color: "red"; width: 50; height: 50; border.color: "black"; radius: 15 } + + Rectangle { + id: blueG1 + width: 50; height: 50 + color: "lightsteelblue" + border.color: "black" + radius: 15 + Behavior on opacity { NumberAnimation {} } + } + + Rectangle { color: "green"; width: 50; height: 50; border.color: "black"; radius: 15 } + + Rectangle { + id: blueG2 + width: 50; height: 50 + color: "lightsteelblue" + border.color: "black" + radius: 15 + Behavior on opacity { NumberAnimation {} } + } + + Rectangle { color: "orange"; width: 50; height: 50; border.color: "black"; radius: 15 } + + Rectangle { + id: blueG3 + width: 50; height: 50 + color: "lightsteelblue" + border.color: "black" + radius: 15 + Behavior on opacity { NumberAnimation {} } + } + + Rectangle { color: "red"; width: 50; height: 50; border.color: "black"; radius: 15 } + Rectangle { color: "green"; width: 50; height: 50; border.color: "black"; radius: 15 } + Rectangle { color: "orange"; width: 50; height: 50; border.color: "black"; radius: 15 } + } + + Flow { + id: layout4 + x: 260; y: 250; width: 150 + + move: Transition { + NumberAnimation { properties: "x,y"; easing.type: Easing.OutBounce } + } + + add: Transition { + NumberAnimation { properties: "x,y"; easing.type: Easing.OutBounce } + } + + Rectangle { color: "red"; width: 50; height: 50; border.color: "black"; radius: 15 } + + Rectangle { + id: blueF1 + width: 60; height: 50 + color: "lightsteelblue" + border.color: "black" + radius: 15 + Behavior on opacity { NumberAnimation {} } + } + + Rectangle { color: "green"; width: 30; height: 50; border.color: "black"; radius: 15 } + + Rectangle { + id: blueF2 + width: 60; height: 50 + color: "lightsteelblue" + border.color: "black" + radius: 15 + Behavior on opacity { NumberAnimation {} } + } + + Rectangle { color: "orange"; width: 50; height: 50; border.color: "black"; radius: 15 } + + Rectangle { + id: blueF3 + width: 40; height: 50 + color: "lightsteelblue" + border.color: "black" + radius: 15 + Behavior on opacity { NumberAnimation {} } + } + + Rectangle { color: "red"; width: 80; height: 50; border.color: "black"; radius: 15 } + } + +} diff --git a/examples/declarative/positioners/addandremove/addandremove.qmlproject b/examples/declarative/positioners/addandremove/addandremove.qmlproject new file mode 100644 index 0000000..e526217 --- /dev/null +++ b/examples/declarative/positioners/addandremove/addandremove.qmlproject @@ -0,0 +1,18 @@ +/* File generated by QtCreator */ + +import QmlProject 1.0 + +Project { + /* Include .qml, .js, and image files from current directory and subdirectories */ + QmlFiles { + directory: "." + } + JavaScriptFiles { + directory: "." + } + ImageFiles { + directory: "." + } + /* List of plugin directories passed to QML runtime */ + // importPaths: [ " ../exampleplugin " ] +} diff --git a/examples/declarative/positioners/addandremove/del.png b/examples/declarative/positioners/addandremove/del.png new file mode 100644 index 0000000..8d2eaed Binary files /dev/null and b/examples/declarative/positioners/addandremove/del.png differ diff --git a/examples/declarative/positioners/del.png b/examples/declarative/positioners/del.png deleted file mode 100644 index 8d2eaed..0000000 Binary files a/examples/declarative/positioners/del.png and /dev/null differ diff --git a/examples/declarative/positioners/layoutdirection/layoutdirection.qml b/examples/declarative/positioners/layoutdirection/layoutdirection.qml new file mode 100644 index 0000000..3e23b15 --- /dev/null +++ b/examples/declarative/positioners/layoutdirection/layoutdirection.qml @@ -0,0 +1,151 @@ +/**************************************************************************** +** +** 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 examples 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 QtQuick 1.1 + +Rectangle { + + width: column.width + 100 + height: column.height + 100 + property int direction: Qt.application.layoutDirection + + Column { + id: column + spacing: 10 + anchors.centerIn: parent + width: 230 + + Text { + text: "Row" + anchors.horizontalCenter: parent.horizontalCenter + } + Row { + layoutDirection: direction + spacing: 10 + move: Transition { + NumberAnimation { + properties: "x" + } + } + Repeater { + model: 4 + Loader { + property int value: index + sourceComponent: delegate + } + } + } + Text { + text: "Grid" + anchors.horizontalCenter: parent.horizontalCenter + } + Grid { + layoutDirection: direction + spacing: 10; columns: 4 + move: Transition { + NumberAnimation { + properties: "x" + } + } + Repeater { + model: 11 + Loader { + property int value: index + sourceComponent: delegate + } + } + } + Text { + text: "Flow" + anchors.horizontalCenter: parent.horizontalCenter + } + Flow { + layoutDirection: direction + spacing: 10; width: parent.width + move: Transition { + NumberAnimation { + properties: "x" + } + } + Repeater { + model: 10 + Loader { + property int value: index + sourceComponent: delegate + } + } + } + Rectangle { + height: 50; width: parent.width + color: mouseArea.pressed ? "black" : "gray" + Text { + text: direction ? "Right to left" : "Left to right" + color: "white" + font.pixelSize: 16 + anchors.centerIn: parent + } + MouseArea { + id: mouseArea + onClicked: { + if (direction == Qt.LeftToRight) { + direction = Qt.RightToLeft; + } else { + direction = Qt.LeftToRight; + } + } + anchors.fill: parent + } + } + } + + Component { + id: delegate + Rectangle { + width: 50; height: 50 + color: Qt.rgba(0.8/(parent.value+1),0.8/(parent.value+1),0.8/(parent.value+1),1.0) + Text { + text: parent.parent.value+1 + color: "white" + font.pixelSize: 20 + anchors.centerIn: parent + } + } + } +} diff --git a/examples/declarative/positioners/layoutdirection/layoutdirection.qmlproject b/examples/declarative/positioners/layoutdirection/layoutdirection.qmlproject new file mode 100644 index 0000000..e526217 --- /dev/null +++ b/examples/declarative/positioners/layoutdirection/layoutdirection.qmlproject @@ -0,0 +1,18 @@ +/* File generated by QtCreator */ + +import QmlProject 1.0 + +Project { + /* Include .qml, .js, and image files from current directory and subdirectories */ + QmlFiles { + directory: "." + } + JavaScriptFiles { + directory: "." + } + ImageFiles { + directory: "." + } + /* List of plugin directories passed to QML runtime */ + // importPaths: [ " ../exampleplugin " ] +} diff --git a/examples/declarative/positioners/positioners.qml b/examples/declarative/positioners/positioners.qml deleted file mode 100644 index 7d6d8fe..0000000 --- a/examples/declarative/positioners/positioners.qml +++ /dev/null @@ -1,253 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the examples 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 QtQuick 1.0 - -Rectangle { - id: page - width: 420; height: 420 - - Column { - id: layout1 - y: 0 - move: Transition { - NumberAnimation { properties: "y"; easing.type: Easing.OutBounce } - } - add: Transition { - NumberAnimation { properties: "y"; easing.type: Easing.OutQuad } - } - - Rectangle { color: "red"; width: 100; height: 50; border.color: "black"; radius: 15 } - - Rectangle { - id: blueV1 - width: 100; height: 50 - color: "lightsteelblue" - border.color: "black" - radius: 15 - Behavior on opacity { NumberAnimation {} } - } - - Rectangle { color: "green"; width: 100; height: 50; border.color: "black"; radius: 15 } - - Rectangle { - id: blueV2 - width: 100; height: 50 - color: "lightsteelblue" - border.color: "black" - radius: 15 - Behavior on opacity { NumberAnimation {} } - } - - Rectangle { color: "orange"; width: 100; height: 50; border.color: "black"; radius: 15 } - } - - Row { - id: layout2 - y: 300 - move: Transition { - NumberAnimation { properties: "x"; easing.type: Easing.OutBounce } - } - add: Transition { - NumberAnimation { properties: "x"; easing.type: Easing.OutQuad } - } - - Rectangle { color: "red"; width: 50; height: 100; border.color: "black"; radius: 15 } - - Rectangle { - id: blueH1 - width: 50; height: 100 - color: "lightsteelblue" - border.color: "black" - radius: 15 - Behavior on opacity { NumberAnimation {} } - } - - Rectangle { color: "green"; width: 50; height: 100; border.color: "black"; radius: 15 } - - Rectangle { - id: blueH2 - width: 50; height: 100 - color: "lightsteelblue" - border.color: "black" - radius: 15 - Behavior on opacity { NumberAnimation {} } - } - - Rectangle { color: "orange"; width: 50; height: 100; border.color: "black"; radius: 15 } - } - - Button { - x: 135; y: 90 - text: "Remove" - icon: "del.png" - - onClicked: { - blueH2.opacity = 0 - blueH1.opacity = 0 - blueV1.opacity = 0 - blueV2.opacity = 0 - blueG1.opacity = 0 - blueG2.opacity = 0 - blueG3.opacity = 0 - blueF1.opacity = 0 - blueF2.opacity = 0 - blueF3.opacity = 0 - } - } - - Button { - x: 145; y: 140 - text: "Add" - icon: "add.png" - - onClicked: { - blueH2.opacity = 1 - blueH1.opacity = 1 - blueV1.opacity = 1 - blueV2.opacity = 1 - blueG1.opacity = 1 - blueG2.opacity = 1 - blueG3.opacity = 1 - blueF1.opacity = 1 - blueF2.opacity = 1 - blueF3.opacity = 1 - } - } - - Grid { - x: 260; y: 0 - columns: 3 - - move: Transition { - NumberAnimation { properties: "x,y"; easing.type: Easing.OutBounce } - } - - add: Transition { - NumberAnimation { properties: "x,y"; easing.type: Easing.OutBounce } - } - - Rectangle { color: "red"; width: 50; height: 50; border.color: "black"; radius: 15 } - - Rectangle { - id: blueG1 - width: 50; height: 50 - color: "lightsteelblue" - border.color: "black" - radius: 15 - Behavior on opacity { NumberAnimation {} } - } - - Rectangle { color: "green"; width: 50; height: 50; border.color: "black"; radius: 15 } - - Rectangle { - id: blueG2 - width: 50; height: 50 - color: "lightsteelblue" - border.color: "black" - radius: 15 - Behavior on opacity { NumberAnimation {} } - } - - Rectangle { color: "orange"; width: 50; height: 50; border.color: "black"; radius: 15 } - - Rectangle { - id: blueG3 - width: 50; height: 50 - color: "lightsteelblue" - border.color: "black" - radius: 15 - Behavior on opacity { NumberAnimation {} } - } - - Rectangle { color: "red"; width: 50; height: 50; border.color: "black"; radius: 15 } - Rectangle { color: "green"; width: 50; height: 50; border.color: "black"; radius: 15 } - Rectangle { color: "orange"; width: 50; height: 50; border.color: "black"; radius: 15 } - } - - Flow { - id: layout4 - x: 260; y: 250; width: 150 - - move: Transition { - NumberAnimation { properties: "x,y"; easing.type: Easing.OutBounce } - } - - add: Transition { - NumberAnimation { properties: "x,y"; easing.type: Easing.OutBounce } - } - - Rectangle { color: "red"; width: 50; height: 50; border.color: "black"; radius: 15 } - - Rectangle { - id: blueF1 - width: 60; height: 50 - color: "lightsteelblue" - border.color: "black" - radius: 15 - Behavior on opacity { NumberAnimation {} } - } - - Rectangle { color: "green"; width: 30; height: 50; border.color: "black"; radius: 15 } - - Rectangle { - id: blueF2 - width: 60; height: 50 - color: "lightsteelblue" - border.color: "black" - radius: 15 - Behavior on opacity { NumberAnimation {} } - } - - Rectangle { color: "orange"; width: 50; height: 50; border.color: "black"; radius: 15 } - - Rectangle { - id: blueF3 - width: 40; height: 50 - color: "lightsteelblue" - border.color: "black" - radius: 15 - Behavior on opacity { NumberAnimation {} } - } - - Rectangle { color: "red"; width: 80; height: 50; border.color: "black"; radius: 15 } - } - -} diff --git a/examples/declarative/positioners/positioners.qmlproject b/examples/declarative/positioners/positioners.qmlproject deleted file mode 100644 index e526217..0000000 --- a/examples/declarative/positioners/positioners.qmlproject +++ /dev/null @@ -1,18 +0,0 @@ -/* File generated by QtCreator */ - -import QmlProject 1.0 - -Project { - /* Include .qml, .js, and image files from current directory and subdirectories */ - QmlFiles { - directory: "." - } - JavaScriptFiles { - directory: "." - } - ImageFiles { - directory: "." - } - /* List of plugin directories passed to QML runtime */ - // importPaths: [ " ../exampleplugin " ] -} diff --git a/src/declarative/graphicsitems/qdeclarativepositioners.cpp b/src/declarative/graphicsitems/qdeclarativepositioners.cpp index 557c88b..a2a167e 100644 --- a/src/declarative/graphicsitems/qdeclarativepositioners.cpp +++ b/src/declarative/graphicsitems/qdeclarativepositioners.cpp @@ -381,7 +381,7 @@ void QDeclarativeBasePositioner::finishApplyTransitions() Items with a width or height of 0 will not be positioned. - \sa Row, Grid, Flow, {declarative/positioners}{Positioners example} + \sa Row, Grid, Flow, {declarative/positioners/addandremove}{Positioners example} */ /*! \qmlproperty Transition Column::add @@ -421,7 +421,7 @@ void QDeclarativeBasePositioner::finishApplyTransitions() } \endqml - \sa add, {declarative/positioners}{Positioners example} + \sa add, {declarative/positioners/addandremove}{Positioners example} */ /*! \qmlproperty int Column::spacing @@ -524,7 +524,7 @@ void QDeclarativeColumn::reportConflictingAnchors() Items with a width or height of 0 will not be positioned. - \sa Column, Grid, Flow, {declarative/positioners}{Positioners example} + \sa Column, Grid, Flow, {declarative/positioners/addandremove}{Positioners example} */ /*! \qmlproperty Transition Row::add @@ -563,7 +563,7 @@ void QDeclarativeColumn::reportConflictingAnchors() } \endqml - \sa add, {declarative/positioners}{Positioners example} + \sa add, {declarative/positioners/addandremove}{Positioners example} */ /*! \qmlproperty int Row::spacing @@ -591,7 +591,7 @@ QDeclarativeRow::QDeclarativeRow(QDeclarativeItem *parent) the right anchor remains to the right of the row. \endlist - \sa Grid::layoutDirection, Flow::layoutDirection + \sa Grid::layoutDirection, Flow::layoutDirection, {declarative/positioners/layoutdirection}{Layout directions example} */ Qt::LayoutDirection QDeclarativeRow::layoutDirection() const { @@ -728,7 +728,7 @@ void QDeclarativeRow::reportConflictingAnchors() Items with a width or height of 0 will not be positioned. - \sa Flow, Row, Column, {declarative/positioners}{Positioners example} + \sa Flow, Row, Column, {declarative/positioners/addandremove}{Positioners example} */ /*! \qmlproperty Transition Grid::add @@ -766,7 +766,7 @@ void QDeclarativeRow::reportConflictingAnchors() } \endqml - \sa add, {declarative/positioners}{Positioners example} + \sa add, {declarative/positioners/addandremove}{Positioners example} */ /*! \qmlproperty int Grid::spacing @@ -868,7 +868,7 @@ void QDeclarativeGrid::setFlow(Flow flow) \l Grid::flow property. \endlist - \sa Flow::layoutDirection, Row::layoutDirection + \sa Flow::layoutDirection, Row::layoutDirection, {declarative/positioners/layoutdirection}{Layout directions example} */ Qt::LayoutDirection QDeclarativeGrid::layoutDirection() const { @@ -1092,7 +1092,7 @@ void QDeclarativeGrid::reportConflictingAnchors() Items with a width or height of 0 will not be positioned. - \sa Column, Row, Grid, {declarative/positioners}{Positioners example} + \sa Column, Row, Grid, {declarative/positioners/addandremove}{Positioners example} */ /*! \qmlproperty Transition Flow::add @@ -1131,7 +1131,7 @@ void QDeclarativeGrid::reportConflictingAnchors() } \endqml - \sa add, {declarative/positioners}{Positioners example} + \sa add, {declarative/positioners/addandremove}{Positioners example} */ /*! \qmlproperty int Flow::spacing @@ -1210,8 +1210,9 @@ void QDeclarativeFlow::setFlow(Flow flow) \l Flow::flow property. \endlist - \sa Grid::layoutDirection, Row::layoutDirection + \sa Grid::layoutDirection, Row::layoutDirection, {declarative/positioners/layoutdirection}{Layout directions example} */ + Qt::LayoutDirection QDeclarativeFlow::layoutDirection() const { Q_D(const QDeclarativeFlow); -- cgit v0.12 From 1f54c358fcc3eb53dc0cf689f59e2e6913dcf239 Mon Sep 17 00:00:00 2001 From: Joona Petrell Date: Tue, 18 Jan 2011 19:13:44 +1000 Subject: Change Qt.application.layoutDirection from bool to correct type of Qt::LayoutDirection Task-number: QTBUG-16424 Reviewed-by: Martin Jones --- src/declarative/util/qdeclarativeapplication.cpp | 13 +++++++++++-- src/declarative/util/qdeclarativeapplication_p.h | 4 ++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/declarative/util/qdeclarativeapplication.cpp b/src/declarative/util/qdeclarativeapplication.cpp index 7559aa9..7ecce1e 100644 --- a/src/declarative/util/qdeclarativeapplication.cpp +++ b/src/declarative/util/qdeclarativeapplication.cpp @@ -103,7 +103,7 @@ bool QDeclarativeApplication::active() const } /*! - \qmlproperty bool Application::layoutDirection + \qmlproperty enumeration Application::layoutDirection This property can be used to query the default layout direction of the application. On system start-up, the default layout direction depends on the @@ -113,8 +113,17 @@ bool QDeclarativeApplication::active() const property to customize your application layouts to support both layout directions. This property is readonly. + Possible values are: + + \list + \o Qt.LeftToRight - Text and graphics elements should be positioned + from left to right. + \o Qt.RightToLeft - Text and graphics elements should be positioned + from right to left. + \endlist + */ -bool QDeclarativeApplication::layoutDirection() const +Qt::LayoutDirection QDeclarativeApplication::layoutDirection() const { Q_D(const QDeclarativeApplication); return d->layoutDirection; diff --git a/src/declarative/util/qdeclarativeapplication_p.h b/src/declarative/util/qdeclarativeapplication_p.h index c5cd227..caaed18 100644 --- a/src/declarative/util/qdeclarativeapplication_p.h +++ b/src/declarative/util/qdeclarativeapplication_p.h @@ -57,13 +57,13 @@ class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeApplication : public QObject { Q_OBJECT Q_PROPERTY(bool active READ active NOTIFY activeChanged) - Q_PROPERTY(bool layoutDirection READ layoutDirection NOTIFY layoutDirectionChanged) + Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection NOTIFY layoutDirectionChanged) public: explicit QDeclarativeApplication(QObject *parent = 0); virtual ~QDeclarativeApplication(); bool active() const; - bool layoutDirection() const; + Qt::LayoutDirection layoutDirection() const; protected: bool eventFilter(QObject *obj, QEvent *event); -- cgit v0.12 From 44060d2129b461754f6bd86153889a869f12440a Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Mon, 24 Jan 2011 14:09:59 +1000 Subject: Add list of new properties/methods in QtQuick 1.1 --- doc/src/declarative/whatsnew.qdoc | 98 +++++++++++++++++++++- .../qdeclarativeitem/data/implicitsize.qml | 19 +++++ 2 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 tests/auto/declarative/qdeclarativeitem/data/implicitsize.qml diff --git a/doc/src/declarative/whatsnew.qdoc b/doc/src/declarative/whatsnew.qdoc index a3ba522..4b94d51 100644 --- a/doc/src/declarative/whatsnew.qdoc +++ b/doc/src/declarative/whatsnew.qdoc @@ -29,7 +29,103 @@ \title What's new in Qt Quick \page qtquick-whatsnew.html -\section1 4.7.1 +\section1 Qt 4.7.3 includes QtQuick 1.1 + +QtQuick 1.1 is a minor feature update. + +\section2 PinchArea + +PinchArea provides support for the common two finger pinch gesture. + +\section2 Text + +Added the following properties: +\list +\o lineSpacing +\o lineCount +\o maximumLineCount +\o truncated +\endlist + +horizontalAlignment now accepts Text.AlignJustify alignment mode. + +\section2 TextEdit + +Added the following properties, methods and signal handlers: +\list +\o canPaste +\o lineCount +\o deselect() +\o moveCursorSelection(int pos, SelectionMode mode) to enable selection by word +\o onLinkActivated(string link) +\endlist + +\section2 TextInput + +Added the following properties and methods: +\list +\o canPaste +\o deselect() +\o moveCursorSelection(int pos, SelectionMode mode) to enable selection by word +\endlist + +\section2 Image and BorderImage + +Added the following properties: +\list +\o cache +\o mirror +\endlist + +\section2 Item + +Added the following properties: +\list +\o implicitWidth and implicitHeight +\endlist + +\section2 Flickable + +Added the following methods: +\list +\o resizeContent(qreal w, qreal h, QPointF center) +\o returnToBounds() +\endlist + +\section2 ListView and GridView + +Added the following methods: +\list +\o positionViewAtBeginning() +\o positionViewAtEnd() +\endlist + +\section2 Flow, Grid, Row + +Added the following properties: +\list +\o layoutDirection +\endlist + +\section2 Repeater + +Added the following methods: +\list +\o onItemAdded() +\o onItemRemoved() +\o itemAt() +\endlist + +\section2 Qt + +Added the following properties: +\list +\o application.layoutDirection +\o application.active +\endlist + + +\section1 Qt 4.7.1 \section2 QtQuick namespace diff --git a/tests/auto/declarative/qdeclarativeitem/data/implicitsize.qml b/tests/auto/declarative/qdeclarativeitem/data/implicitsize.qml new file mode 100644 index 0000000..869c0fc --- /dev/null +++ b/tests/auto/declarative/qdeclarativeitem/data/implicitsize.qml @@ -0,0 +1,19 @@ +import QtQuick 1.1 + +Item { + implicitWidth: 200 + implicitHeight: 100 + + width: 80 + height: 60 + + function resetSize() { + width = undefined + height = undefined + } + + function changeImplicit() { + implicitWidth = 150 + implicitHeight = 80 + } +} -- cgit v0.12 From 6f78a6080b84cc3ef96b73a4ff58d1b5a72f08f4 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Mon, 24 Jan 2011 16:08:46 +1000 Subject: Expose implicitWidth and implicitHeight properties of Item. Overridden as readonly for elements that have an inherent implicit size such as Text, TextEdit, TextInput, positioners, Loader. Task-number: QTBUG-14957 Reviewed-by: Michael Brasser --- src/declarative/graphicsitems/graphicsitems.pri | 8 +- .../graphicsitems/qdeclarativeimagebase.cpp | 2 +- .../graphicsitems/qdeclarativeimagebase_p.h | 4 +- .../graphicsitems/qdeclarativeimagebase_p_p.h | 4 +- .../graphicsitems/qdeclarativeimplicitsizeitem.cpp | 92 +++++++++++++++++++ .../graphicsitems/qdeclarativeimplicitsizeitem_p.h | 100 +++++++++++++++++++++ .../qdeclarativeimplicitsizeitem_p_p.h | 90 +++++++++++++++++++ src/declarative/graphicsitems/qdeclarativeitem.cpp | 85 ++++++++++++++++-- src/declarative/graphicsitems/qdeclarativeitem.h | 5 ++ src/declarative/graphicsitems/qdeclarativeitem_p.h | 11 ++- .../graphicsitems/qdeclarativeitemsmodule.cpp | 5 ++ .../graphicsitems/qdeclarativeloader.cpp | 2 +- .../graphicsitems/qdeclarativeloader_p.h | 4 +- .../graphicsitems/qdeclarativeloader_p_p.h | 4 +- .../graphicsitems/qdeclarativepositioners.cpp | 4 +- .../graphicsitems/qdeclarativepositioners_p.h | 4 +- .../graphicsitems/qdeclarativepositioners_p_p.h | 4 +- src/declarative/graphicsitems/qdeclarativetext.cpp | 62 +++++++++++-- src/declarative/graphicsitems/qdeclarativetext_p.h | 4 +- .../graphicsitems/qdeclarativetext_p_p.h | 9 +- .../graphicsitems/qdeclarativetextedit.cpp | 43 +++++++-- .../graphicsitems/qdeclarativetextedit_p.h | 4 +- .../graphicsitems/qdeclarativetextedit_p_p.h | 11 ++- .../graphicsitems/qdeclarativetextinput.cpp | 2 +- .../graphicsitems/qdeclarativetextinput_p.h | 4 +- .../graphicsitems/qdeclarativetextinput_p_p.h | 4 +- .../qdeclarativeitem/tst_qdeclarativeitem.cpp | 80 +++++++++++++++++ .../qdeclarativetext/tst_qdeclarativetext.cpp | 29 ++++++ .../tst_qdeclarativetextedit.cpp | 29 ++++++ 29 files changed, 652 insertions(+), 57 deletions(-) create mode 100644 src/declarative/graphicsitems/qdeclarativeimplicitsizeitem.cpp create mode 100644 src/declarative/graphicsitems/qdeclarativeimplicitsizeitem_p.h create mode 100644 src/declarative/graphicsitems/qdeclarativeimplicitsizeitem_p_p.h diff --git a/src/declarative/graphicsitems/graphicsitems.pri b/src/declarative/graphicsitems/graphicsitems.pri index 2cd3323..9904274 100644 --- a/src/declarative/graphicsitems/graphicsitems.pri +++ b/src/declarative/graphicsitems/graphicsitems.pri @@ -52,7 +52,10 @@ HEADERS += \ $$PWD/qdeclarativegraphicswidget_p.h \ $$PWD/qdeclarativetextlayout_p.h \ $$PWD/qdeclarativepincharea_p.h \ - $$PWD/qdeclarativepincharea_p_p.h + $$PWD/qdeclarativepincharea_p_p.h \ + $$PWD/qdeclarativeimplicitsizeitem_p.h \ + $$PWD/qdeclarativeimplicitsizeitem_p_p.h + SOURCES += \ $$PWD/qdeclarativeitemsmodule.cpp \ @@ -86,5 +89,6 @@ SOURCES += \ $$PWD/qdeclarativelayoutitem.cpp \ $$PWD/qdeclarativegraphicswidget.cpp \ $$PWD/qdeclarativetextlayout.cpp \ - $$PWD/qdeclarativepincharea.cpp + $$PWD/qdeclarativepincharea.cpp \ + $$PWD/qdeclarativeimplicitsizeitem.cpp diff --git a/src/declarative/graphicsitems/qdeclarativeimagebase.cpp b/src/declarative/graphicsitems/qdeclarativeimagebase.cpp index 7ce357b..8448bd6 100644 --- a/src/declarative/graphicsitems/qdeclarativeimagebase.cpp +++ b/src/declarative/graphicsitems/qdeclarativeimagebase.cpp @@ -49,7 +49,7 @@ QT_BEGIN_NAMESPACE QDeclarativeImageBase::QDeclarativeImageBase(QDeclarativeImageBasePrivate &dd, QDeclarativeItem *parent) - : QDeclarativeItem(dd, parent) + : QDeclarativeImplicitSizeItem(dd, parent) { } diff --git a/src/declarative/graphicsitems/qdeclarativeimagebase_p.h b/src/declarative/graphicsitems/qdeclarativeimagebase_p.h index 4d2aa04..d183bdc 100644 --- a/src/declarative/graphicsitems/qdeclarativeimagebase_p.h +++ b/src/declarative/graphicsitems/qdeclarativeimagebase_p.h @@ -42,14 +42,14 @@ #ifndef QDECLARATIVEIMAGEBASE_H #define QDECLARATIVEIMAGEBASE_H -#include "qdeclarativeitem.h" +#include "qdeclarativeimplicitsizeitem_p.h" QT_BEGIN_HEADER QT_BEGIN_NAMESPACE class QDeclarativeImageBasePrivate; -class Q_AUTOTEST_EXPORT QDeclarativeImageBase : public QDeclarativeItem +class Q_AUTOTEST_EXPORT QDeclarativeImageBase : public QDeclarativeImplicitSizeItem { Q_OBJECT Q_ENUMS(Status) diff --git a/src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h b/src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h index 39cf44e..ab16e66 100644 --- a/src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h @@ -53,7 +53,7 @@ // We mean it. // -#include "private/qdeclarativeitem_p.h" +#include "private/qdeclarativeimplicitsizeitem_p_p.h" #include "private/qdeclarativepixmapcache_p.h" #include @@ -61,7 +61,7 @@ QT_BEGIN_NAMESPACE class QNetworkReply; -class QDeclarativeImageBasePrivate : public QDeclarativeItemPrivate +class QDeclarativeImageBasePrivate : public QDeclarativeImplicitSizeItemPrivate { Q_DECLARE_PUBLIC(QDeclarativeImageBase) diff --git a/src/declarative/graphicsitems/qdeclarativeimplicitsizeitem.cpp b/src/declarative/graphicsitems/qdeclarativeimplicitsizeitem.cpp new file mode 100644 index 0000000..31ac28f --- /dev/null +++ b/src/declarative/graphicsitems/qdeclarativeimplicitsizeitem.cpp @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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/qdeclarativeimplicitsizeitem_p.h" +#include "private/qdeclarativeimplicitsizeitem_p_p.h" + +QT_BEGIN_NAMESPACE + +void QDeclarativeImplicitSizeItemPrivate::implicitWidthChanged() +{ + Q_Q(QDeclarativeImplicitSizeItem); + emit q->implicitWidthChanged(); +} + +void QDeclarativeImplicitSizeItemPrivate::implicitHeightChanged() +{ + Q_Q(QDeclarativeImplicitSizeItem); + emit q->implicitHeightChanged(); +} + +QDeclarativeImplicitSizeItem::QDeclarativeImplicitSizeItem(QDeclarativeItem *parent) + : QDeclarativeItem(*(new QDeclarativeImplicitSizeItemPrivate), parent) +{ +} + +QDeclarativeImplicitSizeItem::QDeclarativeImplicitSizeItem(QDeclarativeImplicitSizeItemPrivate &dd, QDeclarativeItem *parent) + : QDeclarativeItem(dd, parent) +{ +} + + +void QDeclarativeImplicitSizePaintedItemPrivate::implicitWidthChanged() +{ + Q_Q(QDeclarativeImplicitSizePaintedItem); + emit q->implicitWidthChanged(); +} + +void QDeclarativeImplicitSizePaintedItemPrivate::implicitHeightChanged() +{ + Q_Q(QDeclarativeImplicitSizePaintedItem); + emit q->implicitHeightChanged(); +} + +QDeclarativeImplicitSizePaintedItem::QDeclarativeImplicitSizePaintedItem(QDeclarativeItem *parent) + : QDeclarativePaintedItem(*(new QDeclarativeImplicitSizePaintedItemPrivate), parent) +{ +} + +QDeclarativeImplicitSizePaintedItem::QDeclarativeImplicitSizePaintedItem(QDeclarativeImplicitSizePaintedItemPrivate &dd, QDeclarativeItem *parent) + : QDeclarativePaintedItem(dd, parent) +{ +} + +QT_END_NAMESPACE diff --git a/src/declarative/graphicsitems/qdeclarativeimplicitsizeitem_p.h b/src/declarative/graphicsitems/qdeclarativeimplicitsizeitem_p.h new file mode 100644 index 0000000..1863d95 --- /dev/null +++ b/src/declarative/graphicsitems/qdeclarativeimplicitsizeitem_p.h @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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 QDECLARATIVEIMPLICITSIZEITEM_H +#define QDECLARATIVEIMPLICITSIZEITEM_H + +#include "qdeclarativepainteditem_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QDeclarativeImplicitSizeItemPrivate; +class Q_AUTOTEST_EXPORT QDeclarativeImplicitSizeItem : public QDeclarativeItem +{ + Q_OBJECT + Q_PROPERTY(qreal implicitWidth READ implicitWidth NOTIFY implicitWidthChanged REVISION 1) + Q_PROPERTY(qreal implicitHeight READ implicitHeight NOTIFY implicitHeightChanged REVISION 1) + +public: + QDeclarativeImplicitSizeItem(QDeclarativeItem *parent = 0); + +protected: + QDeclarativeImplicitSizeItem(QDeclarativeImplicitSizeItemPrivate &dd, QDeclarativeItem *parent); + +Q_SIGNALS: + Q_REVISION(1) void implicitWidthChanged(); + Q_REVISION(1) void implicitHeightChanged(); + +private: + Q_DISABLE_COPY(QDeclarativeImplicitSizeItem) + Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarativeImplicitSizeItem) +}; + +class QDeclarativeImplicitSizePaintedItemPrivate; +class Q_AUTOTEST_EXPORT QDeclarativeImplicitSizePaintedItem : public QDeclarativePaintedItem +{ + Q_OBJECT + Q_PROPERTY(qreal implicitWidth READ implicitWidth NOTIFY implicitWidthChanged REVISION 1) + Q_PROPERTY(qreal implicitHeight READ implicitHeight NOTIFY implicitHeightChanged REVISION 1) + +public: + QDeclarativeImplicitSizePaintedItem(QDeclarativeItem *parent = 0); + +protected: + QDeclarativeImplicitSizePaintedItem(QDeclarativeImplicitSizePaintedItemPrivate &dd, QDeclarativeItem *parent); + virtual void drawContents(QPainter *, const QRect &) {}; + +Q_SIGNALS: + Q_REVISION(1) void implicitWidthChanged(); + Q_REVISION(1) void implicitHeightChanged(); + +private: + Q_DISABLE_COPY(QDeclarativeImplicitSizePaintedItem) + Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarativeImplicitSizePaintedItem) +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QDECLARATIVEIMPLICITSIZEITEM_H diff --git a/src/declarative/graphicsitems/qdeclarativeimplicitsizeitem_p_p.h b/src/declarative/graphicsitems/qdeclarativeimplicitsizeitem_p_p.h new file mode 100644 index 0000000..0bb7163 --- /dev/null +++ b/src/declarative/graphicsitems/qdeclarativeimplicitsizeitem_p_p.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2011 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 QDECLARATIVEIMPLICITSIZEITEM_P_H +#define QDECLARATIVEIMPLICITSIZEITEM_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/qdeclarativeitem_p.h" +#include "private/qdeclarativepainteditem_p_p.h" + +QT_BEGIN_NAMESPACE + +class QDeclarativeImplicitSizeItemPrivate : public QDeclarativeItemPrivate +{ + Q_DECLARE_PUBLIC(QDeclarativeImplicitSizeItem) + +public: + QDeclarativeImplicitSizeItemPrivate() + { + } + + virtual void implicitWidthChanged(); + virtual void implicitHeightChanged(); +}; + + +class QDeclarativeImplicitSizePaintedItemPrivate : public QDeclarativePaintedItemPrivate +{ + Q_DECLARE_PUBLIC(QDeclarativeImplicitSizePaintedItem) + +public: + QDeclarativeImplicitSizePaintedItemPrivate() + { + } + + virtual void implicitWidthChanged(); + virtual void implicitHeightChanged(); +}; + +QT_END_NAMESPACE + +#endif // QDECLARATIVEIMPLICITSIZEITEM_P_H diff --git a/src/declarative/graphicsitems/qdeclarativeitem.cpp b/src/declarative/graphicsitems/qdeclarativeitem.cpp index 00e06be..afa1b72 100644 --- a/src/declarative/graphicsitems/qdeclarativeitem.cpp +++ b/src/declarative/graphicsitems/qdeclarativeitem.cpp @@ -3056,13 +3056,24 @@ void QDeclarativeItemPrivate::resetWidth() q->setImplicitWidth(q->implicitWidth()); } +void QDeclarativeItemPrivate::implicitWidthChanged() +{ + Q_Q(QDeclarativeItem); + emit q->implicitWidthChanged(); +} + +qreal QDeclarativeItemPrivate::implicitWidth() const +{ + return mImplicitWidth; +} + /*! Returns the width of the item that is implied by other properties that determine the content. */ qreal QDeclarativeItem::implicitWidth() const { Q_D(const QDeclarativeItem); - return d->implicitWidth; + return d->implicitWidth(); } /*! @@ -3072,9 +3083,13 @@ qreal QDeclarativeItem::implicitWidth() const void QDeclarativeItem::setImplicitWidth(qreal w) { Q_D(QDeclarativeItem); - d->implicitWidth = w; - if (d->mWidth == w || widthValid()) + bool changed = w != d->mImplicitWidth; + d->mImplicitWidth = w; + if (d->mWidth == w || widthValid()) { + if (changed) + d->implicitWidthChanged(); return; + } qreal oldWidth = d->mWidth; @@ -3083,6 +3098,9 @@ void QDeclarativeItem::setImplicitWidth(qreal w) geometryChanged(QRectF(x(), y(), width(), height()), QRectF(x(), y(), oldWidth, height())); + + if (changed) + d->implicitWidthChanged(); } /*! @@ -3164,25 +3182,77 @@ void QDeclarativeItemPrivate::resetHeight() q->setImplicitHeight(q->implicitHeight()); } +void QDeclarativeItemPrivate::implicitHeightChanged() +{ + Q_Q(QDeclarativeItem); + emit q->implicitHeightChanged(); +} + +qreal QDeclarativeItemPrivate::implicitHeight() const +{ + return mImplicitHeight; +} + /*! Returns the height of the item that is implied by other properties that determine the content. */ qreal QDeclarativeItem::implicitHeight() const { Q_D(const QDeclarativeItem); - return d->implicitHeight; + return d->implicitHeight(); } /*! + \qmlproperty real Item::implicitWidth + \qmlproperty real Item::implicitHeight + \since Quick 1.1 + + Defines the natural width or height of the Item if no \l width or \l height is specified. + + The default implicit size for most items is 0x0, however some elements have an inherent + implicit size which cannot be overridden, e.g. Image, Text. + + Setting the implicit size is useful for defining components that have a preferred size + based on their content, for example: + + \code + // Label.qml + import QtQuick 1.1 + + Item { + property alias icon: image.source + property alias label: text.text + implicitWidth: text.implicitWidth + image.implicitWidth + implicitHeight: Math.max(text.implicitHeight, image.implicitHeight) + Image { id: image } + Text { + id: text + wrapMode: Text.Wrap + anchors.left: image.right; anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + } + } + \endcode + + \bold Note: using implicitWidth of Text or TextEdit and setting the width explicitly + incurs a performance penalty as the text must be layed out twice. +*/ + + +/*! Sets the implied height of the item to \a h. This is the height implied by other properties that determine the content. */ void QDeclarativeItem::setImplicitHeight(qreal h) { Q_D(QDeclarativeItem); - d->implicitHeight = h; - if (d->mHeight == h || heightValid()) + bool changed = h != d->mImplicitHeight; + d->mImplicitHeight = h; + if (d->mHeight == h || heightValid()) { + if (changed) + d->implicitHeightChanged(); return; + } qreal oldHeight = d->mHeight; @@ -3191,6 +3261,9 @@ void QDeclarativeItem::setImplicitHeight(qreal h) geometryChanged(QRectF(x(), y(), width(), height()), QRectF(x(), y(), width(), oldHeight)); + + if (changed) + d->implicitHeightChanged(); } /*! diff --git a/src/declarative/graphicsitems/qdeclarativeitem.h b/src/declarative/graphicsitems/qdeclarativeitem.h index 0dd3937..839b934 100644 --- a/src/declarative/graphicsitems/qdeclarativeitem.h +++ b/src/declarative/graphicsitems/qdeclarativeitem.h @@ -92,6 +92,9 @@ class Q_DECLARATIVE_EXPORT QDeclarativeItem : public QGraphicsObject, public QDe Q_PROPERTY(TransformOrigin transformOrigin READ transformOrigin WRITE setTransformOrigin NOTIFY transformOriginChanged) Q_PROPERTY(QPointF transformOriginPoint READ transformOriginPoint) // transformOriginPoint is read-only for Item Q_PROPERTY(bool smooth READ smooth WRITE setSmooth NOTIFY smoothChanged) + Q_PROPERTY(qreal implicitWidth READ implicitWidth WRITE setImplicitWidth NOTIFY implicitWidthChanged REVISION 1) + Q_PROPERTY(qreal implicitHeight READ implicitHeight WRITE setImplicitHeight NOTIFY implicitHeightChanged REVISION 1) + Q_ENUMS(TransformOrigin) Q_CLASSINFO("DefaultProperty", "data") @@ -161,6 +164,8 @@ Q_SIGNALS: void transformOriginChanged(TransformOrigin); void smoothChanged(bool); void clipChanged(bool); + Q_REVISION(1) void implicitWidthChanged(); + Q_REVISION(1) void implicitHeightChanged(); protected: bool isComponentComplete() const; diff --git a/src/declarative/graphicsitems/qdeclarativeitem_p.h b/src/declarative/graphicsitems/qdeclarativeitem_p.h index fd9c736..4303c0a 100644 --- a/src/declarative/graphicsitems/qdeclarativeitem_p.h +++ b/src/declarative/graphicsitems/qdeclarativeitem_p.h @@ -126,7 +126,7 @@ public: widthValid(false), heightValid(false), componentComplete(true), keepMouse(false), smooth(false), transformOriginDirty(true), doneEventPreHandler(false), keyHandler(0), - mWidth(0), mHeight(0), implicitWidth(0), implicitHeight(0), hadSubFocusItem(false) + mWidth(0), mHeight(0), mImplicitWidth(0), mImplicitHeight(0), hadSubFocusItem(false) { QGraphicsItemPrivate::acceptedMouseButtons = 0; isDeclarativeItem = 1; @@ -157,6 +157,11 @@ public: void setHeight(qreal); void resetHeight(); + virtual qreal implicitWidth() const; + virtual qreal implicitHeight() const; + virtual void implicitWidthChanged(); + virtual void implicitHeightChanged(); + QDeclarativeListProperty data(); QDeclarativeListProperty resources(); @@ -272,8 +277,8 @@ public: qreal mWidth; qreal mHeight; - qreal implicitWidth; - qreal implicitHeight; + qreal mImplicitWidth; + qreal mImplicitHeight; bool hadSubFocusItem; diff --git a/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp b/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp index 32c71dd..3395397 100644 --- a/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp +++ b/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp @@ -179,6 +179,7 @@ void QDeclarativeItemModule::defineModule() qmlRegisterType("QtQuick",1,1,"PinchArea"); qmlRegisterType("QtQuick",1,1,"Pinch"); qmlRegisterType(); + qmlRegisterType("QtQuick",1,1,"Item"); qmlRegisterType("QtQuick",1,1,"Flickable"); qmlRegisterType("QtQuick",1,1,"ListView"); qmlRegisterType("QtQuick",1,1,"GridView"); @@ -190,6 +191,10 @@ void QDeclarativeItemModule::defineModule() #ifndef QT_NO_LINEEDIT qmlRegisterType("QtQuick",1,1,"TextInput"); #endif + qmlRegisterRevision("QtQuick",1,0); + qmlRegisterRevision("QtQuick",1,1); + qmlRegisterRevision("QtQuick",1,0); + qmlRegisterRevision("QtQuick",1,1); #ifndef QT_NO_IMPORT_QT47_QML #ifdef QT_NO_MOVIE diff --git a/src/declarative/graphicsitems/qdeclarativeloader.cpp b/src/declarative/graphicsitems/qdeclarativeloader.cpp index 86e438f..86d6404 100644 --- a/src/declarative/graphicsitems/qdeclarativeloader.cpp +++ b/src/declarative/graphicsitems/qdeclarativeloader.cpp @@ -216,7 +216,7 @@ void QDeclarativeLoaderPrivate::initResize() */ QDeclarativeLoader::QDeclarativeLoader(QDeclarativeItem *parent) - : QDeclarativeItem(*(new QDeclarativeLoaderPrivate), parent) + : QDeclarativeImplicitSizeItem(*(new QDeclarativeLoaderPrivate), parent) { Q_D(QDeclarativeLoader); d->flags |= QGraphicsItem::ItemIsFocusScope; diff --git a/src/declarative/graphicsitems/qdeclarativeloader_p.h b/src/declarative/graphicsitems/qdeclarativeloader_p.h index 1fe7ae7..96b883c 100644 --- a/src/declarative/graphicsitems/qdeclarativeloader_p.h +++ b/src/declarative/graphicsitems/qdeclarativeloader_p.h @@ -42,7 +42,7 @@ #ifndef QDECLARATIVELOADER_H #define QDECLARATIVELOADER_H -#include "qdeclarativeitem.h" +#include "qdeclarativeimplicitsizeitem_p.h" QT_BEGIN_HEADER @@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) class QDeclarativeLoaderPrivate; -class Q_AUTOTEST_EXPORT QDeclarativeLoader : public QDeclarativeItem +class Q_AUTOTEST_EXPORT QDeclarativeLoader : public QDeclarativeImplicitSizeItem { Q_OBJECT Q_ENUMS(Status) diff --git a/src/declarative/graphicsitems/qdeclarativeloader_p_p.h b/src/declarative/graphicsitems/qdeclarativeloader_p_p.h index 81ca66d..7f1a6da 100644 --- a/src/declarative/graphicsitems/qdeclarativeloader_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativeloader_p_p.h @@ -55,13 +55,13 @@ #include "private/qdeclarativeloader_p.h" -#include "private/qdeclarativeitem_p.h" +#include "private/qdeclarativeimplicitsizeitem_p_p.h" #include "private/qdeclarativeitemchangelistener_p.h" QT_BEGIN_NAMESPACE class QDeclarativeContext; -class QDeclarativeLoaderPrivate : public QDeclarativeItemPrivate, public QDeclarativeItemChangeListener +class QDeclarativeLoaderPrivate : public QDeclarativeImplicitSizeItemPrivate, public QDeclarativeItemChangeListener { Q_DECLARE_PUBLIC(QDeclarativeLoader) diff --git a/src/declarative/graphicsitems/qdeclarativepositioners.cpp b/src/declarative/graphicsitems/qdeclarativepositioners.cpp index a2a167e..9450647 100644 --- a/src/declarative/graphicsitems/qdeclarativepositioners.cpp +++ b/src/declarative/graphicsitems/qdeclarativepositioners.cpp @@ -111,14 +111,14 @@ void QDeclarativeBasePositioner::graphicsWidgetGeometryChanged() Note that the subclass is responsible for adding the spacing in between items. */ QDeclarativeBasePositioner::QDeclarativeBasePositioner(PositionerType at, QDeclarativeItem *parent) - : QDeclarativeItem(*(new QDeclarativeBasePositionerPrivate), parent) + : QDeclarativeImplicitSizeItem(*(new QDeclarativeBasePositionerPrivate), parent) { Q_D(QDeclarativeBasePositioner); d->init(at); } QDeclarativeBasePositioner::QDeclarativeBasePositioner(QDeclarativeBasePositionerPrivate &dd, PositionerType at, QDeclarativeItem *parent) - : QDeclarativeItem(dd, parent) + : QDeclarativeImplicitSizeItem(dd, parent) { Q_D(QDeclarativeBasePositioner); d->init(at); diff --git a/src/declarative/graphicsitems/qdeclarativepositioners_p.h b/src/declarative/graphicsitems/qdeclarativepositioners_p.h index 1306fcd..6b45e49 100644 --- a/src/declarative/graphicsitems/qdeclarativepositioners_p.h +++ b/src/declarative/graphicsitems/qdeclarativepositioners_p.h @@ -42,7 +42,7 @@ #ifndef QDECLARATIVELAYOUTS_H #define QDECLARATIVELAYOUTS_H -#include "qdeclarativeitem.h" +#include "qdeclarativeimplicitsizeitem_p.h" #include #include @@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) class QDeclarativeBasePositionerPrivate; -class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeBasePositioner : public QDeclarativeItem +class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeBasePositioner : public QDeclarativeImplicitSizeItem { Q_OBJECT diff --git a/src/declarative/graphicsitems/qdeclarativepositioners_p_p.h b/src/declarative/graphicsitems/qdeclarativepositioners_p_p.h index c6535a7..df105c6 100644 --- a/src/declarative/graphicsitems/qdeclarativepositioners_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativepositioners_p_p.h @@ -55,7 +55,7 @@ #include "private/qdeclarativepositioners_p.h" -#include "private/qdeclarativeitem_p.h" +#include "private/qdeclarativeimplicitsizeitem_p_p.h" #include #include @@ -67,7 +67,7 @@ #include QT_BEGIN_NAMESPACE -class QDeclarativeBasePositionerPrivate : public QDeclarativeItemPrivate, public QDeclarativeItemChangeListener +class QDeclarativeBasePositionerPrivate : public QDeclarativeImplicitSizeItemPrivate, public QDeclarativeItemChangeListener { Q_DECLARE_PUBLIC(QDeclarativeBasePositioner) diff --git a/src/declarative/graphicsitems/qdeclarativetext.cpp b/src/declarative/graphicsitems/qdeclarativetext.cpp index 64925d0..d424e30 100644 --- a/src/declarative/graphicsitems/qdeclarativetext.cpp +++ b/src/declarative/graphicsitems/qdeclarativetext.cpp @@ -92,7 +92,7 @@ QDeclarativeTextPrivate::QDeclarativeTextPrivate() vAlign(QDeclarativeText::AlignTop), elideMode(QDeclarativeText::ElideNone), format(QDeclarativeText::AutoText), wrapMode(QDeclarativeText::NoWrap), lineCount(1), truncated(false), maximumLineCount(INT_MAX), maximumLineCountValid(false), imageCacheDirty(true), updateOnComponentComplete(true), richText(false), singleline(false), - cacheAllTextAsImage(true), internalWidthUpdate(false), doc(0) + cacheAllTextAsImage(true), internalWidthUpdate(false), requireImplicitWidth(false), naturalWidth(0), doc(0) { cacheAllTextAsImage = enableImageCache(); QGraphicsItemPrivate::acceptedMouseButtons = Qt::LeftButton; @@ -179,6 +179,18 @@ QDeclarativeTextPrivate::~QDeclarativeTextPrivate() { } +qreal QDeclarativeTextPrivate::implicitWidth() const +{ + if (!requireImplicitWidth) { + // We don't calculate implicitWidth unless it is required. + // We need to force a size update now to ensure implicitWidth is calculated + QDeclarativeTextPrivate *me = const_cast(this); + me->requireImplicitWidth = true; + me->updateSize(); + } + return mImplicitWidth; +} + void QDeclarativeTextPrivate::updateLayout() { Q_Q(QDeclarativeText); @@ -222,12 +234,20 @@ void QDeclarativeTextPrivate::updateSize() return; } + if (!requireImplicitWidth) { + emit q->implicitWidthChanged(); + // if the implicitWidth is used, then updateSize() has already been called (recursively) + if (requireImplicitWidth) + return; + } + invalidateImageCache(); QFontMetrics fm(font); if (text.isEmpty()) { q->setImplicitWidth(0); q->setImplicitHeight(fm.height()); + paintedSize = QSize(0, fm.height()); emit q->paintedSizeChanged(); q->update(); return; @@ -251,6 +271,10 @@ void QDeclarativeTextPrivate::updateSize() QTextOption option((Qt::Alignment)int(hAlign | vAlign)); option.setWrapMode(QTextOption::WrapMode(wrapMode)); doc->setDefaultTextOption(option); + if (requireImplicitWidth && q->widthValid()) { + doc->setTextWidth(-1); + naturalWidth = doc->idealWidth(); + } if (wrapMode != QDeclarativeText::NoWrap && q->widthValid()) doc->setTextWidth(q->width()); else @@ -275,10 +299,16 @@ void QDeclarativeTextPrivate::updateSize() //### need to comfirm cost of always setting these for richText internalWidthUpdate = true; - q->setImplicitWidth(size.width()); + if (!q->widthValid()) + q->setImplicitWidth(size.width()); + else if (requireImplicitWidth) + q->setImplicitWidth(naturalWidth); internalWidthUpdate = false; q->setImplicitHeight(size.height()); - emit q->paintedSizeChanged(); + if (paintedSize != size) { + paintedSize = size; + emit q->paintedSizeChanged(); + } q->update(); } @@ -318,6 +348,22 @@ QSize QDeclarativeTextPrivate::setupTextLayout() qreal elideWidth = fm.width(elideChar); elidePos = QPointF(); + if (requireImplicitWidth && q->widthValid()) { + // requires an extra layout + layout.beginLayout(); + forever { + QTextLine line = layout.createLine(); + if (!line.isValid()) + break; + } + layout.endLayout(); + naturalWidth = 0; + for (int i = 0; i < layout.lineCount(); ++i) { + QTextLine line = layout.lineAt(i); + naturalWidth = qMax(naturalWidth, line.naturalTextWidth()); + } + } + if (maximumLineCountValid) { layout.beginLayout(); int y = 0; @@ -383,6 +429,8 @@ QSize QDeclarativeTextPrivate::setupTextLayout() } qreal layoutWidth = q->widthValid() ? q->width() : widthUsed; + if (!q->widthValid()) + naturalWidth = layoutWidth; qreal x = 0; for (int i = 0; i < layout.lineCount(); ++i) { @@ -660,7 +708,7 @@ QPixmap QDeclarativeTextPrivate::drawOutline(const QPixmap &source, const QPixma \sa {declarative/text/fonts}{Fonts example} */ QDeclarativeText::QDeclarativeText(QDeclarativeItem *parent) - : QDeclarativeItem(*(new QDeclarativeTextPrivate), parent) + : QDeclarativeImplicitSizeItem(*(new QDeclarativeTextPrivate), parent) { } @@ -1331,7 +1379,8 @@ void QDeclarativeText::geometryChanged(const QRectF &newGeometry, const QRectF & */ qreal QDeclarativeText::paintedWidth() const { - return implicitWidth(); + Q_D(const QDeclarativeText); + return d->paintedSize.width(); } /*! @@ -1342,7 +1391,8 @@ qreal QDeclarativeText::paintedWidth() const */ qreal QDeclarativeText::paintedHeight() const { - return implicitHeight(); + Q_D(const QDeclarativeText); + return d->paintedSize.height(); } /*! diff --git a/src/declarative/graphicsitems/qdeclarativetext_p.h b/src/declarative/graphicsitems/qdeclarativetext_p.h index 6468a77..ec33b84 100644 --- a/src/declarative/graphicsitems/qdeclarativetext_p.h +++ b/src/declarative/graphicsitems/qdeclarativetext_p.h @@ -43,7 +43,7 @@ #define QDECLARATIVETEXT_H #include -#include "qdeclarativeitem.h" +#include "qdeclarativeimplicitsizeitem_p.h" #include @@ -53,7 +53,7 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) class QDeclarativeTextPrivate; -class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeText : public QDeclarativeItem +class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeText : public QDeclarativeImplicitSizeItem { Q_OBJECT Q_ENUMS(HAlignment) diff --git a/src/declarative/graphicsitems/qdeclarativetext_p_p.h b/src/declarative/graphicsitems/qdeclarativetext_p_p.h index fe2b042..bae2d85 100644 --- a/src/declarative/graphicsitems/qdeclarativetext_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativetext_p_p.h @@ -54,7 +54,7 @@ // #include "qdeclarativeitem.h" -#include "private/qdeclarativeitem_p.h" +#include "private/qdeclarativeimplicitsizeitem_p_p.h" #include "private/qdeclarativetextlayout_p.h" #include @@ -66,7 +66,7 @@ QT_BEGIN_NAMESPACE class QTextLayout; class QTextDocumentWithImageResources; -class QDeclarativeTextPrivate : public QDeclarativeItemPrivate +class QDeclarativeTextPrivate : public QDeclarativeImplicitSizeItemPrivate { Q_DECLARE_PUBLIC(QDeclarativeText) public: @@ -107,9 +107,12 @@ public: bool singleline:1; bool cacheAllTextAsImage:1; bool internalWidthUpdate:1; + bool requireImplicitWidth:1; QSize layedOutTextSize; - + QSize paintedSize; + qreal naturalWidth; + virtual qreal implicitWidth() const; void ensureDoc(); QPixmap textDocumentImage(bool drawStyle); QTextDocumentWithImageResources *doc; diff --git a/src/declarative/graphicsitems/qdeclarativetextedit.cpp b/src/declarative/graphicsitems/qdeclarativetextedit.cpp index 280c8c3..959d655 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextedit.cpp @@ -113,7 +113,7 @@ TextEdit { \a link string provides access to the particular link. */ QDeclarativeTextEdit::QDeclarativeTextEdit(QDeclarativeItem *parent) -: QDeclarativePaintedItem(*(new QDeclarativeTextEditPrivate), parent) +: QDeclarativeImplicitSizePaintedItem(*(new QDeclarativeTextEditPrivate), parent) { Q_D(QDeclarativeTextEdit); d->init(); @@ -559,7 +559,8 @@ int QDeclarativeTextEdit::lineCount() const */ qreal QDeclarativeTextEdit::paintedWidth() const { - return implicitWidth(); + Q_D(const QDeclarativeTextEdit); + return d->paintedSize.width(); } /*! @@ -570,7 +571,8 @@ qreal QDeclarativeTextEdit::paintedWidth() const */ qreal QDeclarativeTextEdit::paintedHeight() const { - return implicitHeight(); + Q_D(const QDeclarativeTextEdit); + return d->paintedSize.height(); } /*! @@ -1482,6 +1484,17 @@ QRectF QDeclarativeTextEdit::boundingRect() const return r.translated(0,d->yoff); } +qreal QDeclarativeTextEditPrivate::implicitWidth() const +{ + Q_Q(const QDeclarativeTextEdit); + if (!requireImplicitWidth) { + // We don't calculate implicitWidth unless it is required. + // We need to force a size update now to ensure implicitWidth is calculated + const_cast(this)->requireImplicitWidth = true; + const_cast(q)->updateSize(); + } + return mImplicitWidth; +} //### we should perhaps be a bit smarter here -- depending on what has changed, we shouldn't // need to do all the calculations each time @@ -1489,16 +1502,27 @@ void QDeclarativeTextEdit::updateSize() { Q_D(QDeclarativeTextEdit); if (isComponentComplete()) { - QFontMetrics fm = QFontMetrics(d->font); - int dy = height(); + qreal naturalWidth = d->mImplicitWidth; // ### assumes that if the width is set, the text will fill to edges // ### (unless wrap is false, then clipping will occur) if (widthValid()) { + if (!d->requireImplicitWidth) { + emit implicitWidthChanged(); + // if the implicitWidth is used, then updateSize() has already been called (recursively) + if (d->requireImplicitWidth) + return; + } + if (d->requireImplicitWidth) { + d->document->setTextWidth(-1); + naturalWidth = d->document->idealWidth(); + } if (d->document->textWidth() != width()) d->document->setTextWidth(width()); } else { d->document->setTextWidth(-1); } + QFontMetrics fm = QFontMetrics(d->font); + int dy = height(); dy -= (int)d->document->size().height(); int nyoff; @@ -1523,12 +1547,15 @@ void QDeclarativeTextEdit::updateSize() if (!widthValid() && d->document->textWidth() != newWidth) d->document->setTextWidth(newWidth); // ### Text does not align if width is not set (QTextDoc bug) // ### Setting the implicitWidth triggers another updateSize(), and unless there are bindings nothing has changed. - setImplicitWidth(newWidth); + if (!widthValid()) + setImplicitWidth(newWidth); + else if (d->requireImplicitWidth) + setImplicitWidth(naturalWidth); qreal newHeight = d->document->isEmpty() ? fm.height() : (int)d->document->size().height(); setImplicitHeight(newHeight); - setContentsSize(QSize(newWidth, newHeight)); - + d->paintedSize = QSize(newWidth, newHeight); + setContentsSize(d->paintedSize); emit paintedSizeChanged(); } else { d->dirty = true; diff --git a/src/declarative/graphicsitems/qdeclarativetextedit_p.h b/src/declarative/graphicsitems/qdeclarativetextedit_p.h index c534623..276d570 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextedit_p.h @@ -43,7 +43,7 @@ #define QDECLARATIVETEXTEDIT_H #include "private/qdeclarativetext_p.h" -#include "private/qdeclarativepainteditem_p.h" +#include "private/qdeclarativeimplicitsizeitem_p.h" #include #include @@ -58,7 +58,7 @@ QT_MODULE(Declarative) class QDeclarativeTextEditPrivate; -class Q_AUTOTEST_EXPORT QDeclarativeTextEdit : public QDeclarativePaintedItem +class Q_AUTOTEST_EXPORT QDeclarativeTextEdit : public QDeclarativeImplicitSizePaintedItem { Q_OBJECT Q_ENUMS(VAlignment) diff --git a/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h b/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h index 13fee50..98b3c6d 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h @@ -54,7 +54,7 @@ // #include "qdeclarativeitem.h" -#include "private/qdeclarativepainteditem_p_p.h" +#include "private/qdeclarativeimplicitsizeitem_p_p.h" #include @@ -62,7 +62,7 @@ QT_BEGIN_NAMESPACE class QTextLayout; class QTextDocument; class QTextControl; -class QDeclarativeTextEditPrivate : public QDeclarativePaintedItemPrivate +class QDeclarativeTextEditPrivate : public QDeclarativeImplicitSizePaintedItemPrivate { Q_DECLARE_PUBLIC(QDeclarativeTextEdit) @@ -70,8 +70,8 @@ public: QDeclarativeTextEditPrivate() : color("black"), hAlign(QDeclarativeTextEdit::AlignLeft), vAlign(QDeclarativeTextEdit::AlignTop), imgDirty(true), dirty(false), richText(false), cursorVisible(false), focusOnPress(true), - showInputPanelOnFocus(true), clickCausedFocus(false), persistentSelection(true), textMargin(0.0), - lastSelectionStart(0), lastSelectionEnd(0), cursorComponent(0), cursor(0), + showInputPanelOnFocus(true), clickCausedFocus(false), persistentSelection(true), requireImplicitWidth(false), + textMargin(0.0), lastSelectionStart(0), lastSelectionEnd(0), cursorComponent(0), cursor(0), format(QDeclarativeTextEdit::AutoText), document(0), wrapMode(QDeclarativeTextEdit::NoWrap), selectByMouse(false), canPaste(false), yoff(0) @@ -88,6 +88,7 @@ public: void updateDefaultTextOption(); void relayoutDocument(); void updateSelection(); + qreal implicitWidth() const; void focusChanged(bool); QString text; @@ -110,6 +111,7 @@ public: bool showInputPanelOnFocus : 1; bool clickCausedFocus : 1; bool persistentSelection : 1; + bool requireImplicitWidth:1; qreal textMargin; int lastSelectionStart; int lastSelectionEnd; @@ -123,6 +125,7 @@ public: bool selectByMouse; bool canPaste; int yoff; + QSize paintedSize; }; QT_END_NAMESPACE diff --git a/src/declarative/graphicsitems/qdeclarativetextinput.cpp b/src/declarative/graphicsitems/qdeclarativetextinput.cpp index bd961f6..911c68c 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextinput.cpp @@ -76,7 +76,7 @@ QT_BEGIN_NAMESPACE \sa TextEdit, Text, {declarative/text/textselection}{Text Selection example} */ QDeclarativeTextInput::QDeclarativeTextInput(QDeclarativeItem* parent) - : QDeclarativePaintedItem(*(new QDeclarativeTextInputPrivate), parent) + : QDeclarativeImplicitSizePaintedItem(*(new QDeclarativeTextInputPrivate), parent) { Q_D(QDeclarativeTextInput); d->init(); diff --git a/src/declarative/graphicsitems/qdeclarativetextinput_p.h b/src/declarative/graphicsitems/qdeclarativetextinput_p.h index 7406fee..543f7a8 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextinput_p.h @@ -43,7 +43,7 @@ #define QDECLARATIVETEXTINPUT_H #include "private/qdeclarativetext_p.h" -#include "private/qdeclarativepainteditem_p.h" +#include "private/qdeclarativeimplicitsizeitem_p.h" #include #include @@ -58,7 +58,7 @@ QT_MODULE(Declarative) class QDeclarativeTextInputPrivate; class QValidator; -class Q_AUTOTEST_EXPORT QDeclarativeTextInput : public QDeclarativePaintedItem +class Q_AUTOTEST_EXPORT QDeclarativeTextInput : public QDeclarativeImplicitSizePaintedItem { Q_OBJECT Q_ENUMS(HAlignment) diff --git a/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h b/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h index 22f452a..9644410 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h @@ -44,7 +44,7 @@ #include "private/qdeclarativetextinput_p.h" -#include "private/qdeclarativepainteditem_p_p.h" +#include "private/qdeclarativeimplicitsizeitem_p_p.h" #include @@ -66,7 +66,7 @@ QT_BEGIN_NAMESPACE -class QDeclarativeTextInputPrivate : public QDeclarativePaintedItemPrivate +class QDeclarativeTextInputPrivate : public QDeclarativeImplicitSizePaintedItemPrivate { Q_DECLARE_PUBLIC(QDeclarativeTextInput) public: diff --git a/tests/auto/declarative/qdeclarativeitem/tst_qdeclarativeitem.cpp b/tests/auto/declarative/qdeclarativeitem/tst_qdeclarativeitem.cpp index dbed799..e636383 100644 --- a/tests/auto/declarative/qdeclarativeitem/tst_qdeclarativeitem.cpp +++ b/tests/auto/declarative/qdeclarativeitem/tst_qdeclarativeitem.cpp @@ -83,6 +83,9 @@ private slots: void mouseFocus(); void transformCrash(); + void implicitSize(); + void testQtQuick11Attributes(); + void testQtQuick11Attributes_data(); private: template @@ -915,6 +918,83 @@ void tst_QDeclarativeItem::transformCrash() delete canvas; } +void tst_QDeclarativeItem::implicitSize() +{ + QDeclarativeView *canvas = new QDeclarativeView(0); + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/implicitsize.qml")); + canvas->show(); + + QDeclarativeItem *item = qobject_cast(canvas->rootObject()); + QVERIFY(item); + QCOMPARE(item->width(), qreal(80)); + QCOMPARE(item->height(), qreal(60)); + + QCOMPARE(item->implicitWidth(), qreal(200)); + QCOMPARE(item->implicitHeight(), qreal(100)); + + QMetaObject::invokeMethod(item, "resetSize"); + + QCOMPARE(item->width(), qreal(200)); + QCOMPARE(item->height(), qreal(100)); + + QMetaObject::invokeMethod(item, "changeImplicit"); + + QCOMPARE(item->implicitWidth(), qreal(150)); + QCOMPARE(item->implicitHeight(), qreal(80)); + QCOMPARE(item->width(), qreal(150)); + QCOMPARE(item->height(), qreal(80)); + + delete canvas; +} + +void tst_QDeclarativeItem::testQtQuick11Attributes() +{ + QFETCH(QString, code); + QFETCH(QString, warning); + QFETCH(QString, error); + + QDeclarativeEngine engine; + QObject *obj; + + QDeclarativeComponent valid(&engine); + valid.setData("import QtQuick 1.1; Item { " + code.toUtf8() + " }", QUrl("")); + obj = valid.create(); + QVERIFY(obj); + QVERIFY(valid.errorString().isEmpty()); + delete obj; + + QDeclarativeComponent invalid(&engine); + invalid.setData("import QtQuick 1.0; Item { " + code.toUtf8() + " }", QUrl("")); + QTest::ignoreMessage(QtWarningMsg, warning.toUtf8()); + obj = invalid.create(); + QCOMPARE(invalid.errorString(), error); + delete obj; +} + +void tst_QDeclarativeItem::testQtQuick11Attributes_data() +{ + QTest::addColumn("code"); + QTest::addColumn("warning"); + QTest::addColumn("error"); + + QTest::newRow("implicitWidth") << "implicitWidth: 100" + << "QDeclarativeComponent: Component is not ready" + << ":1 Property \"implicitWidth\" not available in QtQuick/Item 1.0\n"; + + QTest::newRow("implicitHeight") << "implicitHeight: 100" + << "QDeclarativeComponent: Component is not ready" + << ":1 Property \"implicitHeight\" not available in QtQuick/Item 1.0\n"; + + QTest::newRow("onImplicitWidthChanged") << "onImplicitWidthChanged: x" + << "QDeclarativeComponent: Component is not ready" + << ":1 Signal \"onImplicitWidthChanged\" not available in QtQuick/Item 1.0\n"; + + QTest::newRow("onImplicitHeightChanged") << "onImplicitHeightChanged: x" + << "QDeclarativeComponent: Component is not ready" + << ":1 Signal \"onImplicitHeightChanged\" not available in QtQuick/Item 1.0\n"; +} + + template T *tst_QDeclarativeItem::findItem(QGraphicsObject *parent, const QString &objectName) { diff --git a/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp b/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp index ae521a5..faea448 100644 --- a/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp +++ b/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp @@ -101,6 +101,8 @@ private slots: void clickLink(); void QTBUG_12291(); + void implicitSize_data(); + void implicitSize(); private: QStringList standard; @@ -1050,6 +1052,33 @@ void tst_qdeclarativetext::lineCount() QCOMPARE(myText->maximumLineCount(), 2); } +void tst_qdeclarativetext::implicitSize_data() +{ + QTest::addColumn("text"); + QTest::addColumn("wrap"); + QTest::newRow("plain") << "The quick red fox jumped over the lazy brown dog" << "Text.NoWrap"; + QTest::newRow("richtext") << "The quick red fox jumped over the lazy brown dog" << "Text.NoWrap"; + QTest::newRow("plain_wrap") << "The quick red fox jumped over the lazy brown dog" << "Text.Wrap"; + QTest::newRow("richtext_wrap") << "The quick red fox jumped over the lazy brown dog" << "Text.Wrap"; +} + +void tst_qdeclarativetext::implicitSize() +{ + QFETCH(QString, text); + QFETCH(QString, wrap); + QString componentStr = "import QtQuick 1.1\nText { text: \"" + text + "\"; width: 50; wrapMode: " + wrap + " }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QDeclarativeText *textObject = qobject_cast(textComponent.create()); + + QVERIFY(textObject->width() < textObject->implicitWidth()); + QVERIFY(textObject->height() == textObject->implicitHeight()); + + textObject->resetWidth(); + QVERIFY(textObject->width() == textObject->implicitWidth()); + QVERIFY(textObject->height() == textObject->implicitHeight()); +} + QTEST_MAIN(tst_qdeclarativetext) #include "tst_qdeclarativetext.moc" diff --git a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp index 89e8fec..582b20f 100644 --- a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp +++ b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp @@ -127,6 +127,8 @@ private slots: void openInputPanelOnFocus(); void geometrySignals(); void pastingRichText_QTBUG_14003(); + void implicitSize_data(); + void implicitSize(); private: void simulateKey(QDeclarativeView *, int key); @@ -1447,6 +1449,33 @@ void tst_qdeclarativetextedit::pastingRichText_QTBUG_14003() #endif } +void tst_qdeclarativetextedit::implicitSize_data() +{ + QTest::addColumn("text"); + QTest::addColumn("wrap"); + QTest::newRow("plain") << "The quick red fox jumped over the lazy brown dog" << "TextEdit.NoWrap"; + QTest::newRow("richtext") << "The quick red fox jumped over the lazy brown dog" << "TextEdit.NoWrap"; + QTest::newRow("plain_wrap") << "The quick red fox jumped over the lazy brown dog" << "TextEdit.Wrap"; + QTest::newRow("richtext_wrap") << "The quick red fox jumped over the lazy brown dog" << "TextEdit.Wrap"; +} + +void tst_qdeclarativetextedit::implicitSize() +{ + QFETCH(QString, text); + QFETCH(QString, wrap); + QString componentStr = "import QtQuick 1.1\nTextEdit { text: \"" + text + "\"; width: 50; wrapMode: " + wrap + " }"; + QDeclarativeComponent textComponent(&engine); + textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QDeclarativeTextEdit *textObject = qobject_cast(textComponent.create()); + + QVERIFY(textObject->width() < textObject->implicitWidth()); + QVERIFY(textObject->height() == textObject->implicitHeight()); + + textObject->resetWidth(); + QVERIFY(textObject->width() == textObject->implicitWidth()); + QVERIFY(textObject->height() == textObject->implicitHeight()); +} + QTEST_MAIN(tst_qdeclarativetextedit) #include "tst_qdeclarativetextedit.moc" -- cgit v0.12 From 1aea31ebfdd9a6893b2d88b69f34de0b1456b2e4 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Mon, 24 Jan 2011 14:08:23 +1000 Subject: Fix copy-paste error in QDeclarativeMouseArea::hoverMoveEvent. Reviewed-by: Martin Jones --- src/declarative/graphicsitems/qdeclarativemousearea.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/declarative/graphicsitems/qdeclarativemousearea.cpp b/src/declarative/graphicsitems/qdeclarativemousearea.cpp index 4b555d0..82125f7 100644 --- a/src/declarative/graphicsitems/qdeclarativemousearea.cpp +++ b/src/declarative/graphicsitems/qdeclarativemousearea.cpp @@ -591,7 +591,7 @@ void QDeclarativeMouseArea::hoverMoveEvent(QGraphicsSceneHoverEvent *event) { Q_D(QDeclarativeMouseArea); if (!d->absorb) { - QDeclarativeItem::hoverEnterEvent(event); + QDeclarativeItem::hoverMoveEvent(event); } else { d->lastPos = event->pos(); QDeclarativeMouseEvent me(d->lastPos.x(), d->lastPos.y(), Qt::NoButton, d->lastButtons, d->lastModifiers, false, d->longPress); -- cgit v0.12 From 4768e23056691ee14a91e1f2cf258e8f51847aaf Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Mon, 24 Jan 2011 16:05:17 +1000 Subject: Improve information reported for MouseArea hover events. Reviewed-by: Martin Jones --- src/declarative/graphicsitems/qdeclarativemousearea.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativemousearea.cpp b/src/declarative/graphicsitems/qdeclarativemousearea.cpp index 82125f7..ee6765c 100644 --- a/src/declarative/graphicsitems/qdeclarativemousearea.cpp +++ b/src/declarative/graphicsitems/qdeclarativemousearea.cpp @@ -583,8 +583,12 @@ void QDeclarativeMouseArea::hoverEnterEvent(QGraphicsSceneHoverEvent *event) Q_D(QDeclarativeMouseArea); if (!d->absorb) QDeclarativeItem::hoverEnterEvent(event); - else + else { + d->lastPos = event->pos(); setHovered(true); + QDeclarativeMouseEvent me(d->lastPos.x(), d->lastPos.y(), Qt::NoButton, Qt::NoButton, event->modifiers(), false, false); + emit mousePositionChanged(&me); + } } void QDeclarativeMouseArea::hoverMoveEvent(QGraphicsSceneHoverEvent *event) @@ -594,7 +598,7 @@ void QDeclarativeMouseArea::hoverMoveEvent(QGraphicsSceneHoverEvent *event) QDeclarativeItem::hoverMoveEvent(event); } else { d->lastPos = event->pos(); - QDeclarativeMouseEvent me(d->lastPos.x(), d->lastPos.y(), Qt::NoButton, d->lastButtons, d->lastModifiers, false, d->longPress); + QDeclarativeMouseEvent me(d->lastPos.x(), d->lastPos.y(), Qt::NoButton, Qt::NoButton, event->modifiers(), false, false); emit mousePositionChanged(&me); me.setX(d->lastPos.x()); me.setY(d->lastPos.y()); -- cgit v0.12 From b36859acae472916c35ac31174c8230543d900ab Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Tue, 25 Jan 2011 09:30:45 +1000 Subject: Notify that pressed has changed before calling the onClicked handler. This is a more natural ordering, and makes it trivial to control different state groups with pressed and onClicked. Reviewed-by: Martin Jones --- .../graphicsitems/qdeclarativemousearea.cpp | 3 +- .../qdeclarativemousearea/data/pressedOrdering.qml | 28 +++++++++++++++++ .../tst_qdeclarativemousearea.cpp | 35 ++++++++++++++++++++++ 3 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 tests/auto/declarative/qdeclarativemousearea/data/pressedOrdering.qml diff --git a/src/declarative/graphicsitems/qdeclarativemousearea.cpp b/src/declarative/graphicsitems/qdeclarativemousearea.cpp index ee6765c..273fc53 100644 --- a/src/declarative/graphicsitems/qdeclarativemousearea.cpp +++ b/src/declarative/graphicsitems/qdeclarativemousearea.cpp @@ -863,15 +863,16 @@ bool QDeclarativeMouseArea::setPressed(bool p) me.setX(d->lastPos.x()); me.setY(d->lastPos.y()); emit mousePositionChanged(&me); + emit pressedChanged(); } else { emit released(&me); me.setX(d->lastPos.x()); me.setY(d->lastPos.y()); + emit pressedChanged(); if (isclick && !d->longPress && !d->doubleClick) emit clicked(&me); } - emit pressedChanged(); return me.isAccepted(); } return false; diff --git a/tests/auto/declarative/qdeclarativemousearea/data/pressedOrdering.qml b/tests/auto/declarative/qdeclarativemousearea/data/pressedOrdering.qml new file mode 100644 index 0000000..4a80e83 --- /dev/null +++ b/tests/auto/declarative/qdeclarativemousearea/data/pressedOrdering.qml @@ -0,0 +1,28 @@ +import QtQuick 1.0 + +Item { + id: root + property string value: "base" + + MouseArea { + id: mouseArea + width: 200; height: 200 + onClicked: toggleState.state = "toggled" + } + + StateGroup { + states: State { + name: "pressed" + when: mouseArea.pressed + PropertyChanges { target: root; value: "pressed" } + } + } + + StateGroup { + id: toggleState + states: State { + name: "toggled" + PropertyChanges { target: root; value: "toggled" } + } + } +} diff --git a/tests/auto/declarative/qdeclarativemousearea/tst_qdeclarativemousearea.cpp b/tests/auto/declarative/qdeclarativemousearea/tst_qdeclarativemousearea.cpp index 9d7cc05..845d6bb 100644 --- a/tests/auto/declarative/qdeclarativemousearea/tst_qdeclarativemousearea.cpp +++ b/tests/auto/declarative/qdeclarativemousearea/tst_qdeclarativemousearea.cpp @@ -64,6 +64,7 @@ private slots: void onMousePressRejected(); void doubleClick(); void clickTwice(); + void pressedOrdering(); private: QDeclarativeView *createView(); @@ -477,6 +478,40 @@ void tst_QDeclarativeMouseArea::clickTwice() QCOMPARE(canvas->rootObject()->property("clicked").toInt(), 2); } +void tst_QDeclarativeMouseArea::pressedOrdering() +{ + QDeclarativeView *canvas = createView(); + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/pressedOrdering.qml")); + canvas->show(); + canvas->setFocus(); + QVERIFY(canvas->rootObject() != 0); + + QCOMPARE(canvas->rootObject()->property("value").toString(), QLatin1String("base")); + + QGraphicsScene *scene = canvas->scene(); + QGraphicsSceneMouseEvent pressEvent(QEvent::GraphicsSceneMousePress); + pressEvent.setScenePos(QPointF(100, 100)); + pressEvent.setButton(Qt::LeftButton); + pressEvent.setButtons(Qt::LeftButton); + QApplication::sendEvent(scene, &pressEvent); + + QCOMPARE(canvas->rootObject()->property("value").toString(), QLatin1String("pressed")); + + QGraphicsSceneMouseEvent releaseEvent(QEvent::GraphicsSceneMouseRelease); + releaseEvent.setScenePos(QPointF(100, 100)); + releaseEvent.setButton(Qt::LeftButton); + releaseEvent.setButtons(Qt::LeftButton); + QApplication::sendEvent(scene, &releaseEvent); + + QCOMPARE(canvas->rootObject()->property("value").toString(), QLatin1String("toggled")); + + QApplication::sendEvent(scene, &pressEvent); + + QCOMPARE(canvas->rootObject()->property("value").toString(), QLatin1String("pressed")); + + delete canvas; +} + QTEST_MAIN(tst_QDeclarativeMouseArea) #include "tst_qdeclarativemousearea.moc" -- cgit v0.12 From 1873b12eb8f5175aa852341a7055add77b6fcc80 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Mon, 17 Jan 2011 10:36:45 +1000 Subject: Add "Complete" message for tracing. --- src/declarative/debugger/qdeclarativedebugtrace.cpp | 6 ++++++ src/declarative/debugger/qdeclarativedebugtrace_p.h | 1 + 2 files changed, 7 insertions(+) diff --git a/src/declarative/debugger/qdeclarativedebugtrace.cpp b/src/declarative/debugger/qdeclarativedebugtrace.cpp index cdf0001..9fa1f5b 100644 --- a/src/declarative/debugger/qdeclarativedebugtrace.cpp +++ b/src/declarative/debugger/qdeclarativedebugtrace.cpp @@ -165,6 +165,12 @@ void QDeclarativeDebugTrace::sendMessages() for (int i = 0; i < m_data.count(); ++i) sendMessage(m_data.at(i).toByteArray()); m_data.clear(); + + //indicate completion + QByteArray data; + QDataStream ds(&data, QIODevice::WriteOnly); + ds << (qint64)-1 << (int)Complete; + sendMessage(data); } } diff --git a/src/declarative/debugger/qdeclarativedebugtrace_p.h b/src/declarative/debugger/qdeclarativedebugtrace_p.h index 008c59e..39268fe 100644 --- a/src/declarative/debugger/qdeclarativedebugtrace_p.h +++ b/src/declarative/debugger/qdeclarativedebugtrace_p.h @@ -70,6 +70,7 @@ public: RangeStart, RangeData, RangeEnd, + Complete, MaximumMessage }; -- cgit v0.12 From d7a95474fad9d5ddcc9c9a7473a49644c03e0f7a Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Fri, 21 Jan 2011 13:48:36 +1000 Subject: Add location information for tracing. --- .../debugger/qdeclarativedebugtrace.cpp | 42 +++++++++++++++++++--- .../debugger/qdeclarativedebugtrace_p.h | 12 +++++-- src/declarative/qml/qdeclarativebinding.cpp | 1 + src/declarative/qml/qdeclarativeboundsignal.cpp | 10 ++++-- src/declarative/qml/qdeclarativeengine.cpp | 10 ++++-- 5 files changed, 63 insertions(+), 12 deletions(-) diff --git a/src/declarative/debugger/qdeclarativedebugtrace.cpp b/src/declarative/debugger/qdeclarativedebugtrace.cpp index 9fa1f5b..4bad405 100644 --- a/src/declarative/debugger/qdeclarativedebugtrace.cpp +++ b/src/declarative/debugger/qdeclarativedebugtrace.cpp @@ -58,6 +58,8 @@ QByteArray QDeclarativeDebugData::toByteArray() const ds << time << messageType << detailType; if (messageType == (int)QDeclarativeDebugTrace::RangeData) ds << detailData; + if (messageType == (int)QDeclarativeDebugTrace::RangeLocation) + ds << detailData << line; return data; } @@ -92,6 +94,18 @@ void QDeclarativeDebugTrace::rangeData(RangeType t, const QUrl &data) traceInstance()->rangeDataImpl(t, data); } +void QDeclarativeDebugTrace::rangeLocation(RangeType t, const QString &fileName, int line) +{ + if (QDeclarativeDebugService::isDebuggingEnabled()) + traceInstance()->rangeLocationImpl(t, fileName, line); +} + +void QDeclarativeDebugTrace::rangeLocation(RangeType t, const QUrl &fileName, int line) +{ + if (QDeclarativeDebugService::isDebuggingEnabled()) + traceInstance()->rangeLocationImpl(t, fileName, line); +} + void QDeclarativeDebugTrace::endRange(RangeType t) { if (QDeclarativeDebugService::isDebuggingEnabled()) @@ -103,7 +117,7 @@ void QDeclarativeDebugTrace::addEventImpl(EventType event) if (status() != Enabled || !m_enabled) return; - QDeclarativeDebugData ed = {m_timer.elapsed(), (int)Event, (int)event, QString()}; + QDeclarativeDebugData ed = {m_timer.elapsed(), (int)Event, (int)event, QString(), -1}; processMessage(ed); } @@ -112,7 +126,7 @@ void QDeclarativeDebugTrace::startRangeImpl(RangeType range) if (status() != Enabled || !m_enabled) return; - QDeclarativeDebugData rd = {m_timer.elapsed(), (int)RangeStart, (int)range, QString()}; + QDeclarativeDebugData rd = {m_timer.elapsed(), (int)RangeStart, (int)range, QString(), -1}; processMessage(rd); } @@ -121,7 +135,7 @@ void QDeclarativeDebugTrace::rangeDataImpl(RangeType range, const QString &rData if (status() != Enabled || !m_enabled) return; - QDeclarativeDebugData rd = {m_timer.elapsed(), (int)RangeData, (int)range, rData}; + QDeclarativeDebugData rd = {m_timer.elapsed(), (int)RangeData, (int)range, rData, -1}; processMessage(rd); } @@ -130,7 +144,25 @@ void QDeclarativeDebugTrace::rangeDataImpl(RangeType range, const QUrl &rData) if (status() != Enabled || !m_enabled) return; - QDeclarativeDebugData rd = {m_timer.elapsed(), (int)RangeData, (int)range, rData.toEncoded(QUrl::FormattingOption(0x100))}; + QDeclarativeDebugData rd = {m_timer.elapsed(), (int)RangeData, (int)range, rData.toEncoded(QUrl::FormattingOption(0x100)), -1}; + processMessage(rd); +} + +void QDeclarativeDebugTrace::rangeLocationImpl(RangeType range, const QString &fileName, int line) +{ + if (status() != Enabled || !m_enabled) + return; + + QDeclarativeDebugData rd = {m_timer.elapsed(), (int)RangeLocation, (int)range, fileName, line}; + processMessage(rd); +} + +void QDeclarativeDebugTrace::rangeLocationImpl(RangeType range, const QUrl &fileName, int line) +{ + if (status() != Enabled || !m_enabled) + return; + + QDeclarativeDebugData rd = {m_timer.elapsed(), (int)RangeLocation, (int)range, fileName.toEncoded(QUrl::FormattingOption(0x100)), line}; processMessage(rd); } @@ -139,7 +171,7 @@ void QDeclarativeDebugTrace::endRangeImpl(RangeType range) if (status() != Enabled || !m_enabled) return; - QDeclarativeDebugData rd = {m_timer.elapsed(), (int)RangeEnd, (int)range, QString()}; + QDeclarativeDebugData rd = {m_timer.elapsed(), (int)RangeEnd, (int)range, QString(), -1}; processMessage(rd); } diff --git a/src/declarative/debugger/qdeclarativedebugtrace_p.h b/src/declarative/debugger/qdeclarativedebugtrace_p.h index 39268fe..ae0653e 100644 --- a/src/declarative/debugger/qdeclarativedebugtrace_p.h +++ b/src/declarative/debugger/qdeclarativedebugtrace_p.h @@ -54,13 +54,14 @@ struct QDeclarativeDebugData qint64 time; int messageType; int detailType; - QString detailData; + + //### + QString detailData; //used by RangeData and RangeLocation + int line; //used by RangeLocation QByteArray toByteArray() const; }; -Q_DECLARE_TYPEINFO(QDeclarativeDebugData,Q_PRIMITIVE_TYPE); - class QUrl; class Q_AUTOTEST_EXPORT QDeclarativeDebugTrace : public QDeclarativeDebugService { @@ -69,6 +70,7 @@ public: Event, RangeStart, RangeData, + RangeLocation, RangeEnd, Complete, @@ -98,6 +100,8 @@ public: static void startRange(RangeType); static void rangeData(RangeType, const QString &); static void rangeData(RangeType, const QUrl &); + static void rangeLocation(RangeType, const QString &, int); + static void rangeLocation(RangeType, const QUrl &, int); static void endRange(RangeType); QDeclarativeDebugTrace(); @@ -108,6 +112,8 @@ private: void startRangeImpl(RangeType); void rangeDataImpl(RangeType, const QString &); void rangeDataImpl(RangeType, const QUrl &); + void rangeLocationImpl(RangeType, const QString &, int); + void rangeLocationImpl(RangeType, const QUrl &, int); void endRangeImpl(RangeType); void processMessage(const QDeclarativeDebugData &); void sendMessages(); diff --git a/src/declarative/qml/qdeclarativebinding.cpp b/src/declarative/qml/qdeclarativebinding.cpp index bd1ac5a..b2d0738 100644 --- a/src/declarative/qml/qdeclarativebinding.cpp +++ b/src/declarative/qml/qdeclarativebinding.cpp @@ -298,6 +298,7 @@ public: { QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Binding); QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::Binding, bind->expression()); + QDeclarativeDebugTrace::rangeLocation(QDeclarativeDebugTrace::Binding, bind->sourceFile(), bind->lineNumber()); } ~QDeclarativeBindingProfiler() diff --git a/src/declarative/qml/qdeclarativeboundsignal.cpp b/src/declarative/qml/qdeclarativeboundsignal.cpp index 9b7e570..d5c9bfc 100644 --- a/src/declarative/qml/qdeclarativeboundsignal.cpp +++ b/src/declarative/qml/qdeclarativeboundsignal.cpp @@ -51,6 +51,7 @@ #include "private/qdeclarativeglobal_p.h" #include "private/qdeclarativedebugtrace_p.h" +#include #include QT_BEGIN_NAMESPACE @@ -166,8 +167,13 @@ QDeclarativeBoundSignal *QDeclarativeBoundSignal::cast(QObject *o) int QDeclarativeBoundSignal::qt_metacall(QMetaObject::Call c, int id, void **a) { if (c == QMetaObject::InvokeMetaMethod && id == evaluateIdx) { - QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::HandlingSignal); - QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::HandlingSignal, QLatin1String(m_signal.signature()) + QLatin1String(": ") + (m_expression ? m_expression->expression() : QLatin1String(""))); + if (!m_expression) + return -1; + if (QDeclarativeDebugService::isDebuggingEnabled()) { + QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::HandlingSignal); + QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::HandlingSignal, QLatin1String(m_signal.signature()) % QLatin1String(": ") % m_expression->expression()); + QDeclarativeDebugTrace::rangeLocation(QDeclarativeDebugTrace::HandlingSignal, m_expression->sourceFile(), m_expression->lineNumber()); + } m_isEvaluating = true; if (!m_paramsValid) { if (!m_signal.parameterTypes().isEmpty()) diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp index 0f3f20c..99a098e 100644 --- a/src/declarative/qml/qdeclarativeengine.cpp +++ b/src/declarative/qml/qdeclarativeengine.cpp @@ -964,8 +964,14 @@ Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object) QDeclarativeData *data = QDeclarativeData::get(object); if (data && data->deferredComponent) { - QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Creating); - QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::Creating, QLatin1String("Deferred Creation:") + object->metaObject()->className()); + if (QDeclarativeDebugService::isDebuggingEnabled()) { + QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Creating); + QDeclarativeType *type = QDeclarativeMetaType::qmlType(object->metaObject()); + QString typeName = type ? QLatin1String(type->qmlTypeName()) : QString::fromLatin1(object->metaObject()->className()); + QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::Creating, typeName); + if (data->outerContext) + QDeclarativeDebugTrace::rangeLocation(QDeclarativeDebugTrace::Creating, data->outerContext->url, data->lineNumber); + } QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(data->context->engine); QDeclarativeComponentPrivate::ConstructionState state; -- cgit v0.12 From 6bcd2f316ef8d2f070f798cd6ac59ed67fecb0e1 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Tue, 25 Jan 2011 13:28:49 +1000 Subject: Fix critical spelling mistake. --- src/declarative/graphicsitems/qdeclarativeitem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/declarative/graphicsitems/qdeclarativeitem.cpp b/src/declarative/graphicsitems/qdeclarativeitem.cpp index afa1b72..e1c138f 100644 --- a/src/declarative/graphicsitems/qdeclarativeitem.cpp +++ b/src/declarative/graphicsitems/qdeclarativeitem.cpp @@ -3235,7 +3235,7 @@ qreal QDeclarativeItem::implicitHeight() const \endcode \bold Note: using implicitWidth of Text or TextEdit and setting the width explicitly - incurs a performance penalty as the text must be layed out twice. + incurs a performance penalty as the text must be laid out twice. */ -- cgit v0.12 From f15778e60ba538b8715f6433a472ffe08a21d934 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Tue, 25 Jan 2011 14:59:03 +1000 Subject: Fix warnings. --- src/declarative/debugger/qdeclarativedebugtrace.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/declarative/debugger/qdeclarativedebugtrace.cpp b/src/declarative/debugger/qdeclarativedebugtrace.cpp index 4bad405..6f28736 100644 --- a/src/declarative/debugger/qdeclarativedebugtrace.cpp +++ b/src/declarative/debugger/qdeclarativedebugtrace.cpp @@ -144,7 +144,7 @@ void QDeclarativeDebugTrace::rangeDataImpl(RangeType range, const QUrl &rData) if (status() != Enabled || !m_enabled) return; - QDeclarativeDebugData rd = {m_timer.elapsed(), (int)RangeData, (int)range, rData.toEncoded(QUrl::FormattingOption(0x100)), -1}; + QDeclarativeDebugData rd = {m_timer.elapsed(), (int)RangeData, (int)range, rData.toString(QUrl::FormattingOption(0x100)), -1}; processMessage(rd); } @@ -162,7 +162,7 @@ void QDeclarativeDebugTrace::rangeLocationImpl(RangeType range, const QUrl &file if (status() != Enabled || !m_enabled) return; - QDeclarativeDebugData rd = {m_timer.elapsed(), (int)RangeLocation, (int)range, fileName.toEncoded(QUrl::FormattingOption(0x100)), line}; + QDeclarativeDebugData rd = {m_timer.elapsed(), (int)RangeLocation, (int)range, fileName.toString(QUrl::FormattingOption(0x100)), line}; processMessage(rd); } -- cgit v0.12 From d9e4393ef212dba9eeba68277b270d68bcdbc733 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 27 Jan 2011 13:49:12 +1000 Subject: Implement property versioning inside the declarative engine Task-number: QTBUG-13451 --- src/declarative/qml/qdeclarativecompileddata.cpp | 30 ++++ src/declarative/qml/qdeclarativecompiler.cpp | 174 +++++++++++++++------ src/declarative/qml/qdeclarativecompiler_p.h | 7 +- src/declarative/qml/qdeclarativeengine.cpp | 121 ++++++++++++++ src/declarative/qml/qdeclarativeengine_p.h | 37 +++-- src/declarative/qml/qdeclarativemetatype.cpp | 76 +++++---- src/declarative/qml/qdeclarativemetatype_p.h | 6 +- .../qml/qdeclarativeobjectscriptclass.cpp | 21 +-- src/declarative/qml/qdeclarativeparser.cpp | 3 +- src/declarative/qml/qdeclarativeparser_p.h | 2 + src/declarative/qml/qdeclarativepropertycache.cpp | 21 +++ src/declarative/qml/qdeclarativepropertycache_p.h | 37 ++++- src/declarative/qml/qdeclarativetypeloader.cpp | 2 + src/declarative/qml/qdeclarativetypeloader_p.h | 4 +- src/declarative/qml/qdeclarativevme.cpp | 15 +- src/script/bridge/qscriptdeclarativeclass.cpp | 5 + src/script/bridge/qscriptdeclarativeclass_p.h | 1 + .../qdeclarativeitem/tst_qdeclarativeitem.cpp | 8 +- .../data/allowedRevisionOverloads.qml | 6 + .../data/disallowedRevisionOverloads.errors.txt | 1 + .../data/disallowedRevisionOverloads.qml | 7 + .../data/metaobjectRevision.1.errors.txt | 2 +- .../data/metaobjectRevision.1.qml | 1 + .../data/metaobjectRevision.2.errors.txt | 2 +- .../data/metaobjectRevision.3.errors.txt | 2 +- .../qdeclarativelanguage/data/revisions10.qml | 8 - .../qdeclarativelanguage/data/revisionssub10.qml | 10 -- .../declarative/qdeclarativelanguage/testtypes.cpp | 2 + .../declarative/qdeclarativelanguage/testtypes.h | 12 ++ .../tst_qdeclarativelanguage.cpp | 45 ++---- .../tst_qdeclarativerepeater.cpp | 4 +- 31 files changed, 494 insertions(+), 178 deletions(-) create mode 100644 tests/auto/declarative/qdeclarativelanguage/data/allowedRevisionOverloads.qml create mode 100644 tests/auto/declarative/qdeclarativelanguage/data/disallowedRevisionOverloads.errors.txt create mode 100644 tests/auto/declarative/qdeclarativelanguage/data/disallowedRevisionOverloads.qml delete mode 100644 tests/auto/declarative/qdeclarativelanguage/data/revisions10.qml delete mode 100644 tests/auto/declarative/qdeclarativelanguage/data/revisionssub10.qml diff --git a/src/declarative/qml/qdeclarativecompileddata.cpp b/src/declarative/qml/qdeclarativecompileddata.cpp index 70cace4..03deea1 100644 --- a/src/declarative/qml/qdeclarativecompileddata.cpp +++ b/src/declarative/qml/qdeclarativecompileddata.cpp @@ -171,6 +171,8 @@ QDeclarativeCompiledData::~QDeclarativeCompiledData() for (int ii = 0; ii < types.count(); ++ii) { if (types.at(ii).component) types.at(ii).component->release(); + if (types.at(ii).typePropertyCache) + types.at(ii).typePropertyCache->release(); } for (int ii = 0; ii < propertyCaches.count(); ++ii) @@ -209,6 +211,34 @@ const QMetaObject *QDeclarativeCompiledData::TypeReference::metaObject() const } } +/*! +Returns the property cache, if one alread exists. The cache is not referenced. +*/ +QDeclarativePropertyCache *QDeclarativeCompiledData::TypeReference::propertyCache() const +{ + if (type) + return typePropertyCache; + else + return component->rootPropertyCache; +} + +/*! +Returns the property cache, creating one if it doesn't already exist. The cache is not referenced. +*/ +QDeclarativePropertyCache *QDeclarativeCompiledData::TypeReference::createPropertyCache(QDeclarativeEngine *engine) +{ + if (typePropertyCache) { + return typePropertyCache; + } else if (type) { + typePropertyCache = QDeclarativeEnginePrivate::get(engine)->cache(type->metaObject()); + typePropertyCache->addref(); + return typePropertyCache; + } else { + return component->rootPropertyCache; + } +} + + void QDeclarativeCompiledData::dumpInstructions() { if (!name.isEmpty()) diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp index 8bfc260..a0236c0 100644 --- a/src/declarative/qml/qdeclarativecompiler.cpp +++ b/src/declarative/qml/qdeclarativecompiler.cpp @@ -589,6 +589,18 @@ bool QDeclarativeCompiler::compile(QDeclarativeEngine *engine, err = tr( "Element is not creatable."); COMPILE_EXCEPTION(parserRef->refObjects.first(), err); } + + if (ref.type->containsRevisionedAttributes()) { + QDeclarativeError cacheError; + ref.typePropertyCache = + QDeclarativeEnginePrivate::get(engine)->cache(ref.type, resolvedTypes.at(ii).minorVersion, cacheError); + + if (!ref.typePropertyCache) { + COMPILE_EXCEPTION(parserRef->refObjects.first(), cacheError.description()); + } + ref.typePropertyCache->addref(); + } + } else if (tref.typeData) { ref.component = tref.typeData->compiledData(); } @@ -886,8 +898,7 @@ bool QDeclarativeCompiler::buildObject(Object *obj, const BindingContext &ctxt) void QDeclarativeCompiler::genObject(QDeclarativeParser::Object *obj) { - const QDeclarativeCompiledData::TypeReference &tr = - output->types.at(obj->type); + QDeclarativeCompiledData::TypeReference &tr = output->types[obj->type]; if (tr.type && obj->metatype == &QDeclarativeComponent::staticMetaObject) { genComponent(obj); return; @@ -936,16 +947,10 @@ void QDeclarativeCompiler::genObject(QDeclarativeParser::Object *obj) meta.storeMeta.data = output->indexForByteArray(obj->metadata); meta.storeMeta.aliasData = output->indexForByteArray(obj->synthdata); meta.storeMeta.propertyCache = output->propertyCaches.count(); - // ### Surely the creation of this property cache could be more efficient - QDeclarativePropertyCache *propertyCache = 0; - if (tr.component) - propertyCache = tr.component->rootPropertyCache->copy(); - else - propertyCache = enginePrivate->cache(obj->metaObject()->superClass())->copy(); - propertyCache->append(engine, obj->metaObject(), QDeclarativePropertyCache::Data::NoFlags, - QDeclarativePropertyCache::Data::IsVMEFunction, - QDeclarativePropertyCache::Data::IsVMESignal); + QDeclarativePropertyCache *propertyCache = obj->synthCache; + Q_ASSERT(propertyCache); + propertyCache->addref(); // Add flag for alias properties if (!obj->synthdata.isEmpty()) { @@ -965,11 +970,7 @@ void QDeclarativeCompiler::genObject(QDeclarativeParser::Object *obj) output->propertyCaches << propertyCache; output->bytecode << meta; } else if (obj == unitRoot) { - if (tr.component) - output->rootPropertyCache = tr.component->rootPropertyCache; - else - output->rootPropertyCache = enginePrivate->cache(obj->metaObject()); - + output->rootPropertyCache = tr.createPropertyCache(engine); output->rootPropertyCache->addref(); } @@ -1104,15 +1105,7 @@ void QDeclarativeCompiler::genObjectBody(QDeclarativeParser::Object *obj) meta.line = 0; meta.storeMeta.data = output->indexForByteArray(prop->value->metadata); meta.storeMeta.aliasData = output->indexForByteArray(prop->value->synthdata); - meta.storeMeta.propertyCache = output->propertyCaches.count(); - // ### Surely the creation of this property cache could be more efficient - QDeclarativePropertyCache *propertyCache = - enginePrivate->cache(prop->value->metaObject()->superClass())->copy(); - propertyCache->append(engine, prop->value->metaObject(), QDeclarativePropertyCache::Data::NoFlags, - QDeclarativePropertyCache::Data::IsVMEFunction, - QDeclarativePropertyCache::Data::IsVMESignal); - - output->propertyCaches << propertyCache; + meta.storeMeta.propertyCache = -1; output->bytecode << meta; } @@ -1352,11 +1345,18 @@ bool QDeclarativeCompiler::buildSignal(QDeclarativeParser::Property *prop, QDecl if(name[0] >= 'A' && name[0] <= 'Z') name[0] = name[0] - 'A' + 'a'; - QMetaMethod method = QDeclarativePropertyPrivate::findSignalByName(obj->metaObject(), name); - int sigIdx = method.methodIndex(); + bool notInRevision = false; + int sigIdx = indexOfSignal(obj, name, ¬InRevision); if (sigIdx == -1) { + if (notInRevision && -1 == indexOfProperty(obj, prop->name, 0)) { + Q_ASSERT(obj->type != -1); + const QList &resolvedTypes = unit->resolvedTypes(); + const QDeclarativeTypeData::TypeReference &type = resolvedTypes.at(obj->type); + COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(QString::fromUtf8(obj->className)).arg(QString::fromUtf8(prop->name)).arg(QString::fromUtf8(type.type->module())).arg(type.majorVersion).arg(type.minorVersion)); + } + // If the "on" name doesn't resolve into a signal, try it as a // property. COMPILE_CHECK(buildProperty(prop, obj, ctxt)); @@ -1366,13 +1366,6 @@ bool QDeclarativeCompiler::buildSignal(QDeclarativeParser::Property *prop, QDecl if (prop->value || prop->values.count() != 1) COMPILE_EXCEPTION(prop, tr("Incorrectly specified signal assignment")); - if (method.revision() > 0) { - QDeclarativeType *type = output->types.at(obj->type).type; - if (!type->isMethodAvailable(sigIdx, method.revision())) { - COMPILE_EXCEPTION(prop, tr("Signal \"%1\" not available in %2 %3.%4").arg(QString::fromUtf8(prop->name)).arg(QString::fromUtf8(type->qmlTypeName())).arg(obj->majorVersion).arg(obj->minorVersion)); - } - } - prop->index = sigIdx; obj->addSignalProperty(prop); @@ -1412,7 +1405,7 @@ bool QDeclarativeCompiler::doesPropertyExist(QDeclarativeParser::Property *prop, QMetaProperty p = QDeclarativeMetaType::defaultProperty(mo); return p.name() != 0; } else { - int idx = mo->indexOfProperty(prop->name.constData()); + int idx = indexOfProperty(obj, prop->name); return idx != -1 && mo->property(idx).isScriptable(); } } @@ -1473,7 +1466,13 @@ bool QDeclarativeCompiler::buildProperty(QDeclarativeParser::Property *prop, } } else { - prop->index = metaObject->indexOfProperty(prop->name.constData()); + bool notInRevision = false; + prop->index = indexOfProperty(obj, prop->name, ¬InRevision); + if (prop->index == -1 && notInRevision) { + const QList &resolvedTypes = unit->resolvedTypes(); + const QDeclarativeTypeData::TypeReference &type = resolvedTypes.at(obj->type); + COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(QString::fromUtf8(obj->className)).arg(QString::fromUtf8(prop->name)).arg(QString::fromUtf8(type.type->module())).arg(type.majorVersion).arg(type.minorVersion)); + } if (prop->index != -1) { p = metaObject->property(prop->index); @@ -1488,15 +1487,8 @@ bool QDeclarativeCompiler::buildProperty(QDeclarativeParser::Property *prop, // We can't error here as the "id" property does not require a // successful index resolution - if (p.name()) { + if (p.name()) prop->type = p.userType(); - if (p.revision() > 0) { - QDeclarativeType *type = output->types.at(obj->type).type; - if (!type->isPropertyAvailable(prop->index, p.revision())) { - COMPILE_EXCEPTION(prop, tr("Property \"%1\" not available in %2 %3.%4").arg(QString::fromUtf8(prop->name)).arg(QString::fromUtf8(type->qmlTypeName())).arg(obj->majorVersion).arg(obj->minorVersion)); - } - } - } // Check if this is an alias if (prop->index != -1 && @@ -2430,8 +2422,7 @@ bool QDeclarativeCompiler::buildDynamicMeta(QDeclarativeParser::Object *obj, Dyn for (int ii = 0; ii < obj->dynamicProperties.count(); ++ii) { const Object::DynamicProperty &p = obj->dynamicProperties.at(ii); - int propIdx = - obj->metaObject()->indexOfProperty(p.name.constData()); + int propIdx = obj->metaObject()->indexOfProperty(p.name.constData()); if (-1 != propIdx) { QMetaProperty prop = obj->metaObject()->property(propIdx); if (prop.isFinal()) @@ -2616,6 +2607,19 @@ bool QDeclarativeCompiler::buildDynamicMeta(QDeclarativeParser::Object *obj, Dyn obj->synthdata = dynamicData; + if (obj->synthCache) { + obj->synthCache->release(); + obj->synthCache = 0; + } + + if (obj->type != -1) { + QDeclarativePropertyCache *cache = output->types[obj->type].createPropertyCache(engine)->copy(); + cache->append(engine, &obj->extObject, QDeclarativePropertyCache::Data::NoFlags, + QDeclarativePropertyCache::Data::IsVMEFunction, + QDeclarativePropertyCache::Data::IsVMESignal); + obj->synthCache = cache; + } + return true; } @@ -2665,9 +2669,9 @@ static QStringList astNodeToStringList(QDeclarativeJS::AST::Node *node) } bool QDeclarativeCompiler::compileAlias(QMetaObjectBuilder &builder, - QByteArray &data, - Object *obj, - const Object::DynamicProperty &prop) + QByteArray &data, + Object *obj, + const Object::DynamicProperty &prop) { if (!prop.defaultValue) COMPILE_EXCEPTION(obj, tr("No property alias location")); @@ -2697,7 +2701,7 @@ bool QDeclarativeCompiler::compileAlias(QMetaObjectBuilder &builder, int flags = 0; bool writable = false; if (alias.count() == 2 || alias.count() == 3) { - propIdx = idObject->metaObject()->indexOfProperty(alias.at(1).toUtf8().constData()); + propIdx = indexOfProperty(idObject, alias.at(1).toUtf8()); if (-1 == propIdx) { COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location")); @@ -3038,4 +3042,74 @@ QStringList QDeclarativeCompiler::deferredProperties(QDeclarativeParser::Object return rv; } +// This code must match the semantics of QDeclarativePropertyPrivate::findSignalByName +int QDeclarativeCompiler::indexOfSignal(QDeclarativeParser::Object *object, const QByteArray &name, + bool *notInRevision) +{ + if (notInRevision) *notInRevision = false; + + if (object->synthCache || (object->type != -1 && output->types.at(object->type).propertyCache())) { + // XXX fromUtf8 + QString strName(QString::fromUtf8(name)); + QDeclarativePropertyCache *cache = + object->synthCache?object->synthCache:output->types.at(object->type).propertyCache(); + + QDeclarativePropertyCache::Data *d = cache->property(strName); + if (notInRevision) *notInRevision = false; + + while (d && !(d->flags & QDeclarativePropertyCache::Data::IsFunction)) + d = cache->overrideData(d); + + if (d && !cache->isAllowedInRevision(d)) { + if (notInRevision) *notInRevision = true; + return -1; + } else if (d) { + return d->coreIndex; + } + + if (name.endsWith("Changed")) { + QByteArray propName = name.mid(0, name.length() - 7); + + int propIndex = indexOfProperty(object, propName, notInRevision); + if (propIndex != -1) { + d = cache->property(propIndex); + return d->notifyIndex; + } + } + + return -1; + } else { + return QDeclarativePropertyPrivate::findSignalByName(object->metaObject(), name).methodIndex(); + } + +} + +int QDeclarativeCompiler::indexOfProperty(QDeclarativeParser::Object *object, const QByteArray &name, + bool *notInRevision) +{ + if (notInRevision) *notInRevision = false; + + if (object->synthCache || (object->type != -1 && output->types.at(object->type).propertyCache())) { + // XXX fromUtf8 + QString strName(QString::fromUtf8(name)); + QDeclarativePropertyCache *cache = + object->synthCache?object->synthCache:output->types.at(object->type).propertyCache(); + + QDeclarativePropertyCache::Data *d = cache->property(strName); + // Find the first property + while (d && d->flags & QDeclarativePropertyCache::Data::IsFunction) + d = cache->overrideData(d); + + if (d && !cache->isAllowedInRevision(d)) { + if (notInRevision) *notInRevision = true; + return -1; + } else { + return d?d->coreIndex:-1; + } + } else { + const QMetaObject *mo = object->metaObject(); + return mo->indexOfProperty(name.constData()); + } +} + QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativecompiler_p.h b/src/declarative/qml/qdeclarativecompiler_p.h index 5e990e7..93b6a09 100644 --- a/src/declarative/qml/qdeclarativecompiler_p.h +++ b/src/declarative/qml/qdeclarativecompiler_p.h @@ -89,14 +89,17 @@ public: struct TypeReference { TypeReference() - : type(0), component(0) {} + : type(0), typePropertyCache(0), component(0) {} QByteArray className; QDeclarativeType *type; + QDeclarativePropertyCache *typePropertyCache; QDeclarativeCompiledData *component; QObject *createInstance(QDeclarativeContextData *, const QBitField &, QList *) const; const QMetaObject *metaObject() const; + QDeclarativePropertyCache *propertyCache() const; + QDeclarativePropertyCache *createPropertyCache(QDeclarativeEngine *); }; QList types; struct CustomTypeData @@ -277,6 +280,8 @@ private: bool canCoerce(int to, QDeclarativeParser::Object *from); QStringList deferredProperties(QDeclarativeParser::Object *); + int indexOfProperty(QDeclarativeParser::Object *, const QByteArray &, bool *notInRevision = 0); + int indexOfSignal(QDeclarativeParser::Object *, const QByteArray &, bool *notInRevision = 0); void addId(const QString &, QDeclarativeParser::Object *); diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp index 99a098e..e3be599 100644 --- a/src/declarative/qml/qdeclarativeengine.cpp +++ b/src/declarative/qml/qdeclarativeengine.cpp @@ -460,6 +460,8 @@ QDeclarativeEnginePrivate::~QDeclarativeEnginePrivate() (*iter)->release(); for(QHash::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter) (*iter)->release(); + for(QHash, QDeclarativePropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter) + (*iter)->release(); } @@ -2207,6 +2209,125 @@ static void *voidptr_constructor(const void *v) } } +QDeclarativePropertyCache *QDeclarativeEnginePrivate::createCache(const QMetaObject *mo) +{ + Q_Q(QDeclarativeEngine); + + if (!mo->superClass()) { + QDeclarativePropertyCache *rv = new QDeclarativePropertyCache(q, mo); + propertyCache.insert(mo, rv); + return rv; + } else { + QDeclarativePropertyCache *super = cache(mo->superClass()); + QDeclarativePropertyCache *rv = super->copy(); + rv->append(q, mo); + propertyCache.insert(mo, rv); + return rv; + } +} + +QDeclarativePropertyCache *QDeclarativeEnginePrivate::createCache(QDeclarativeType *type, int minorVersion, + QDeclarativeError &error) +{ + QList types; + + int maxMinorVersion = 0; + + const QMetaObject *metaObject = type->metaObject(); + while (metaObject) { + QDeclarativeType *t = QDeclarativeMetaType::qmlType(metaObject, type->module(), + type->majorVersion(), minorVersion); + if (t) { + maxMinorVersion = qMax(maxMinorVersion, t->minorVersion()); + types << t; + } else { + types << 0; + } + + metaObject = metaObject->superClass(); + } + + if (QDeclarativePropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) { + c->addref(); + typePropertyCache.insert(qMakePair(type, minorVersion), c); + return c; + } + + QDeclarativePropertyCache *raw = cache(type->metaObject()); + + bool hasCopied = false; + + for (int ii = 0; ii < types.count(); ++ii) { + QDeclarativeType *currentType = types.at(ii); + if (!currentType) + continue; + + int rev = currentType->metaObjectRevision(); + int moIndex = types.count() - 1 - ii; + + if (raw->allowedRevisionCache[moIndex] != rev) { + if (!hasCopied) { + raw = raw->copy(); + hasCopied = true; + } + raw->allowedRevisionCache[moIndex] = rev; + } + } + + // Test revision compatibility - the basic rule is: + // * Anything that is excluded, cannot overload something that is not excluded * + + // Signals override: + // * other signals and methods of the same name. + // * properties named on + // * automatic Changed notify signals + + // Methods override: + // * other methods of the same name + + // Properties override: + // * other elements of the same name + + bool overloadError = false; + QString overloadName; + +#if 0 + for (QDeclarativePropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin(); + !overloadError && iter != raw->stringCache.end(); + ++iter) { + + QDeclarativePropertyCache::Data *d = *iter; + if (raw->isAllowedInRevision(d)) + continue; // Not excluded - no problems + + // check that a regular "name" overload isn't happening + QDeclarativePropertyCache::Data *current = d; + while (!overloadError && current) { + current = d->overrideData(current); + if (current && raw->isAllowedInRevision(current)) + overloadError = true; + } + } +#endif + + if (overloadError) { + if (hasCopied) raw->release(); + + error.setDescription(QLatin1String("Type ") + QString::fromUtf8(type->qmlTypeName()) + QLatin1String(" ") + QString::number(type->majorVersion()) + QLatin1String(".") + QString::number(minorVersion) + QLatin1String(" contains an illegal property \"") + overloadName + QLatin1String("\". This is an error in the type's implementation.")); + return 0; + } + + if (!hasCopied) raw->addref(); + typePropertyCache.insert(qMakePair(type, minorVersion), raw); + + if (minorVersion != maxMinorVersion) { + raw->addref(); + typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw); + } + + return raw; +} + void QDeclarativeEnginePrivate::registerCompositeType(QDeclarativeCompiledData *data) { QByteArray name = data->root->className(); diff --git a/src/declarative/qml/qdeclarativeengine_p.h b/src/declarative/qml/qdeclarativeengine_p.h index fc996b5..1cc9dc5 100644 --- a/src/declarative/qml/qdeclarativeengine_p.h +++ b/src/declarative/qml/qdeclarativeengine_p.h @@ -251,8 +251,12 @@ public: QDeclarativeValueTypeFactory valueTypes; QHash propertyCache; + QHash, QDeclarativePropertyCache *> typePropertyCache; inline QDeclarativePropertyCache *cache(QObject *obj); inline QDeclarativePropertyCache *cache(const QMetaObject *); + inline QDeclarativePropertyCache *cache(QDeclarativeType *, int, QDeclarativeError &error); + QDeclarativePropertyCache *createCache(const QMetaObject *); + QDeclarativePropertyCache *createCache(QDeclarativeType *, int, QDeclarativeError &error); void registerCompositeType(QDeclarativeCompiledData *); @@ -330,19 +334,17 @@ Returns a QDeclarativePropertyCache for \a obj if one is available. If \a obj is null, being deleted or contains a dynamic meta object 0 is returned. + +The returned cache is not referenced, so if it is to be stored, call addref(). */ QDeclarativePropertyCache *QDeclarativeEnginePrivate::cache(QObject *obj) { - Q_Q(QDeclarativeEngine); if (!obj || QObjectPrivate::get(obj)->metaObject || QObjectPrivate::get(obj)->wasDeleted) return 0; const QMetaObject *mo = obj->metaObject(); QDeclarativePropertyCache *rv = propertyCache.value(mo); - if (!rv) { - rv = new QDeclarativePropertyCache(q, mo); - propertyCache.insert(mo, rv); - } + if (!rv) rv = createCache(mo); return rv; } @@ -352,18 +354,33 @@ Returns a QDeclarativePropertyCache for \a metaObject. As the cache is persisted for the life of the engine, \a metaObject must be a static "compile time" meta-object, or a meta-object that is otherwise known to exist for the lifetime of the QDeclarativeEngine. + +The returned cache is not referenced, so if it is to be stored, call addref(). */ QDeclarativePropertyCache *QDeclarativeEnginePrivate::cache(const QMetaObject *metaObject) { - Q_Q(QDeclarativeEngine); Q_ASSERT(metaObject); QDeclarativePropertyCache *rv = propertyCache.value(metaObject); - if (!rv) { - rv = new QDeclarativePropertyCache(q, metaObject); - propertyCache.insert(metaObject, rv); - } + if (!rv) rv = createCache(metaObject); + return rv; +} + +/*! +Returns a QDeclarativePropertyCache for \a type with \a minorVersion. + +The returned cache is not referenced, so if it is to be stored, call addref(). +*/ +QDeclarativePropertyCache *QDeclarativeEnginePrivate::cache(QDeclarativeType *type, int minorVersion, QDeclarativeError &error) +{ + Q_ASSERT(type); + Q_ASSERT(minorVersion >= 0); + + if (!type->containsRevisionedAttributes()) + return cache(type->metaObject()); + QDeclarativePropertyCache *rv = typePropertyCache.value(qMakePair(type, minorVersion)); + if (!rv) rv = createCache(type, minorVersion, error); return rv; } diff --git a/src/declarative/qml/qdeclarativemetatype.cpp b/src/declarative/qml/qdeclarativemetatype.cpp index bdac3d0..4867cc5 100644 --- a/src/declarative/qml/qdeclarativemetatype.cpp +++ b/src/declarative/qml/qdeclarativemetatype.cpp @@ -140,6 +140,7 @@ public: int m_version_min; int m_typeId; int m_listId; int m_revision; + mutable bool m_containsRevisionedAttributes; mutable QDeclarativeType *m_superType; int m_allocationSize; @@ -167,10 +168,11 @@ public: QHash QDeclarativeTypePrivate::m_attachedPropertyIds; QDeclarativeTypePrivate::QDeclarativeTypePrivate() -: m_isInterface(false), m_iid(0), m_typeId(0), m_listId(0), m_revision(0), m_superType(0), - m_allocationSize(0), m_newFunc(0), m_baseMetaObject(0), m_attachedPropertiesFunc(0), m_attachedPropertiesType(0), - m_parserStatusCast(-1), m_propertyValueSourceCast(-1), m_propertyValueInterceptorCast(-1), - m_extFunc(0), m_extMetaObject(0), m_index(-1), m_customParser(0), m_isSetup(false), m_haveSuperType(false) +: m_isInterface(false), m_iid(0), m_typeId(0), m_listId(0), m_revision(0), m_containsRevisionedAttributes(false), + m_superType(0), m_allocationSize(0), m_newFunc(0), m_baseMetaObject(0), m_attachedPropertiesFunc(0), + m_attachedPropertiesType(0), m_parserStatusCast(-1), m_propertyValueSourceCast(-1), + m_propertyValueInterceptorCast(-1), m_extFunc(0), m_extMetaObject(0), m_index(-1), m_customParser(0), + m_isSetup(false), m_haveSuperType(false) { } @@ -235,6 +237,11 @@ QDeclarativeType::~QDeclarativeType() delete d; } +QByteArray QDeclarativeType::module() const +{ + return d->m_module; +} + int QDeclarativeType::majorVersion() const { return d->m_version_maj; @@ -270,36 +277,6 @@ QDeclarativeType *QDeclarativeType::superType() const return d->m_superType; } -bool QDeclarativeType::isPropertyAvailable(int index, int revision) const -{ - if (revision == 0) - return true; - - if (index < d->m_baseMetaObject->propertyOffset()) { - if (QDeclarativeType *super = superType()) - return super->isPropertyAvailable(index, revision); - } else if (index < d->m_baseMetaObject->propertyOffset() + d->m_baseMetaObject->propertyCount()) { - return d->m_revision >= revision; - } - - return false; -} - -bool QDeclarativeType::isMethodAvailable(int index, int revision) const -{ - if (revision == 0) - return true; - - if (index < d->m_baseMetaObject->methodOffset()) { - if (QDeclarativeType *super = superType()) - return super->isMethodAvailable(index, revision); - } else if (index < d->m_baseMetaObject->methodOffset() + d->m_baseMetaObject->methodCount()) { - return d->m_revision >= revision; - } - - return false; -} - static void clone(QMetaObjectBuilder &builder, const QMetaObject *mo, const QMetaObject *ignoreStart, const QMetaObject *ignoreEnd) { @@ -413,6 +390,25 @@ void QDeclarativeTypePrivate::init() const m_metaObjects[ii].methodOffset = m_metaObjects.at(ii).metaObject->methodOffset(); } + + // Check for revisioned details + { + const QMetaObject *mo = 0; + if (m_metaObjects.isEmpty()) + mo = m_baseMetaObject; + else + mo = m_metaObjects.first().metaObject; + + for (int ii = 0; !m_containsRevisionedAttributes && ii < mo->propertyCount(); ++ii) { + if (mo->property(ii).revision() != 0) + m_containsRevisionedAttributes = true; + } + + for (int ii = 0; !m_containsRevisionedAttributes && ii < mo->methodCount(); ++ii) { + if (mo->method(ii).revision() != 0) + m_containsRevisionedAttributes = true; + } + } m_isSetup = true; lock.unlock(); @@ -521,6 +517,18 @@ const QMetaObject *QDeclarativeType::baseMetaObject() const return d->m_baseMetaObject; } +bool QDeclarativeType::containsRevisionedAttributes() const +{ + d->init(); + + return d->m_containsRevisionedAttributes; +} + +int QDeclarativeType::metaObjectRevision() const +{ + return d->m_revision; +} + QDeclarativeAttachedPropertiesFunc QDeclarativeType::attachedPropertiesFunction() const { return d->m_attachedPropertiesFunc; diff --git a/src/declarative/qml/qdeclarativemetatype_p.h b/src/declarative/qml/qdeclarativemetatype_p.h index 564218f..0e4d61c 100644 --- a/src/declarative/qml/qdeclarativemetatype_p.h +++ b/src/declarative/qml/qdeclarativemetatype_p.h @@ -113,12 +113,12 @@ public: QByteArray typeName() const; QByteArray qmlTypeName() const; + QByteArray module() const; int majorVersion() const; int minorVersion() const; + bool availableInVersion(int vmajor, int vminor) const; bool availableInVersion(const QByteArray &module, int vmajor, int vminor) const; - bool isPropertyAvailable(int index, int revision) const; - bool isMethodAvailable(int index, int revision) const; QObject *create() const; void create(QObject **, void **, size_t) const; @@ -139,6 +139,8 @@ public: const QMetaObject *metaObject() const; const QMetaObject *baseMetaObject() const; + int metaObjectRevision() const; + bool containsRevisionedAttributes() const; QDeclarativeAttachedPropertiesFunc attachedPropertiesFunction() const; const QMetaObject *attachedPropertiesType() const; diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp index 1c2aec9..cbbf2b9 100644 --- a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp +++ b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp @@ -149,8 +149,8 @@ QDeclarativeObjectScriptClass::queryProperty(Object *object, const Identifier &n QScriptClass::QueryFlags QDeclarativeObjectScriptClass::queryProperty(QObject *obj, const Identifier &name, - QScriptClass::QueryFlags flags, QDeclarativeContextData *evalContext, - QueryHints hints) + QScriptClass::QueryFlags flags, QDeclarativeContextData *evalContext, + QueryHints hints) { Q_UNUSED(flags); lastData = 0; @@ -165,19 +165,10 @@ QDeclarativeObjectScriptClass::queryProperty(QObject *obj, const Identifier &nam QDeclarativeEnginePrivate *enginePrivate = QDeclarativeEnginePrivate::get(engine); lastData = QDeclarativePropertyCache::property(engine, obj, name, local); - - if (lastData && lastData->revision > 0 && (hints & ImplicitObject)) { - QDeclarativeData *data = QDeclarativeData::get(obj); - if (data) { - if (!data->type) { - lastData = 0; - } else if (lastData->flags & QDeclarativePropertyCache::Data::IsFunction) { - if (!data->type->isMethodAvailable(lastData->coreIndex, lastData->revision)) - lastData = 0; - } else if (!data->type->isPropertyAvailable(lastData->coreIndex, lastData->revision)) { - lastData = 0; - } - } + if ((hints & ImplicitObject) && lastData && lastData->revision != 0) { + QDeclarativeData *ddata = QDeclarativeData::get(obj); + if (ddata && ddata->propertyCache && !ddata->propertyCache->isAllowedInRevision(lastData)) + return 0; } if (lastData) diff --git a/src/declarative/qml/qdeclarativeparser.cpp b/src/declarative/qml/qdeclarativeparser.cpp index da4016e..35bb0f1 100644 --- a/src/declarative/qml/qdeclarativeparser.cpp +++ b/src/declarative/qml/qdeclarativeparser.cpp @@ -66,13 +66,14 @@ using namespace QDeclarativeJS; using namespace QDeclarativeParser; QDeclarativeParser::Object::Object() -: type(-1), majorVersion(-1), minorVersion(-1), idIndex(-1), metatype(0), defaultProperty(0), parserStatusCast(-1) +: type(-1), majorVersion(-1), minorVersion(-1), idIndex(-1), metatype(0), synthCache(0), defaultProperty(0), parserStatusCast(-1) { } QDeclarativeParser::Object::~Object() { if (defaultProperty) defaultProperty->release(); + if (synthCache) synthCache->release(); foreach(Property *prop, properties) prop->release(); foreach(Property *prop, valueProperties) diff --git a/src/declarative/qml/qdeclarativeparser_p.h b/src/declarative/qml/qdeclarativeparser_p.h index 6ef2811..8f41a91 100644 --- a/src/declarative/qml/qdeclarativeparser_p.h +++ b/src/declarative/qml/qdeclarativeparser_p.h @@ -71,6 +71,7 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) +class QDeclarativePropertyCache; namespace QDeclarativeJS { namespace AST { class Node; } } /* @@ -154,6 +155,7 @@ namespace QDeclarativeParser QAbstractDynamicMetaObject extObject; QByteArray metadata; // Generated by compiler QByteArray synthdata; // Generated by compiler + QDeclarativePropertyCache *synthCache; // Generated by compiler Property *getDefaultProperty(); Property *getProperty(const QByteArray &name, bool create=true); diff --git a/src/declarative/qml/qdeclarativepropertycache.cpp b/src/declarative/qml/qdeclarativepropertycache.cpp index 5397694..6a39a65 100644 --- a/src/declarative/qml/qdeclarativepropertycache.cpp +++ b/src/declarative/qml/qdeclarativepropertycache.cpp @@ -218,6 +218,7 @@ QDeclarativePropertyCache *QDeclarativePropertyCache::copy() const cache->methodIndexCache = methodIndexCache; cache->stringCache = stringCache; cache->identifierCache = identifierCache; + cache->allowedRevisionCache = allowedRevisionCache; for (int ii = 0; ii < indexCache.count(); ++ii) { if (indexCache.at(ii)) indexCache.at(ii)->addref(); @@ -236,6 +237,17 @@ QDeclarativePropertyCache *QDeclarativePropertyCache::copy() const void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaObject *metaObject, Data::Flag propertyFlags, Data::Flag methodFlags, Data::Flag signalFlags) { + append(engine, metaObject, -1, propertyFlags, methodFlags, signalFlags); +} + +void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaObject *metaObject, + int revision, + Data::Flag propertyFlags, Data::Flag methodFlags, Data::Flag signalFlags) +{ + Q_UNUSED(revision); + + allowedRevisionCache.append(0); + QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(engine); int methodCount = metaObject->methodCount(); // 3 to block the destroyed signal and the deleteLater() slot @@ -262,11 +274,15 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb else if (m.methodType() == QMetaMethod::Signal) data->flags |= signalFlags; + data->metaObjectOffset = allowedRevisionCache.count() - 1; + if (stringCache.contains(methodName)) { RData *old = stringCache[methodName]; // We only overload methods in the same class, exactly like C++ if (old->flags & Data::IsFunction && old->coreIndex >= methodOffset) data->relatedIndex = old->coreIndex; + data->overrideIndexIsProperty = !bool(old->flags & Data::IsFunction); + data->overrideIndex = old->coreIndex; stringCache[methodName]->release(); identifierCache[data->identifier.identifier]->release(); } @@ -295,7 +311,12 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb data->load(p, engine); data->flags |= propertyFlags; + data->metaObjectOffset = allowedRevisionCache.count() - 1; + if (stringCache.contains(propName)) { + RData *old = stringCache[propName]; + data->overrideIndexIsProperty = !bool(old->flags & Data::IsFunction); + data->overrideIndex = old->coreIndex; stringCache[propName]->release(); identifierCache[data->identifier.identifier]->release(); } diff --git a/src/declarative/qml/qdeclarativepropertycache_p.h b/src/declarative/qml/qdeclarativepropertycache_p.h index 2f02c98..eeeff1a 100644 --- a/src/declarative/qml/qdeclarativepropertycache_p.h +++ b/src/declarative/qml/qdeclarativepropertycache_p.h @@ -110,7 +110,10 @@ public: int notifyIndex; // When !IsFunction int relatedIndex; // When IsFunction }; - int revision; + uint overrideIndexIsProperty : 1; + int overrideIndex : 31; + int revision; + int metaObjectOffset; static Flags flagsForProperty(const QMetaProperty &, QDeclarativeEngine *engine = 0); void load(const QMetaProperty &, QDeclarativeEngine *engine = 0); @@ -132,8 +135,9 @@ public: QDeclarativePropertyCache *copy() const; void append(QDeclarativeEngine *, const QMetaObject *, Data::Flag propertyFlags = Data::NoFlags, Data::Flag methodFlags = Data::NoFlags, Data::Flag signalFlags = Data::NoFlags); + void append(QDeclarativeEngine *, const QMetaObject *, int revision, Data::Flag propertyFlags = Data::NoFlags, + Data::Flag methodFlags = Data::NoFlags, Data::Flag signalFlags = Data::NoFlags); - static QDeclarativePropertyCache *create(QDeclarativeEngine *, const QMetaObject *); static Data create(const QMetaObject *, const QString &); inline Data *property(const QScriptDeclarativeClass::Identifier &id) const; @@ -142,13 +146,19 @@ public: Data *method(int) const; QStringList propertyNames() const; + inline Data *overrideData(Data *) const; + inline bool isAllowedInRevision(Data *) const; + inline QDeclarativeEngine *qmlEngine() const; static Data *property(QDeclarativeEngine *, QObject *, const QScriptDeclarativeClass::Identifier &, Data &); static Data *property(QDeclarativeEngine *, QObject *, const QString &, Data &); + protected: virtual void clear(); private: + friend class QDeclarativeEnginePrivate; + struct RData : public Data, public QDeclarativeRefCount { QScriptDeclarativeClass::PersistentIdentifier identifier; }; @@ -156,6 +166,7 @@ private: typedef QVector IndexCache; typedef QHash StringCache; typedef QHash IdentifierCache; + typedef QVector AllowedRevisionCache; void updateRecur(QDeclarativeEngine *, const QMetaObject *); @@ -164,11 +175,13 @@ private: IndexCache methodIndexCache; StringCache stringCache; IdentifierCache identifierCache; + AllowedRevisionCache allowedRevisionCache; }; Q_DECLARE_OPERATORS_FOR_FLAGS(QDeclarativePropertyCache::Data::Flags); QDeclarativePropertyCache::Data::Data() -: flags(0), propType(0), coreIndex(-1), notifyIndex(-1) +: flags(0), propType(0), coreIndex(-1), notifyIndex(-1), overrideIndexIsProperty(false), overrideIndex(-1), + revision(0), metaObjectOffset(-1) { } @@ -182,6 +195,18 @@ bool QDeclarativePropertyCache::Data::operator==(const QDeclarativePropertyCache } QDeclarativePropertyCache::Data * +QDeclarativePropertyCache::overrideData(Data *data) const +{ + if (data->overrideIndex < 0) + return 0; + + if (data->overrideIndexIsProperty) + return indexCache.at(data->overrideIndex); + else + return methodIndexCache.at(data->overrideIndex); +} + +QDeclarativePropertyCache::Data * QDeclarativePropertyCache::property(const QScriptDeclarativeClass::Identifier &id) const { return identifierCache.value(id); @@ -199,6 +224,12 @@ bool QDeclarativePropertyCache::ValueTypeData::operator==(const ValueTypeData &o valueTypePropType == o.valueTypePropType; } +bool QDeclarativePropertyCache::isAllowedInRevision(Data *data) const +{ + return (data->metaObjectOffset == -1 && data->revision == 0) || + (allowedRevisionCache[data->metaObjectOffset] >= data->revision); +} + QDeclarativeEngine *QDeclarativePropertyCache::qmlEngine() const { return engine; diff --git a/src/declarative/qml/qdeclarativetypeloader.cpp b/src/declarative/qml/qdeclarativetypeloader.cpp index 302cdcc..36cdde9 100644 --- a/src/declarative/qml/qdeclarativetypeloader.cpp +++ b/src/declarative/qml/qdeclarativetypeloader.cpp @@ -1005,6 +1005,8 @@ void QDeclarativeTypeData::resolveTypes() } if (ref.type) { + ref.majorVersion = majorVersion; + ref.minorVersion = minorVersion; foreach (QDeclarativeParser::Object *obj, parserRef->refObjects) { // store namespace for DOM obj->majorVersion = majorVersion; diff --git a/src/declarative/qml/qdeclarativetypeloader_p.h b/src/declarative/qml/qdeclarativetypeloader_p.h index beee358..6938892 100644 --- a/src/declarative/qml/qdeclarativetypeloader_p.h +++ b/src/declarative/qml/qdeclarativetypeloader_p.h @@ -215,10 +215,12 @@ class Q_AUTOTEST_EXPORT QDeclarativeTypeData : public QDeclarativeDataBlob public: struct TypeReference { - TypeReference() : type(0), typeData(0) {} + TypeReference() : type(0), majorVersion(0), minorVersion(0), typeData(0) {} QDeclarativeParser::Location location; QDeclarativeType *type; + int majorVersion; + int minorVersion; QDeclarativeTypeData *typeData; }; diff --git a/src/declarative/qml/qdeclarativevme.cpp b/src/declarative/qml/qdeclarativevme.cpp index f3e7809..657b10d 100644 --- a/src/declarative/qml/qdeclarativevme.cpp +++ b/src/declarative/qml/qdeclarativevme.cpp @@ -324,10 +324,12 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack &stack, (void)new QDeclarativeVMEMetaObject(target, &mo, data, comp); - QDeclarativeData *ddata = QDeclarativeData::get(target, true); - if (ddata->propertyCache) ddata->propertyCache->release(); - ddata->propertyCache = propertyCaches.at(instr.storeMeta.propertyCache); - ddata->propertyCache->addref(); + if (instr.storeMeta.propertyCache != -1) { + QDeclarativeData *ddata = QDeclarativeData::get(target, true); + if (ddata->propertyCache) ddata->propertyCache->release(); + ddata->propertyCache = propertyCaches.at(instr.storeMeta.propertyCache); + ddata->propertyCache->addref(); + } } break; @@ -978,6 +980,11 @@ QDeclarativeCompiledData::TypeReference::createInstance(QDeclarativeContextData ddata->ownMemory = false; QObjectPrivate::get(rv)->declarativeData = ddata; + if (typePropertyCache && !ddata->propertyCache) { + ddata->propertyCache = typePropertyCache; + ddata->propertyCache->addref(); + } + return rv; } else { Q_ASSERT(component); diff --git a/src/script/bridge/qscriptdeclarativeclass.cpp b/src/script/bridge/qscriptdeclarativeclass.cpp index 4782852..6126b32 100644 --- a/src/script/bridge/qscriptdeclarativeclass.cpp +++ b/src/script/bridge/qscriptdeclarativeclass.cpp @@ -179,6 +179,11 @@ QScriptDeclarativeClass::PersistentIdentifier::operator=(const PersistentIdentif return *this; } +QString QScriptDeclarativeClass::PersistentIdentifier::toString() const +{ + return ((JSC::Identifier &)d).ustring(); +} + QScriptDeclarativeClass::QScriptDeclarativeClass(QScriptEngine *engine) : d_ptr(new QScriptDeclarativeClassPrivate) { diff --git a/src/script/bridge/qscriptdeclarativeclass_p.h b/src/script/bridge/qscriptdeclarativeclass_p.h index 3123b3c..e4c18f5 100644 --- a/src/script/bridge/qscriptdeclarativeclass_p.h +++ b/src/script/bridge/qscriptdeclarativeclass_p.h @@ -107,6 +107,7 @@ public: PersistentIdentifier(const PersistentIdentifier &other); PersistentIdentifier &operator=(const PersistentIdentifier &other); + QString toString() const; private: friend class QScriptDeclarativeClass; PersistentIdentifier(QScriptEnginePrivate *e) : identifier(0), engine(e), d(0) {} diff --git a/tests/auto/declarative/qdeclarativeitem/tst_qdeclarativeitem.cpp b/tests/auto/declarative/qdeclarativeitem/tst_qdeclarativeitem.cpp index e636383..447b57b 100644 --- a/tests/auto/declarative/qdeclarativeitem/tst_qdeclarativeitem.cpp +++ b/tests/auto/declarative/qdeclarativeitem/tst_qdeclarativeitem.cpp @@ -979,19 +979,19 @@ void tst_QDeclarativeItem::testQtQuick11Attributes_data() QTest::newRow("implicitWidth") << "implicitWidth: 100" << "QDeclarativeComponent: Component is not ready" - << ":1 Property \"implicitWidth\" not available in QtQuick/Item 1.0\n"; + << ":1 \"Item.implicitWidth\" is not available in QtQuick 1.0.\n"; QTest::newRow("implicitHeight") << "implicitHeight: 100" << "QDeclarativeComponent: Component is not ready" - << ":1 Property \"implicitHeight\" not available in QtQuick/Item 1.0\n"; + << ":1 \"Item.implicitHeight\" is not available in QtQuick 1.0.\n"; QTest::newRow("onImplicitWidthChanged") << "onImplicitWidthChanged: x" << "QDeclarativeComponent: Component is not ready" - << ":1 Signal \"onImplicitWidthChanged\" not available in QtQuick/Item 1.0\n"; + << ":1 \"Item.onImplicitWidthChanged\" is not available in QtQuick 1.0.\n"; QTest::newRow("onImplicitHeightChanged") << "onImplicitHeightChanged: x" << "QDeclarativeComponent: Component is not ready" - << ":1 Signal \"onImplicitHeightChanged\" not available in QtQuick/Item 1.0\n"; + << ":1 \"Item.onImplicitHeightChanged\" is not available in QtQuick 1.0.\n"; } diff --git a/tests/auto/declarative/qdeclarativelanguage/data/allowedRevisionOverloads.qml b/tests/auto/declarative/qdeclarativelanguage/data/allowedRevisionOverloads.qml new file mode 100644 index 0000000..64acbd1 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/allowedRevisionOverloads.qml @@ -0,0 +1,6 @@ +import Test 1.0 + +MyRevisionedLegalOverload +{ +} + diff --git a/tests/auto/declarative/qdeclarativelanguage/data/disallowedRevisionOverloads.errors.txt b/tests/auto/declarative/qdeclarativelanguage/data/disallowedRevisionOverloads.errors.txt new file mode 100644 index 0000000..e9b449d --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/disallowedRevisionOverloads.errors.txt @@ -0,0 +1 @@ +3:1:Type Test/MyRevisionedIllegalOverload 1.0 contains an illegal property "propA". This is an error in the type's implementation. diff --git a/tests/auto/declarative/qdeclarativelanguage/data/disallowedRevisionOverloads.qml b/tests/auto/declarative/qdeclarativelanguage/data/disallowedRevisionOverloads.qml new file mode 100644 index 0000000..612bcfe --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/disallowedRevisionOverloads.qml @@ -0,0 +1,7 @@ +import Test 1.0 + +MyRevisionedIllegalOverload +{ +} + + diff --git a/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.1.errors.txt b/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.1.errors.txt index 6ad6bfa..29342dc 100644 --- a/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.1.errors.txt +++ b/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.1.errors.txt @@ -1 +1 @@ -7:5:Property "prop2" not available in Test/MyRevisionedClass 1.0 +8:5:"MyRevisionedClass.prop2" is not available in Test 1.0. diff --git a/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.1.qml b/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.1.qml index 4662d5e..4b37ed3 100644 --- a/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.1.qml +++ b/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.1.qml @@ -1,3 +1,4 @@ +// Check that a property in a later revision (prop2) cannot be assigned import QtQuick 1.0 import Test 1.0 diff --git a/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.2.errors.txt b/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.2.errors.txt index 92ccd9a..57b5764 100644 --- a/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.2.errors.txt +++ b/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.2.errors.txt @@ -1 +1 @@ -6:5:Signal "onSignal2" not available in Test/MyRevisionedClass 1.0 +6:5:"MyRevisionedClass.onSignal2" is not available in Test 1.0. diff --git a/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.3.errors.txt b/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.3.errors.txt index b3c33c4..45364a0 100644 --- a/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.3.errors.txt +++ b/tests/auto/declarative/qdeclarativelanguage/data/metaobjectRevision.3.errors.txt @@ -1 +1 @@ -9:5:Property "propD" not available in Test/MyRevisionedClass 1.1 +9:5:"MyRevisionedClass.propD" is not available in Test 1.1. diff --git a/tests/auto/declarative/qdeclarativelanguage/data/revisions10.qml b/tests/auto/declarative/qdeclarativelanguage/data/revisions10.qml deleted file mode 100644 index c4974cf..0000000 --- a/tests/auto/declarative/qdeclarativelanguage/data/revisions10.qml +++ /dev/null @@ -1,8 +0,0 @@ -import QtQuick 1.0 -import Test 1.0 - -MyRevisionedClass -{ - property real prop2: 10 - prop1: 1 -} diff --git a/tests/auto/declarative/qdeclarativelanguage/data/revisionssub10.qml b/tests/auto/declarative/qdeclarativelanguage/data/revisionssub10.qml deleted file mode 100644 index b5de4a3..0000000 --- a/tests/auto/declarative/qdeclarativelanguage/data/revisionssub10.qml +++ /dev/null @@ -1,10 +0,0 @@ -import QtQuick 1.0 -import Test 1.0 - -MyRevisionedSubclass -{ - property real prop4: 10 - property real prop2: 10 - prop1: 5 - prop3: 7 -} diff --git a/tests/auto/declarative/qdeclarativelanguage/testtypes.cpp b/tests/auto/declarative/qdeclarativelanguage/testtypes.cpp index 5e91e95..69cba76 100644 --- a/tests/auto/declarative/qdeclarativelanguage/testtypes.cpp +++ b/tests/auto/declarative/qdeclarativelanguage/testtypes.cpp @@ -54,6 +54,8 @@ void registerTypes() qmlRegisterType(); qmlRegisterType("Test",1,0,"MyRevisionedClass"); qmlRegisterType("Test",1,1,"MyRevisionedClass"); + qmlRegisterType("Test",1,0,"MyRevisionedIllegalOverload"); + qmlRegisterType("Test",1,0,"MyRevisionedLegalOverload"); // Register the uncreatable base class qmlRegisterRevision("Test",1,1); diff --git a/tests/auto/declarative/qdeclarativelanguage/testtypes.h b/tests/auto/declarative/qdeclarativelanguage/testtypes.h index 4f44f81..12424d0 100644 --- a/tests/auto/declarative/qdeclarativelanguage/testtypes.h +++ b/tests/auto/declarative/qdeclarativelanguage/testtypes.h @@ -640,6 +640,18 @@ protected: qreal m_pb; }; +class MyRevisionedIllegalOverload : public MyRevisionedBaseClassRegistered +{ + Q_OBJECT + Q_PROPERTY(qreal propA READ propA WRITE setPropA REVISION 1); +}; + +class MyRevisionedLegalOverload : public MyRevisionedBaseClassRegistered +{ + Q_OBJECT + Q_PROPERTY(qreal propB READ propB WRITE setPropB REVISION 1); +}; + class MyRevisionedBaseClassUnregistered : public MyRevisionedBaseClassRegistered { Q_OBJECT diff --git a/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp b/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp index 67b9d49..f3f41a9 100644 --- a/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp +++ b/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp @@ -154,6 +154,7 @@ private slots: void variantNotify(); void revisions(); + void revisionOverloads(); // regression tests for crashes void crash1(); @@ -1897,18 +1898,6 @@ void tst_qdeclarativelanguage::variantNotify() void tst_qdeclarativelanguage::revisions() { { - QDeclarativeComponent component(&engine, TEST_FILE("revisions10.qml")); - - VERIFY_ERRORS(0); - MyRevisionedClass *object = qobject_cast(component.create()); - QVERIFY(object != 0); - - QCOMPARE(object->prop2(), 2.0); - QCOMPARE(object->property("prop2").toReal(), 10.0); - - delete object; - } - { QDeclarativeComponent component(&engine, TEST_FILE("revisions11.qml")); VERIFY_ERRORS(0); @@ -1920,21 +1909,6 @@ void tst_qdeclarativelanguage::revisions() delete object; } { - QDeclarativeComponent component(&engine, TEST_FILE("revisionssub10.qml")); - - VERIFY_ERRORS(0); - MyRevisionedSubclass *object = qobject_cast(component.create()); - QVERIFY(object != 0); - - QCOMPARE(object->prop2(), 2.0); - QCOMPARE(object->property("prop2").toReal(), 10.0); - - QCOMPARE(object->prop4(), 4.0); - QCOMPARE(object->property("prop4").toReal(), 10.0); - - delete object; - } - { QDeclarativeEngine myEngine; QDeclarativeComponent component(&myEngine, TEST_FILE("revisionssub11.qml")); @@ -1950,10 +1924,7 @@ void tst_qdeclarativelanguage::revisions() delete object; } { - // If this is uncommented it will work - // qmlRegisterType("Test",1,1,"MySubclass"); QDeclarativeComponent component(&engine, TEST_FILE("versionedbase.qml")); - QEXPECT_FAIL("", "Class version 1.0 with base class version 1.1 registered", Abort); VERIFY_ERRORS(0); MySubclass *object = qobject_cast(component.create()); QVERIFY(object != 0); @@ -1965,6 +1936,20 @@ void tst_qdeclarativelanguage::revisions() } } +void tst_qdeclarativelanguage::revisionOverloads() +{ + { + QDeclarativeComponent component(&engine, TEST_FILE("allowedRevisionOverloads.qml")); + VERIFY_ERRORS(0); + } + { + QDeclarativeComponent component(&engine, TEST_FILE("disallowedRevisionOverloads.qml")); + QEXPECT_FAIL("", "QTBUG-13849", Abort); + QVERIFY(0); + VERIFY_ERRORS("disallowedRevisionOverloads.errors.txt"); + } +} + void tst_qdeclarativelanguage::initTestCase() { registerTypes(); diff --git a/tests/auto/declarative/qdeclarativerepeater/tst_qdeclarativerepeater.cpp b/tests/auto/declarative/qdeclarativerepeater/tst_qdeclarativerepeater.cpp index d94ebbe..6b840a3 100644 --- a/tests/auto/declarative/qdeclarativerepeater/tst_qdeclarativerepeater.cpp +++ b/tests/auto/declarative/qdeclarativerepeater/tst_qdeclarativerepeater.cpp @@ -633,11 +633,11 @@ void tst_QDeclarativeRepeater::testQtQuick11Attributes_data() QTest::newRow("itemAdded") << "onItemAdded: count" << "QDeclarativeComponent: Component is not ready" - << ":1 Signal \"onItemAdded\" not available in QtQuick/Repeater 1.0\n"; + << ":1 \"Repeater.onItemAdded\" is not available in QtQuick 1.0.\n"; QTest::newRow("itemRemoved") << "onItemRemoved: count" << "QDeclarativeComponent: Component is not ready" - << ":1 Signal \"onItemRemoved\" not available in QtQuick/Repeater 1.0\n"; + << ":1 \"Repeater.onItemRemoved\" is not available in QtQuick 1.0.\n"; QTest::newRow("itemAt") << "Component.onCompleted: itemAt(0)" << ":1: ReferenceError: Can't find variable: itemAt" -- cgit v0.12 From 43b8305367156c1ceb09eb4a056bdae3f325b5eb Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Thu, 27 Jan 2011 15:34:34 +1000 Subject: Allow property bindings to be easily created from JavaScript Properties can now be assigned a function that returns the binding value. Task-number: QTBUG-14964 Reviewed-by: Aaron Kennedy --- doc/src/declarative/javascriptblocks.qdoc | 42 ++------- doc/src/declarative/propertybinding.qdoc | 103 +++++++++++++++++---- src/declarative/qml/qdeclarativebinding.cpp | 20 ++++ src/declarative/qml/qdeclarativebinding_p.h | 9 ++ src/declarative/qml/qdeclarativeexpression.cpp | 41 +++++++- src/declarative/qml/qdeclarativeexpression.h | 3 + src/declarative/qml/qdeclarativeexpression_p.h | 12 +++ .../qml/qdeclarativeobjectscriptclass.cpp | 19 +++- src/declarative/qml/qdeclarativeproperty.cpp | 25 +++-- src/declarative/qml/qdeclarativeproperty_p.h | 5 + .../qml/qdeclarativevaluetypescriptclass.cpp | 32 ++++++- .../data/functionAssignment.2.qml | 66 ++++++++++++- .../data/functionAssignment.js | 17 ++++ .../tst_qdeclarativeecmascript.cpp | 64 ++++++++++--- 14 files changed, 375 insertions(+), 83 deletions(-) create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/functionAssignment.js diff --git a/doc/src/declarative/javascriptblocks.qdoc b/doc/src/declarative/javascriptblocks.qdoc index d221205..65877f9 100644 --- a/doc/src/declarative/javascriptblocks.qdoc +++ b/doc/src/declarative/javascriptblocks.qdoc @@ -200,37 +200,12 @@ Likewise, the \l {Component::onDestruction} attached property is triggered on component destruction. -\section1 Property Assignment vs Property Binding +\section1 JavaScript and Property Binding -When working with both QML and JavaScript, it is important to differentiate between -QML \l {Property Binding} and JavaScript value assignment. In QML, a property -binding is created using the \e {property: value} syntax: +Property bindings can be created in JavaScript by assigning the property with a \c function +that returns the required value. -\code -Rectangle { - width: otherItem.width -} -\endcode - -The \c width of the above \l Rectangle is updated whenever \c otherItem.width changes. On the other -hand, take the following JavaScript code snippet, that runs when the \l Rectangle is created: - -\code -Rectangle { - - Component.onCompleted: { - width = otherItem.width; - } -} -\endcode - -The \c width of this \l Rectangle is \e assigned the value of \c otherItem.width using the -\e {property = value} syntax in JavaScript. Unlike the QML \e {property: value} syntax, this -does not invoke QML property binding; the \c rectangle.width property is set to the value -of \c otherItem.width at the time of the assignment and will not be updated if that value -changes. - -See \l {Property Binding} for more information. +See \l {Binding Properties from JavaScript} for details. \section1 Receiving QML Signals in JavaScript @@ -315,10 +290,13 @@ This restriction exists as the QML environment is not yet fully established. To run code after the environment setup has completed, refer to \l {Running JavaScript at Startup}. -\o The value of \c this is currently undefined in QML +\o The value of \c this is currently undefined in QML in the majority of contexts + +The \c this keyword is supported when \l {Binding Properties from JavaScript} +{binding properties from JavaScript}. In all other situations, the value of +\c this is undefined in QML. -The value of \c this is undefined in QML. To refer to any element, provide -an \c id. For example: +To refer to any element, provide an \c id. For example: \qml Item { diff --git a/doc/src/declarative/propertybinding.qdoc b/doc/src/declarative/propertybinding.qdoc index 2fa95d4..379a4ec 100644 --- a/doc/src/declarative/propertybinding.qdoc +++ b/doc/src/declarative/propertybinding.qdoc @@ -95,44 +95,109 @@ Rectangle { \endcode -\section1 Effects of Property Assignment in JavaScript +\section1 Binding Properties from JavaScript -Assigning a property value from JavaScript does \e not create a property binding. -For example: +When working with both QML and JavaScript, it is important to differentiate between +\l {Property Binding} syntax in QML and simple \e {property assignment} in JavaScript. Take +the example below, which uses property binding to ensure the item's \c height is always twice +its \c width: + +\qml +Item { + width: 100 + height: width * 2 +} +\endqml + +On the other hand, take the following JavaScript code snippet, which \e assigns, rather +than \e binds, the value of the \c height property: \code -Rectangle { +Item { + width: 100 Component.onCompleted: { - width = otherItem.width; + height = width * 2 // if width changes later, height is not updated! } } \endcode -Instead of creating a property binding, this simply sets the \c width of the \l Rectangle -to the value of \c other.width at the time the JavaScript code is invoked. See -\l {Property Assignment vs Property Binding} for more details. +Instead of creating a property binding, this simply sets the \c height property to the correct +value \e {at the time that} the JavaScript code is invoked. Unlike the first example, the +\c height will never change if \c width changes. + +The \e {property : value} syntax for property binding is QML-specific and cannot be used in +JavaScript. Instead, to bind a property from JavaScript, assign a \e function to the property +that returns the required value. The following code correctly sets the property binding +created in the first example, but creates the binding in JavaScript rather than QML: + +\qml +Item { + width: 100 + + Component.onCompleted: { + height = (function() { return width * 2 }) + } +} +\endqml + + +\section2 Using \c this to create a binding + +When creating a property binding from JavaScript, QML allows the use of the \c this keyword to +refer to the object to which the property binding will be assigned. This allows one to +explicitly refer to a property within an object when there may be ambiguity about the exact +property that should be used for the binding. -Also note that assigning a value to a property that is currently bound will remove the binding. -A property can only have one value at a time, and if any code explicitly sets -this value, the binding is removed. The \l Rectangle in the example below will have -a width of 13, regardless of the \c otherItem's width. +For example, the \c Component.onCompleted handler below is defined within the scope of the +\l Item, and references to \c width within this scope would refer to the \l Item's width, rather +than that of the \l Rectangle. To bind the \l Rectangle's \c height to its own \c width, the +function needs to explicitly refer to \c this.width rather than just \c width. Otherwise, the +height of the \l Rectangle would be bound to the width of the \l Item and not the \l Rectangle. + +\qml +Item { + width: 500 + height: 500 + + Rectangle { + id: rect + width: 100 + color: "yellow" + } + + Component.onCompleted: { + rect.height = (function() { return this.width * 2 }) + } +} +\endqml + +(In this case, the function could also have referred to \c rect.width rather than \c this.width.) + +Note that the value of \c this is not defined outside of its use in property binding. +See \l {QML JavaScript Restrictions} for details. + + +\section2 Effects of property assignment + +Note that assigning a value to a property that is currently bound will remove the binding. +A property can only have one value at a time, and if any code explicitly sets this value, the +binding is removed. In the following example, although \c width has been bound to \c height, +the binding is removed by the JavaScript code that assigns \c width to 50: \code -Rectangle { - width: otherItem.width +Item { + width: height * 2 + height: 100 Component.onCompleted: { - width = 13; + width = 50; } } \endcode -There is no way to create a property binding directly from imperative JavaScript code, -although it is possible to set up a \l Binding object (shown below). - -\section1 Binding Element +\section1 The Binding Element The implicit binding syntax shown previously is easy to use and works perfectly for most uses of bindings. In some advanced cases, it is necessary to create bindings explicitly using the diff --git a/src/declarative/qml/qdeclarativebinding.cpp b/src/declarative/qml/qdeclarativebinding.cpp index b2d0738..a5bd604 100644 --- a/src/declarative/qml/qdeclarativebinding.cpp +++ b/src/declarative/qml/qdeclarativebinding.cpp @@ -274,6 +274,13 @@ QDeclarativeBinding::QDeclarativeBinding(const QString &str, QObject *obj, QDecl setNotifyOnValueChanged(true); } +QDeclarativeBinding::QDeclarativeBinding(const QScriptValue &func, QObject *obj, QDeclarativeContextData *ctxt, QObject *parent) +: QDeclarativeExpression(ctxt, obj, func, *new QDeclarativeBindingPrivate) +{ + setParent(parent); + setNotifyOnValueChanged(true); +} + QDeclarativeBinding::~QDeclarativeBinding() { } @@ -292,6 +299,19 @@ QDeclarativeProperty QDeclarativeBinding::property() const return d->property; } +void QDeclarativeBinding::setEvaluateFlags(EvaluateFlags flags) +{ + Q_D(QDeclarativeBinding); + d->setEvaluateFlags(QDeclarativeQtScriptExpression::EvaluateFlags(static_cast(flags))); +} + +QDeclarativeBinding::EvaluateFlags QDeclarativeBinding::evaluateFlags() const +{ + Q_D(const QDeclarativeBinding); + return QDeclarativeBinding::EvaluateFlags(static_cast(d->evaluateFlags())); +} + + class QDeclarativeBindingProfiler { public: QDeclarativeBindingProfiler(QDeclarativeBinding *bind) diff --git a/src/declarative/qml/qdeclarativebinding_p.h b/src/declarative/qml/qdeclarativebinding_p.h index 19e7099..0260b95 100644 --- a/src/declarative/qml/qdeclarativebinding_p.h +++ b/src/declarative/qml/qdeclarativebinding_p.h @@ -147,14 +147,21 @@ class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeBinding : public QDeclarativeExpr { Q_OBJECT public: + enum EvaluateFlag { RequiresThisObject = 0x01 }; + Q_DECLARE_FLAGS(EvaluateFlags, EvaluateFlag) + QDeclarativeBinding(const QString &, QObject *, QDeclarativeContext *, QObject *parent=0); QDeclarativeBinding(const QString &, QObject *, QDeclarativeContextData *, QObject *parent=0); QDeclarativeBinding(void *, QDeclarativeRefCount *, QObject *, QDeclarativeContextData *, const QString &, int, QObject *parent); + QDeclarativeBinding(const QScriptValue &, QObject *, QDeclarativeContextData *, QObject *parent=0); void setTarget(const QDeclarativeProperty &); QDeclarativeProperty property() const; + void setEvaluateFlags(EvaluateFlags flags); + EvaluateFlags evaluateFlags() const; + bool enabled() const; // Inherited from QDeclarativeAbstractBinding @@ -177,6 +184,8 @@ private: Q_DECLARE_PRIVATE(QDeclarativeBinding) }; +Q_DECLARE_OPERATORS_FOR_FLAGS(QDeclarativeBinding::EvaluateFlags) + QT_END_NAMESPACE Q_DECLARE_METATYPE(QDeclarativeBinding*) diff --git a/src/declarative/qml/qdeclarativeexpression.cpp b/src/declarative/qml/qdeclarativeexpression.cpp index 26c91a5..7a85ada 100644 --- a/src/declarative/qml/qdeclarativeexpression.cpp +++ b/src/declarative/qml/qdeclarativeexpression.cpp @@ -103,6 +103,19 @@ void QDeclarativeExpressionPrivate::init(QDeclarativeContextData *ctxt, const QS expressionFunctionValid = false; } +void QDeclarativeExpressionPrivate::init(QDeclarativeContextData *ctxt, const QScriptValue &func, + QObject *me) +{ + expression = func.toString(); + + QDeclarativeAbstractExpression::setContext(ctxt); + scopeObject = me; + + expressionFunction = func; + expressionFunctionMode = ExplicitContext; + expressionFunctionValid = true; +} + void QDeclarativeExpressionPrivate::init(QDeclarativeContextData *ctxt, void *expr, QDeclarativeRefCount *rc, QObject *me, const QString &srcUrl, int lineNumber) @@ -304,6 +317,19 @@ QDeclarativeExpression::QDeclarativeExpression(QDeclarativeContextData *ctxt, QO d->setNotifyObject(this, QDeclarativeExpression_notifyIdx); } +/*! \internal */ +QDeclarativeExpression::QDeclarativeExpression(QDeclarativeContextData *ctxt, QObject *scope, const QScriptValue &func, + QDeclarativeExpressionPrivate &dd) +: QObject(dd, 0) +{ + Q_D(QDeclarativeExpression); + d->init(ctxt, func, scope); + + if (QDeclarativeExpression_notifyIdx == -1) + QDeclarativeExpression_notifyIdx = QDeclarativeExpression::staticMetaObject.indexOfMethod("_q_notify()"); + d->setNotifyObject(this, QDeclarativeExpression_notifyIdx); +} + /*! Destroy the QDeclarativeExpression instance. */ @@ -412,6 +438,16 @@ void QDeclarativeQtScriptExpression::setNotifyObject(QObject *object, int notify } } +void QDeclarativeQtScriptExpression::setEvaluateFlags(EvaluateFlags flags) +{ + evalFlags = flags; +} + +QDeclarativeQtScriptExpression::EvaluateFlags QDeclarativeQtScriptExpression::evaluateFlags() const +{ + return evalFlags; +} + QScriptValue QDeclarativeQtScriptExpression::scriptValue(QObject *secondaryScope, bool *isUndefined) { Q_ASSERT(context() && context()->engine); @@ -476,7 +512,10 @@ QScriptValue QDeclarativeQtScriptExpression::eval(QObject *secondaryScope, bool oldOverride = ep->contextClass->setOverrideObject(expressionContext, secondaryScope); } - QScriptValue svalue = expressionFunction.call(); // This could cause this to be deleted + QScriptValue thisObject; + if (evalFlags & RequiresThisObject) + thisObject = ep->objectClass->newQObject(scopeObject); + QScriptValue svalue = expressionFunction.call(thisObject); // This could cause this c++ object to be deleted if (isShared) { ep->sharedContext = oldSharedContext; diff --git a/src/declarative/qml/qdeclarativeexpression.h b/src/declarative/qml/qdeclarativeexpression.h index 72c5947..d40094b 100644 --- a/src/declarative/qml/qdeclarativeexpression.h +++ b/src/declarative/qml/qdeclarativeexpression.h @@ -59,6 +59,7 @@ class QDeclarativeEngine; class QDeclarativeContext; class QDeclarativeExpressionPrivate; class QDeclarativeContextData; +class QScriptValue; class Q_DECLARATIVE_EXPORT QDeclarativeExpression : public QObject { Q_OBJECT @@ -94,6 +95,8 @@ Q_SIGNALS: protected: QDeclarativeExpression(QDeclarativeContextData *, QObject *, const QString &, QDeclarativeExpressionPrivate &dd); + QDeclarativeExpression(QDeclarativeContextData *, QObject *, const QScriptValue &, + QDeclarativeExpressionPrivate &dd); QDeclarativeExpression(QDeclarativeContextData *, void *, QDeclarativeRefCount *rc, QObject *me, const QString &, int, QDeclarativeExpressionPrivate &dd); diff --git a/src/declarative/qml/qdeclarativeexpression_p.h b/src/declarative/qml/qdeclarativeexpression_p.h index 1d25609..51cae0f 100644 --- a/src/declarative/qml/qdeclarativeexpression_p.h +++ b/src/declarative/qml/qdeclarativeexpression_p.h @@ -113,6 +113,9 @@ class QDeclarativeQtScriptExpression : public QDeclarativeAbstractExpression, public: enum Mode { SharedContext, ExplicitContext }; + enum EvaluateFlag { RequiresThisObject = 0x01 }; + Q_DECLARE_FLAGS(EvaluateFlags, EvaluateFlag) + QDeclarativeQtScriptExpression(); virtual ~QDeclarativeQtScriptExpression(); @@ -131,6 +134,9 @@ public: void resetNotifyOnChange(); void setNotifyObject(QObject *, int ); + void setEvaluateFlags(EvaluateFlags flags); + EvaluateFlags evaluateFlags() const; + QScriptValue scriptValue(QObject *secondaryScope, bool *isUndefined); class DeleteWatcher { @@ -157,8 +163,13 @@ private: QObject *guardObject; int guardObjectNotifyIndex; bool *deleted; + + EvaluateFlags evalFlags; }; +Q_DECLARE_OPERATORS_FOR_FLAGS(QDeclarativeQtScriptExpression::EvaluateFlags) + + class QDeclarativeExpression; class QString; class QDeclarativeExpressionPrivate : public QObjectPrivate, public QDeclarativeQtScriptExpression @@ -169,6 +180,7 @@ public: ~QDeclarativeExpressionPrivate(); void init(QDeclarativeContextData *, const QString &, QObject *); + void init(QDeclarativeContextData *, const QScriptValue &, QObject *); void init(QDeclarativeContextData *, void *, QDeclarativeRefCount *, QObject *, const QString &, int); QVariant value(QObject *secondaryScope = 0, bool *isUndefined = 0); diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp index cbbf2b9..7701a23 100644 --- a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp +++ b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp @@ -359,8 +359,20 @@ void QDeclarativeObjectScriptClass::setProperty(QObject *obj, } } + QDeclarativeBinding *newBinding = 0; + if (value.isFunction() && !value.isRegExp()) { + QScriptContextInfo ctxtInfo(context); + QDeclarativePropertyCache::ValueTypeData valueTypeData; + + newBinding = new QDeclarativeBinding(value, obj, evalContext); + newBinding->setSourceLocation(ctxtInfo.fileName(), ctxtInfo.functionStartLineNumber()); + newBinding->setTarget(QDeclarativePropertyPrivate::restore(*lastData, valueTypeData, obj, evalContext)); + if (newBinding->expression().contains("this")) + newBinding->setEvaluateFlags(newBinding->evaluateFlags() | QDeclarativeBinding::RequiresThisObject); + } + QDeclarativeAbstractBinding *delBinding = - QDeclarativePropertyPrivate::setBinding(obj, lastData->coreIndex, -1, 0); + QDeclarativePropertyPrivate::setBinding(obj, lastData->coreIndex, -1, newBinding); if (delBinding) delBinding->destroy(); @@ -379,10 +391,7 @@ void QDeclarativeObjectScriptClass::setProperty(QObject *obj, QString error = QLatin1String("Cannot assign [undefined] to ") + QLatin1String(QMetaType::typeName(lastData->propType)); context->throwError(error); - } else if (!value.isRegExp() && value.isFunction()) { - QString error = QLatin1String("Cannot assign a function to a property."); - context->throwError(error); - } else { + } else if (!value.isFunction()) { QVariant v; if (lastData->flags & QDeclarativePropertyCache::Data::IsQList) v = enginePriv->scriptValueToVariant(value, qMetaTypeId >()); diff --git a/src/declarative/qml/qdeclarativeproperty.cpp b/src/declarative/qml/qdeclarativeproperty.cpp index 76829b7..61e3002 100644 --- a/src/declarative/qml/qdeclarativeproperty.cpp +++ b/src/declarative/qml/qdeclarativeproperty.cpp @@ -1480,19 +1480,28 @@ QDeclarativePropertyPrivate::restore(const QByteArray &data, QObject *object, QD if (data.isEmpty()) return prop; - prop.d = new QDeclarativePropertyPrivate; - prop.d->object = object; - prop.d->context = ctxt; - prop.d->engine = ctxt->engine; - const SerializedData *sd = (const SerializedData *)data.constData(); if (sd->isValueType) { const ValueTypeSerializedData *vt = (const ValueTypeSerializedData *)sd; - prop.d->core = vt->core; - prop.d->valueType = vt->valueType; + return restore(vt->core, vt->valueType, object, ctxt); } else { - prop.d->core = sd->core; + QDeclarativePropertyCache::ValueTypeData data; + return restore(sd->core, data, object, ctxt); } +} + +QDeclarativeProperty +QDeclarativePropertyPrivate::restore(const QDeclarativePropertyCache::Data &data, const QDeclarativePropertyCache::ValueTypeData &valueType, QObject *object, QDeclarativeContextData *ctxt) +{ + QDeclarativeProperty prop; + + prop.d = new QDeclarativePropertyPrivate; + prop.d->object = object; + prop.d->context = ctxt; + prop.d->engine = ctxt->engine; + + prop.d->core = data; + prop.d->valueType = valueType; return prop; } diff --git a/src/declarative/qml/qdeclarativeproperty_p.h b/src/declarative/qml/qdeclarativeproperty_p.h index fa0fef4..bd2c891 100644 --- a/src/declarative/qml/qdeclarativeproperty_p.h +++ b/src/declarative/qml/qdeclarativeproperty_p.h @@ -112,7 +112,12 @@ public: static QByteArray saveValueType(const QMetaObject *, int, const QMetaObject *, int); static QByteArray saveProperty(const QMetaObject *, int); + static QDeclarativeProperty restore(const QByteArray &, QObject *, QDeclarativeContextData *); + static QDeclarativeProperty restore(const QDeclarativePropertyCache::Data &, + const QDeclarativePropertyCache::ValueTypeData &, + QObject *, + QDeclarativeContextData *); static bool equal(const QMetaObject *, const QMetaObject *); static bool canConvert(const QMetaObject *from, const QMetaObject *to); diff --git a/src/declarative/qml/qdeclarativevaluetypescriptclass.cpp b/src/declarative/qml/qdeclarativevaluetypescriptclass.cpp index 558ef90..200cc1c 100644 --- a/src/declarative/qml/qdeclarativevaluetypescriptclass.cpp +++ b/src/declarative/qml/qdeclarativevaluetypescriptclass.cpp @@ -46,6 +46,8 @@ #include "private/qdeclarativeengine_p.h" #include "private/qdeclarativeguard_p.h" +#include + QT_BEGIN_NAMESPACE struct QDeclarativeValueTypeObject : public QScriptDeclarativeClass::Object { @@ -161,17 +163,41 @@ void QDeclarativeValueTypeScriptClass::setProperty(Object *obj, const Identifier if (o->objectType == QDeclarativeValueTypeObject::Reference) { QDeclarativeValueTypeReference *ref = static_cast(obj); + ref->type->read(ref->object, ref->property); + QMetaProperty p = ref->type->metaObject()->property(m_lastIndex); + + QDeclarativeBinding *newBinding = 0; + if (value.isFunction() && !value.isRegExp()) { + QDeclarativeContextData *ctxt = QDeclarativeEnginePrivate::get(engine)->getContext(context()); + + QDeclarativePropertyCache::Data cacheData; + cacheData.flags = QDeclarativePropertyCache::Data::IsWritable; + cacheData.propType = ref->object->metaObject()->property(ref->property).userType(); + cacheData.coreIndex = ref->property; + + QDeclarativePropertyCache::ValueTypeData valueTypeData; + valueTypeData.valueTypeCoreIdx = m_lastIndex; + valueTypeData.valueTypePropType = p.userType(); + + newBinding = new QDeclarativeBinding(value, ref->object, ctxt); + QScriptContextInfo ctxtInfo(context()); + newBinding->setSourceLocation(ctxtInfo.fileName(), ctxtInfo.functionStartLineNumber()); + QDeclarativeProperty prop = QDeclarativePropertyPrivate::restore(cacheData, valueTypeData, ref->object, ctxt); + newBinding->setTarget(prop); + if (newBinding->expression().contains("this")) + newBinding->setEvaluateFlags(newBinding->evaluateFlags() | QDeclarativeBinding::RequiresThisObject); + } + QDeclarativeAbstractBinding *delBinding = - QDeclarativePropertyPrivate::setBinding(ref->object, ref->property, m_lastIndex, 0); + QDeclarativePropertyPrivate::setBinding(ref->object, ref->property, m_lastIndex, newBinding); if (delBinding) delBinding->destroy(); - ref->type->read(ref->object, ref->property); - QMetaProperty p = ref->type->metaObject()->property(m_lastIndex); if (p.isEnumType() && (QMetaType::Type)v.type() == QMetaType::Double) v = v.toInt(); p.write(ref->type, v); ref->type->write(ref->object, ref->property, 0); + } else { QDeclarativeValueTypeCopy *copy = static_cast(obj); copy->type->setValue(copy->value); diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/functionAssignment.2.qml b/tests/auto/declarative/qdeclarativeecmascript/data/functionAssignment.2.qml index 948b39c..c8c926a 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/data/functionAssignment.2.qml +++ b/tests/auto/declarative/qdeclarativeecmascript/data/functionAssignment.2.qml @@ -1,13 +1,73 @@ import Qt.test 1.0 +import QtQuick 1.0 + +import "functionAssignment.js" as Script MyQmlObject { property variant a - property bool runTest: false - onRunTestChanged: { + property int aNumber: 10 + + property bool assignToProperty: false + property bool assignToPropertyFromJsFile: false + + property bool assignWithThis: false + property bool assignWithThisFromJsFile: false + + property bool assignToValueType: false + + property bool assignFuncWithoutReturn: false + property bool assignWrongType: false + property bool assignWrongTypeToValueType: false + + + onAssignToPropertyChanged: { + function myFunction() { + return aNumber * 10; + } + a = myFunction; + } + + property QtObject obj: QtObject { + property int aNumber: 4212 + function myFunction() { + return this.aNumber * 10; // should use the aNumber from root, not this object + } + } + onAssignWithThisChanged: { + a = obj.myFunction; + } + + onAssignToPropertyFromJsFileChanged: { + Script.bindPropertyWithThis() + } + + onAssignWithThisFromJsFileChanged: { + Script.bindProperty() + } + + property Text text: Text { } + onAssignToValueTypeChanged: { + text.font.pixelSize = (function() { return aNumber * 10; }) + a = (function() { return text.font.pixelSize; }) + } + + + // detecting errors: + + onAssignFuncWithoutReturnChanged: { function myFunction() { - console.log("hello world"); } a = myFunction; } + onAssignWrongTypeChanged: { + function myFunction() { + return 'a string'; + } + aNumber = myFunction; + } + + onAssignWrongTypeToValueTypeChanged: { + text.font.pixelSize = (function() { return 'a string'; }) + } } diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/functionAssignment.js b/tests/auto/declarative/qdeclarativeecmascript/data/functionAssignment.js new file mode 100644 index 0000000..14daa76 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/functionAssignment.js @@ -0,0 +1,17 @@ +function bindProperty() +{ + a = (function(){ return aNumber * 10 }) +} + + +function TestObject() { } +TestObject.prototype.aNumber = 928349 +TestObject.prototype.bindFunction = function() { + return this.aNumber * 10 // this should not use the TestObject's aNumber +} +var testObj = new TestObject() + +function bindPropertyWithThis() +{ + a = testObj.bindFunction +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp index cfe8cad..e7f9a2c 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp +++ b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp @@ -155,7 +155,10 @@ private slots: void qtcreatorbug_1289(); void noSpuriousWarningsAtShutdown(); void canAssignNullToQObject(); - void functionAssignment(); + void functionAssignment_fromBinding(); + void functionAssignment_fromJS(); + void functionAssignment_fromJS_data(); + void functionAssignmentfromJS_invalid(); void eval(); void function(); void qtbug_10696(); @@ -2514,9 +2517,8 @@ void tst_qdeclarativeecmascript::canAssignNullToQObject() } } -void tst_qdeclarativeecmascript::functionAssignment() +void tst_qdeclarativeecmascript::functionAssignment_fromBinding() { - { QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.1.qml")); QString url = component.url().toString(); @@ -2529,26 +2531,64 @@ void tst_qdeclarativeecmascript::functionAssignment() QVERIFY(!o->property("a").isValid()); delete o; - } +} - { +void tst_qdeclarativeecmascript::functionAssignment_fromJS() +{ + QFETCH(QString, triggerProperty); + + QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml")); + QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString())); + + MyQmlObject *o = qobject_cast(component.create()); + QVERIFY(o != 0); + QVERIFY(!o->property("a").isValid()); + + o->setProperty("aNumber", QVariant(5)); + o->setProperty(triggerProperty.toUtf8().constData(), true); + QCOMPARE(o->property("a"), QVariant(50)); + + o->setProperty("aNumber", QVariant(10)); + QCOMPARE(o->property("a"), QVariant(100)); + + delete o; +} + +void tst_qdeclarativeecmascript::functionAssignment_fromJS_data() +{ + QTest::addColumn("triggerProperty"); + + QTest::newRow("assign to property") << "assignToProperty"; + QTest::newRow("assign to property, from JS file") << "assignToPropertyFromJsFile"; + + QTest::newRow("assign to value type") << "assignToValueType"; + + QTest::newRow("use 'this'") << "assignWithThis"; + QTest::newRow("use 'this' from JS file") << "assignWithThisFromJsFile"; +} + +void tst_qdeclarativeecmascript::functionAssignmentfromJS_invalid() +{ QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml")); + QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString())); MyQmlObject *o = qobject_cast(component.create()); QVERIFY(o != 0); + QVERIFY(!o->property("a").isValid()); + o->setProperty("assignFuncWithoutReturn", true); QVERIFY(!o->property("a").isValid()); - + QString url = component.url().toString(); - QString warning = url + ":10: Error: Cannot assign a function to a property."; + QString warning = url + ":63: Unable to assign QString to int"; QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); - - o->setProperty("runTest", true); - - QVERIFY(!o->property("a").isValid()); + o->setProperty("assignWrongType", true); + + warning = url + ":70: Unable to assign QString to int"; + QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); + o->setProperty("assignWrongTypeToValueType", true); delete o; - } } void tst_qdeclarativeecmascript::eval() -- cgit v0.12 From 80f74d3801ddece4d34b4a663bf1bdc23ecc4a67 Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Thu, 27 Jan 2011 15:53:45 +1000 Subject: Don't load components until the Loader component itself is completed Previously components were loaded as soon as setSource() or setSourceComponent() were called, even if the Loader component was not complete. If a source component had been set, the itemChanged(), statusChanged() etc. signals would be emitted before the Loader would be complete and before the internal item had been sized. If a source had been set via url, these signals were not emitted at all. It also caused loaded() to be emitted twice for components set by setSourceComponent(). Task-number: QTBUG-16319 Reviewed-by: Martin Jones --- .../graphicsitems/qdeclarativeloader.cpp | 57 +++++++------ .../graphicsitems/qdeclarativeloader_p_p.h | 1 + .../qdeclarativeloader/tst_qdeclarativeloader.cpp | 94 +++++++++++++--------- 3 files changed, 86 insertions(+), 66 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativeloader.cpp b/src/declarative/graphicsitems/qdeclarativeloader.cpp index 242435c..871850d 100644 --- a/src/declarative/graphicsitems/qdeclarativeloader.cpp +++ b/src/declarative/graphicsitems/qdeclarativeloader.cpp @@ -262,6 +262,7 @@ void QDeclarativeLoader::setSource(const QUrl &url) d->clear(); d->source = url; + if (d->source.isEmpty()) { emit sourceChanged(); emit statusChanged(); @@ -272,18 +273,9 @@ void QDeclarativeLoader::setSource(const QUrl &url) d->component = new QDeclarativeComponent(qmlEngine(this), d->source, this); d->ownComponent = true; - if (!d->component->isLoading()) { - d->_q_sourceLoaded(); - } else { - connect(d->component, SIGNAL(statusChanged(QDeclarativeComponent::Status)), - this, SLOT(_q_sourceLoaded())); - connect(d->component, SIGNAL(progressChanged(qreal)), - this, SIGNAL(progressChanged())); - emit statusChanged(); - emit progressChanged(); - emit sourceChanged(); - emit itemChanged(); - } + + if (isComponentComplete()) + d->load(); } /*! @@ -324,6 +316,7 @@ void QDeclarativeLoader::setSourceComponent(QDeclarativeComponent *comp) d->component = comp; d->ownComponent = false; + if (!d->component) { emit sourceChanged(); emit statusChanged(); @@ -332,18 +325,8 @@ void QDeclarativeLoader::setSourceComponent(QDeclarativeComponent *comp) return; } - if (!d->component->isLoading()) { - d->_q_sourceLoaded(); - } else { - connect(d->component, SIGNAL(statusChanged(QDeclarativeComponent::Status)), - this, SLOT(_q_sourceLoaded())); - connect(d->component, SIGNAL(progressChanged(qreal)), - this, SIGNAL(progressChanged())); - emit progressChanged(); - emit sourceChanged(); - emit statusChanged(); - emit itemChanged(); - } + if (isComponentComplete()) + d->load(); } void QDeclarativeLoader::resetSourceComponent() @@ -351,6 +334,27 @@ void QDeclarativeLoader::resetSourceComponent() setSourceComponent(0); } +void QDeclarativeLoaderPrivate::load() +{ + Q_Q(QDeclarativeLoader); + + if (!q->isComponentComplete() || !component) + return; + + if (!component->isLoading()) { + _q_sourceLoaded(); + } else { + QObject::connect(component, SIGNAL(statusChanged(QDeclarativeComponent::Status)), + q, SLOT(_q_sourceLoaded())); + QObject::connect(component, SIGNAL(progressChanged(qreal)), + q, SIGNAL(progressChanged())); + emit q->statusChanged(); + emit q->progressChanged(); + emit q->sourceChanged(); + emit q->itemChanged(); + } +} + void QDeclarativeLoaderPrivate::_q_sourceLoaded() { Q_Q(QDeclarativeLoader); @@ -465,9 +469,10 @@ QDeclarativeLoader::Status QDeclarativeLoader::status() const void QDeclarativeLoader::componentComplete() { + Q_D(QDeclarativeLoader); + QDeclarativeItem::componentComplete(); - if (status() == Ready) - emit loaded(); + d->load(); } diff --git a/src/declarative/graphicsitems/qdeclarativeloader_p_p.h b/src/declarative/graphicsitems/qdeclarativeloader_p_p.h index 2239b16..e366a14 100644 --- a/src/declarative/graphicsitems/qdeclarativeloader_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativeloader_p_p.h @@ -72,6 +72,7 @@ public: void itemGeometryChanged(QDeclarativeItem *item, const QRectF &newGeometry, const QRectF &oldGeometry); void clear(); void initResize(); + void load(); QUrl source; QGraphicsObject *item; diff --git a/tests/auto/declarative/qdeclarativeloader/tst_qdeclarativeloader.cpp b/tests/auto/declarative/qdeclarativeloader/tst_qdeclarativeloader.cpp index bfa81ed..358822e 100644 --- a/tests/auto/declarative/qdeclarativeloader/tst_qdeclarativeloader.cpp +++ b/tests/auto/declarative/qdeclarativeloader/tst_qdeclarativeloader.cpp @@ -69,9 +69,8 @@ public: tst_QDeclarativeLoader(); private slots: - void url(); - void invalidUrl(); - void component(); + void sourceOrComponent(); + void sourceOrComponent_data(); void clear(); void urlToComponent(); void componentToUrl(); @@ -100,56 +99,71 @@ tst_QDeclarativeLoader::tst_QDeclarativeLoader() { } -void tst_QDeclarativeLoader::url() +void tst_QDeclarativeLoader::sourceOrComponent() { + QFETCH(QString, sourceDefinition); + QFETCH(QUrl, sourceUrl); + QFETCH(QString, errorString); + + bool error = !errorString.isEmpty(); + if (error) + QTest::ignoreMessage(QtWarningMsg, errorString.toUtf8().constData()); + QDeclarativeComponent component(&engine); - component.setData(QByteArray("import QtQuick 1.0\nLoader { property int did_load: 0; onLoaded: did_load=123; source: \"Rect120x60.qml\" }"), TEST_FILE("")); + component.setData(QByteArray( + "import QtQuick 1.0\n" + "Loader {\n" + " property int onItemChangedCount: 0\n" + " property int onSourceChangedCount: 0\n" + " property int onStatusChangedCount: 0\n" + " property int onProgressChangedCount: 0\n" + " property int onLoadedCount: 0\n") + + sourceDefinition.toUtf8() + + QByteArray( + " onItemChanged: onItemChangedCount += 1\n" + " onSourceChanged: onSourceChangedCount += 1\n" + " onStatusChanged: onStatusChangedCount += 1\n" + " onProgressChanged: onProgressChangedCount += 1\n" + " onLoaded: onLoadedCount += 1\n" + "}") + , TEST_FILE("")); + QDeclarativeLoader *loader = qobject_cast(component.create()); QVERIFY(loader != 0); - QVERIFY(loader->item()); - QVERIFY(loader->source() == QUrl::fromLocalFile(SRCDIR "/data/Rect120x60.qml")); + QCOMPARE(loader->item() == 0, error); + QCOMPARE(loader->source(), sourceUrl); QCOMPARE(loader->progress(), 1.0); - QCOMPARE(loader->status(), QDeclarativeLoader::Ready); - QCOMPARE(loader->property("did_load").toInt(), 123); - QCOMPARE(static_cast(loader)->children().count(), 1); - delete loader; -} + QCOMPARE(loader->status(), error ? QDeclarativeLoader::Error : QDeclarativeLoader::Ready); + QCOMPARE(static_cast(loader)->children().count(), error ? 0: 1); -void tst_QDeclarativeLoader::component() -{ - QDeclarativeComponent component(&engine, TEST_FILE("/SetSourceComponent.qml")); - QDeclarativeItem *item = qobject_cast(component.create()); - QVERIFY(item); + if (!error) { + QDeclarativeComponent *c = qobject_cast(loader->QGraphicsObject::children().at(0)); + QVERIFY(c); + QCOMPARE(loader->sourceComponent(), c); + } - QDeclarativeLoader *loader = qobject_cast(item->QGraphicsObject::children().at(1)); - QVERIFY(loader); - QVERIFY(loader->item()); - QCOMPARE(loader->progress(), 1.0); - QCOMPARE(loader->status(), QDeclarativeLoader::Ready); - QCOMPARE(static_cast(loader)->children().count(), 1); + QCOMPARE(loader->property("onSourceChangedCount").toInt(), 1); + QCOMPARE(loader->property("onStatusChangedCount").toInt(), 1); + QCOMPARE(loader->property("onProgressChangedCount").toInt(), 1); - QDeclarativeComponent *c = qobject_cast(item->QGraphicsObject::children().at(0)); - QVERIFY(c); - QCOMPARE(loader->sourceComponent(), c); + QCOMPARE(loader->property("onItemChangedCount").toInt(), error ? 0 : 1); + QCOMPARE(loader->property("onLoadedCount").toInt(), error ? 0 : 1); - delete item; + delete loader; } -void tst_QDeclarativeLoader::invalidUrl() +void tst_QDeclarativeLoader::sourceOrComponent_data() { - QTest::ignoreMessage(QtWarningMsg, QString(QUrl::fromLocalFile(SRCDIR "/data/IDontExist.qml").toString() + ": File not found").toUtf8().constData()); + QTest::addColumn("sourceDefinition"); + QTest::addColumn("sourceUrl"); + QTest::addColumn("errorString"); - QDeclarativeComponent component(&engine); - component.setData(QByteArray("import QtQuick 1.0\nLoader { source: \"IDontExist.qml\" }"), TEST_FILE("")); - QDeclarativeLoader *loader = qobject_cast(component.create()); - QVERIFY(loader != 0); - QVERIFY(loader->item() == 0); - QCOMPARE(loader->progress(), 1.0); - QCOMPARE(loader->status(), QDeclarativeLoader::Error); - QCOMPARE(static_cast(loader)->children().count(), 0); + QTest::newRow("source") << "source: 'Rect120x60.qml'\n" << QUrl::fromLocalFile(SRCDIR "/data/Rect120x60.qml") << ""; + QTest::newRow("sourceComponent") << "Component { id: comp; Rectangle { width: 100; height: 50 } }\n sourceComponent: comp\n" << QUrl() << ""; - delete loader; + QTest::newRow("invalid source") << "source: 'IDontExist.qml'\n" << QUrl::fromLocalFile(SRCDIR "/data/IDontExist.qml") + << QString(QUrl::fromLocalFile(SRCDIR "/data/IDontExist.qml").toString() + ": File not found"); } void tst_QDeclarativeLoader::clear() @@ -446,7 +460,7 @@ void tst_QDeclarativeLoader::networkRequestUrl() server.serveDirectory(SRCDIR "/data"); QDeclarativeComponent component(&engine); - component.setData(QByteArray("import QtQuick 1.0\nLoader { property int did_load : 0; source: \"http://127.0.0.1:14450/Rect120x60.qml\"; onLoaded: did_load=123 }"), QUrl::fromLocalFile(SRCDIR "/dummy.qml")); + component.setData(QByteArray("import QtQuick 1.0\nLoader { property int signalCount : 0; source: \"http://127.0.0.1:14450/Rect120x60.qml\"; onLoaded: signalCount += 1 }"), QUrl::fromLocalFile(SRCDIR "/dummy.qml")); if (component.isError()) qDebug() << component.errors(); QDeclarativeLoader *loader = qobject_cast(component.create()); @@ -456,7 +470,7 @@ void tst_QDeclarativeLoader::networkRequestUrl() QVERIFY(loader->item()); QCOMPARE(loader->progress(), 1.0); - QCOMPARE(loader->property("did_load").toInt(), 123); + QCOMPARE(loader->property("signalCount").toInt(), 1); QCOMPARE(static_cast(loader)->children().count(), 1); delete loader; -- cgit v0.12 From aa40f956bab22678b62f630af97f51f9e8fab9f8 Mon Sep 17 00:00:00 2001 From: Christopher Ham Date: Thu, 27 Jan 2011 16:34:07 +1000 Subject: Fix righ-to-left support in text components. In text, textEdit and textInput, the layout of the text should automatically align to the right if the it is deemed to be right-to-left text. Task-number: QTBUG-15880 Reviewed-by: Bea Lam --- src/declarative/qml/qdeclarativecomponent.cpp | 67 +++++++++++++++++----- src/declarative/qml/qdeclarativecomponent.h | 1 + src/declarative/qml/qdeclarativecomponent_p.h | 2 + .../data/createObjectWithScript.qml | 21 +++++++ .../tst_qdeclarativecomponent.cpp | 28 +++++++++ 5 files changed, 106 insertions(+), 13 deletions(-) create mode 100644 tests/auto/declarative/qdeclarativecomponent/data/createObjectWithScript.qml diff --git a/src/declarative/qml/qdeclarativecomponent.cpp b/src/declarative/qml/qdeclarativecomponent.cpp index 8865ddd..bd6e2d8 100644 --- a/src/declarative/qml/qdeclarativecomponent.cpp +++ b/src/declarative/qml/qdeclarativecomponent.cpp @@ -54,11 +54,13 @@ #include "private/qdeclarativescriptparser_p.h" #include "private/qdeclarativedebugtrace_p.h" #include "private/qdeclarativeenginedebug_p.h" +#include #include #include #include #include +#include QT_BEGIN_NAMESPACE @@ -613,7 +615,7 @@ QDeclarativeComponent::QDeclarativeComponent(QDeclarativeComponentPrivate &dd, Q } /*! - \qmlmethod object Component::createObject(Item parent) + \qmlmethod object Component::createObject(Item parent, Script valuemap = null) Creates and returns an object instance of this component that will have the given \a parent. Returns null if object creation fails. @@ -631,6 +633,12 @@ QDeclarativeComponent::QDeclarativeComponent(QDeclarativeComponentPrivate &dd, Q it is not destroyed by the garbage collector. This is regardless of Item.parent being set afterwards, since setting the Item parent does not change object ownership; only the graphical parent is changed. + Since QtQuick 1.1, a map of property values can be optionally passed to the method that applies values to the object's properties + before its creation is finalised. This will avoid binding issues that can occur when the object is + instantiated before property bindings have been set. For example: + + \code component.createObject(parent, {"x": 100, "y": 100, "specialProperty": someObject}); \endcode + Dynamically created instances can be deleted with the \c destroy() method. See \l {Dynamic Object Management in QML} for more information. */ @@ -646,25 +654,46 @@ QDeclarativeComponent::QDeclarativeComponent(QDeclarativeComponentPrivate &dd, Q QScriptValue QDeclarativeComponent::createObject(QObject* parent) { Q_D(QDeclarativeComponent); - QDeclarativeContext* ctxt = creationContext(); - if(!ctxt && d->engine) - ctxt = d->engine->rootContext(); + return d->createObject(parent, QScriptValue(QScriptValue::NullValue)); +} + +/*! + \internal + Overloadable method allows properties to be set during creation +*/ +QScriptValue QDeclarativeComponent::createObject(QObject* parent, const QScriptValue& valuemap) +{ + Q_D(QDeclarativeComponent); + + if (valuemap.isObject() && !valuemap.isArray()) { + qmlInfo(this) << tr("creatObject: value is not an object"); + return QScriptValue(QScriptValue::NullValue); + } + return d->createObject(parent, valuemap); +} + +QScriptValue QDeclarativeComponentPrivate::createObject(QObject *publicParent, const QScriptValue valuemap) +{ + Q_Q(QDeclarativeComponent); + QDeclarativeContext* ctxt = q->creationContext(); + if(!ctxt && engine) + ctxt = engine->rootContext(); if (!ctxt) return QScriptValue(QScriptValue::NullValue); - QObject* ret = beginCreate(ctxt); + QObject* ret = q->beginCreate(ctxt); if (!ret) { - completeCreate(); + q->completeCreate(); return QScriptValue(QScriptValue::NullValue); } - if (parent) { - ret->setParent(parent); + if (publicParent) { + ret->setParent(publicParent); QList functions = QDeclarativeMetaType::parentFunctions(); bool needParent = false; for (int ii = 0; ii < functions.count(); ++ii) { - QDeclarativePrivate::AutoParentResult res = functions.at(ii)(ret, parent); + QDeclarativePrivate::AutoParentResult res = functions.at(ii)(ret, publicParent); if (res == QDeclarativePrivate::Parented) { needParent = false; break; @@ -673,14 +702,26 @@ QScriptValue QDeclarativeComponent::createObject(QObject* parent) } } - if (needParent) + if (needParent) qWarning("QDeclarativeComponent: Created graphical object was not placed in the graphics scene."); } - completeCreate(); - QDeclarativeEnginePrivate *priv = QDeclarativeEnginePrivate::get(d->engine); + QDeclarativeEnginePrivate *priv = QDeclarativeEnginePrivate::get(engine); QDeclarativeData::get(ret, true)->setImplicitDestructible(); - return priv->objectClass->newQObject(ret, QMetaType::QObjectStar); + QScriptValue newObject = priv->objectClass->newQObject(ret, QMetaType::QObjectStar); + + if (valuemap.isObject() && !valuemap.isArray()) { + //Iterate through and assign properties + QScriptValueIterator it(valuemap); + while (it.hasNext()) { + it.next(); + newObject.setProperty(it.name(), it.value(), QScriptValue::KeepExistingFlags); + } + } + + q->completeCreate(); + + return newObject; } /*! diff --git a/src/declarative/qml/qdeclarativecomponent.h b/src/declarative/qml/qdeclarativecomponent.h index 6f28f2e..3d318c3 100644 --- a/src/declarative/qml/qdeclarativecomponent.h +++ b/src/declarative/qml/qdeclarativecomponent.h @@ -110,6 +110,7 @@ Q_SIGNALS: protected: QDeclarativeComponent(QDeclarativeComponentPrivate &dd, QObject* parent); Q_INVOKABLE QScriptValue createObject(QObject* parent); + Q_INVOKABLE QScriptValue createObject(QObject* parent, const QScriptValue& valuemap); //XXX Versioning private: QDeclarativeComponent(QDeclarativeEngine *, QDeclarativeCompiledData *, int, int, QObject *parent); diff --git a/src/declarative/qml/qdeclarativecomponent_p.h b/src/declarative/qml/qdeclarativecomponent_p.h index 02a6ce8..f8bec2b 100644 --- a/src/declarative/qml/qdeclarativecomponent_p.h +++ b/src/declarative/qml/qdeclarativecomponent_p.h @@ -116,6 +116,8 @@ public: ConstructionState *state); static void complete(QDeclarativeEnginePrivate *enginePriv, ConstructionState *state); + QScriptValue createObject(QObject *publicParent, const QScriptValue valuemap); + QDeclarativeEngine *engine; QDeclarativeGuardedContextData creationContext; diff --git a/tests/auto/declarative/qdeclarativecomponent/data/createObjectWithScript.qml b/tests/auto/declarative/qdeclarativecomponent/data/createObjectWithScript.qml new file mode 100644 index 0000000..60d4c44 --- /dev/null +++ b/tests/auto/declarative/qdeclarativecomponent/data/createObjectWithScript.qml @@ -0,0 +1,21 @@ +import QtQuick 1.0 + +Item{ + id: root + property QtObject declarativerectangle : null + property QtObject declarativeitem : null + Component{id: a; Rectangle{} } + Component{ + id: b + Item{ + property bool testBool: false + property int testInt: null + property QtObject testObject: null + } + } + + Component.onCompleted: { + root.declarativerectangle = a.createObject(root, {"x":17,"y":17, "color":"white"}); + root.declarativeitem = b.createObject(root, {"x":17,"y":17,"testBool":true,"testInt":17,"testObject":root}); + } +} diff --git a/tests/auto/declarative/qdeclarativecomponent/tst_qdeclarativecomponent.cpp b/tests/auto/declarative/qdeclarativecomponent/tst_qdeclarativecomponent.cpp index 4db538e..829b762 100644 --- a/tests/auto/declarative/qdeclarativecomponent/tst_qdeclarativecomponent.cpp +++ b/tests/auto/declarative/qdeclarativecomponent/tst_qdeclarativecomponent.cpp @@ -44,6 +44,8 @@ #include #include #include +#include +#include #ifdef Q_OS_SYMBIAN // In Symbian OS test data is located in applications private dir @@ -60,6 +62,7 @@ private slots: void null(); void loadEmptyUrl(); void qmlCreateObject(); + void qmlCreatObjectWithScript(); private: QDeclarativeEngine engine; @@ -118,6 +121,31 @@ void tst_qdeclarativecomponent::qmlCreateObject() QCOMPARE(testObject3->metaObject()->className(), "QDeclarativeGraphicsWidget"); } +void tst_qdeclarativecomponent::qmlCreatObjectWithScript() +{ + QDeclarativeEngine engine; + QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/createObjectWithScript.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + + QObject *testObject1 = object->property("declarativerectangle").value(); + QVERIFY(testObject1); + QVERIFY(testObject1->parent() == object); + QCOMPARE(testObject1->property("x").value(), 17); + QCOMPARE(testObject1->property("y").value(), 17); + QCOMPARE(testObject1->property("color").value(), QColor(255,255,255)); + + QObject *testObject2 = object->property("declarativeitem").value(); + QVERIFY(testObject2); + QVERIFY(testObject2->parent() == object); + QCOMPARE(testObject2->metaObject()->className(), "QDeclarativeItem_QML_2"); + QCOMPARE(testObject2->property("x").value(), 17); + QCOMPARE(testObject2->property("y").value(), 17); + QCOMPARE(testObject2->property("testBool").value(), true); + QCOMPARE(testObject2->property("testInt").value(), 17); + QCOMPARE(testObject2->property("testObject").value(), object); +} + QTEST_MAIN(tst_qdeclarativecomponent) #include "tst_qdeclarativecomponent.moc" -- cgit v0.12 From b427b69a8efc0502cb06c388c70c8877a13db2f4 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Thu, 27 Jan 2011 16:43:23 +1000 Subject: Setting the size of a loader overwrote its implict size. If the created item does not have a valid width/height then our implictWidth/Height should be the same as the items implict size. Task-number: QTBUG-16928 Reviewed-by: Bea Lam --- .../graphicsitems/qdeclarativeloader.cpp | 22 +++++++++++++++++---- .../graphicsitems/qdeclarativeloader_p_p.h | 3 +++ .../qdeclarativeloader/data/QTBUG_16928.qml | 23 ++++++++++++++++++++++ .../qdeclarativeloader/tst_qdeclarativeloader.cpp | 13 ++++++++++++ 4 files changed, 57 insertions(+), 4 deletions(-) create mode 100644 tests/auto/declarative/qdeclarativeloader/data/QTBUG_16928.qml diff --git a/src/declarative/graphicsitems/qdeclarativeloader.cpp b/src/declarative/graphicsitems/qdeclarativeloader.cpp index 86d6404..b5f8b1d 100644 --- a/src/declarative/graphicsitems/qdeclarativeloader.cpp +++ b/src/declarative/graphicsitems/qdeclarativeloader.cpp @@ -48,7 +48,8 @@ QT_BEGIN_NAMESPACE QDeclarativeLoaderPrivate::QDeclarativeLoaderPrivate() - : item(0), component(0), ownComponent(false), isComponentComplete(false) + : item(0), component(0), ownComponent(false), isComponentComplete(false), updatingSize(false), + itemWidthValid(false), itemHeightValid(false) { } @@ -99,6 +100,10 @@ void QDeclarativeLoaderPrivate::initResize() QDeclarativeItemPrivate *p = static_cast(QGraphicsItemPrivate::get(qmlItem)); p->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry); + // We may override the item's size, so we need to remember + // whether the item provided its own valid size. + itemWidthValid = p->widthValid; + itemHeightValid = p->heightValid; } else if (item && item->isWidget()) { QGraphicsWidget *widget = static_cast(item); widget->installEventFilter(q); @@ -510,13 +515,21 @@ qreal QDeclarativeLoader::progress() const void QDeclarativeLoaderPrivate::_q_updateSize(bool loaderGeometryChanged) { Q_Q(QDeclarativeLoader); - if (!item) + if (!item || updatingSize) return; + + updatingSize = true; if (QDeclarativeItem *qmlItem = qobject_cast(item)) { - q->setImplicitWidth(qmlItem->width()); + if (!itemWidthValid) + q->setImplicitWidth(qmlItem->implicitWidth()); + else + q->setImplicitWidth(qmlItem->width()); if (loaderGeometryChanged && q->widthValid()) qmlItem->setWidth(q->width()); - q->setImplicitHeight(qmlItem->height()); + if (!itemHeightValid) + q->setImplicitHeight(qmlItem->implicitHeight()); + else + q->setImplicitHeight(qmlItem->height()); if (loaderGeometryChanged && q->heightValid()) qmlItem->setHeight(q->height()); } else if (item && item->isWidget()) { @@ -531,6 +544,7 @@ void QDeclarativeLoaderPrivate::_q_updateSize(bool loaderGeometryChanged) if (widget->size() != widgetSize) widget->resize(widgetSize); } + updatingSize = false; } /*! diff --git a/src/declarative/graphicsitems/qdeclarativeloader_p_p.h b/src/declarative/graphicsitems/qdeclarativeloader_p_p.h index 7f1a6da..6a40bf3 100644 --- a/src/declarative/graphicsitems/qdeclarativeloader_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativeloader_p_p.h @@ -79,6 +79,9 @@ public: QDeclarativeComponent *component; bool ownComponent : 1; bool isComponentComplete : 1; + bool updatingSize: 1; + bool itemWidthValid : 1; + bool itemHeightValid : 1; void _q_sourceLoaded(); void _q_updateSize(bool loaderGeometryChanged = true); diff --git a/tests/auto/declarative/qdeclarativeloader/data/QTBUG_16928.qml b/tests/auto/declarative/qdeclarativeloader/data/QTBUG_16928.qml new file mode 100644 index 0000000..9949e34 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeloader/data/QTBUG_16928.qml @@ -0,0 +1,23 @@ +import QtQuick 1.1 + +Rectangle { + color: "green" + width: loader.implicitWidth+50 + height: loader.implicitHeight+50 + + Loader { + id: loader + sourceComponent: Item { + anchors.centerIn: parent + + implicitWidth: 200 + implicitHeight: 200 + Rectangle { + color: "red" + anchors.fill: parent + } + } + anchors.fill: parent + anchors.margins: 15 + } +} diff --git a/tests/auto/declarative/qdeclarativeloader/tst_qdeclarativeloader.cpp b/tests/auto/declarative/qdeclarativeloader/tst_qdeclarativeloader.cpp index 358822e..ea8ea16 100644 --- a/tests/auto/declarative/qdeclarativeloader/tst_qdeclarativeloader.cpp +++ b/tests/auto/declarative/qdeclarativeloader/tst_qdeclarativeloader.cpp @@ -89,6 +89,7 @@ private slots: void nonItem(); void vmeErrors(); void creationContext(); + void QTBUG_16928(); private: QDeclarativeEngine engine; @@ -590,6 +591,18 @@ void tst_QDeclarativeLoader::creationContext() delete o; } +void tst_QDeclarativeLoader::QTBUG_16928() +{ + QDeclarativeComponent component(&engine, TEST_FILE("QTBUG_16928.qml")); + QDeclarativeItem *item = qobject_cast(component.create()); + QVERIFY(item); + + QCOMPARE(item->width(), 250.); + QCOMPARE(item->height(), 250.); + + delete item; +} + QTEST_MAIN(tst_QDeclarativeLoader) #include "tst_qdeclarativeloader.moc" -- cgit v0.12 From ed742d3c46eca7584b6fcb20c2de941852613fb2 Mon Sep 17 00:00:00 2001 From: Christopher Ham Date: Thu, 27 Jan 2011 16:49:21 +1000 Subject: Apply property bindings during component creation. Add versioning Versioning for QtQuick 1.1 was added for invokable method in component. Full changes are in: aa40f956bab22678b62f630af97f51f9e8fab9f8 Task-number: QTBUG-13087 Reviewed-by: Bea Lam --- src/declarative/qml/qdeclarativecomponent.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/declarative/qml/qdeclarativecomponent.h b/src/declarative/qml/qdeclarativecomponent.h index 3d318c3..9a60a8b 100644 --- a/src/declarative/qml/qdeclarativecomponent.h +++ b/src/declarative/qml/qdeclarativecomponent.h @@ -110,7 +110,7 @@ Q_SIGNALS: protected: QDeclarativeComponent(QDeclarativeComponentPrivate &dd, QObject* parent); Q_INVOKABLE QScriptValue createObject(QObject* parent); - Q_INVOKABLE QScriptValue createObject(QObject* parent, const QScriptValue& valuemap); //XXX Versioning + Q_INVOKABLE Q_REVISION(1) QScriptValue createObject(QObject* parent, const QScriptValue& valuemap); //XXX Versioning private: QDeclarativeComponent(QDeclarativeEngine *, QDeclarativeCompiledData *, int, int, QObject *parent); -- cgit v0.12 From ab71df83ba4eb9d749efc0f3a2d4a0fe5486023f Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Thu, 27 Jan 2011 16:52:54 +1000 Subject: Add missing revisions for QtQuick 1.1 additions Task-number: QTBUG-15279 Reviewed-by: Michael Brasser --- .../graphicsitems/qdeclarativeimagebase.cpp | 5 +++ .../graphicsitems/qdeclarativeimagebase_p.h | 9 +++-- .../graphicsitems/qdeclarativeitemsmodule.cpp | 2 + .../graphicsitems/qdeclarativepositioners_p.h | 6 +-- src/declarative/graphicsitems/qdeclarativetext_p.h | 12 +++--- .../graphicsitems/qdeclarativetextedit_p.h | 2 +- .../qdeclarativeimage/tst_qdeclarativeimage.cpp | 45 +++++++++++++++++++++- .../qdeclarativetext/data/lineCount.qml | 2 +- .../qdeclarativetext/tst_qdeclarativetext.cpp | 41 ++++++++++++++++++++ .../tst_qdeclarativetextedit.cpp | 41 ++++++++++++++++++++ 10 files changed, 148 insertions(+), 17 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativeimagebase.cpp b/src/declarative/graphicsitems/qdeclarativeimagebase.cpp index 8448bd6..471c87f 100644 --- a/src/declarative/graphicsitems/qdeclarativeimagebase.cpp +++ b/src/declarative/graphicsitems/qdeclarativeimagebase.cpp @@ -48,6 +48,11 @@ QT_BEGIN_NAMESPACE +QDeclarativeImageBase::QDeclarativeImageBase(QDeclarativeItem *parent) + : QDeclarativeImplicitSizeItem(*(new QDeclarativeImageBasePrivate), parent) +{ +} + QDeclarativeImageBase::QDeclarativeImageBase(QDeclarativeImageBasePrivate &dd, QDeclarativeItem *parent) : QDeclarativeImplicitSizeItem(dd, parent) { diff --git a/src/declarative/graphicsitems/qdeclarativeimagebase_p.h b/src/declarative/graphicsitems/qdeclarativeimagebase_p.h index d183bdc..abee25d 100644 --- a/src/declarative/graphicsitems/qdeclarativeimagebase_p.h +++ b/src/declarative/graphicsitems/qdeclarativeimagebase_p.h @@ -58,11 +58,12 @@ class Q_AUTOTEST_EXPORT QDeclarativeImageBase : public QDeclarativeImplicitSizeI Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged) Q_PROPERTY(qreal progress READ progress NOTIFY progressChanged) Q_PROPERTY(bool asynchronous READ asynchronous WRITE setAsynchronous NOTIFY asynchronousChanged) - Q_PROPERTY(bool cache READ cache WRITE setCache NOTIFY cacheChanged) // ### VERSIONING: Only in QtQuick 1.1 + Q_PROPERTY(bool cache READ cache WRITE setCache NOTIFY cacheChanged REVISION 1) Q_PROPERTY(QSize sourceSize READ sourceSize WRITE setSourceSize NOTIFY sourceSizeChanged) - Q_PROPERTY(bool mirror READ mirror WRITE setMirror NOTIFY mirrorChanged) // ### VERSIONING: Only in QtQuick 1.1 + Q_PROPERTY(bool mirror READ mirror WRITE setMirror NOTIFY mirrorChanged REVISION 1) public: + QDeclarativeImageBase(QDeclarativeItem *parent=0); ~QDeclarativeImageBase(); enum Status { Null, Ready, Loading, Error }; Status status() const; @@ -89,8 +90,8 @@ Q_SIGNALS: void statusChanged(QDeclarativeImageBase::Status); void progressChanged(qreal progress); void asynchronousChanged(); - void cacheChanged(); - void mirrorChanged(); + Q_REVISION(1) void cacheChanged(); + Q_REVISION(1) void mirrorChanged(); protected: virtual void load(); diff --git a/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp b/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp index 3395397..bc4a2d0 100644 --- a/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp +++ b/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp @@ -187,10 +187,12 @@ void QDeclarativeItemModule::defineModule() qmlRegisterType("QtQuick",1,1,"Grid"); qmlRegisterType("QtQuick",1,1,"Flow"); qmlRegisterType("QtQuick",1,1,"Repeater"); + qmlRegisterType("QtQuick",1,1,"Text"); qmlRegisterType("QtQuick",1,1,"TextEdit"); #ifndef QT_NO_LINEEDIT qmlRegisterType("QtQuick",1,1,"TextInput"); #endif + qmlRegisterRevision("QtQuick",1,1); qmlRegisterRevision("QtQuick",1,0); qmlRegisterRevision("QtQuick",1,1); qmlRegisterRevision("QtQuick",1,0); diff --git a/src/declarative/graphicsitems/qdeclarativepositioners_p.h b/src/declarative/graphicsitems/qdeclarativepositioners_p.h index 6b45e49..55d8fa1 100644 --- a/src/declarative/graphicsitems/qdeclarativepositioners_p.h +++ b/src/declarative/graphicsitems/qdeclarativepositioners_p.h @@ -129,7 +129,7 @@ private: class Q_AUTOTEST_EXPORT QDeclarativeRow: public QDeclarativeBasePositioner { Q_OBJECT - Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged REVISION 1); + Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged REVISION 1) public: QDeclarativeRow(QDeclarativeItem *parent=0); @@ -153,7 +153,7 @@ class Q_AUTOTEST_EXPORT QDeclarativeGrid : public QDeclarativeBasePositioner Q_PROPERTY(int rows READ rows WRITE setRows NOTIFY rowsChanged) Q_PROPERTY(int columns READ columns WRITE setColumns NOTIFY columnsChanged) Q_PROPERTY(Flow flow READ flow WRITE setFlow NOTIFY flowChanged) - Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged REVISION 1); + Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged REVISION 1) public: QDeclarativeGrid(QDeclarativeItem *parent=0); @@ -194,7 +194,7 @@ class QDeclarativeFlowPrivate; class Q_AUTOTEST_EXPORT QDeclarativeFlow: public QDeclarativeBasePositioner { Q_OBJECT - Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged REVISION 1); + Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged REVISION 1) Q_PROPERTY(Flow flow READ flow WRITE setFlow NOTIFY flowChanged) public: QDeclarativeFlow(QDeclarativeItem *parent=0); diff --git a/src/declarative/graphicsitems/qdeclarativetext_p.h b/src/declarative/graphicsitems/qdeclarativetext_p.h index ec33b84..58751e7 100644 --- a/src/declarative/graphicsitems/qdeclarativetext_p.h +++ b/src/declarative/graphicsitems/qdeclarativetext_p.h @@ -71,9 +71,9 @@ class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeText : public QDeclarativeImplici Q_PROPERTY(HAlignment horizontalAlignment READ hAlign WRITE setHAlign NOTIFY horizontalAlignmentChanged) Q_PROPERTY(VAlignment verticalAlignment READ vAlign WRITE setVAlign NOTIFY verticalAlignmentChanged) Q_PROPERTY(WrapMode wrapMode READ wrapMode WRITE setWrapMode NOTIFY wrapModeChanged) - Q_PROPERTY(int lineCount READ lineCount NOTIFY lineCountChanged) - Q_PROPERTY(bool truncated READ truncated NOTIFY truncatedChanged) - Q_PROPERTY(int maximumLineCount READ maximumLineCount WRITE setMaximumLineCount NOTIFY maximumLineCountChanged RESET resetMaximumLineCount) + Q_PROPERTY(int lineCount READ lineCount NOTIFY lineCountChanged REVISION 1) + Q_PROPERTY(bool truncated READ truncated NOTIFY truncatedChanged REVISION 1) + Q_PROPERTY(int maximumLineCount READ maximumLineCount WRITE setMaximumLineCount NOTIFY maximumLineCountChanged RESET resetMaximumLineCount REVISION 1) Q_PROPERTY(TextFormat textFormat READ textFormat WRITE setTextFormat NOTIFY textFormatChanged) Q_PROPERTY(TextElideMode elide READ elideMode WRITE setElideMode NOTIFY elideModeChanged) //### elideMode? @@ -169,9 +169,9 @@ Q_SIGNALS: void horizontalAlignmentChanged(HAlignment alignment); void verticalAlignmentChanged(VAlignment alignment); void wrapModeChanged(); - void lineCountChanged(); - void truncatedChanged(); - void maximumLineCountChanged(); + Q_REVISION(1) void lineCountChanged(); + Q_REVISION(1) void truncatedChanged(); + Q_REVISION(1) void maximumLineCountChanged(); void textFormatChanged(TextFormat textFormat); void elideModeChanged(TextElideMode mode); void paintedSizeChanged(); diff --git a/src/declarative/graphicsitems/qdeclarativetextedit_p.h b/src/declarative/graphicsitems/qdeclarativetextedit_p.h index 276d570..db3cb2d 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextedit_p.h @@ -75,7 +75,7 @@ class Q_AUTOTEST_EXPORT QDeclarativeTextEdit : public QDeclarativeImplicitSizePa Q_PROPERTY(HAlignment horizontalAlignment READ hAlign WRITE setHAlign NOTIFY horizontalAlignmentChanged) Q_PROPERTY(VAlignment verticalAlignment READ vAlign WRITE setVAlign NOTIFY verticalAlignmentChanged) Q_PROPERTY(WrapMode wrapMode READ wrapMode WRITE setWrapMode NOTIFY wrapModeChanged) - Q_PROPERTY(int lineCount READ lineCount NOTIFY lineCountChanged) + Q_PROPERTY(int lineCount READ lineCount NOTIFY lineCountChanged REVISION 1) Q_PROPERTY(qreal paintedWidth READ paintedWidth NOTIFY paintedSizeChanged) Q_PROPERTY(qreal paintedHeight READ paintedHeight NOTIFY paintedSizeChanged) Q_PROPERTY(TextFormat textFormat READ textFormat WRITE setTextFormat NOTIFY textFormatChanged) diff --git a/tests/auto/declarative/qdeclarativeimage/tst_qdeclarativeimage.cpp b/tests/auto/declarative/qdeclarativeimage/tst_qdeclarativeimage.cpp index c277eb7..f1fe2bd 100644 --- a/tests/auto/declarative/qdeclarativeimage/tst_qdeclarativeimage.cpp +++ b/tests/auto/declarative/qdeclarativeimage/tst_qdeclarativeimage.cpp @@ -90,6 +90,8 @@ private slots: void paintedWidthHeight(); void sourceSize_QTBUG_14303(); void nullPixmapPaint(); + void testQtQuick11Attributes(); + void testQtQuick11Attributes_data(); private: template @@ -164,7 +166,7 @@ void tst_qdeclarativeimage::imageSource() if (!error.isEmpty()) QTest::ignoreMessage(QtWarningMsg, error.toUtf8()); - QString componentStr = "import QtQuick 1.0\nImage { source: \"" + source + "\"; asynchronous: " + QString componentStr = "import QtQuick 1.1\nImage { source: \"" + source + "\"; asynchronous: " + (async ? QLatin1String("true") : QLatin1String("false")) + "; cache: " + (cache ? QLatin1String("true") : QLatin1String("false")) + " }"; QDeclarativeComponent component(&engine); @@ -280,7 +282,7 @@ void tst_qdeclarativeimage::mirror() qreal height = 250; QString src = QUrl::fromLocalFile(SRCDIR "/data/heart200.png").toString(); - QString componentStr = "import QtQuick 1.0\nImage { source: \"" + src + "\"; }"; + QString componentStr = "import QtQuick 1.1\nImage { source: \"" + src + "\"; }"; QDeclarativeComponent component(&engine); component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); @@ -667,6 +669,45 @@ void tst_qdeclarativeimage::nullPixmapPaint() delete image; } +void tst_qdeclarativeimage::testQtQuick11Attributes() +{ + QFETCH(QString, code); + QFETCH(QString, warning); + QFETCH(QString, error); + + QDeclarativeEngine engine; + QObject *obj; + + QDeclarativeComponent valid(&engine); + valid.setData("import QtQuick 1.1; Image { " + code.toUtf8() + " }", QUrl("")); + obj = valid.create(); + QVERIFY(obj); + QVERIFY(valid.errorString().isEmpty()); + delete obj; + + QDeclarativeComponent invalid(&engine); + invalid.setData("import QtQuick 1.0; Image { " + code.toUtf8() + " }", QUrl("")); + QTest::ignoreMessage(QtWarningMsg, warning.toUtf8()); + obj = invalid.create(); + QCOMPARE(invalid.errorString(), error); + delete obj; +} + +void tst_qdeclarativeimage::testQtQuick11Attributes_data() +{ + QTest::addColumn("code"); + QTest::addColumn("warning"); + QTest::addColumn("error"); + + QTest::newRow("mirror") << "mirror: true" + << "QDeclarativeComponent: Component is not ready" + << ":1 \"Image.mirror\" is not available in QtQuick 1.0.\n"; + + QTest::newRow("cache") << "cache: true" + << "QDeclarativeComponent: Component is not ready" + << ":1 \"Image.cache\" is not available in QtQuick 1.0.\n"; +} + /* Find an item with the specified objectName. If index is supplied then the item must also evaluate the {index} expression equal to index diff --git a/tests/auto/declarative/qdeclarativetext/data/lineCount.qml b/tests/auto/declarative/qdeclarativetext/data/lineCount.qml index b3d7bc1..63817f6 100644 --- a/tests/auto/declarative/qdeclarativetext/data/lineCount.qml +++ b/tests/auto/declarative/qdeclarativetext/data/lineCount.qml @@ -1,4 +1,4 @@ -import QtQuick 1.0 +import QtQuick 1.1 Item { width: 200 diff --git a/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp b/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp index faea448..fabae18 100644 --- a/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp +++ b/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp @@ -103,6 +103,8 @@ private slots: void QTBUG_12291(); void implicitSize_data(); void implicitSize(); + void testQtQuick11Attributes(); + void testQtQuick11Attributes_data(); private: QStringList standard; @@ -1079,6 +1081,45 @@ void tst_qdeclarativetext::implicitSize() QVERIFY(textObject->height() == textObject->implicitHeight()); } +void tst_qdeclarativetext::testQtQuick11Attributes() +{ + QFETCH(QString, code); + QFETCH(QString, warning); + QFETCH(QString, error); + + QDeclarativeEngine engine; + QObject *obj; + + QDeclarativeComponent valid(&engine); + valid.setData("import QtQuick 1.1; Text { " + code.toUtf8() + " }", QUrl("")); + obj = valid.create(); + QVERIFY(obj); + QVERIFY(valid.errorString().isEmpty()); + delete obj; + + QDeclarativeComponent invalid(&engine); + invalid.setData("import QtQuick 1.0; Text { " + code.toUtf8() + " }", QUrl("")); + QTest::ignoreMessage(QtWarningMsg, warning.toUtf8()); + obj = invalid.create(); + QCOMPARE(invalid.errorString(), error); + delete obj; +} + +void tst_qdeclarativetext::testQtQuick11Attributes_data() +{ + QTest::addColumn("code"); + QTest::addColumn("warning"); + QTest::addColumn("error"); + + QTest::newRow("maximumLineCount") << "maximumLineCount: 4" + << "QDeclarativeComponent: Component is not ready" + << ":1 \"Text.maximumLineCount\" is not available in QtQuick 1.0.\n"; + + QTest::newRow("truncated") << "property int foo: lineCount" + << ":1: ReferenceError: Can't find variable: lineCount" + << ""; +} + QTEST_MAIN(tst_qdeclarativetext) #include "tst_qdeclarativetext.moc" diff --git a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp index 582b20f..cd1977a 100644 --- a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp +++ b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp @@ -129,6 +129,8 @@ private slots: void pastingRichText_QTBUG_14003(); void implicitSize_data(); void implicitSize(); + void testQtQuick11Attributes(); + void testQtQuick11Attributes_data(); private: void simulateKey(QDeclarativeView *, int key); @@ -1476,6 +1478,45 @@ void tst_qdeclarativetextedit::implicitSize() QVERIFY(textObject->height() == textObject->implicitHeight()); } +void tst_qdeclarativetextedit::testQtQuick11Attributes() +{ + QFETCH(QString, code); + QFETCH(QString, warning); + QFETCH(QString, error); + + QDeclarativeEngine engine; + QObject *obj; + + QDeclarativeComponent valid(&engine); + valid.setData("import QtQuick 1.1; Text { " + code.toUtf8() + " }", QUrl("")); + obj = valid.create(); + QVERIFY(obj); + QVERIFY(valid.errorString().isEmpty()); + delete obj; + + QDeclarativeComponent invalid(&engine); + invalid.setData("import QtQuick 1.0; Text { " + code.toUtf8() + " }", QUrl("")); + QTest::ignoreMessage(QtWarningMsg, warning.toUtf8()); + obj = invalid.create(); + QCOMPARE(invalid.errorString(), error); + delete obj; +} + +void tst_qdeclarativetextedit::testQtQuick11Attributes_data() +{ + QTest::addColumn("code"); + QTest::addColumn("warning"); + QTest::addColumn("error"); + + QTest::newRow("canPaste") << "property bool foo: canPaste" + << ":1: ReferenceError: Can't find variable: canPaste" + << ""; + + QTest::newRow("lineCount") << "property int foo: lineCount" + << ":1: ReferenceError: Can't find variable: lineCount" + << ""; +} + QTEST_MAIN(tst_qdeclarativetextedit) #include "tst_qdeclarativetextedit.moc" -- cgit v0.12 From 44c2b8bc246640a011010fc30ebfdc90988ef626 Mon Sep 17 00:00:00 2001 From: Christopher Ham Date: Thu, 27 Jan 2011 18:04:38 +1000 Subject: Fix object check in createObject The 'if' check for the value map was inverted. Spelling in warning was fixed. Task-number: QTBUG-13087 Reviewed-by: Bea Lam --- src/declarative/qml/qdeclarativecomponent.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/declarative/qml/qdeclarativecomponent.cpp b/src/declarative/qml/qdeclarativecomponent.cpp index bd6e2d8..b634a7a 100644 --- a/src/declarative/qml/qdeclarativecomponent.cpp +++ b/src/declarative/qml/qdeclarativecomponent.cpp @@ -665,8 +665,8 @@ QScriptValue QDeclarativeComponent::createObject(QObject* parent, const QScriptV { Q_D(QDeclarativeComponent); - if (valuemap.isObject() && !valuemap.isArray()) { - qmlInfo(this) << tr("creatObject: value is not an object"); + if (!valuemap.isObject() || valuemap.isArray()) { + qmlInfo(this) << tr("createObject: value is not an object"); return QScriptValue(QScriptValue::NullValue); } return d->createObject(parent, valuemap); -- cgit v0.12 From 281ff52c266e54030ca48326e79eab2d452c2e83 Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Thu, 27 Jan 2011 18:22:15 +1000 Subject: Test for passing functions to createObject() for property bindings --- .../data/createObjectWithScript.qml | 17 ++++++++++++++++ .../tst_qdeclarativecomponent.cpp | 23 ++++++++++++++++++++-- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/tests/auto/declarative/qdeclarativecomponent/data/createObjectWithScript.qml b/tests/auto/declarative/qdeclarativecomponent/data/createObjectWithScript.qml index 60d4c44..6f9ddc1 100644 --- a/tests/auto/declarative/qdeclarativecomponent/data/createObjectWithScript.qml +++ b/tests/auto/declarative/qdeclarativecomponent/data/createObjectWithScript.qml @@ -4,6 +4,10 @@ Item{ id: root property QtObject declarativerectangle : null property QtObject declarativeitem : null + + property QtObject bindingTestObject : null + property QtObject bindingThisTestObject : null + Component{id: a; Rectangle{} } Component{ id: b @@ -14,8 +18,21 @@ Item{ } } + // test passing in bindings + width: 100 + Component { + id: c + Item { + property int testValue + width: 300 + } + } + Component.onCompleted: { root.declarativerectangle = a.createObject(root, {"x":17,"y":17, "color":"white"}); root.declarativeitem = b.createObject(root, {"x":17,"y":17,"testBool":true,"testInt":17,"testObject":root}); + + root.bindingTestObject = c.createObject(root, {'testValue': (function(){return width * 3}) }) // use root.width + root.bindingThisTestObject = c.createObject(root, {'testValue': (function(){return this.width * 3}) }) // use width of Item within 'c' } } diff --git a/tests/auto/declarative/qdeclarativecomponent/tst_qdeclarativecomponent.cpp b/tests/auto/declarative/qdeclarativecomponent/tst_qdeclarativecomponent.cpp index 829b762..62c6bb5 100644 --- a/tests/auto/declarative/qdeclarativecomponent/tst_qdeclarativecomponent.cpp +++ b/tests/auto/declarative/qdeclarativecomponent/tst_qdeclarativecomponent.cpp @@ -62,7 +62,7 @@ private slots: void null(); void loadEmptyUrl(); void qmlCreateObject(); - void qmlCreatObjectWithScript(); + void qmlCreateObjectWithProperties(); private: QDeclarativeEngine engine; @@ -121,10 +121,11 @@ void tst_qdeclarativecomponent::qmlCreateObject() QCOMPARE(testObject3->metaObject()->className(), "QDeclarativeGraphicsWidget"); } -void tst_qdeclarativecomponent::qmlCreatObjectWithScript() +void tst_qdeclarativecomponent::qmlCreateObjectWithProperties() { QDeclarativeEngine engine; QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/createObjectWithScript.qml")); + QVERIFY2(component.errorString().isEmpty(), component.errorString().toUtf8()); QObject *object = component.create(); QVERIFY(object != 0); @@ -134,6 +135,7 @@ void tst_qdeclarativecomponent::qmlCreatObjectWithScript() QCOMPARE(testObject1->property("x").value(), 17); QCOMPARE(testObject1->property("y").value(), 17); QCOMPARE(testObject1->property("color").value(), QColor(255,255,255)); + delete testObject1; QObject *testObject2 = object->property("declarativeitem").value(); QVERIFY(testObject2); @@ -144,6 +146,23 @@ void tst_qdeclarativecomponent::qmlCreatObjectWithScript() QCOMPARE(testObject2->property("testBool").value(), true); QCOMPARE(testObject2->property("testInt").value(), 17); QCOMPARE(testObject2->property("testObject").value(), object); + delete testObject2; + + QObject *testBindingObj = object->property("bindingTestObject").value(); + QVERIFY(testBindingObj); + QCOMPARE(testBindingObj->parent(), object); + QCOMPARE(testBindingObj->property("testValue").value(), 300); + object->setProperty("width", 150); + QCOMPARE(testBindingObj->property("testValue").value(), 150 * 3); + delete testBindingObj; + + QObject *testBindingThisObj = object->property("bindingThisTestObject").value(); + QVERIFY(testBindingThisObj); + QCOMPARE(testBindingThisObj->parent(), object); + QCOMPARE(testBindingThisObj->property("testValue").value(), 900); + testBindingThisObj->setProperty("width", 200); + QCOMPARE(testBindingThisObj->property("testValue").value(), 200 * 3); + delete testBindingThisObj; } QTEST_MAIN(tst_qdeclarativecomponent) -- cgit v0.12 From eb55d07febf858474d8755e31cb554a4b8fabcdc Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 27 Jan 2011 18:43:01 +1000 Subject: Don't crash when appending a null item Task-number: QTBUG-16871 --- src/gui/graphicsview/qgraphicsitem.cpp | 12 +++++++----- tests/auto/declarative/qdeclarativeitem/data/qtbug_16871.qml | 5 +++++ .../declarative/qdeclarativeitem/tst_qdeclarativeitem.cpp | 9 +++++++++ 3 files changed, 21 insertions(+), 5 deletions(-) create mode 100644 tests/auto/declarative/qdeclarativeitem/data/qtbug_16871.qml diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 52e4d79..f463887 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -7689,11 +7689,13 @@ void QGraphicsObject::updateMicroFocus() void QGraphicsItemPrivate::children_append(QDeclarativeListProperty *list, QGraphicsObject *item) { - QGraphicsObject *graphicsObject = static_cast(list->object); - if (QGraphicsItemPrivate::get(graphicsObject)->sendParentChangeNotification) { - item->setParentItem(graphicsObject); - } else { - QGraphicsItemPrivate::get(item)->setParentItemHelper(graphicsObject, 0, 0); + if (item) { + QGraphicsObject *graphicsObject = static_cast(list->object); + if (QGraphicsItemPrivate::get(graphicsObject)->sendParentChangeNotification) { + item->setParentItem(graphicsObject); + } else { + QGraphicsItemPrivate::get(item)->setParentItemHelper(graphicsObject, 0, 0); + } } } diff --git a/tests/auto/declarative/qdeclarativeitem/data/qtbug_16871.qml b/tests/auto/declarative/qdeclarativeitem/data/qtbug_16871.qml new file mode 100644 index 0000000..8102df1 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeitem/data/qtbug_16871.qml @@ -0,0 +1,5 @@ +import QtQuick 1.0 + +Item { + children: [ 10 ] +} diff --git a/tests/auto/declarative/qdeclarativeitem/tst_qdeclarativeitem.cpp b/tests/auto/declarative/qdeclarativeitem/tst_qdeclarativeitem.cpp index 447b57b..137522d 100644 --- a/tests/auto/declarative/qdeclarativeitem/tst_qdeclarativeitem.cpp +++ b/tests/auto/declarative/qdeclarativeitem/tst_qdeclarativeitem.cpp @@ -86,6 +86,7 @@ private slots: void implicitSize(); void testQtQuick11Attributes(); void testQtQuick11Attributes_data(); + void qtbug_16871(); private: template @@ -994,6 +995,14 @@ void tst_QDeclarativeItem::testQtQuick11Attributes_data() << ":1 \"Item.onImplicitHeightChanged\" is not available in QtQuick 1.0.\n"; } +void tst_QDeclarativeItem::qtbug_16871() +{ + QDeclarativeComponent component(&engine, SRCDIR "/data/qtbug_16871.qml"); + QObject *o = component.create(); + QVERIFY(o != 0); + delete o; +} + template T *tst_QDeclarativeItem::findItem(QGraphicsObject *parent, const QString &objectName) -- cgit v0.12 From bd6c9225328b6042ff14dfddb28e2e1279ba0e46 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 27 Jan 2011 10:01:48 +0100 Subject: Make syncqt not complain about missing header macros. qsharedpointer_impl.h contains class definitions that are also mirrored in qsharedpointer.h (which is there for qdoc3), so we have a macro to stop processing. Task-number: QTBUG-16912 Reviewed-by: Olivier Goffart --- src/corelib/tools/qsharedpointer_impl.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h index 2404d2a..0337c1f 100644 --- a/src/corelib/tools/qsharedpointer_impl.h +++ b/src/corelib/tools/qsharedpointer_impl.h @@ -44,7 +44,17 @@ #ifndef QSHAREDPOINTER_H #error Do not include qsharedpointer_impl.h directly #endif + #if 0 +// These macros are duplicated here to make syncqt not complain a about +// this header, as we have a "qt_sync_stop_processing" below, which in turn +// is here because this file contains a template mess and duplicates the +// classes found in qsharedpointer.h +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE +QT_MODULE(Core) +QT_END_NAMESPACE +QT_END_HEADER #pragma qt_sync_stop_processing #endif -- cgit v0.12 From 4ec245a3e75470186557d00b2383af3872a720b0 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Thu, 27 Jan 2011 12:40:33 +0200 Subject: No longer replace dash and dot in TARGET with underscore in Symbian There is no fundamental reason to not have dash or dot in binary names in Symbian, so do not replace them with underscore. One thing that doesn't work with a dot in the filename is launching an application via resources, so automatic resource generation is suppressed for applications that have a dot in filename portion of the TARGET value. Task-number: QTBUG-16888 Reviewed-by: axis --- mkspecs/common/symbian/symbian.conf | 9 +-- mkspecs/features/symbian/application_icon.prf | 106 ++++++++++++++------------ qmake/generators/symbian/symbiancommon.cpp | 23 ++---- qmake/generators/symbian/symbiancommon.h | 1 - qmake/generators/symbian/symmake.cpp | 31 ++++++-- 5 files changed, 89 insertions(+), 81 deletions(-) diff --git a/mkspecs/common/symbian/symbian.conf b/mkspecs/common/symbian/symbian.conf index 5619d4f..0bb3a29 100644 --- a/mkspecs/common/symbian/symbian.conf +++ b/mkspecs/common/symbian/symbian.conf @@ -215,19 +215,14 @@ default_deployment.pkg_prerules += pkg_depends_webkit pkg_depends_qt pkg_platfor DEPLOYMENT += default_deployment default_bin_deployment default_resource_deployment default_reg_deployment defineReplace(symbianRemoveSpecialCharacters) { - # Produce identical string to what SymbianCommonGenerator::removeSpecialCharacters and - # SymbianCommonGenerator::removeEpocSpecialCharacters produce + # Produce identical string to what SymbianCommonGenerator::removeSpecialCharacters fixedStr = $$1 fixedStr = $$replace(fixedStr, /,_) fixedStr = $$replace(fixedStr, \\\\,_) fixedStr = $$replace(fixedStr, " ",_) - symbian-abld|symbian-sbsv2 { - fixedStr = $$replace(fixedStr, -,_) - fixedStr = $$replace(fixedStr, \\.,_) - fixedStr = $$replace(fixedStr, :,_) - } + fixedStr = $$replace(fixedStr, :,_) return ($$fixedStr) } diff --git a/mkspecs/features/symbian/application_icon.prf b/mkspecs/features/symbian/application_icon.prf index 6e1aa8e..b6be89b 100644 --- a/mkspecs/features/symbian/application_icon.prf +++ b/mkspecs/features/symbian/application_icon.prf @@ -11,68 +11,74 @@ contains(CONFIG, no_icon) { !contains(CONFIG, no_icon) { baseTarget = $$symbianRemoveSpecialCharacters($$basename(TARGET)) - symbian-abld|symbian-sbsv2 { - resourceZDir = $$EPOCROOT$$HW_ZDIR$$APP_RESOURCE_DIR - regZDir = $$EPOCROOT$$HW_ZDIR$$REG_RESOURCE_IMPORT_DIR + contains(baseTarget, "^.*\\..*$") { + CONFIG += no_icon + ICON = + warning("Symbian resources do not support '.' character in TARGET, skipping resource generation.") } else { - contains(DESTDIR, "/.*") { - resourceZDir = $$DESTDIR - } else:isEmpty(DESTDIR) { - resourceZDir = $$OUT_PWD + symbian-abld|symbian-sbsv2 { + resourceZDir = $$EPOCROOT$$HW_ZDIR$$APP_RESOURCE_DIR + regZDir = $$EPOCROOT$$HW_ZDIR$$REG_RESOURCE_IMPORT_DIR } else { - resourceZDir = $$OUT_PWD/$$DESTDIR + contains(DESTDIR, "/.*") { + resourceZDir = $$DESTDIR + } else:isEmpty(DESTDIR) { + resourceZDir = $$OUT_PWD + } else { + resourceZDir = $$OUT_PWD/$$DESTDIR + } + regZDir = $$resourceZDir } - regZDir = $$resourceZDir - } - default_resource_deployment.sources += $$resourceZDir/$${baseTarget}.rsc - default_resource_deployment.path = $$APP_RESOURCE_DIR - default_reg_deployment.sources += $$regZDir/$${baseTarget}_reg.rsc - default_reg_deployment.path = $$REG_RESOURCE_IMPORT_DIR + default_resource_deployment.sources += $$resourceZDir/$${baseTarget}.rsc + default_resource_deployment.path = $$APP_RESOURCE_DIR + default_reg_deployment.sources += $$regZDir/$${baseTarget}_reg.rsc + default_reg_deployment.path = $$REG_RESOURCE_IMPORT_DIR - !isEmpty(ICON) { - !count(ICON, 1) { - ICON = $$first(ICON) - warning("Only first icon specified in ICON variable is used: $$ICON") - } + !isEmpty(ICON) { + !count(ICON, 1) { + ICON = $$first(ICON) + warning("Only first icon specified in ICON variable is used: $$ICON") + } - # Note: symbian-sbsv2 builds can't utilize extra compiler for mifconv, so ICON handling is done in code - !symbian-sbsv2 { - # Absolute path required for shadow builds. - # However, in older Symbian environments abld toolchain can't handle even moderately long - # paths, so don't force absolute there. - !symbian-abld:!contains(ICON, "^(/|\\\\|.:).*"):ICON = $$_PRO_FILE_PWD_/$$ICON + # Note: symbian-sbsv2 builds can't utilize extra compiler for mifconv, so ICON handling is done in code + !symbian-sbsv2 { + # Absolute path required for shadow builds. + # However, in older Symbian environments abld toolchain can't handle even moderately long + # paths, so don't force absolute there. + !symbian-abld:!contains(ICON, "^(/|\\\\|.:).*"):ICON = $$_PRO_FILE_PWD_/$$ICON - #Makefile: requires paths with backslash - ICON_backslashed = $$ICON + #Makefile: requires paths with backslash + ICON_backslashed = $$ICON - symbian-abld { - # ${ZDIR} is defined in Makefile - mifIconZDir = ${ZDIR}$$APP_RESOURCE_DIR - } else { - mifIconZDir = $$resourceZDir - } + symbian-abld { + # ${ZDIR} is defined in Makefile + mifIconZDir = ${ZDIR}$$APP_RESOURCE_DIR + } else { + mifIconZDir = $$resourceZDir + } - # Extra compiler rules for mifconv - mifconv.target = $$mifIconZDir/$${baseTarget}.mif - contains(QMAKE_HOST.os, "Windows") { - ICON_backslashed = $$replace(ICON_backslashed, /, \\) - mifconv.target = $$replace(mifconv.target, /, \\) + # Extra compiler rules for mifconv + mifconv.target = $$mifIconZDir/$${baseTarget}.mif + contains(QMAKE_HOST.os, "Windows") { + ICON_backslashed = $$replace(ICON_backslashed, /, \\) + mifconv.target = $$replace(mifconv.target, /, \\) + } + # Based on: http://www.forum.nokia.com/document/Cpp_Developers_Library + # svg-t icons should always use /c32 depth + mifconv.commands = mifconv $$mifconv.target /c32 $$ICON_backslashed + + mifconv.depends = $$ICON + PRE_TARGETDEPS += $$mifconv.target + QMAKE_EXTRA_TARGETS += mifconv + QMAKE_DISTCLEAN += $$mifconv.target } - # Based on: http://www.forum.nokia.com/document/Cpp_Developers_Library - # svg-t icons should always use /c32 depth - mifconv.commands = mifconv $$mifconv.target /c32 $$ICON_backslashed + # Rules to use generated MIF file from symbian resources + RSS_RULES.number_of_icons = $$size(ICON_backslashed) + RSS_RULES.icon_file = $$APP_RESOURCE_DIR/$${baseTarget}.mif - mifconv.depends = $$ICON - PRE_TARGETDEPS += $$mifconv.target - QMAKE_EXTRA_TARGETS += mifconv - QMAKE_DISTCLEAN += $$mifconv.target + default_resource_deployment.sources += $$resourceZDir/$${baseTarget}.mif } - # Rules to use generated MIF file from symbian resources - RSS_RULES.number_of_icons = $$size(ICON_backslashed) - RSS_RULES.icon_file = $$APP_RESOURCE_DIR/$${baseTarget}.mif - - default_resource_deployment.sources += $$resourceZDir/$${baseTarget}.mif } } diff --git a/qmake/generators/symbian/symbiancommon.cpp b/qmake/generators/symbian/symbiancommon.cpp index 2270c2e..96d7725 100644 --- a/qmake/generators/symbian/symbiancommon.cpp +++ b/qmake/generators/symbian/symbiancommon.cpp @@ -79,11 +79,7 @@ void SymbianCommonGenerator::init() fixedTarget = project->first("TARGET"); fixedTarget = generator->unescapeFilePath(fixedTarget); fixedTarget = removePathSeparators(fixedTarget); - if (project->first("MAKEFILE_GENERATOR") == "SYMBIAN_ABLD" - || project->first("MAKEFILE_GENERATOR") == "SYMBIAN_SBSV2") - removeEpocSpecialCharacters(fixedTarget); - else - removeSpecialCharacters(fixedTarget); + removeSpecialCharacters(fixedTarget); // This should not be empty since the mkspecs are supposed to set it if missing. uid3 = project->first("TARGET.UID3").trimmed(); @@ -131,18 +127,11 @@ bool SymbianCommonGenerator::containsStartWithItem(const QChar &c, const QString void SymbianCommonGenerator::removeSpecialCharacters(QString& str) { // When modifying this method check also symbianRemoveSpecialCharacters in symbian.conf - str.replace(QString("/"), QString("_")); - str.replace(QString("\\"), QString("_")); - str.replace(QString(" "), QString("_")); -} - -void SymbianCommonGenerator::removeEpocSpecialCharacters(QString& str) -{ - // When modifying this method check also symbianRemoveSpecialCharacters in symbian.conf - str.replace(QString("-"), QString("_")); - str.replace(QString(":"), QString("_")); - str.replace(QString("."), QString("_")); - removeSpecialCharacters(str); + QString underscore = QLatin1String("_"); + str.replace(QLatin1String("/"), underscore); + str.replace(QLatin1String("\\"), underscore); + str.replace(QLatin1String(" "), underscore); + str.replace(QLatin1String(":"), underscore); } QString romPath(const QString& path) diff --git a/qmake/generators/symbian/symbiancommon.h b/qmake/generators/symbian/symbiancommon.h index 0b5f53d..5182021 100644 --- a/qmake/generators/symbian/symbiancommon.h +++ b/qmake/generators/symbian/symbiancommon.h @@ -82,7 +82,6 @@ protected: QString removePathSeparators(QString &file); void removeSpecialCharacters(QString& str); - void removeEpocSpecialCharacters(QString& str); void generatePkgFile(const QString &iconFile, bool epocBuild, const SymbianLocalizationList &symbianLocalizationList); diff --git a/qmake/generators/symbian/symmake.cpp b/qmake/generators/symbian/symmake.cpp index a2b567d..4f9f22d 100644 --- a/qmake/generators/symbian/symmake.cpp +++ b/qmake/generators/symbian/symmake.cpp @@ -83,6 +83,8 @@ #define VAR_CFLAGS "QMAKE_CFLAGS" #define VAR_LFLAGS "QMAKE_LFLAGS" +#define DEFINE_REPLACE_REGEXP "[^A-Z0-9_]" + QString SymbianMakefileGenerator::fixPathForMmp(const QString& origPath, const QDir& parentDir) { static QString epocRootStr; @@ -165,11 +167,15 @@ void SymbianMakefileGenerator::writeHeader(QTextStream &t) QString bldinfDefine = shortProFilename; bldinfDefine.append("_"); bldinfDefine.append(generate_uid(project->projectFile())); + bldinfDefine = bldinfDefine.toUpper(); + + // replace anything not alphanumeric with underscore + QRegExp replacementMask(DEFINE_REPLACE_REGEXP); + bldinfDefine.replace(replacementMask, QLatin1String("_")); bldinfDefine.prepend("BLD_INF_"); - removeEpocSpecialCharacters(bldinfDefine); - t << "#define " << bldinfDefine.toUpper() << endl << endl; + t << "#define " << bldinfDefine << endl << endl; } bool SymbianMakefileGenerator::writeMakefile(QTextStream &t) @@ -902,13 +908,17 @@ void SymbianMakefileGenerator::writeBldInfContent(QTextStream &t, bool addDeploy const QStringList &subdirs = project->values("SUBDIRS"); foreach(QString item, subdirs) { + bool fromFile = false; QString fixedItem; if (!project->isEmpty(item + ".file")) { fixedItem = project->first(item + ".file"); + fromFile = true; } else if (!project->isEmpty(item + ".subdir")) { fixedItem = project->first(item + ".subdir"); + fromFile = false; } else { fixedItem = item; + fromFile = item.endsWith(Option::pro_ext); } QString condition; @@ -917,9 +927,15 @@ void SymbianMakefileGenerator::writeBldInfContent(QTextStream &t, bool addDeploy QFileInfo subdir(fileInfo(fixedItem)); QString relativePath = directory.relativeFilePath(fixedItem); - QString subdirFileName = subdir.completeBaseName(); - QString fullProName = subdir.absoluteFilePath();; + QString fullProName = subdir.absoluteFilePath(); QString bldinfFilename; + QString subdirFileName; + + if (fromFile) { + subdirFileName = subdir.completeBaseName(); + } else { + subdirFileName = subdir.fileName(); + } if (subdir.isDir()) { // Subdir is a regular project @@ -941,7 +957,10 @@ void SymbianMakefileGenerator::writeBldInfContent(QTextStream &t, bool addDeploy QString uid = generate_uid(fullProName); QString bldinfDefine = QString("BLD_INF_") + subdirFileName + QString("_") + uid; bldinfDefine = bldinfDefine.toUpper(); - removeEpocSpecialCharacters(bldinfDefine); + + // replace anything not alphanumeric with underscore + QRegExp replacementMask(DEFINE_REPLACE_REGEXP); + bldinfDefine.replace(replacementMask, QLatin1String("_")); if (!condition.isEmpty()) t << "#if defined(" << condition << ")" << endl; @@ -1124,4 +1143,4 @@ QString SymbianMakefileGenerator::generateLocFileTarget(QTextStream& t, const QS } return locFile; -} \ No newline at end of file +} -- cgit v0.12 From 2e72a8b19ea6c674fb4777860dac50faa5d387e6 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 27 Jan 2011 11:49:49 +0100 Subject: Restore Qt 4.6 behaviour: exec() always enters the event loop. In Qt 4.6 as well as 4.7's QCoreApplication and QEventLoop, calling exec() always enters the event loop, even if you had tried to quit()/exit() it before entering, with one exception (noted in the unit tests; this difference has been in Qt since at least Qt 4.2). Add unit tests to ensure all of the three classes have the same behaviour. Decide if we want to match the behaviours in Qt 4.8. Reviewed-by: Bradley T. Hughes --- src/corelib/thread/qthread.cpp | 5 +- .../auto/qcoreapplication/tst_qcoreapplication.cpp | 45 +++++ tests/auto/qeventloop/tst_qeventloop.cpp | 41 ++++- tests/auto/qthread/tst_qthread.cpp | 191 +++++++++++++++------ 4 files changed, 221 insertions(+), 61 deletions(-) diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp index f368192..f4bfa5d 100644 --- a/src/corelib/thread/qthread.cpp +++ b/src/corelib/thread/qthread.cpp @@ -482,10 +482,7 @@ int QThread::exec() Q_D(QThread); QMutexLocker locker(&d->mutex); d->data->quitNow = false; - if (d->exited) { - d->exited = false; - return d->returnCode; - } + d->exited = false; locker.unlock(); QEventLoop eventLoop; diff --git a/tests/auto/qcoreapplication/tst_qcoreapplication.cpp b/tests/auto/qcoreapplication/tst_qcoreapplication.cpp index 95055d1..bc69461 100644 --- a/tests/auto/qcoreapplication/tst_qcoreapplication.cpp +++ b/tests/auto/qcoreapplication/tst_qcoreapplication.cpp @@ -59,6 +59,9 @@ private slots: void applicationPid(); void globalPostedEventsCount(); void processEventsAlwaysSendsPostedEvents(); + void reexec(); + void execAfterExit(); + void eventLoopExecAfterExit(); }; class EventSpy : public QObject @@ -524,5 +527,47 @@ void tst_QCoreApplication::processEventsAlwaysSendsPostedEvents() } while (t.elapsed() < 3000); } +void tst_QCoreApplication::reexec() +{ + int argc = 1; + char *argv[] = { "tst_qcoreapplication" }; + QCoreApplication app(argc, argv); + + // exec once + QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection); + QCOMPARE(app.exec(), 0); + + // and again + QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection); + QCOMPARE(app.exec(), 0); +} + +void tst_QCoreApplication::execAfterExit() +{ + int argc = 1; + char *argv[] = { "tst_qcoreapplication" }; + QCoreApplication app(argc, argv); + + app.exit(1); + QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection); + QCOMPARE(app.exec(), 0); +} + +void tst_QCoreApplication::eventLoopExecAfterExit() +{ + int argc = 1; + char *argv[] = { "tst_qcoreapplication" }; + QCoreApplication app(argc, argv); + + // exec once and exit + QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection); + QCOMPARE(app.exec(), 0); + + // and again, but this time using a QEventLoop + QEventLoop loop; + QMetaObject::invokeMethod(&loop, "quit", Qt::QueuedConnection); + QCOMPARE(loop.exec(), 0); +} + QTEST_APPLESS_MAIN(tst_QCoreApplication) #include "tst_qcoreapplication.moc" diff --git a/tests/auto/qeventloop/tst_qeventloop.cpp b/tests/auto/qeventloop/tst_qeventloop.cpp index 7af722f..6860f19 100644 --- a/tests/auto/qeventloop/tst_qeventloop.cpp +++ b/tests/auto/qeventloop/tst_qeventloop.cpp @@ -112,6 +112,10 @@ signals: public: QMutex mutex; QWaitCondition cond; + volatile int result1; + volatile int result2; + MultipleExecThread() : result1(0xdead), result2(0xbeef) {} + void run() { QMutexLocker locker(&mutex); @@ -124,13 +128,13 @@ public: connect(&timer, SIGNAL(timeout()), SLOT(quit()), Qt::DirectConnection); timer.setInterval(1000); timer.start(); - (void) exec(); + result1 = exec(); // this should return immediately, since exit() has been called cond.wakeOne(); cond.wait(&mutex); QEventLoop eventLoop; - (void) eventLoop.exec(); + result2 = eventLoop.exec(); } }; @@ -197,7 +201,9 @@ private slots: void symbianNestedActiveSchedulerLoop(); void processEvents(); void exec(); + void reexec(); void exit(); + void execAfterExit(); void wakeUp(); void quit(); void processEventsExcludeSocket(); @@ -398,7 +404,9 @@ void tst_QEventLoop::exec() } { - // calling exec() after exit()/quit() should return immediately + // calling QEventLoop::exec() after a thread loop has exit()ed should return immediately + // Note: this behaviour differs from QCoreApplication and QEventLoop + // see tst_QCoreApplication::eventLoopExecAfterExit, tst_QEventLoop::reexec MultipleExecThread thread; // start thread and wait for checkpoint @@ -411,6 +419,8 @@ void tst_QEventLoop::exec() thread.cond.wakeOne(); thread.cond.wait(&thread.mutex); QVERIFY(spy.count() > 0); + int v = thread.result1; + QCOMPARE(v, 0); // exec should return immediately spy.clear(); @@ -418,6 +428,8 @@ void tst_QEventLoop::exec() thread.mutex.unlock(); thread.wait(); QCOMPARE(spy.count(), 0); + v = thread.result2; + QCOMPARE(v, -1); } { @@ -462,9 +474,32 @@ void tst_QEventLoop::exec() #endif } +void tst_QEventLoop::reexec() +{ + QEventLoop loop; + + // exec once + QMetaObject::invokeMethod(&loop, "quit", Qt::QueuedConnection); + QCOMPARE(loop.exec(), 0); + + // and again + QMetaObject::invokeMethod(&loop, "quit", Qt::QueuedConnection); + QCOMPARE(loop.exec(), 0); +} + void tst_QEventLoop::exit() { DEPENDS_ON(exec()); } +void tst_QEventLoop::execAfterExit() +{ + QEventLoop loop; + EventLoopExiter obj(&loop); + + QMetaObject::invokeMethod(&obj, "exit", Qt::QueuedConnection); + loop.exit(1); + QCOMPARE(loop.exec(), 0); +} + void tst_QEventLoop::wakeUp() { EventLoopThread thread; diff --git a/tests/auto/qthread/tst_qthread.cpp b/tests/auto/qthread/tst_qthread.cpp index e6bf9ce..c7036e4 100644 --- a/tests/auto/qthread/tst_qthread.cpp +++ b/tests/auto/qthread/tst_qthread.cpp @@ -86,6 +86,7 @@ private slots: void start(); void terminate(); void quit(); + void execAfterQuit(); void wait(); void started(); void finished(); @@ -265,6 +266,34 @@ public: } }; +class ExecAfterQuitThreadHelper: public QObject +{ + Q_OBJECT + QThread *thr; +public: + ExecAfterQuitThreadHelper(QThread *thr) : thr(thr) {} +public slots: + void doIt() { thr->exit(0); } +}; + +class ExecAfterQuitThread: public QThread +{ +public: + int returnValue; + void run() + { + ExecAfterQuitThreadHelper obj(this); + + QMetaObject::invokeMethod(&obj, "doIt", Qt::QueuedConnection); + exit(1); + + // returnValue will be either 0 or 1, depending on which of the two + // above take effect. The correct value is 0, since exit(1) before + // exec() should have no effect + returnValue = exec(); + } +}; + tst_QThread::tst_QThread() { @@ -424,34 +453,52 @@ void tst_QThread::stackSize() void tst_QThread::exit() { - Exit_Thread thread; - thread.object = new Exit_Object; - thread.object->moveToThread(&thread); - thread.code = 42; - thread.result = 0; - QVERIFY(!thread.isFinished()); - QVERIFY(!thread.isRunning()); - QMutexLocker locker(&thread.mutex); - thread.start(); - QVERIFY(thread.isRunning()); - QVERIFY(!thread.isFinished()); - thread.cond.wait(locker.mutex()); - QVERIFY(thread.wait(five_minutes)); - QVERIFY(thread.isFinished()); - QVERIFY(!thread.isRunning()); - QCOMPARE(thread.result, thread.code); - delete thread.object; + { + Exit_Thread thread; + thread.object = new Exit_Object; + thread.object->moveToThread(&thread); + thread.code = 42; + thread.result = 0; + QVERIFY(!thread.isFinished()); + QVERIFY(!thread.isRunning()); - Exit_Thread thread2; - thread2.object = 0; - thread2.code = 53; - thread2.result = 0; - QMutexLocker locker2(&thread2.mutex); - thread2.start(); - thread2.exit(thread2.code); - thread2.cond.wait(locker2.mutex()); - QVERIFY(thread2.wait(five_minutes)); - QCOMPARE(thread2.result, thread2.code); + QMutexLocker locker(&thread.mutex); + thread.start(); + QVERIFY(thread.isRunning()); + QVERIFY(!thread.isFinished()); + // but the thread is not running the event loop yet (the mutex is locked) + + // start the event loop + thread.cond.wait(locker.mutex()); + + // the Exit_Object above will cause the thread to exit + QVERIFY(thread.wait(five_minutes)); + QVERIFY(thread.isFinished()); + QVERIFY(!thread.isRunning()); + QCOMPARE(thread.result, thread.code); + delete thread.object; + } + + { + Exit_Thread thread2; + thread2.object = 0; + thread2.code = 53; + thread2.result = 0; + QMutexLocker locker2(&thread2.mutex); + thread2.start(); + + // the mutex is locked, so the thread has *not* started running the event loop yet + // this will do nothing: + thread2.exit(thread2.code); + + // the thread will now start running + thread2.cond.wait(locker2.mutex()); + + // this will cause it to exit now + thread2.exit(++thread2.code); + QVERIFY(thread2.wait(five_minutes)); + QCOMPARE(thread2.result, thread2.code); + } } void tst_QThread::start() @@ -498,32 +545,59 @@ void tst_QThread::terminate() void tst_QThread::quit() { - Quit_Thread thread; - thread.object = new Quit_Object; - thread.object->moveToThread(&thread); - thread.result = -1; - QVERIFY(!thread.isFinished()); - QVERIFY(!thread.isRunning()); - QMutexLocker locker(&thread.mutex); - thread.start(); - QVERIFY(thread.isRunning()); - QVERIFY(!thread.isFinished()); - thread.cond.wait(locker.mutex()); - QVERIFY(thread.wait(five_minutes)); - QVERIFY(thread.isFinished()); - QVERIFY(!thread.isRunning()); - QCOMPARE(thread.result, 0); - delete thread.object; + // very similar to exit() above + { + Quit_Thread thread; + thread.object = new Quit_Object; + thread.object->moveToThread(&thread); + thread.result = -1; + QVERIFY(!thread.isFinished()); + QVERIFY(!thread.isRunning()); - Quit_Thread thread2; - thread2.object = 0; - thread2.result = -1; - QMutexLocker locker2(&thread2.mutex); - thread2.start(); - thread2.quit(); - thread2.cond.wait(locker2.mutex()); - QVERIFY(thread2.wait(five_minutes)); - QCOMPARE(thread2.result, 0); + // start the thread, but keep the event loop from starting + // (while the mutex is locked) + QMutexLocker locker(&thread.mutex); + thread.start(); + QVERIFY(thread.isRunning()); + QVERIFY(!thread.isFinished()); + + // unlock the mutex and let the event loop run + // the Quit_Object above will cause the thread to quit + thread.cond.wait(locker.mutex()); + QVERIFY(thread.wait(five_minutes)); + QVERIFY(thread.isFinished()); + QVERIFY(!thread.isRunning()); + QCOMPARE(thread.result, 0); + delete thread.object; + } + + { + Quit_Thread thread2; + thread2.object = 0; + thread2.result = -1; + + // start the thread, but keep the event loop from starting + // (while the mutex is locked) + QMutexLocker locker2(&thread2.mutex); + thread2.start(); + thread2.quit(); // does nothing, the event loop is not running! + + // unlock the mutex and let the event loop run + thread2.cond.wait(locker2.mutex()); + + // there's no Quit_Object so it won't quit on its own + thread2.quit(); + QVERIFY(thread2.wait(five_minutes)); + QCOMPARE(thread2.result, 0); + } +} + +void tst_QThread::execAfterQuit() +{ + ExecAfterQuitThread thread; + thread.start(); + QVERIFY(thread.wait()); + QCOMPARE(thread.returnValue, 0); } void tst_QThread::wait() @@ -994,8 +1068,17 @@ void tst_QThread::QTBUG15378_exitAndExec() Thread thread; thread.value = 0; thread.start(); - thread.exit(556); - thread.sem1.release(); //should exit the first loop + thread.exit(42); // will do nothing, this value should not appear + thread.sem1.release(); //should enter the first loop + + Exit_Object *exit_object = new Exit_Object; + exit_object->code = 556; + exit_object->thread = &thread; + QMetaObject::invokeMethod(exit_object, "slot", Qt::QueuedConnection); + exit_object->deleteLater(); + exit_object->moveToThread(&thread); // should exit the first loop + exit_object = 0; + thread.sem2.acquire(); int v = thread.value; QCOMPARE(v, 556); -- cgit v0.12 From e0489b905d6a31c7a904ca2b62a1e60cd12dba4f Mon Sep 17 00:00:00 2001 From: mread Date: Tue, 25 Jan 2011 14:29:41 +0000 Subject: Orientation control implementation for Symbian This used the orientation control QWidget attributes API from maemo5, and provides a simple implementation for Symbian. The essense of the implementation is that the latest setting of one of these QWidget orientation attributes will set the orientation for the whole app. Testing the attributes will return only the last attribute set, it will not return the app orientation state. A new task, QTBUG-16972, has been created to provide a more comprehensive implementation in the future. This may provide a more effective emulation of the maemo5 behaviour, or may incorporate further reaching concepts for QML rotations. Task-number: QTBUG-11785 Reviewed-by: Shane Kearns --- src/corelib/global/qnamespace.h | 13 ++++++++++--- src/gui/kernel/qt_s60_p.h | 2 ++ src/gui/kernel/qwidget.cpp | 40 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index 4f3a742..e492345 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -511,9 +511,16 @@ public: #if 0 // these values are reserved for Maemo5 - do not re-use them WA_Maemo5NonComposited = 126, WA_Maemo5StackedWindow = 127, - WA_Maemo5PortraitOrientation = 128, - WA_Maemo5LandscapeOrientation = 129, - WA_Maemo5AutoOrientation = 130, +#endif + + WA_LockPortraitOrientation = 128, + WA_LockLandscapeOrientation = 129, + WA_AutoOrientation = 130, + +#if 0 // these values are reserved for Maemo5 - do not re-use them + WA_Maemo5PortraitOrientation = WA_LockPortraitOrientation, + WA_Maemo5LandscapeOrientation = WA_LockLandscapeOrientation, + WA_Maemo5AutoOrientation = WA_AutoOrientation, WA_Maemo5ShowProgressIndicator = 131, #endif diff --git a/src/gui/kernel/qt_s60_p.h b/src/gui/kernel/qt_s60_p.h index fdb35d5..40697bf 100644 --- a/src/gui/kernel/qt_s60_p.h +++ b/src/gui/kernel/qt_s60_p.h @@ -141,6 +141,7 @@ public: int supportsPremultipliedAlpha : 1; int avkonComponentsSupportTransparency : 1; int menuBeingConstructed : 1; + int orientationSet : 1; QApplication::QS60MainApplicationFactory s60ApplicationFactory; // typedef'ed pointer type static CEikButtonGroupContainer *cba; @@ -295,6 +296,7 @@ inline QS60Data::QS60Data() supportsPremultipliedAlpha(0), avkonComponentsSupportTransparency(0), menuBeingConstructed(0), + orientationSet(0), s60ApplicationFactory(0) #ifdef Q_OS_SYMBIAN ,s60InstalledTrapHandler(0) diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 9a76b0a..e542a59 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -124,6 +124,10 @@ #include "qtabwidget.h" // Needed in inTabWidget() #endif // QT_KEYPAD_NAVIGATION +#ifdef Q_WS_S60 +#include +#endif + // widget/widget data creation count //#define QWIDGET_EXTRA_DEBUG //#define ALIEN_DEBUG @@ -10810,6 +10814,42 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) d->registerTouchWindow(); #endif break; + case Qt::WA_LockPortraitOrientation: + case Qt::WA_LockLandscapeOrientation: + case Qt::WA_AutoOrientation: { + const Qt::WidgetAttribute orientations[3] = { + Qt::WA_LockPortraitOrientation, + Qt::WA_LockLandscapeOrientation, + Qt::WA_AutoOrientation + }; + + if (on) { + // We can only have one of these set at a time + for (int i = 0; i < 3; ++i) { + if (orientations[i] != attribute) + setAttribute_internal(orientations[i], false, data, d); + } + } + +#ifdef Q_WS_S60 + CAknAppUiBase* appUi = static_cast(CEikonEnv::Static()->EikAppUi()); + const CAknAppUiBase::TAppUiOrientation s60orientations[] = { + CAknAppUiBase::EAppUiOrientationPortrait, + CAknAppUiBase::EAppUiOrientationLandscape, + CAknAppUiBase::EAppUiOrientationAutomatic + }; + CAknAppUiBase::TAppUiOrientation s60orientation = CAknAppUiBase::EAppUiOrientationUnspecified; + for (int i = 0; i < 3; ++i) { + if (testAttribute(orientations[i])) { + s60orientation = s60orientations[i]; + break; + } + } + QT_TRAP_THROWING(appUi->SetOrientationL(s60orientation)); + S60->orientationSet = true; +#endif + break; + } default: break; } -- cgit v0.12 From 547e2162c872ca5707f5bc54d06b3c39c9bd6477 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Fri, 28 Jan 2011 10:24:20 +1000 Subject: Add test for Loader implicitWidth/implicitHeight --- .../qdeclarativeloader/data/implicitSize.qml | 28 ++++++++++++++++++++++ .../qdeclarativeloader/tst_qdeclarativeloader.cpp | 18 ++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 tests/auto/declarative/qdeclarativeloader/data/implicitSize.qml diff --git a/tests/auto/declarative/qdeclarativeloader/data/implicitSize.qml b/tests/auto/declarative/qdeclarativeloader/data/implicitSize.qml new file mode 100644 index 0000000..53aad97 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeloader/data/implicitSize.qml @@ -0,0 +1,28 @@ +import QtQuick 1.1 + +Rectangle { + property real implWidth: 0 + property real implHeight: 0 + color: "green" + width: loader.implicitWidth+50 + height: loader.implicitHeight+50 + + Loader { + id: loader + sourceComponent: Item { + anchors.centerIn: parent + + implicitWidth: 100 + implicitHeight: 100 + Rectangle { + color: "red" + anchors.fill: parent + } + } + + anchors.fill: parent + anchors.margins: 50 + onImplicitWidthChanged: implWidth = implicitWidth + onImplicitHeightChanged: implHeight = loader.implicitHeight + } +} diff --git a/tests/auto/declarative/qdeclarativeloader/tst_qdeclarativeloader.cpp b/tests/auto/declarative/qdeclarativeloader/tst_qdeclarativeloader.cpp index ea8ea16..a5e708b 100644 --- a/tests/auto/declarative/qdeclarativeloader/tst_qdeclarativeloader.cpp +++ b/tests/auto/declarative/qdeclarativeloader/tst_qdeclarativeloader.cpp @@ -90,6 +90,7 @@ private slots: void vmeErrors(); void creationContext(); void QTBUG_16928(); + void implicitSize(); private: QDeclarativeEngine engine; @@ -603,6 +604,23 @@ void tst_QDeclarativeLoader::QTBUG_16928() delete item; } +void tst_QDeclarativeLoader::implicitSize() +{ + QDeclarativeComponent component(&engine, TEST_FILE("implicitSize.qml")); + QDeclarativeItem *item = qobject_cast(component.create()); + QVERIFY(item); + + QCOMPARE(item->width(), 150.); + QCOMPARE(item->height(), 150.); + + QCOMPARE(item->property("implHeight").toReal(), 100.); + + QEXPECT_FAIL("", "versioned property implicit object reference", Continue); + QCOMPARE(item->property("implWidth").toReal(), 100.); + + delete item; +} + QTEST_MAIN(tst_QDeclarativeLoader) #include "tst_qdeclarativeloader.moc" -- cgit v0.12 From cb6b9ee680f792750d0cb265ea59ff3ff4643562 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 28 Jan 2011 12:00:21 +1000 Subject: Ensure simple objects also get the appropriate property cache Task-number: QTBUG-13849 --- src/declarative/qml/qdeclarativedata_p.h | 5 +---- src/declarative/qml/qdeclarativeobjectscriptclass.cpp | 3 ++- src/declarative/qml/qdeclarativevme.cpp | 12 ++++++------ .../qdeclarativeecmascript/data/metaobjectRevision4.qml | 14 ++++++++++++++ .../qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp | 9 +++++++++ 5 files changed, 32 insertions(+), 11 deletions(-) create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevision4.qml diff --git a/src/declarative/qml/qdeclarativedata_p.h b/src/declarative/qml/qdeclarativedata_p.h index f0ff0c0..33458dc 100644 --- a/src/declarative/qml/qdeclarativedata_p.h +++ b/src/declarative/qml/qdeclarativedata_p.h @@ -66,7 +66,6 @@ class QDeclarativePropertyCache; class QDeclarativeContextData; class QDeclarativeNotifier; class QDeclarativeDataExtended; -class QDeclarativeType; // This class is structured in such a way, that simply zero'ing it is the // default state for elemental object allocations. This is crucial in the // workings of the QDeclarativeInstruction::CreateSimpleObject instruction. @@ -78,7 +77,7 @@ public: : ownMemory(true), ownContext(false), indestructible(true), explicitIndestructibleSet(false), context(0), outerContext(0), bindings(0), nextContextObject(0), prevContextObject(0), bindingBitsSize(0), bindingBits(0), lineNumber(0), columnNumber(0), deferredComponent(0), deferredIdx(0), - scriptValue(0), objectDataRefCount(0), propertyCache(0), guards(0), type(0), extendedData(0) { + scriptValue(0), objectDataRefCount(0), propertyCache(0), guards(0), extendedData(0) { init(); } @@ -137,8 +136,6 @@ public: QDeclarativeGuard *guards; - const QDeclarativeType *type; - static QDeclarativeData *get(const QObject *object, bool create = false) { QObjectPrivate *priv = QObjectPrivate::get(const_cast(object)); if (priv->wasDeleted) { diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp index 7701a23..ee47d0b 100644 --- a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp +++ b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp @@ -166,8 +166,9 @@ QDeclarativeObjectScriptClass::queryProperty(QObject *obj, const Identifier &nam QDeclarativeEnginePrivate *enginePrivate = QDeclarativeEnginePrivate::get(engine); lastData = QDeclarativePropertyCache::property(engine, obj, name, local); if ((hints & ImplicitObject) && lastData && lastData->revision != 0) { + QDeclarativeData *ddata = QDeclarativeData::get(obj); - if (ddata && ddata->propertyCache && !ddata->propertyCache->isAllowedInRevision(lastData)) + if (ddata && ddata->propertyCache && !ddata->propertyCache->isAllowedInRevision(lastData)) return 0; } diff --git a/src/declarative/qml/qdeclarativevme.cpp b/src/declarative/qml/qdeclarativevme.cpp index 657b10d..366c64b 100644 --- a/src/declarative/qml/qdeclarativevme.cpp +++ b/src/declarative/qml/qdeclarativevme.cpp @@ -194,8 +194,6 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack &stack, QDeclarativeData *ddata = QDeclarativeData::get(o); Q_ASSERT(ddata); - if (types.at(instr.create.type).type) - ddata->type = types.at(instr.create.type).type; if (stack.isEmpty()) { if (ddata->context) { @@ -249,10 +247,12 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack &stack, ::memset(o, 0, instr.createSimple.typeSize + sizeof(QDeclarativeData)); instr.createSimple.create(o); - QDeclarativeData *ddata = - (QDeclarativeData *)(((const char *)o) + instr.createSimple.typeSize); - if (types.at(instr.createSimple.type).type) - ddata->type = types.at(instr.createSimple.type).type; + QDeclarativeData *ddata = (QDeclarativeData *)(((const char *)o) + instr.createSimple.typeSize); + const QDeclarativeCompiledData::TypeReference &ref = types.at(instr.createSimple.type); + if (!ddata->propertyCache && ref.typePropertyCache) { + ddata->propertyCache = ref.typePropertyCache; + ddata->propertyCache->addref(); + } ddata->lineNumber = instr.line; ddata->columnNumber = instr.createSimple.column; diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevision4.qml b/tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevision4.qml new file mode 100644 index 0000000..81ea536 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/metaobjectRevision4.qml @@ -0,0 +1,14 @@ +import Qt.test 1.1 +import QtQuick 1.0 + +QtObject { + property variant a + property real test + + a: MyRevisionedClass { + prop2: 11 + + Component.onCompleted: test = prop2 + } +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp index e7f9a2c..f66cd0b 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp +++ b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp @@ -2983,6 +2983,15 @@ void tst_qdeclarativeecmascript::revision() MyRevisionedClass *object = qobject_cast(component.create()); QVERIFY(object != 0); } + // Test that non-root classes can resolve revisioned methods + { + QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision4.qml")); + + QObject *object = component.create(); + QVERIFY(object != 0); + QCOMPARE(object->property("test").toReal(), 11.); + delete object; + } } QTEST_MAIN(tst_qdeclarativeecmascript) -- cgit v0.12 From 57ddd7c69705dfbf3d06b8a0157e5e706120c818 Mon Sep 17 00:00:00 2001 From: Christopher Ham Date: Fri, 28 Jan 2011 12:55:57 +1000 Subject: Fix MaximumLineCount in Text and add tests Fixed MaximumLineCount not truncating when wrapMode was not set. Visual autotests were added to test various possible options for maximumLineCount. Task-number: QTBUG-12305 Reviewed-by: Michael Brasser --- src/declarative/graphicsitems/qdeclarativetext.cpp | 44 ++++++++++----------- .../maximumLineCount/data-X11/newLines.0.png | Bin 0 -> 343 bytes .../maximumLineCount/data-X11/newLines.qml | 11 ++++++ .../maximumLineCount/data-X11/newLines_wrap.0.png | Bin 0 -> 465 bytes .../maximumLineCount/data-X11/newLines_wrap.qml | 11 ++++++ .../data-X11/newLines_wrap_elide.0.png | Bin 0 -> 469 bytes .../data-X11/newLines_wrap_elide.qml | 11 ++++++ .../maximumLineCount/data-X11/wrap.0.png | Bin 0 -> 557 bytes .../maximumLineCount/data-X11/wrap.qml | 11 ++++++ .../maximumLineCount/data-X11/wrap_elide.0.png | Bin 0 -> 537 bytes .../maximumLineCount/data-X11/wrap_elide.qml | 11 ++++++ .../maximumLineCount/data/newLines.0.png | Bin 0 -> 343 bytes .../maximumLineCount/data/newLines.qml | 11 ++++++ .../maximumLineCount/data/newLines_wrap.0.png | Bin 0 -> 465 bytes .../maximumLineCount/data/newLines_wrap.qml | 11 ++++++ .../data/newLines_wrap_elide.0.png | Bin 0 -> 469 bytes .../maximumLineCount/data/newLines_wrap_elide.qml | 11 ++++++ .../maximumLineCount/data/wrap.0.png | Bin 0 -> 557 bytes .../maximumLineCount/data/wrap.qml | 11 ++++++ .../maximumLineCount/data/wrap_elide.0.png | Bin 0 -> 537 bytes .../maximumLineCount/data/wrap_elide.qml | 11 ++++++ .../qdeclarativetext/maximumLineCount/newLines.qml | 13 ++++++ .../maximumLineCount/newLines_wrap.qml | 14 +++++++ .../maximumLineCount/newLines_wrap_elide.qml | 15 +++++++ .../qdeclarativetext/maximumLineCount/wrap.qml | 14 +++++++ .../maximumLineCount/wrap_elide.qml | 15 +++++++ 26 files changed, 201 insertions(+), 24 deletions(-) create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/newLines.0.png create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/newLines.qml create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/newLines_wrap.0.png create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/newLines_wrap.qml create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/newLines_wrap_elide.0.png create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/newLines_wrap_elide.qml create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/wrap.0.png create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/wrap.qml create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/wrap_elide.0.png create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/wrap_elide.qml create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/newLines.0.png create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/newLines.qml create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/newLines_wrap.0.png create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/newLines_wrap.qml create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/newLines_wrap_elide.0.png create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/newLines_wrap_elide.qml create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/wrap.0.png create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/wrap.qml create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/wrap_elide.0.png create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/wrap_elide.qml create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/newLines.qml create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/newLines_wrap.qml create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/newLines_wrap_elide.qml create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/wrap.qml create mode 100644 tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/wrap_elide.qml diff --git a/src/declarative/graphicsitems/qdeclarativetext.cpp b/src/declarative/graphicsitems/qdeclarativetext.cpp index d424e30..1e0988d 100644 --- a/src/declarative/graphicsitems/qdeclarativetext.cpp +++ b/src/declarative/graphicsitems/qdeclarativetext.cpp @@ -366,6 +366,8 @@ QSize QDeclarativeTextPrivate::setupTextLayout() if (maximumLineCountValid) { layout.beginLayout(); + if (!lineWidth) + lineWidth = INT_MAX; int y = 0; int linesLeft = maximumLineCount; while (linesLeft > 0) { @@ -374,34 +376,28 @@ QSize QDeclarativeTextPrivate::setupTextLayout() break; visibleCount++; - - if (lineWidth) { - if (--linesLeft == 0) { - line.setLineWidth(q->width()*2); // Set out more than is required, but not too much. - if (line.naturalTextWidth() > lineWidth) - line.setLineWidth(lineWidth - elideWidth); - visibleTextLength += line.textLength(); // Used to catch new lines that are shorter than the layout width. - - if (visibleTextLength < text.length()) { - truncate = true; - if (elideMode==QDeclarativeText::ElideRight) { - // Need to correct for alignment - int x = line.naturalTextWidth(); - if (hAlign == QDeclarativeText::AlignRight) { - x = q->width()-elideWidth; - } else if (hAlign == QDeclarativeText::AlignHCenter) { - x = (q->width()+line.naturalTextWidth()-elideWidth)/2; - } - elidePos = QPointF(x, y + fm.ascent()); + line.setLineWidth(lineWidth); + visibleTextLength += line.textLength(); + + if (--linesLeft == 0) { + if (visibleTextLength < text.length()) { + truncate = true; + if (elideMode==QDeclarativeText::ElideRight && q->widthValid()) { + // Need to correct for alignment + line.setLineWidth(lineWidth-elideWidth); + int x = line.naturalTextWidth(); + if (hAlign == QDeclarativeText::AlignRight) { + x = q->width()-elideWidth; + } else if (hAlign == QDeclarativeText::AlignHCenter) { + x = (q->width()+line.naturalTextWidth()-elideWidth)/2; } + elidePos = QPointF(x, y + fm.ascent()); + elideText = true; } - } else { - line.setLineWidth(lineWidth); - visibleTextLength += line.textLength(); } - - y += line.height(); } + + y += line.height(); } layout.endLayout(); diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/newLines.0.png b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/newLines.0.png new file mode 100644 index 0000000..c24c7c6 Binary files /dev/null and b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/newLines.0.png differ diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/newLines.qml b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/newLines.qml new file mode 100644 index 0000000..affd3a6 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/newLines.qml @@ -0,0 +1,11 @@ +import Qt.VisualTest 4.7 + +VisualTest { + Frame { + msec: 0 + } + Frame { + msec: 16 + image: "newLines.0.png" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/newLines_wrap.0.png b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/newLines_wrap.0.png new file mode 100644 index 0000000..0ba68e5 Binary files /dev/null and b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/newLines_wrap.0.png differ diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/newLines_wrap.qml b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/newLines_wrap.qml new file mode 100644 index 0000000..410b47d --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/newLines_wrap.qml @@ -0,0 +1,11 @@ +import Qt.VisualTest 4.7 + +VisualTest { + Frame { + msec: 0 + } + Frame { + msec: 16 + image: "newLines_wrap.0.png" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/newLines_wrap_elide.0.png b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/newLines_wrap_elide.0.png new file mode 100644 index 0000000..3f1144b Binary files /dev/null and b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/newLines_wrap_elide.0.png differ diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/newLines_wrap_elide.qml b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/newLines_wrap_elide.qml new file mode 100644 index 0000000..94cf1d2 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/newLines_wrap_elide.qml @@ -0,0 +1,11 @@ +import Qt.VisualTest 4.7 + +VisualTest { + Frame { + msec: 0 + } + Frame { + msec: 16 + image: "newLines_wrap_elide.0.png" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/wrap.0.png b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/wrap.0.png new file mode 100644 index 0000000..f0ad965 Binary files /dev/null and b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/wrap.0.png differ diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/wrap.qml b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/wrap.qml new file mode 100644 index 0000000..4b55312 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/wrap.qml @@ -0,0 +1,11 @@ +import Qt.VisualTest 4.7 + +VisualTest { + Frame { + msec: 0 + } + Frame { + msec: 16 + image: "wrap.0.png" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/wrap_elide.0.png b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/wrap_elide.0.png new file mode 100644 index 0000000..62274ce Binary files /dev/null and b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/wrap_elide.0.png differ diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/wrap_elide.qml b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/wrap_elide.qml new file mode 100644 index 0000000..7d002ea --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data-X11/wrap_elide.qml @@ -0,0 +1,11 @@ +import Qt.VisualTest 4.7 + +VisualTest { + Frame { + msec: 0 + } + Frame { + msec: 16 + image: "wrap_elide.0.png" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/newLines.0.png b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/newLines.0.png new file mode 100644 index 0000000..c24c7c6 Binary files /dev/null and b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/newLines.0.png differ diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/newLines.qml b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/newLines.qml new file mode 100644 index 0000000..affd3a6 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/newLines.qml @@ -0,0 +1,11 @@ +import Qt.VisualTest 4.7 + +VisualTest { + Frame { + msec: 0 + } + Frame { + msec: 16 + image: "newLines.0.png" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/newLines_wrap.0.png b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/newLines_wrap.0.png new file mode 100644 index 0000000..0ba68e5 Binary files /dev/null and b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/newLines_wrap.0.png differ diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/newLines_wrap.qml b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/newLines_wrap.qml new file mode 100644 index 0000000..410b47d --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/newLines_wrap.qml @@ -0,0 +1,11 @@ +import Qt.VisualTest 4.7 + +VisualTest { + Frame { + msec: 0 + } + Frame { + msec: 16 + image: "newLines_wrap.0.png" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/newLines_wrap_elide.0.png b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/newLines_wrap_elide.0.png new file mode 100644 index 0000000..3f1144b Binary files /dev/null and b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/newLines_wrap_elide.0.png differ diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/newLines_wrap_elide.qml b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/newLines_wrap_elide.qml new file mode 100644 index 0000000..94cf1d2 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/newLines_wrap_elide.qml @@ -0,0 +1,11 @@ +import Qt.VisualTest 4.7 + +VisualTest { + Frame { + msec: 0 + } + Frame { + msec: 16 + image: "newLines_wrap_elide.0.png" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/wrap.0.png b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/wrap.0.png new file mode 100644 index 0000000..f0ad965 Binary files /dev/null and b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/wrap.0.png differ diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/wrap.qml b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/wrap.qml new file mode 100644 index 0000000..4b55312 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/wrap.qml @@ -0,0 +1,11 @@ +import Qt.VisualTest 4.7 + +VisualTest { + Frame { + msec: 0 + } + Frame { + msec: 16 + image: "wrap.0.png" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/wrap_elide.0.png b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/wrap_elide.0.png new file mode 100644 index 0000000..62274ce Binary files /dev/null and b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/wrap_elide.0.png differ diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/wrap_elide.qml b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/wrap_elide.qml new file mode 100644 index 0000000..7d002ea --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/data/wrap_elide.qml @@ -0,0 +1,11 @@ +import Qt.VisualTest 4.7 + +VisualTest { + Frame { + msec: 0 + } + Frame { + msec: 16 + image: "wrap_elide.0.png" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/newLines.qml b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/newLines.qml new file mode 100644 index 0000000..4e993c6 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/newLines.qml @@ -0,0 +1,13 @@ +import QtQuick 1.0 +import "../../shared" 1.0 + +Rectangle { + width: childrenRect.width + height: childrenRect.height + + TestText { + width: 80 + maximumLineCount: 2 + text: "Line1\nLine2\nLine3\nLine4" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/newLines_wrap.qml b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/newLines_wrap.qml new file mode 100644 index 0000000..5d8f50b --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/newLines_wrap.qml @@ -0,0 +1,14 @@ +import QtQuick 1.0 +import "../../shared" 1.0 + +Rectangle { + width: childrenRect.width + height: childrenRect.height + + TestText { + width: 80 + maximumLineCount: 3 + wrapMode: Text.WordWrap + text: "Line1 has a more\nLine2\nLine3\nLine4" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/newLines_wrap_elide.qml b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/newLines_wrap_elide.qml new file mode 100644 index 0000000..ac7b5cb --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/newLines_wrap_elide.qml @@ -0,0 +1,15 @@ +import QtQuick 1.0 +import "../../shared" 1.0 + +Rectangle { + width: childrenRect.width + height: childrenRect.height + + TestText { + width: 80 + maximumLineCount: 3 + wrapMode: Text.WordWrap + elide: Text.ElideRight + text: "Line1 has a more\nLine2\nLine3\nLine4" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/wrap.qml b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/wrap.qml new file mode 100644 index 0000000..6d72430 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/wrap.qml @@ -0,0 +1,14 @@ +import QtQuick 1.0 +import "../../shared" 1.0 + +Rectangle { + width: childrenRect.width + height: childrenRect.height + + TestText { + width: 80 + maximumLineCount: 3 + wrapMode: Text.WordWrap + text: "The quick brown fox jumped over the lazy dog" + } +} diff --git a/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/wrap_elide.qml b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/wrap_elide.qml new file mode 100644 index 0000000..785c5f5 --- /dev/null +++ b/tests/auto/declarative/qmlvisual/qdeclarativetext/maximumLineCount/wrap_elide.qml @@ -0,0 +1,15 @@ +import QtQuick 1.0 +import "../../shared" 1.0 + +Rectangle { + width: childrenRect.width + height: childrenRect.height + + TestText { + width: 80 + maximumLineCount: 3 + wrapMode: Text.WordWrap + elide: Text.ElideRight + text: "The quick brown fox jumped over the lazy dog" + } +} -- cgit v0.12 From 64c0ee4e5f1f05105ab6168ebb4cb188e8fd838f Mon Sep 17 00:00:00 2001 From: Christopher Ham Date: Fri, 28 Jan 2011 13:32:25 +1000 Subject: Fixing right-to-left text in Text and TextInput The Text and TextInput items should now automatically flip the alignment of right-to-left text. Autotests also added to ensure the text is on the correct side (added for TextInput also). Task-number: QTBUG-15880 Reviewed-by: Martin Jones --- src/declarative/graphicsitems/qdeclarativetext.cpp | 24 ++++++++++++++----- .../graphicsitems/qdeclarativetext_p_p.h | 2 +- .../graphicsitems/qdeclarativetextinput.cpp | 15 ++++++++---- .../graphicsitems/qdeclarativetextinput_p_p.h | 6 ++++- .../data/horizontalAlignment_RightToLeft.qml | 23 ++++++++++++++++++ .../qdeclarativetext/tst_qdeclarativetext.cpp | 28 ++++++++++++++++++++++ .../data/horizontalAlignment_RightToLeft.qml | 23 ++++++++++++++++++ .../tst_qdeclarativetextedit.cpp | 25 +++++++++++++++++++ .../data/horizontalAlignment_RightToLeft.qml | 23 ++++++++++++++++++ .../tst_qdeclarativetextinput.cpp | 26 ++++++++++++++++++++ 10 files changed, 183 insertions(+), 12 deletions(-) create mode 100644 tests/auto/declarative/qdeclarativetext/data/horizontalAlignment_RightToLeft.qml create mode 100644 tests/auto/declarative/qdeclarativetextedit/data/horizontalAlignment_RightToLeft.qml create mode 100644 tests/auto/declarative/qdeclarativetextinput/data/horizontalAlignment_RightToLeft.qml diff --git a/src/declarative/graphicsitems/qdeclarativetext.cpp b/src/declarative/graphicsitems/qdeclarativetext.cpp index 1e0988d..5edfc31 100644 --- a/src/declarative/graphicsitems/qdeclarativetext.cpp +++ b/src/declarative/graphicsitems/qdeclarativetext.cpp @@ -268,7 +268,8 @@ void QDeclarativeTextPrivate::updateSize() singleline = false; // richtext can't elide or be optimized for single-line case ensureDoc(); doc->setDefaultFont(font); - QTextOption option((Qt::Alignment)int(hAlign | vAlign)); + QTextOption option; + option.setAlignment((Qt::Alignment)int(hAlign | vAlign)); option.setWrapMode(QTextOption::WrapMode(wrapMode)); doc->setDefaultTextOption(option); if (requireImplicitWidth && q->widthValid()) { @@ -341,6 +342,17 @@ QSize QDeclarativeTextPrivate::setupTextLayout() textOption.setWrapMode(QTextOption::WrapMode(wrapMode)); layout.setTextOption(textOption); + QDeclarativeText::HAlignment hAlignment = hAlign; + if(text.isRightToLeft()) { + if ((hAlign == QDeclarativeText::AlignLeft) || (hAlign == QDeclarativeText::AlignJustify)) { + hAlignment = QDeclarativeText::AlignRight; + } else if (hAlign == QDeclarativeText::AlignRight) { + hAlignment = QDeclarativeText::AlignLeft; + } else { + hAlignment = hAlign; + } + } + bool elideText = false; bool truncate = false; @@ -386,9 +398,9 @@ QSize QDeclarativeTextPrivate::setupTextLayout() // Need to correct for alignment line.setLineWidth(lineWidth-elideWidth); int x = line.naturalTextWidth(); - if (hAlign == QDeclarativeText::AlignRight) { + if (hAlignment == QDeclarativeText::AlignRight) { x = q->width()-elideWidth; - } else if (hAlign == QDeclarativeText::AlignHCenter) { + } else if (hAlignment == QDeclarativeText::AlignHCenter) { x = (q->width()+line.naturalTextWidth()-elideWidth)/2; } elidePos = QPointF(x, y + fm.ascent()); @@ -435,13 +447,13 @@ QSize QDeclarativeTextPrivate::setupTextLayout() height += line.height(); if (!cacheAllTextAsImage) { - if ((hAlign == QDeclarativeText::AlignLeft) || (hAlign == QDeclarativeText::AlignJustify)) { + if ((hAlignment == QDeclarativeText::AlignLeft) || (hAlignment == QDeclarativeText::AlignJustify)) { x = 0; - } else if (hAlign == QDeclarativeText::AlignRight) { + } else if (hAlignment == QDeclarativeText::AlignRight) { x = layoutWidth - line.naturalTextWidth(); if (elideText && i == layout.lineCount()-1) x -= elideWidth; // Correct for when eliding multilines - } else if (hAlign == QDeclarativeText::AlignHCenter) { + } else if (hAlignment == QDeclarativeText::AlignHCenter) { x = (layoutWidth - line.naturalTextWidth()) / 2; if (elideText && i == layout.lineCount()-1) x -= elideWidth/2; // Correct for when eliding multilines diff --git a/src/declarative/graphicsitems/qdeclarativetext_p_p.h b/src/declarative/graphicsitems/qdeclarativetext_p_p.h index bae2d85..01e0ab5 100644 --- a/src/declarative/graphicsitems/qdeclarativetext_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativetext_p_p.h @@ -66,7 +66,7 @@ QT_BEGIN_NAMESPACE class QTextLayout; class QTextDocumentWithImageResources; -class QDeclarativeTextPrivate : public QDeclarativeImplicitSizeItemPrivate +class Q_AUTOTEST_EXPORT QDeclarativeTextPrivate : public QDeclarativeImplicitSizeItemPrivate { Q_DECLARE_PUBLIC(QDeclarativeText) public: diff --git a/src/declarative/graphicsitems/qdeclarativetextinput.cpp b/src/declarative/graphicsitems/qdeclarativetextinput.cpp index 911c68c..3d2466d 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextinput.cpp @@ -51,6 +51,7 @@ #include #include #include +#include #ifndef QT_NO_LINEEDIT @@ -1094,10 +1095,11 @@ void QDeclarativeTextInputPrivate::updateHorizontalScroll() int cix = qRound(control->cursorToX()); QRect br(q->boundingRect().toRect()); int widthUsed = calculateTextWidth(); + Qt::Alignment va = QStyle::visualAlignment(control->layoutDirection(), QFlag(Qt::Alignment(hAlign))); if (autoScroll) { if (widthUsed <= br.width()) { // text fits in br; use hscroll for alignment - switch (hAlign & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) { + switch (va & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) { case Qt::AlignRight: hscroll = widthUsed - br.width() - 1; break; @@ -1121,12 +1123,17 @@ void QDeclarativeTextInputPrivate::updateHorizontalScroll() hscroll = widthUsed - br.width() + 1; } } else { - if(hAlign == QDeclarativeTextInput::AlignRight){ + switch (va & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) { + case Qt::AlignRight: hscroll = q->width() - widthUsed; - }else if(hAlign == QDeclarativeTextInput::AlignHCenter){ + break; + case Qt::AlignHCenter: hscroll = (q->width() - widthUsed) / 2; - } else { + break; + default: + // Left hscroll = 0; + break; } } } diff --git a/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h b/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h index 9644410..1f45c11 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h @@ -66,7 +66,7 @@ QT_BEGIN_NAMESPACE -class QDeclarativeTextInputPrivate : public QDeclarativeImplicitSizePaintedItemPrivate +class Q_AUTOTEST_EXPORT QDeclarativeTextInputPrivate : public QDeclarativeImplicitSizePaintedItemPrivate { Q_DECLARE_PUBLIC(QDeclarativeTextInput) public: @@ -132,6 +132,10 @@ public: bool autoScroll; bool selectByMouse; bool canPaste; + + static inline QDeclarativeTextInputPrivate *get(QDeclarativeTextInput *t) { + return t->d_func(); + } }; QT_END_NAMESPACE diff --git a/tests/auto/declarative/qdeclarativetext/data/horizontalAlignment_RightToLeft.qml b/tests/auto/declarative/qdeclarativetext/data/horizontalAlignment_RightToLeft.qml new file mode 100644 index 0000000..4f58944 --- /dev/null +++ b/tests/auto/declarative/qdeclarativetext/data/horizontalAlignment_RightToLeft.qml @@ -0,0 +1,23 @@ +import QtQuick 1.0 + +Rectangle { + id: top + width: 200; height: 70; + + property alias horizontalAlignment: text.horizontalAlignment + property string text: "اختبا" + + Rectangle { + anchors.centerIn: parent + width: 180 + height: 20 + color: "green" + + Text { + id: text + objectName: "text" + anchors.fill: parent + text: top.text + } + } +} diff --git a/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp b/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp index fabae18..c9b5295 100644 --- a/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp +++ b/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -83,6 +84,7 @@ private slots: // ### these tests may be trivial void horizontalAlignment(); + void horizontalAlignment_RightToLeft(); void verticalAlignment(); void font(); void style(); @@ -502,6 +504,32 @@ void tst_qdeclarativetext::horizontalAlignment() } +void tst_qdeclarativetext::horizontalAlignment_RightToLeft() +{ + QDeclarativeView *canvas = createView(SRCDIR "/data/horizontalAlignment_RightToLeft.qml"); + QDeclarativeText *text = canvas->rootObject()->findChild("text"); + QVERIFY(text != 0); + canvas->show(); + + QDeclarativeTextPrivate *textPrivate = QDeclarativeTextPrivate::get(text); + QVERIFY(textPrivate != 0); + + QVERIFY(textPrivate->layout.lineAt(0).x() > canvas->width()/2); + + // "Right" aligned + text->setHAlign(QDeclarativeText::AlignRight); + QCOMPARE(text->hAlign(), QDeclarativeText::AlignRight); + QVERIFY(textPrivate->layout.lineAt(0).x() < canvas->width()/2); + + // Center aligned + text->setHAlign(QDeclarativeText::AlignHCenter); + QCOMPARE(text->hAlign(), QDeclarativeText::AlignHCenter); + QVERIFY(textPrivate->layout.lineAt(0).x() < canvas->width()/2); + QVERIFY(textPrivate->layout.lineAt(0).x() + textPrivate->layout.lineAt(0).width() > canvas->width()/2); + + delete canvas; +} + void tst_qdeclarativetext::verticalAlignment() { //test one align each, and then test if two align fails. diff --git a/tests/auto/declarative/qdeclarativetextedit/data/horizontalAlignment_RightToLeft.qml b/tests/auto/declarative/qdeclarativetextedit/data/horizontalAlignment_RightToLeft.qml new file mode 100644 index 0000000..43ea8d8 --- /dev/null +++ b/tests/auto/declarative/qdeclarativetextedit/data/horizontalAlignment_RightToLeft.qml @@ -0,0 +1,23 @@ +import QtQuick 1.0 + +Rectangle { + id: top + width: 200; height: 70; + + property alias horizontalAlignment: text.horizontalAlignment + property string text: "اختبا" + + Rectangle { + anchors.centerIn: parent + width: 200 + height: 20 + color: "green" + + TextEdit { + id: text + objectName: "text" + anchors.fill: parent + text: top.text + } + } +} diff --git a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp index cd1977a..b1e0cb9 100644 --- a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp +++ b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp @@ -102,6 +102,7 @@ private slots: // ### these tests may be trivial void hAlign(); + void hAlign_RightToLeft(); void vAlign(); void font(); void color(); @@ -424,6 +425,30 @@ void tst_qdeclarativetextedit::hAlign() } +void tst_qdeclarativetextedit::hAlign_RightToLeft() +{ + QDeclarativeView *canvas = createView(SRCDIR "/data/horizontalAlignment_RightToLeft.qml"); + QDeclarativeTextEdit *textEdit = canvas->rootObject()->findChild("text"); + QVERIFY(textEdit != 0); + canvas->show(); + + QVERIFY(textEdit->positionToRectangle(0).x() > canvas->width()/2); + + // "Right" align + textEdit->setHAlign(QDeclarativeTextEdit::AlignRight); + QCOMPARE(textEdit->hAlign(), QDeclarativeTextEdit::AlignRight); + QVERIFY(textEdit->positionToRectangle(0).x() < canvas->width()/2); + + // Center align + // Note that position 0 is on the right-hand side + textEdit->setHAlign(QDeclarativeTextEdit::AlignHCenter); + QCOMPARE(textEdit->hAlign(), QDeclarativeTextEdit::AlignHCenter); + QVERIFY(textEdit->positionToRectangle(0).x() - textEdit->width() < canvas->width()/2); + QVERIFY(textEdit->positionToRectangle(0).x() > canvas->width()/2); + + delete canvas; +} + void tst_qdeclarativetextedit::vAlign() { //test one align each, and then test if two align fails. diff --git a/tests/auto/declarative/qdeclarativetextinput/data/horizontalAlignment_RightToLeft.qml b/tests/auto/declarative/qdeclarativetextinput/data/horizontalAlignment_RightToLeft.qml new file mode 100644 index 0000000..b11535e --- /dev/null +++ b/tests/auto/declarative/qdeclarativetextinput/data/horizontalAlignment_RightToLeft.qml @@ -0,0 +1,23 @@ +import QtQuick 1.0 + +Rectangle { + id: top + width: 200; height: 70; + + property alias horizontalAlignment: text.horizontalAlignment + property string text: "اختبا" + + Rectangle { + anchors.centerIn: parent + width: 180 + height: 20 + color: "green" + + TextInput { + id: text + objectName: "text" + anchors.fill: parent + text: top.text + } + } +} diff --git a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp index 69c1f7e..78f6693 100644 --- a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp +++ b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp @@ -95,6 +95,7 @@ private slots: void horizontalAlignment_data(); void horizontalAlignment(); + void horizontalAlignment_RightToLeft(); void positionAt(); @@ -662,6 +663,31 @@ void tst_qdeclarativetextinput::horizontalAlignment() delete canvas; } +void tst_qdeclarativetextinput::horizontalAlignment_RightToLeft() +{ + QDeclarativeView *canvas = createView(SRCDIR "/data/horizontalAlignment_RightToLeft.qml"); + QDeclarativeTextInput *textInput = canvas->rootObject()->findChild("text"); + QVERIFY(textInput != 0); + canvas->show(); + + QDeclarativeTextInputPrivate *textInputPrivate = QDeclarativeTextInputPrivate::get(textInput); + QVERIFY(textInputPrivate != 0); + QVERIFY(-textInputPrivate->hscroll > canvas->width()/2); + + // "Right" Align + textInput->setHAlign(QDeclarativeTextInput::AlignRight); + QCOMPARE(textInput->hAlign(), QDeclarativeTextInput::AlignRight); + QVERIFY(-textInputPrivate->hscroll < canvas->width()/2); + + // Center Align + textInput->setHAlign(QDeclarativeTextInput::AlignHCenter); + QCOMPARE(textInput->hAlign(), QDeclarativeTextInput::AlignHCenter); + QVERIFY(-textInputPrivate->hscroll < canvas->width()/2); + QVERIFY(-textInputPrivate->hscroll + textInputPrivate->width() > canvas->width()/2); + + delete canvas; +} + void tst_qdeclarativetextinput::positionAt() { QDeclarativeView *canvas = createView(SRCDIR "/data/positionAt.qml"); -- cgit v0.12 From 7c1ab9b6a8e1b3d64c08a4f5067448884b068945 Mon Sep 17 00:00:00 2001 From: Yann Bodson Date: Fri, 28 Jan 2011 11:58:10 +1000 Subject: Add support for line spacing in Text element. This change adds the lineHeight and lineHeightMode properties. Task-number: QTBUG-14296 Reviewed-by: Martin Jones --- src/declarative/graphicsitems/qdeclarativetext.cpp | 84 +++++++++++++++++++++- src/declarative/graphicsitems/qdeclarativetext_p.h | 13 ++++ .../graphicsitems/qdeclarativetext_p_p.h | 2 + src/gui/text/qtextdocumentlayout.cpp | 17 ++++- src/gui/text/qtextdocumentlayout_p.h | 5 +- .../qdeclarativetext/data/lineHeight.qml | 15 ++++ .../qdeclarativetext/tst_qdeclarativetext.cpp | 32 +++++++++ 7 files changed, 162 insertions(+), 6 deletions(-) create mode 100644 tests/auto/declarative/qdeclarativetext/data/lineHeight.qml diff --git a/src/declarative/graphicsitems/qdeclarativetext.cpp b/src/declarative/graphicsitems/qdeclarativetext.cpp index 5edfc31..fb1ae06 100644 --- a/src/declarative/graphicsitems/qdeclarativetext.cpp +++ b/src/declarative/graphicsitems/qdeclarativetext.cpp @@ -41,6 +41,7 @@ #include "private/qdeclarativetext_p.h" #include "private/qdeclarativetext_p_p.h" +#include #include #include #include @@ -83,6 +84,14 @@ private: static QSet errors; }; +class QDeclarativeTextDocumentLayout : public QTextDocumentLayout +{ + Q_OBJECT +public: + QDeclarativeTextDocumentLayout(QTextDocument *doc); + void setLineHeight(qreal lineHeight, QDeclarativeText::LineHeightMode mode); +}; + DEFINE_BOOL_CONFIG_OPTION(enableImageCache, QML_ENABLE_TEXT_IMAGE_CACHE); QString QDeclarativeTextPrivate::elideChar = QString(0x2026); @@ -90,7 +99,8 @@ QString QDeclarativeTextPrivate::elideChar = QString(0x2026); QDeclarativeTextPrivate::QDeclarativeTextPrivate() : color((QRgb)0), style(QDeclarativeText::Normal), hAlign(QDeclarativeText::AlignLeft), vAlign(QDeclarativeText::AlignTop), elideMode(QDeclarativeText::ElideNone), - format(QDeclarativeText::AutoText), wrapMode(QDeclarativeText::NoWrap), lineCount(1), truncated(false), maximumLineCount(INT_MAX), + format(QDeclarativeText::AutoText), wrapMode(QDeclarativeText::NoWrap), lineHeight(1), lineHeightMode(QDeclarativeText::MultiplyHeight), + lineCount(1), truncated(false), maximumLineCount(INT_MAX), maximumLineCountValid(false), imageCacheDirty(true), updateOnComponentComplete(true), richText(false), singleline(false), cacheAllTextAsImage(true), internalWidthUpdate(false), requireImplicitWidth(false), naturalWidth(0), doc(0) { @@ -175,6 +185,15 @@ void QTextDocumentWithImageResources::setText(const QString &text) QSet QTextDocumentWithImageResources::errors; +QDeclarativeTextDocumentLayout::QDeclarativeTextDocumentLayout(QTextDocument *doc) + : QTextDocumentLayout(doc) { +} + +void QDeclarativeTextDocumentLayout::setLineHeight(qreal lineHeight, QDeclarativeText::LineHeightMode mode = QDeclarativeText::MultiplyHeight) +{ + QTextDocumentLayout::setLineHeight(lineHeight, QTextDocumentLayout::LineHeightMode(mode)); +} + QDeclarativeTextPrivate::~QDeclarativeTextPrivate() { } @@ -220,6 +239,11 @@ void QDeclarativeTextPrivate::updateLayout() singleline = false; QDeclarativeStyledText::parse(text, layout); } + } else { + ensureDoc(); + QDeclarativeTextDocumentLayout *layout = new QDeclarativeTextDocumentLayout(doc); + layout->setLineHeight(lineHeight, lineHeightMode); + doc->setDocumentLayout(layout); } updateSize(); @@ -444,7 +468,7 @@ QSize QDeclarativeTextPrivate::setupTextLayout() for (int i = 0; i < layout.lineCount(); ++i) { QTextLine line = layout.lineAt(i); line.setPosition(QPointF(0, height)); - height += line.height(); + height += (lineHeightMode == QDeclarativeText::PixelHeight) ? lineHeight : line.height() * lineHeight; if (!cacheAllTextAsImage) { if ((hAlignment == QDeclarativeText::AlignLeft) || (hAlignment == QDeclarativeText::AlignJustify)) { @@ -468,7 +492,7 @@ QSize QDeclarativeTextPrivate::setupTextLayout() emit q->lineCountChanged(); } - return layout.boundingRect().toAlignedRect().size(); + return QSize(qCeil(widthUsed), qCeil(height)); } /*! @@ -1404,6 +1428,60 @@ qreal QDeclarativeText::paintedHeight() const } /*! + \qmlproperty real Text::lineHeight + + Sets the line height for the text. + The value can be in pixels or a multiplier depending on lineHeightMode. + +*/ +qreal QDeclarativeText::lineHeight() const +{ + Q_D(const QDeclarativeText); + return d->lineHeight; +} + +void QDeclarativeText::setLineHeight(qreal lineHeight) +{ + Q_D(QDeclarativeText); + + if ((d->lineHeight == lineHeight) || (lineHeight < 0.0)) + return; + + d->lineHeight = lineHeight; + d->updateLayout(); + emit lineHeightChanged(lineHeight); +} + +/*! + \qmlproperty real Text::lineHeightMode + + This property determines how the line height is specified. + The possible values are: + + \list + \o Text.MultiplyHeight (default) - specifies a line height multiplier, + \o Text.PixelHeight - specifies the line height in pixels. + \endlist +*/ +QDeclarativeText::LineHeightMode QDeclarativeText::lineHeightMode() const +{ + Q_D(const QDeclarativeText); + return d->lineHeightMode; +} + +void QDeclarativeText::setLineHeightMode(LineHeightMode mode) +{ + Q_D(QDeclarativeText); + if (mode == d->lineHeightMode) + return; + + d->lineHeightMode = mode; + d->updateLayout(); + + emit lineHeightModeChanged(mode); +} + +/*! Returns the number of resources (images) that are being loaded asynchronously. */ int QDeclarativeText::resourcesLoading() const diff --git a/src/declarative/graphicsitems/qdeclarativetext_p.h b/src/declarative/graphicsitems/qdeclarativetext_p.h index 58751e7..f3697d5 100644 --- a/src/declarative/graphicsitems/qdeclarativetext_p.h +++ b/src/declarative/graphicsitems/qdeclarativetext_p.h @@ -62,6 +62,7 @@ class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeText : public QDeclarativeImplici Q_ENUMS(TextFormat) Q_ENUMS(TextElideMode) Q_ENUMS(WrapMode) + Q_ENUMS(LineHeightMode) Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged) Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged) @@ -79,6 +80,8 @@ class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeText : public QDeclarativeImplici Q_PROPERTY(TextElideMode elide READ elideMode WRITE setElideMode NOTIFY elideModeChanged) //### elideMode? Q_PROPERTY(qreal paintedWidth READ paintedWidth NOTIFY paintedSizeChanged) Q_PROPERTY(qreal paintedHeight READ paintedHeight NOTIFY paintedSizeChanged) + Q_PROPERTY(qreal lineHeight READ lineHeight WRITE setLineHeight NOTIFY lineHeightChanged REVISION 1) + Q_PROPERTY(LineHeightMode lineHeightMode READ lineHeightMode WRITE setLineHeightMode NOTIFY lineHeightModeChanged REVISION 1) public: QDeclarativeText(QDeclarativeItem *parent=0); @@ -111,6 +114,8 @@ public: Wrap = QTextOption::WrapAtWordBoundaryOrAnywhere }; + enum LineHeightMode { MultiplyHeight, PixelHeight }; + QString text() const; void setText(const QString &); @@ -148,6 +153,12 @@ public: TextElideMode elideMode() const; void setElideMode(TextElideMode); + qreal lineHeight() const; + void setLineHeight(qreal lineHeight); + + LineHeightMode lineHeightMode() const; + void setLineHeightMode(LineHeightMode); + void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *); virtual void componentComplete(); @@ -175,6 +186,8 @@ Q_SIGNALS: void textFormatChanged(TextFormat textFormat); void elideModeChanged(TextElideMode mode); void paintedSizeChanged(); + Q_REVISION(1) void lineHeightChanged(qreal lineHeight); + Q_REVISION(1) void lineHeightModeChanged(LineHeightMode mode); protected: void mousePressEvent(QGraphicsSceneMouseEvent *event); diff --git a/src/declarative/graphicsitems/qdeclarativetext_p_p.h b/src/declarative/graphicsitems/qdeclarativetext_p_p.h index 01e0ab5..36ae123 100644 --- a/src/declarative/graphicsitems/qdeclarativetext_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativetext_p_p.h @@ -89,6 +89,8 @@ public: QDeclarativeText::TextElideMode elideMode; QDeclarativeText::TextFormat format; QDeclarativeText::WrapMode wrapMode; + qreal lineHeight; + QDeclarativeText::LineHeightMode lineHeightMode; int lineCount; bool truncated; int maximumLineCount; diff --git a/src/gui/text/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp index d721c91..c1c3768 100644 --- a/src/gui/text/qtextdocumentlayout.cpp +++ b/src/gui/text/qtextdocumentlayout.cpp @@ -513,6 +513,9 @@ public: qreal scaleToDevice(qreal value) const; QFixed scaleToDevice(QFixed value) const; + + qreal lineH; + QTextDocumentLayout::LineHeightMode lineHeightMode; }; QTextDocumentLayoutPrivate::QTextDocumentLayoutPrivate() @@ -520,7 +523,9 @@ QTextDocumentLayoutPrivate::QTextDocumentLayoutPrivate() cursorWidth(1), currentLazyLayoutPosition(-1), lazyLayoutStepSize(1000), - lastPageCount(-1) + lastPageCount(-1), + lineH(1), + lineHeightMode(QTextDocumentLayout::MultiplyHeight) { showLayoutProgress = true; insideDocumentChange = false; @@ -2639,7 +2644,8 @@ void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosi } - QFixed lineHeight = QFixed::fromReal(line.height()); + QFixed lineHeight = (lineHeightMode == QTextDocumentLayout::PixelHeight) ? QFixed::fromReal(lineH) : QFixed::fromReal(line.height() * lineH); + if (layoutStruct->pageHeight > 0 && layoutStruct->absoluteY() + lineHeight > layoutStruct->pageBottom) { layoutStruct->newPage(); @@ -2714,6 +2720,13 @@ void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosi } } +void QTextDocumentLayout::setLineHeight(qreal lineH, QTextDocumentLayout::LineHeightMode mode = QTextDocumentLayout::MultiplyHeight) +{ + Q_D(QTextDocumentLayout); + d->lineH = lineH; + d->lineHeightMode = mode; +} + void QTextDocumentLayoutPrivate::floatMargins(const QFixed &y, const QTextLayoutStruct *layoutStruct, QFixed *left, QFixed *right) const { diff --git a/src/gui/text/qtextdocumentlayout_p.h b/src/gui/text/qtextdocumentlayout_p.h index 3c0383c..efc408b 100644 --- a/src/gui/text/qtextdocumentlayout_p.h +++ b/src/gui/text/qtextdocumentlayout_p.h @@ -63,7 +63,7 @@ class QTextListFormat; class QTextDocumentLayoutPrivate; -class Q_AUTOTEST_EXPORT QTextDocumentLayout : public QAbstractTextDocumentLayout +class Q_GUI_EXPORT QTextDocumentLayout : public QAbstractTextDocumentLayout { Q_DECLARE_PRIVATE(QTextDocumentLayout) Q_OBJECT @@ -109,6 +109,9 @@ protected: void drawInlineObject(QPainter *p, const QRectF &rect, QTextInlineObject item, int posInDocument, const QTextFormat &format); virtual void timerEvent(QTimerEvent *e); + enum LineHeightMode { MultiplyHeight, PixelHeight }; + void setLineHeight(qreal lineHeight, QTextDocumentLayout::LineHeightMode mode); + private: QRectF doLayout(int from, int oldLength, int length); void layoutFinished(); diff --git a/tests/auto/declarative/qdeclarativetext/data/lineHeight.qml b/tests/auto/declarative/qdeclarativetext/data/lineHeight.qml new file mode 100644 index 0000000..851d871 --- /dev/null +++ b/tests/auto/declarative/qdeclarativetext/data/lineHeight.qml @@ -0,0 +1,15 @@ +import QtQuick 1.1 + +Item { + width: 200 + height: 200 + + Text { + id: myText + objectName: "myText" + width: 200 + wrapMode: Text.WordWrap + font.pixelSize: 13 + text: "Lorem ipsum sit amet, consectetur adipiscing elit. Integer felis nisl, varius in pretium nec, venenatis non erat. Proin lobortis interdum dictum." + } +} diff --git a/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp b/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp index c9b5295..b96fbff 100644 --- a/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp +++ b/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp @@ -81,6 +81,7 @@ private slots: void embeddedImages(); void lineCount(); + void lineHeight(); // ### these tests may be trivial void horizontalAlignment(); @@ -1082,6 +1083,37 @@ void tst_qdeclarativetext::lineCount() QCOMPARE(myText->maximumLineCount(), 2); } +void tst_qdeclarativetext::lineHeight() +{ + QDeclarativeView *canvas = createView(SRCDIR "/data/lineHeight.qml"); + + QDeclarativeText *myText = canvas->rootObject()->findChild("myText"); + QVERIFY(myText != 0); + + QVERIFY(myText->lineHeight() == 1); + QVERIFY(myText->lineHeightMode() == QDeclarativeText::MultiplyHeight); + + qreal h = myText->height(); + myText->setLineHeight(1.5); + QVERIFY(myText->height() == h * 1.5); + + myText->setLineHeightMode(QDeclarativeText::PixelHeight); + myText->setLineHeight(20); + QCOMPARE(myText->height(), 120.0); + + myText->setText("Lorem ipsum sit amet, consectetur adipiscing elit. Integer felis nisl, varius in pretium nec, venenatis non erat. Proin lobortis interdum dictum."); + myText->setLineHeightMode(QDeclarativeText::MultiplyHeight); + myText->setLineHeight(1); + + qreal h2 = myText->height(); + myText->setLineHeight(1.25); + QVERIFY(myText->height() == h2 * 1.25); + + myText->setLineHeightMode(QDeclarativeText::PixelHeight); + myText->setLineHeight(10); + QCOMPARE(myText->height(), 60.0); +} + void tst_qdeclarativetext::implicitSize_data() { QTest::addColumn("text"); -- cgit v0.12 From 92488ca7e538e6bcf87d5cea4a78c39bb26346b7 Mon Sep 17 00:00:00 2001 From: Yann Bodson Date: Fri, 28 Jan 2011 14:55:25 +1000 Subject: Doc fix for lineHeight. --- src/declarative/graphicsitems/qdeclarativetext.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/declarative/graphicsitems/qdeclarativetext.cpp b/src/declarative/graphicsitems/qdeclarativetext.cpp index fb1ae06..54b4c3a 100644 --- a/src/declarative/graphicsitems/qdeclarativetext.cpp +++ b/src/declarative/graphicsitems/qdeclarativetext.cpp @@ -1433,6 +1433,8 @@ qreal QDeclarativeText::paintedHeight() const Sets the line height for the text. The value can be in pixels or a multiplier depending on lineHeightMode. + The default value is a multiplier of 1.0. + The line height must be a positive value. */ qreal QDeclarativeText::lineHeight() const { @@ -1453,7 +1455,7 @@ void QDeclarativeText::setLineHeight(qreal lineHeight) } /*! - \qmlproperty real Text::lineHeightMode + \qmlproperty enumeration Text::lineHeightMode This property determines how the line height is specified. The possible values are: -- cgit v0.12 From 7db57713a7961657fb1e133cf8fe3fbbd6378cfd Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Fri, 28 Jan 2011 15:05:53 +1000 Subject: Fix typo in error message. Task-number: QTBUG-16964 --- src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp b/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp index 065a388..9e89203 100644 --- a/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp +++ b/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp @@ -1076,7 +1076,7 @@ QDeclarativeItem *QDeclarativeVisualDataModel::item(int index, const QByteArray } else { delete data; delete ctxt; - qmlInfo(this, d->m_delegate->errors()) << "Error creating delgate"; + qmlInfo(this, d->m_delegate->errors()) << "Error creating delegate"; } } QDeclarativeItem *item = qobject_cast(nobj); -- cgit v0.12 From de223987715ad747496099165121aabdc38c8b0a Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Fri, 28 Jan 2011 12:58:15 +1000 Subject: Fix test breakage for qdeclarativeworkerscript Broken by 43b8305367156c1ceb09eb4a056bdae3f325b5eb. --- src/declarative/qml/qdeclarativeobjectscriptclass.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp index ee47d0b..2aa2059 100644 --- a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp +++ b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp @@ -392,7 +392,9 @@ void QDeclarativeObjectScriptClass::setProperty(QObject *obj, QString error = QLatin1String("Cannot assign [undefined] to ") + QLatin1String(QMetaType::typeName(lastData->propType)); context->throwError(error); - } else if (!value.isFunction()) { + } else if (value.isFunction() && !value.isRegExp()) { + // this is handled by the binding creation above + } else { QVariant v; if (lastData->flags & QDeclarativePropertyCache::Data::IsQList) v = enginePriv->scriptValueToVariant(value, qMetaTypeId >()); -- cgit v0.12 From 5010d88ff9bbe32f3cc0477647370cfe8b49394b Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Fri, 28 Jan 2011 15:14:27 +1000 Subject: Fix failing test on mac for Qt.application setActiveWindow(0) on mac does not deactivate the current application. --- .../qdeclarativeapplication/tst_qdeclarativeapplication.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/auto/declarative/qdeclarativeapplication/tst_qdeclarativeapplication.cpp b/tests/auto/declarative/qdeclarativeapplication/tst_qdeclarativeapplication.cpp index 3011257..64f327b 100644 --- a/tests/auto/declarative/qdeclarativeapplication/tst_qdeclarativeapplication.cpp +++ b/tests/auto/declarative/qdeclarativeapplication/tst_qdeclarativeapplication.cpp @@ -87,9 +87,13 @@ void tst_qdeclarativeapplication::active() QCOMPARE(item->property("active").toBool(), QApplication::activeWindow() != 0); // not active again + // on mac, setActiveWindow(0) on mac does not deactivate the current application + // (you have to switch to a different app or hide the current app to trigger this) +#if !defined(Q_WS_MAC) QApplication::setActiveWindow(0); QVERIFY(!item->property("active").toBool()); QCOMPARE(item->property("active").toBool(), QApplication::activeWindow() != 0); +#endif } void tst_qdeclarativeapplication::layoutDirection() -- cgit v0.12 From 7837e65c99324b539582066be308fb26ae439ecc Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Fri, 28 Jan 2011 15:14:45 +1000 Subject: disable some pincharea tests on mac temporarily --- .../qdeclarativepincharea/tst_qdeclarativepincharea.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/auto/declarative/qdeclarativepincharea/tst_qdeclarativepincharea.cpp b/tests/auto/declarative/qdeclarativepincharea/tst_qdeclarativepincharea.cpp index f175033..6683db2 100644 --- a/tests/auto/declarative/qdeclarativepincharea/tst_qdeclarativepincharea.cpp +++ b/tests/auto/declarative/qdeclarativepincharea/tst_qdeclarativepincharea.cpp @@ -228,8 +228,14 @@ void tst_QDeclarativePinchArea::scale() p2 += QPoint(10,10); QTest::touchEvent(vp).move(0, p1).move(1, p2); +#ifdef Q_OS_MAC + QEXPECT_FAIL("", "todo on mac", Continue); +#endif QCOMPARE(root->property("scale").toReal(), 1.5); QCOMPARE(root->property("center").toPointF(), QPointF(40, 40)); // blackrect is at 50,50 +#ifdef Q_OS_MAC + QEXPECT_FAIL("", "todo on mac", Continue); +#endif QCOMPARE(blackRect->scale(), 1.5); // scale beyond bound @@ -237,6 +243,9 @@ void tst_QDeclarativePinchArea::scale() p2 += QPoint(50,50); QTest::touchEvent(vp).move(0, p1).move(1, p2); +#ifdef Q_OS_MAC + QEXPECT_FAIL("", "todo on mac", Continue); +#endif QCOMPARE(blackRect->scale(), 2.0); QTest::touchEvent(vp).release(0, p1).release(1, p2); -- cgit v0.12 From 0e28a97c16f78e222841981653e71175313a4f4c Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Fri, 28 Jan 2011 15:40:55 +1000 Subject: photoviewer needs QtQuick 1.1 for Image::cache --- demos/declarative/photoviewer/PhotoViewerCore/PhotoDelegate.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demos/declarative/photoviewer/PhotoViewerCore/PhotoDelegate.qml b/demos/declarative/photoviewer/PhotoViewerCore/PhotoDelegate.qml index bfc8756..dcb1112 100644 --- a/demos/declarative/photoviewer/PhotoViewerCore/PhotoDelegate.qml +++ b/demos/declarative/photoviewer/PhotoViewerCore/PhotoDelegate.qml @@ -39,7 +39,7 @@ ** ****************************************************************************/ -import QtQuick 1.0 +import QtQuick 1.1 import "script/script.js" as Script Package { -- cgit v0.12 From 1391ebba9eb214f1f7f7b236f0e22eb41828f72c Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Fri, 28 Jan 2011 15:53:49 +1000 Subject: Test failure fixed - remove XFAIL --- tests/auto/declarative/qdeclarativeloader/tst_qdeclarativeloader.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/auto/declarative/qdeclarativeloader/tst_qdeclarativeloader.cpp b/tests/auto/declarative/qdeclarativeloader/tst_qdeclarativeloader.cpp index a5e708b..42746e8 100644 --- a/tests/auto/declarative/qdeclarativeloader/tst_qdeclarativeloader.cpp +++ b/tests/auto/declarative/qdeclarativeloader/tst_qdeclarativeloader.cpp @@ -614,8 +614,6 @@ void tst_QDeclarativeLoader::implicitSize() QCOMPARE(item->height(), 150.); QCOMPARE(item->property("implHeight").toReal(), 100.); - - QEXPECT_FAIL("", "versioned property implicit object reference", Continue); QCOMPARE(item->property("implWidth").toReal(), 100.); delete item; -- cgit v0.12 From 6bdac26b9fc1575ee7783a47604108efc7058dcb Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Fri, 28 Jan 2011 15:58:07 +1000 Subject: Update test, versioning is fixed so expect-fail no longer needed --- tests/auto/declarative/qdeclarativeloader/tst_qdeclarativeloader.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/auto/declarative/qdeclarativeloader/tst_qdeclarativeloader.cpp b/tests/auto/declarative/qdeclarativeloader/tst_qdeclarativeloader.cpp index a5e708b..4626c9c 100644 --- a/tests/auto/declarative/qdeclarativeloader/tst_qdeclarativeloader.cpp +++ b/tests/auto/declarative/qdeclarativeloader/tst_qdeclarativeloader.cpp @@ -615,7 +615,6 @@ void tst_QDeclarativeLoader::implicitSize() QCOMPARE(item->property("implHeight").toReal(), 100.); - QEXPECT_FAIL("", "versioned property implicit object reference", Continue); QCOMPARE(item->property("implWidth").toReal(), 100.); delete item; -- cgit v0.12 From 281f449dfcb533448c0f2df955b4f5c059db7ba2 Mon Sep 17 00:00:00 2001 From: Christopher Ham Date: Fri, 28 Jan 2011 15:57:12 +1000 Subject: Adding support for group properties in Component::CreateObject() The QScriptValue overload for Component::CreateObject() should be able to set group properties. This change also allows for property binding from Javascript to continue to function. Task-number: QTBUG-13087 Reviewed-by: Bea Lam --- src/declarative/qml/qdeclarativecomponent.cpp | 6 +++++- .../qdeclarativecomponent/data/createObjectWithScript.qml | 2 +- .../declarative/qdeclarativecomponent/tst_qdeclarativecomponent.cpp | 2 ++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/declarative/qml/qdeclarativecomponent.cpp b/src/declarative/qml/qdeclarativecomponent.cpp index b634a7a..06bf3fd 100644 --- a/src/declarative/qml/qdeclarativecomponent.cpp +++ b/src/declarative/qml/qdeclarativecomponent.cpp @@ -715,7 +715,11 @@ QScriptValue QDeclarativeComponentPrivate::createObject(QObject *publicParent, c QScriptValueIterator it(valuemap); while (it.hasNext()) { it.next(); - newObject.setProperty(it.name(), it.value(), QScriptValue::KeepExistingFlags); + if (it.value().isFunction()) { // To allow property binding from javascript to work + newObject.setProperty(it.name(), it.value()); + } else { + QDeclarativeProperty::write(ret,it.name(),it.value().toVariant()); + } } } diff --git a/tests/auto/declarative/qdeclarativecomponent/data/createObjectWithScript.qml b/tests/auto/declarative/qdeclarativecomponent/data/createObjectWithScript.qml index 6f9ddc1..2ce76ed 100644 --- a/tests/auto/declarative/qdeclarativecomponent/data/createObjectWithScript.qml +++ b/tests/auto/declarative/qdeclarativecomponent/data/createObjectWithScript.qml @@ -29,7 +29,7 @@ Item{ } Component.onCompleted: { - root.declarativerectangle = a.createObject(root, {"x":17,"y":17, "color":"white"}); + root.declarativerectangle = a.createObject(root, {"x":17,"y":17, "color":"white", "border.width":3}); root.declarativeitem = b.createObject(root, {"x":17,"y":17,"testBool":true,"testInt":17,"testObject":root}); root.bindingTestObject = c.createObject(root, {'testValue': (function(){return width * 3}) }) // use root.width diff --git a/tests/auto/declarative/qdeclarativecomponent/tst_qdeclarativecomponent.cpp b/tests/auto/declarative/qdeclarativecomponent/tst_qdeclarativecomponent.cpp index 62c6bb5..7b7b392 100644 --- a/tests/auto/declarative/qdeclarativecomponent/tst_qdeclarativecomponent.cpp +++ b/tests/auto/declarative/qdeclarativecomponent/tst_qdeclarativecomponent.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include #ifdef Q_OS_SYMBIAN @@ -135,6 +136,7 @@ void tst_qdeclarativecomponent::qmlCreateObjectWithProperties() QCOMPARE(testObject1->property("x").value(), 17); QCOMPARE(testObject1->property("y").value(), 17); QCOMPARE(testObject1->property("color").value(), QColor(255,255,255)); + QCOMPARE(QDeclarativeProperty::read(testObject1,"border.width").toInt(), 3); delete testObject1; QObject *testObject2 = object->property("declarativeitem").value(); -- cgit v0.12 From 74329f77d567e0b7e8cd4cab2ff6ce3f2b8892ad Mon Sep 17 00:00:00 2001 From: Christopher Ham Date: Fri, 28 Jan 2011 16:03:22 +1000 Subject: Update Docs, Examples and Demos for new CreateObject overloadable Dynamic object in Docs explains QScriptValue argument. SameGame and Dynamic scene now make use of overloadable. Task-number: QTBUG-13087 Reviewed-by: Bea Lam --- demos/declarative/samegame/SamegameCore/BoomBlock.qml | 2 +- demos/declarative/samegame/SamegameCore/Button.qml | 2 +- demos/declarative/samegame/SamegameCore/Dialog.qml | 2 +- demos/declarative/samegame/SamegameCore/samegame.js | 11 ++++++----- demos/declarative/samegame/samegame.qml | 2 +- doc/src/declarative/dynamicobjects.qdoc | 14 ++++++++++---- doc/src/snippets/declarative/componentCreation.js | 6 +----- examples/declarative/toys/dynamicscene/qml/itemCreation.js | 7 ++----- 8 files changed, 23 insertions(+), 23 deletions(-) diff --git a/demos/declarative/samegame/SamegameCore/BoomBlock.qml b/demos/declarative/samegame/SamegameCore/BoomBlock.qml index da51230..009aeca 100644 --- a/demos/declarative/samegame/SamegameCore/BoomBlock.qml +++ b/demos/declarative/samegame/SamegameCore/BoomBlock.qml @@ -39,7 +39,7 @@ ** ****************************************************************************/ -import QtQuick 1.0 +import QtQuick 1.1 import Qt.labs.particles 1.0 Item { diff --git a/demos/declarative/samegame/SamegameCore/Button.qml b/demos/declarative/samegame/SamegameCore/Button.qml index aea4e53..b2b232c 100644 --- a/demos/declarative/samegame/SamegameCore/Button.qml +++ b/demos/declarative/samegame/SamegameCore/Button.qml @@ -39,7 +39,7 @@ ** ****************************************************************************/ -import QtQuick 1.0 +import QtQuick 1.1 Rectangle { id: container diff --git a/demos/declarative/samegame/SamegameCore/Dialog.qml b/demos/declarative/samegame/SamegameCore/Dialog.qml index b11c65c..ecac475 100644 --- a/demos/declarative/samegame/SamegameCore/Dialog.qml +++ b/demos/declarative/samegame/SamegameCore/Dialog.qml @@ -39,7 +39,7 @@ ** ****************************************************************************/ -import QtQuick 1.0 +import QtQuick 1.1 Rectangle { id: page diff --git a/demos/declarative/samegame/SamegameCore/samegame.js b/demos/declarative/samegame/SamegameCore/samegame.js index 9266767..b838790 100755 --- a/demos/declarative/samegame/SamegameCore/samegame.js +++ b/demos/declarative/samegame/SamegameCore/samegame.js @@ -177,18 +177,19 @@ function createBlock(column,row){ // not be ready immediately. There is a statusChanged signal on the // component you could use if you want to wait to load remote files. if(component.status == Component.Ready){ - var dynamicObject = component.createObject(gameCanvas); + var dynamicObject = component.createObject(gameCanvas, + {"type": Math.floor(Math.random() * 3), + "x": column*gameCanvas.blockSize, + "width": gameCanvas.blockSize, + "height": gameCanvas.blockSize}); if(dynamicObject == null){ console.log("error creating block"); console.log(component.errorString()); return false; } - dynamicObject.type = Math.floor(Math.random() * 3); - dynamicObject.x = column*gameCanvas.blockSize; dynamicObject.y = row*gameCanvas.blockSize; - dynamicObject.width = gameCanvas.blockSize; - dynamicObject.height = gameCanvas.blockSize; dynamicObject.spawned = true; + board[index(column,row)] = dynamicObject; }else{ console.log("error loading block component"); diff --git a/demos/declarative/samegame/samegame.qml b/demos/declarative/samegame/samegame.qml index ebb8e4a..ab64156 100644 --- a/demos/declarative/samegame/samegame.qml +++ b/demos/declarative/samegame/samegame.qml @@ -39,7 +39,7 @@ ** ****************************************************************************/ -import QtQuick 1.0 +import QtQuick 1.1 import "SamegameCore" import "SamegameCore/samegame.js" as Logic diff --git a/doc/src/declarative/dynamicobjects.qdoc b/doc/src/declarative/dynamicobjects.qdoc index 073e0c4..f186dca 100644 --- a/doc/src/declarative/dynamicobjects.qdoc +++ b/doc/src/declarative/dynamicobjects.qdoc @@ -62,10 +62,16 @@ To dynamically load a component defined in a QML file, call the This function takes the URL of the QML file as its only argument and creates a \l Component object from this URL. -Once you have a \l Component, you can call its \l {Component::createObject()}{createObject()} method to create an instance of -the component. This function takes exactly one argument, which is the parent for the new item. Since graphical items will -not appear on the scene without a parent, it is recommended that you set the parent this way. However, if you wish to set -the parent later you can safely pass \c null to this function. +Once you have a \l Component, you can call its \l {Component::createObject()}{createObject()} method to create an instance of +the component. This function can take one or two arguments: +\list +\o The first is the parent for the new item. Since graphical items will not appear on the scene without a parent, it is + recommended that you set the parent this way. However, if you wish to set the parent later you can safely pass \c null to + this function. +\o The second is optional and is a script which assigns values to the item's properties during creation. This avoids warnings + when certain properties have been bound to before they have been set by the code. Additionally, there are small performance + benefits when instantiating objects in this way. +\endlist Here is an example. First there is \c Sprite.qml, which defines a simple QML component: diff --git a/doc/src/snippets/declarative/componentCreation.js b/doc/src/snippets/declarative/componentCreation.js index c29a1f9..cf59777 100644 --- a/doc/src/snippets/declarative/componentCreation.js +++ b/doc/src/snippets/declarative/componentCreation.js @@ -17,15 +17,11 @@ function createSpriteObjects() { //![local] component = Qt.createComponent("Sprite.qml"); - sprite = component.createObject(appWindow); + sprite = component.createObject(appWindow, {"x": 100, "y": 100}); if (sprite == null) { // Error Handling console.log("Error creating object"); - } else { - sprite.x = 100; - sprite.y = 100; - // ... } //![local] diff --git a/examples/declarative/toys/dynamicscene/qml/itemCreation.js b/examples/declarative/toys/dynamicscene/qml/itemCreation.js index e74f7b0..4ee74c2 100644 --- a/examples/declarative/toys/dynamicscene/qml/itemCreation.js +++ b/examples/declarative/toys/dynamicscene/qml/itemCreation.js @@ -28,11 +28,8 @@ function loadComponent() { function createItem() { if (itemComponent.status == Component.Ready && draggedItem == null) { - draggedItem = itemComponent.createObject(window); - draggedItem.image = paletteItem.image; - draggedItem.x = posnInWindow.x; - draggedItem.y = posnInWindow.y; - draggedItem.z = 3; // make sure created item is above the ground layer + draggedItem = itemComponent.createObject(window, {"image": paletteItem.image, "x": posnInWindow.x, "y": posnInWindow.y, "z": 3}); + // make sure created item is above the ground layer } else if (itemComponent.status == Component.Error) { draggedItem = null; console.log("error creating component"); -- cgit v0.12 From c98bd0ae192cac1254b2c98b497002e6256f0fbc Mon Sep 17 00:00:00 2001 From: Yann Bodson Date: Fri, 28 Jan 2011 17:48:04 +1000 Subject: Fix lineHeight autotests. --- tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp b/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp index b96fbff..8111cd2 100644 --- a/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp +++ b/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp @@ -1099,19 +1099,19 @@ void tst_qdeclarativetext::lineHeight() myText->setLineHeightMode(QDeclarativeText::PixelHeight); myText->setLineHeight(20); - QCOMPARE(myText->height(), 120.0); + QCOMPARE(myText->height(), myText->lineCount() * 20.0); myText->setText("Lorem ipsum sit amet, consectetur adipiscing elit. Integer felis nisl, varius in pretium nec, venenatis non erat. Proin lobortis interdum dictum."); myText->setLineHeightMode(QDeclarativeText::MultiplyHeight); myText->setLineHeight(1); qreal h2 = myText->height(); - myText->setLineHeight(1.25); - QVERIFY(myText->height() == h2 * 1.25); + myText->setLineHeight(2.0); + QVERIFY(myText->height() == h2 * 2.0); myText->setLineHeightMode(QDeclarativeText::PixelHeight); myText->setLineHeight(10); - QCOMPARE(myText->height(), 60.0); + QCOMPARE(myText->height(), myText->lineCount() * 10.0); } void tst_qdeclarativetext::implicitSize_data() -- cgit v0.12 From c22ec835589a2484059bcb94b5536cf3b9a7f69f Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Fri, 28 Jan 2011 18:18:38 +1000 Subject: Allow functions to be passed in as values for grouped properties Using QDeclarativeProperty::write() works for grouped properties but stops functions values from being passed in, and using QScriptValue::setProperty() on the object being created allows functions to be passed in but doesn't work for grouped properties. This fix walks down the tree for grouped properties to find the property that should be set so that functions can be set for grouped property values. Reviewed-by: Aaron Kennedy --- src/declarative/qml/qdeclarativecomponent.cpp | 17 ++++++++++++++--- .../data/createObjectWithScript.qml | 9 +++++++-- .../qdeclarativecomponent/tst_qdeclarativecomponent.cpp | 3 ++- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/declarative/qml/qdeclarativecomponent.cpp b/src/declarative/qml/qdeclarativecomponent.cpp index 06bf3fd..5840f70 100644 --- a/src/declarative/qml/qdeclarativecomponent.cpp +++ b/src/declarative/qml/qdeclarativecomponent.cpp @@ -715,10 +715,21 @@ QScriptValue QDeclarativeComponentPrivate::createObject(QObject *publicParent, c QScriptValueIterator it(valuemap); while (it.hasNext()) { it.next(); - if (it.value().isFunction()) { // To allow property binding from javascript to work - newObject.setProperty(it.name(), it.value()); + QScriptValue prop = newObject; + QString propName = it.name(); + int index = propName.indexOf(QLatin1Char('.')); + if (index > 0) { + QString subProp = propName; + int lastIndex = 0; + while (index > 0) { + subProp = propName.mid(lastIndex, index - lastIndex); + prop = prop.property(subProp); + lastIndex = index + 1; + index = propName.indexOf(QLatin1Char('.'), index + 1); + } + prop.setProperty(propName.mid(propName.lastIndexOf(QLatin1Char('.')) + 1), it.value()); } else { - QDeclarativeProperty::write(ret,it.name(),it.value().toVariant()); + newObject.setProperty(propName, it.value()); } } } diff --git a/tests/auto/declarative/qdeclarativecomponent/data/createObjectWithScript.qml b/tests/auto/declarative/qdeclarativecomponent/data/createObjectWithScript.qml index 2ce76ed..0da3bda 100644 --- a/tests/auto/declarative/qdeclarativecomponent/data/createObjectWithScript.qml +++ b/tests/auto/declarative/qdeclarativecomponent/data/createObjectWithScript.qml @@ -8,7 +8,12 @@ Item{ property QtObject bindingTestObject : null property QtObject bindingThisTestObject : null - Component{id: a; Rectangle{} } + Component{ + id: a + Rectangle { + property Rectangle innerRect: Rectangle { border.width: 20 } + } + } Component{ id: b Item{ @@ -29,7 +34,7 @@ Item{ } Component.onCompleted: { - root.declarativerectangle = a.createObject(root, {"x":17,"y":17, "color":"white", "border.width":3}); + root.declarativerectangle = a.createObject(root, {"x":17,"y":17, "color":"white", "border.width":3, "innerRect.border.width": 20}); root.declarativeitem = b.createObject(root, {"x":17,"y":17,"testBool":true,"testInt":17,"testObject":root}); root.bindingTestObject = c.createObject(root, {'testValue': (function(){return width * 3}) }) // use root.width diff --git a/tests/auto/declarative/qdeclarativecomponent/tst_qdeclarativecomponent.cpp b/tests/auto/declarative/qdeclarativecomponent/tst_qdeclarativecomponent.cpp index 7b7b392..4340fce 100644 --- a/tests/auto/declarative/qdeclarativecomponent/tst_qdeclarativecomponent.cpp +++ b/tests/auto/declarative/qdeclarativecomponent/tst_qdeclarativecomponent.cpp @@ -137,12 +137,13 @@ void tst_qdeclarativecomponent::qmlCreateObjectWithProperties() QCOMPARE(testObject1->property("y").value(), 17); QCOMPARE(testObject1->property("color").value(), QColor(255,255,255)); QCOMPARE(QDeclarativeProperty::read(testObject1,"border.width").toInt(), 3); + QCOMPARE(QDeclarativeProperty::read(testObject1,"innerRect.border.width").toInt(), 20); delete testObject1; QObject *testObject2 = object->property("declarativeitem").value(); QVERIFY(testObject2); QVERIFY(testObject2->parent() == object); - QCOMPARE(testObject2->metaObject()->className(), "QDeclarativeItem_QML_2"); + //QCOMPARE(testObject2->metaObject()->className(), "QDeclarativeItem_QML_2"); QCOMPARE(testObject2->property("x").value(), 17); QCOMPARE(testObject2->property("y").value(), 17); QCOMPARE(testObject2->property("testBool").value(), true); -- cgit v0.12 From 44e358047d60aa31f568a120a97dfe36f150d7e0 Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Fri, 28 Jan 2011 18:28:02 +1000 Subject: expect fail for some PinchArea tests on mac --- .../qdeclarativepincharea/tst_qdeclarativepincharea.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/auto/declarative/qdeclarativepincharea/tst_qdeclarativepincharea.cpp b/tests/auto/declarative/qdeclarativepincharea/tst_qdeclarativepincharea.cpp index 6683db2..b7e7a99 100644 --- a/tests/auto/declarative/qdeclarativepincharea/tst_qdeclarativepincharea.cpp +++ b/tests/auto/declarative/qdeclarativepincharea/tst_qdeclarativepincharea.cpp @@ -292,9 +292,18 @@ void tst_QDeclarativePinchArea::pan() p2 += QPoint(10,10); QTest::touchEvent(vp).move(0, p1).move(1, p2); +#ifdef Q_OS_MAC + QEXPECT_FAIL("", "todo mac", Continue); +#endif QCOMPARE(root->property("center").toPointF(), QPointF(60, 60)); // blackrect is at 50,50 +#ifdef Q_OS_MAC + QEXPECT_FAIL("", "todo mac", Continue); +#endif QCOMPARE(blackRect->x(), 60.0); +#ifdef Q_OS_MAC + QEXPECT_FAIL("", "todo mac", Continue); +#endif QCOMPARE(blackRect->y(), 60.0); // pan x beyond bound @@ -302,7 +311,13 @@ void tst_QDeclarativePinchArea::pan() p2 += QPoint(100,100); QTest::touchEvent(vp).move(0, p1).move(1, p2); +#ifdef Q_OS_MAC + QEXPECT_FAIL("", "todo mac", Continue); +#endif QCOMPARE(blackRect->x(), 140.0); +#ifdef Q_OS_MAC + QEXPECT_FAIL("", "todo mac", Continue); +#endif QCOMPARE(blackRect->y(), 160.0); QTest::touchEvent(vp).release(0, p1).release(1, p2); -- cgit v0.12 From ead20f4c1edc2e1c5c39f47bf7c9e56600d6362b Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Thu, 27 Jan 2011 16:29:52 +0100 Subject: Fix alignment issue causing crash in QtScript/JavaScriptCore When creating a substring, JSC::UStringImpl required that the base string pointer was 8-byte aligned. However, on platforms where FastMalloc isn't enabled (such as Symbian), it's possible that the system malloc() returns a pointer that is only 4-byte aligned. (On Symbian, this can happen if the argument to malloc() itself isn't a multiple of 8.) Cherry-picked http://trac.webkit.org/changeset/54743 from WebKit trunk, which fixes this issue. (The commit happened shortly after we rebased QtScript/JSC for 4.7, so it applies cleanly to our copy.) Task-number: QTBUG-16828 Reviewed-by: Simon Hausmann --- .../javascriptcore/JavaScriptCore/ChangeLog | 25 +++++ .../JavaScriptCore/runtime/UStringImpl.cpp | 14 +-- .../JavaScriptCore/runtime/UStringImpl.h | 117 ++++++++------------- src/3rdparty/javascriptcore/VERSION | 4 +- 4 files changed, 76 insertions(+), 84 deletions(-) diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/ChangeLog b/src/3rdparty/javascriptcore/JavaScriptCore/ChangeLog index c2b1155..9cbf0c1 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/ChangeLog +++ b/src/3rdparty/javascriptcore/JavaScriptCore/ChangeLog @@ -358,6 +358,31 @@ * wtf/AlwaysInline.h: +2010-02-12 Gavin Barraclough + + Reviewed by Darin Adler. + + https://bugs.webkit.org/show_bug.cgi?id=33731 + Many false leaks in release builds due to PtrAndFlags + + Remove UntypedPtrAndBitfield (similar to PtrAndFlags) in UStringImpl, + and steal bits from the refCount instead. + + * runtime/UStringImpl.cpp: + (JSC::UStringImpl::baseSharedBuffer): + (JSC::UStringImpl::~UStringImpl): + * runtime/UStringImpl.h: + (JSC::UStringImpl::cost): + (JSC::UStringImpl::isIdentifier): + (JSC::UStringImpl::setIsIdentifier): + (JSC::UStringImpl::ref): + (JSC::UStringImpl::deref): + (JSC::UStringImpl::UStringImpl): + (JSC::UStringImpl::bufferOwnerString): + (JSC::UStringImpl::bufferOwnership): + (JSC::UStringImpl::isStatic): + (JSC::UStringImpl::): + 2010-02-12 Kwang Yul Seo Reviewed by Adam Barth. diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/UStringImpl.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/UStringImpl.cpp index 4b0d1c9..4fde49e 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/UStringImpl.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/UStringImpl.cpp @@ -38,12 +38,14 @@ namespace JSC { SharedUChar* UStringImpl::baseSharedBuffer() { ASSERT((bufferOwnership() == BufferShared) - || ((bufferOwnership() == BufferOwned) && !m_dataBuffer.asPtr())); + || ((bufferOwnership() == BufferOwned) && !m_buffer)); - if (bufferOwnership() != BufferShared) - m_dataBuffer = UntypedPtrAndBitfield(SharedUChar::create(new OwnFastMallocPtr(m_data)).releaseRef(), BufferShared); + if (bufferOwnership() != BufferShared) { + m_refCountAndFlags = (m_refCountAndFlags & ~s_refCountMaskBufferOwnership) | BufferShared; + m_bufferShared = SharedUChar::create(new OwnFastMallocPtr(m_data)).releaseRef(); + } - return m_dataBuffer.asPtr(); + return m_bufferShared; } SharedUChar* UStringImpl::sharedBuffer() @@ -71,10 +73,10 @@ UStringImpl::~UStringImpl() if (bufferOwnership() == BufferOwned) fastFree(m_data); else if (bufferOwnership() == BufferSubstring) - m_dataBuffer.asPtr()->deref(); + m_bufferSubstring->deref(); else { ASSERT(bufferOwnership() == BufferShared); - m_dataBuffer.asPtr()->deref(); + m_bufferShared->deref(); } } } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/UStringImpl.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/UStringImpl.h index 4e1ddc7..e6d1a8a 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/UStringImpl.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/UStringImpl.h @@ -40,48 +40,6 @@ class IdentifierTable; typedef CrossThreadRefCounted > SharedUChar; -class UntypedPtrAndBitfield { -public: - UntypedPtrAndBitfield() {} - - UntypedPtrAndBitfield(void* ptrValue, uintptr_t bitValue) - : m_value(reinterpret_cast(ptrValue) | bitValue) -#ifndef NDEBUG - , m_leaksPtr(ptrValue) -#endif - { - ASSERT(ptrValue == asPtr()); - ASSERT((*this & ~s_alignmentMask) == bitValue); - } - - template - T asPtr() const { return reinterpret_cast(m_value & s_alignmentMask); } - - UntypedPtrAndBitfield& operator&=(uintptr_t bits) - { - m_value &= bits | s_alignmentMask; - return *this; - } - - UntypedPtrAndBitfield& operator|=(uintptr_t bits) - { - m_value |= bits & ~s_alignmentMask; - return *this; - } - - uintptr_t operator&(uintptr_t mask) const - { - return m_value & mask & ~s_alignmentMask; - } - -private: - static const uintptr_t s_alignmentMask = ~static_cast(0x7); - uintptr_t m_value; -#ifndef NDEBUG - void* m_leaksPtr; // Only used to allow tools like leaks on OSX to detect that the memory is referenced. -#endif -}; - class UStringImpl : Noncopyable { public: template @@ -151,21 +109,27 @@ public: { // For substrings, return the cost of the base string. if (bufferOwnership() == BufferSubstring) - return m_dataBuffer.asPtr()->cost(); + return m_bufferSubstring->cost(); - if (m_dataBuffer & s_reportedCostBit) + if (m_refCountAndFlags & s_refCountFlagHasReportedCost) return 0; - m_dataBuffer |= s_reportedCostBit; + m_refCountAndFlags |= s_refCountFlagHasReportedCost; return m_length; } unsigned hash() const { if (!m_hash) m_hash = computeHash(data(), m_length); return m_hash; } unsigned existingHash() const { ASSERT(m_hash); return m_hash; } // fast path for Identifiers void setHash(unsigned hash) { ASSERT(hash == computeHash(data(), m_length)); m_hash = hash; } // fast path for Identifiers - bool isIdentifier() const { return m_isIdentifier; } - void setIsIdentifier(bool isIdentifier) { m_isIdentifier = isIdentifier; } + bool isIdentifier() const { return m_refCountAndFlags & s_refCountFlagIsIdentifier; } + void setIsIdentifier(bool isIdentifier) + { + if (isIdentifier) + m_refCountAndFlags |= s_refCountFlagIsIdentifier; + else + m_refCountAndFlags &= ~s_refCountFlagIsIdentifier; + } - UStringImpl* ref() { m_refCount += s_refCountIncrement; return this; } - ALWAYS_INLINE void deref() { if (!(m_refCount -= s_refCountIncrement)) delete this; } + UStringImpl* ref() { m_refCountAndFlags += s_refCountIncrement; return this; } + ALWAYS_INLINE void deref() { m_refCountAndFlags -= s_refCountIncrement; if (!(m_refCountAndFlags & s_refCountMask)) delete this; } static void copyChars(UChar* destination, const UChar* source, unsigned numCharacters) { @@ -205,11 +169,10 @@ private: // Used to construct normal strings with an internal or external buffer. UStringImpl(UChar* data, int length, BufferOwnership ownership) : m_data(data) + , m_buffer(0) , m_length(length) - , m_refCount(s_refCountIncrement) + , m_refCountAndFlags(s_refCountIncrement | ownership) , m_hash(0) - , m_isIdentifier(false) - , m_dataBuffer(0, ownership) { ASSERT((ownership == BufferInternal) || (ownership == BufferOwned)); checkConsistency(); @@ -221,11 +184,10 @@ private: enum StaticStringConstructType { ConstructStaticString }; UStringImpl(UChar* data, int length, StaticStringConstructType) : m_data(data) + , m_buffer(0) , m_length(length) - , m_refCount(s_staticRefCountInitialValue) + , m_refCountAndFlags(s_refCountFlagStatic | BufferOwned) , m_hash(0) - , m_isIdentifier(false) - , m_dataBuffer(0, BufferOwned) { checkConsistency(); } @@ -233,28 +195,26 @@ private: // Used to create new strings that are a substring of an existing string. UStringImpl(UChar* data, int length, PassRefPtr base) : m_data(data) + , m_bufferSubstring(base.releaseRef()) , m_length(length) - , m_refCount(s_refCountIncrement) + , m_refCountAndFlags(s_refCountIncrement | BufferSubstring) , m_hash(0) - , m_isIdentifier(false) - , m_dataBuffer(base.releaseRef(), BufferSubstring) { // Do use static strings as a base for substrings; UntypedPtrAndBitfield assumes // that all pointers will be at least 8-byte aligned, we cannot guarantee that of // UStringImpls that are not heap allocated. - ASSERT(m_dataBuffer.asPtr()->size()); - ASSERT(!m_dataBuffer.asPtr()->isStatic()); + ASSERT(m_bufferSubstring->size()); + ASSERT(!m_bufferSubstring->isStatic()); checkConsistency(); } // Used to construct new strings sharing an existing shared buffer. UStringImpl(UChar* data, int length, PassRefPtr sharedBuffer) : m_data(data) + , m_bufferShared(sharedBuffer.releaseRef()) , m_length(length) - , m_refCount(s_refCountIncrement) + , m_refCountAndFlags(s_refCountIncrement | BufferShared) , m_hash(0) - , m_isIdentifier(false) - , m_dataBuffer(sharedBuffer.releaseRef(), BufferShared) { checkConsistency(); } @@ -277,26 +237,31 @@ private: // This number must be at least 2 to avoid sharing empty, null as well as 1 character strings from SmallStrings. static const int s_minLengthToShare = 10; static const unsigned s_copyCharsInlineCutOff = 20; - static const uintptr_t s_bufferOwnershipMask = 3; - static const uintptr_t s_reportedCostBit = 4; // We initialize and increment/decrement the refCount for all normal (non-static) strings by the value 2. // We initialize static strings with an odd number (specifically, 1), such that the refCount cannot reach zero. - static const int s_refCountIncrement = 2; - static const int s_staticRefCountInitialValue = 1; - - UStringImpl* bufferOwnerString() { return (bufferOwnership() == BufferSubstring) ? m_dataBuffer.asPtr() : this; } - const UStringImpl* bufferOwnerString() const { return (bufferOwnership() == BufferSubstring) ? m_dataBuffer.asPtr() : this; } + static const unsigned s_refCountMask = 0xFFFFFFF0; + static const int s_refCountIncrement = 0x20; + static const int s_refCountFlagStatic = 0x10; + static const unsigned s_refCountFlagHasReportedCost = 0x8; + static const unsigned s_refCountFlagIsIdentifier = 0x4; + static const unsigned s_refCountMaskBufferOwnership = 0x3; + + UStringImpl* bufferOwnerString() { return (bufferOwnership() == BufferSubstring) ? m_bufferSubstring : this; } + const UStringImpl* bufferOwnerString() const { return (bufferOwnership() == BufferSubstring) ? m_bufferSubstring : this; } SharedUChar* baseSharedBuffer(); - unsigned bufferOwnership() const { return m_dataBuffer & s_bufferOwnershipMask; } - bool isStatic() const { return m_refCount & 1; } + unsigned bufferOwnership() const { return m_refCountAndFlags & s_refCountMaskBufferOwnership; } + bool isStatic() const { return m_refCountAndFlags & s_refCountFlagStatic; } // unshared data UChar* m_data; + union { + void* m_buffer; + UStringImpl* m_bufferSubstring; + SharedUChar* m_bufferShared; + }; int m_length; - unsigned m_refCount; - mutable unsigned m_hash : 31; - mutable unsigned m_isIdentifier : 1; - UntypedPtrAndBitfield m_dataBuffer; + unsigned m_refCountAndFlags; + mutable unsigned m_hash; JS_EXPORTDATA static UStringImpl* s_null; JS_EXPORTDATA static UStringImpl* s_empty; diff --git a/src/3rdparty/javascriptcore/VERSION b/src/3rdparty/javascriptcore/VERSION index b4744b7..13943b2 100644 --- a/src/3rdparty/javascriptcore/VERSION +++ b/src/3rdparty/javascriptcore/VERSION @@ -4,8 +4,8 @@ This is a snapshot of JavaScriptCore from The commit imported was from the - javascriptcore-snapshot-24012011 branch/tag + javascriptcore-snapshot-27012011 branch/tag and has the sha1 checksum - d143bde5ae8cff229aebd43487a2fce5e713e990 + 3ab0f621048fbeb480b687a28ed31d92d8506150 -- cgit v0.12 From b127b1036ec75c625920a6c029b64a95e3702bf9 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Fri, 28 Jan 2011 10:10:31 +0100 Subject: Invalidate QScriptPrograms when engine is destroyed If the engine is destroyed before the program, the program must be invalidated; otherwise the program destructor will access a stale engine pointer, which can cause a crash (it crashes on Symbian, but "only" gives a Valgrind warning on Linux for our autotests). We need to keep track of all associated programs, just like we already do for values and strings. This fix follows the exact same pattern, but uses a QSet to keep the patch minimal. No new tests, but the evaluateProgram() test runs successfully on Symbian now, and there are no more Valgrind warnings. Task-number: QTBUG-16987 Reviewed-by: Olivier Goffart --- src/script/api/qscriptengine.cpp | 9 +++++++++ src/script/api/qscriptengine_p.h | 18 ++++++++++++++++++ src/script/api/qscriptprogram.cpp | 21 ++++++++++++++------- src/script/api/qscriptprogram_p.h | 1 + 4 files changed, 42 insertions(+), 7 deletions(-) diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp index 9e338d4..54039c0 100644 --- a/src/script/api/qscriptengine.cpp +++ b/src/script/api/qscriptengine.cpp @@ -1022,6 +1022,7 @@ QScriptEnginePrivate::~QScriptEnginePrivate() while (!ownedAgents.isEmpty()) delete ownedAgents.takeFirst(); + detachAllRegisteredScriptPrograms(); detachAllRegisteredScriptValues(); detachAllRegisteredScriptStrings(); qDeleteAll(m_qobjectData); @@ -1576,6 +1577,14 @@ bool QScriptEnginePrivate::scriptDisconnect(JSC::JSValue signal, JSC::JSValue re #endif +void QScriptEnginePrivate::detachAllRegisteredScriptPrograms() +{ + QSet::const_iterator it; + for (it = registeredScriptPrograms.constBegin(); it != registeredScriptPrograms.constEnd(); ++it) + (*it)->detachFromEngine(); + registeredScriptPrograms.clear(); +} + void QScriptEnginePrivate::detachAllRegisteredScriptValues() { QScriptValuePrivate *it; diff --git a/src/script/api/qscriptengine_p.h b/src/script/api/qscriptengine_p.h index 05a8901..f8144e9 100644 --- a/src/script/api/qscriptengine_p.h +++ b/src/script/api/qscriptengine_p.h @@ -87,6 +87,7 @@ class QScriptEngineAgent; class QScriptEnginePrivate; class QScriptSyntaxCheckResult; class QScriptEngine; +class QScriptProgramPrivate; namespace QScript { @@ -273,6 +274,10 @@ public: static QScriptSyntaxCheckResult checkSyntax(const QString &program); static bool canEvaluate(const QString &program); + inline void registerScriptProgram(QScriptProgramPrivate *program); + inline void unregisterScriptProgram(QScriptProgramPrivate *program); + void detachAllRegisteredScriptPrograms(); + inline QScriptValuePrivate *allocateScriptValuePrivate(size_t); inline void freeScriptValuePrivate(QScriptValuePrivate *p); @@ -368,6 +373,7 @@ public: static const int maxFreeScriptValues = 256; int freeScriptValuesCount; QScriptStringPrivate *registeredScriptStrings; + QSet registeredScriptPrograms; QHash m_typeInfos; int processEventsInterval; QScriptValue abortResult; @@ -566,6 +572,18 @@ inline QByteArray convertToLatin1(const JSC::UString &str) } // namespace QScript +inline void QScriptEnginePrivate::registerScriptProgram(QScriptProgramPrivate *program) +{ + Q_ASSERT(!registeredScriptPrograms.contains(program)); + registeredScriptPrograms.insert(program); +} + +inline void QScriptEnginePrivate::unregisterScriptProgram(QScriptProgramPrivate *program) +{ + Q_ASSERT(registeredScriptPrograms.contains(program)); + registeredScriptPrograms.remove(program); +} + inline QScriptValuePrivate *QScriptEnginePrivate::allocateScriptValuePrivate(size_t size) { if (freeScriptValues) { diff --git a/src/script/api/qscriptprogram.cpp b/src/script/api/qscriptprogram.cpp index da103bb..31af9a0 100644 --- a/src/script/api/qscriptprogram.cpp +++ b/src/script/api/qscriptprogram.cpp @@ -64,6 +64,7 @@ QScriptProgramPrivate::~QScriptProgramPrivate() if (engine) { QScript::APIShim shim(engine); _executable.clear(); + engine->unregisterScriptProgram(this); } } @@ -78,7 +79,10 @@ JSC::EvalExecutable *QScriptProgramPrivate::executable(JSC::ExecState *exec, if (_executable) { if (eng == engine) return _executable.get(); - _executable = 0; + // "Migrating" to another engine; clean up old state + QScript::APIShim shim(engine); + _executable.clear(); + engine->unregisterScriptProgram(this); } WTF::PassRefPtr provider = QScript::UStringSourceProviderWithFeedback::create(sourceCode, fileName, firstLineNumber, eng); @@ -86,10 +90,19 @@ JSC::EvalExecutable *QScriptProgramPrivate::executable(JSC::ExecState *exec, JSC::SourceCode source(provider, firstLineNumber); //after construction of SourceCode provider variable will be null. _executable = JSC::EvalExecutable::create(exec, source); engine = eng; + engine->registerScriptProgram(this); isCompiled = false; return _executable.get(); } +void QScriptProgramPrivate::detachFromEngine() +{ + _executable.clear(); + sourceId = -1; + isCompiled = false; + engine = 0; +} + /*! Constructs a null QScriptProgram. */ @@ -122,9 +135,6 @@ QScriptProgram::QScriptProgram(const QScriptProgram &other) */ QScriptProgram::~QScriptProgram() { - // Q_D(QScriptProgram); - // if (d->engine && (d->ref == 1)) - // d->engine->unregisterScriptProgram(d); } /*! @@ -132,9 +142,6 @@ QScriptProgram::~QScriptProgram() */ QScriptProgram &QScriptProgram::operator=(const QScriptProgram &other) { - // if (d_func() && d_func()->engine && (d_func()->ref == 1)) - // d_func()->engine->unregisterScriptProgram(d_func()); - // } d_ptr = other.d_ptr; return *this; } diff --git a/src/script/api/qscriptprogram_p.h b/src/script/api/qscriptprogram_p.h index d2fd234..e7809ab 100644 --- a/src/script/api/qscriptprogram_p.h +++ b/src/script/api/qscriptprogram_p.h @@ -61,6 +61,7 @@ public: JSC::EvalExecutable *executable(JSC::ExecState *exec, QScriptEnginePrivate *engine); + void detachFromEngine(); QBasicAtomicInt ref; -- cgit v0.12 From 298b54b4fa99db47d62ec37eacefb4f419b79a69 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 28 Jan 2011 11:12:50 +0100 Subject: Revert "Improve timer ID safety by using a serial counter per ID." This reverts commit 121e2b39043a4ffc6583f250aebb9a3a746076c1. It was considered too dangerous for 4.7. --- src/corelib/kernel/qabstracteventdispatcher.cpp | 30 +++++-------------------- 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/src/corelib/kernel/qabstracteventdispatcher.cpp b/src/corelib/kernel/qabstracteventdispatcher.cpp index cc08f092..e79f87a 100644 --- a/src/corelib/kernel/qabstracteventdispatcher.cpp +++ b/src/corelib/kernel/qabstracteventdispatcher.cpp @@ -137,12 +137,6 @@ void QAbstractEventDispatcherPrivate::init() // free list). As an added protection, we use the cell to store an invalid // (negative) value that we can later check for integrity. // -// ABA prevention simply adds a value to 7 of the top 8 bits when resetting -// nextFreeTimerId. -// -// The extra code is the bucket allocation which allows us to start with a -// very small bucket size and grow as needed. -// // (continues below). int QAbstractEventDispatcherPrivate::allocateTimerId() { @@ -170,8 +164,6 @@ int QAbstractEventDispatcherPrivate::allocateTimerId() newTimerId = prepareNewValueWithSerialNumber(timerId, b[at]); } while (!nextFreeTimerId.testAndSetRelaxed(timerId, newTimerId)); - timerId &= TimerIdMask; - timerId |= b[at] & TimerSerialMask; b[at] = -timerId; return timerId; @@ -182,13 +174,12 @@ int QAbstractEventDispatcherPrivate::allocateTimerId() // X[timerId] = nextFreeTimerId; // then we update nextFreeTimerId to the timer we've just released // +// The extra code in allocateTimerId and releaseTimerId are ABA prevention +// and bucket memory. The buckets are simply to make sure we allocate only +// the necessary number of timers. See above. +// // ABA prevention simply adds a value to 7 of the top 8 bits when resetting // nextFreeTimerId. -// -// In addition to that, we update the same 7 bits in each entry in the bucket -// as a counter. That way, a timer ID allocated and released will always be -// returned with a different ID. This reduces the chances of timers being released -// erroneously by application code. void QAbstractEventDispatcherPrivate::releaseTimerId(int timerId) { int which = timerId & TimerIdMask; @@ -196,21 +187,12 @@ void QAbstractEventDispatcherPrivate::releaseTimerId(int timerId) int at = bucketIndex(bucket, which); int *b = timerIds[bucket]; -#ifndef QT_NO_DEBUG - // debug code - Q_ASSERT_X(timerId == -b[at], "QAbstractEventDispatcher::releaseTimerId", "Timer ID was not found, fix application"); -#else - if (timerId != -b[at]) { - // release code - qWarning("Timer ID %d was not found, fix application", timerId); - return; - } -#endif + Q_ASSERT(b[at] == -timerId); int freeId, newTimerId; do { freeId = nextFreeTimerId;//.loadAcquire(); // ### FIXME Proper memory ordering semantics - b[at] = prepareNewValueWithSerialNumber(-b[at], freeId); + b[at] = freeId & TimerIdMask; newTimerId = prepareNewValueWithSerialNumber(freeId, timerId); } while (!nextFreeTimerId.testAndSetRelease(freeId, newTimerId)); -- cgit v0.12 From 97503dfd7fad9c8023b2f9632e6ef865ccd0cad8 Mon Sep 17 00:00:00 2001 From: Jani Hautakangas Date: Fri, 28 Jan 2011 13:12:47 +0200 Subject: Fix typo in qglthreads auto test. Reviewed-by: TRUSTME --- tests/auto/qglthreads/tst_qglthreads.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/qglthreads/tst_qglthreads.cpp b/tests/auto/qglthreads/tst_qglthreads.cpp index 0bcc4f6..65bebb0 100644 --- a/tests/auto/qglthreads/tst_qglthreads.cpp +++ b/tests/auto/qglthreads/tst_qglthreads.cpp @@ -216,7 +216,7 @@ public: // That's why we create only small textures. width = 50; height = 20; -#else +#endif QImage image(width, height, QImage::Format_RGB32); QPainter p(&image); p.fillRect(image.rect(), QColor(rand() % 256, rand() % 256, rand() % 256)); -- cgit v0.12 From bdf3782b40b0fc2ebfda960be08c90b549cfd970 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 28 Jan 2011 12:23:08 +0100 Subject: Fix potential networking crash due to null-pointer dereference An internal bug report suggests that we unconditionally dereference the backend pointer in QNetworkReplyImpl when checking for the synchronity of the originating request. The dereferencing code was introduced in commit ad1e82323225e996720136e8b2d669166b8d8441. Unfortunately the report does not detail where/how the crash happened, but it appears plausible that the backend pointer became null, and the surrounding code that has extra checks suggests this, too. In an attempt of defensive programming this patch introduces the missing check in the reported line 112 as well as in other places where it seems appropriate. Reviewed-by: Peter Hartmann --- src/network/access/qnetworkreplyimpl.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp index 9d7082c..343f344 100644 --- a/src/network/access/qnetworkreplyimpl.cpp +++ b/src/network/access/qnetworkreplyimpl.cpp @@ -109,7 +109,7 @@ void QNetworkReplyImplPrivate::_q_startOperation() } #endif - if (backend->isSynchronous()) { + if (backend && backend->isSynchronous()) { state = Finished; } else { if (state != Finished) { @@ -296,7 +296,7 @@ void QNetworkReplyImplPrivate::setup(QNetworkAccessManager::Operation op, const // in QtWebKit. QVariant synchronousHttpAttribute = req.attribute( static_cast(QNetworkRequest::DownloadBufferAttribute + 1)); - if (synchronousHttpAttribute.toBool()) { + if (backend && synchronousHttpAttribute.toBool()) { backend->setSynchronous(true); if (outgoingData && outgoingData->isSequential()) { outgoingDataBuffer = new QRingBuffer(); @@ -351,7 +351,7 @@ void QNetworkReplyImplPrivate::setup(QNetworkAccessManager::Operation op, const QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection); } #else - if (backend->isSynchronous()) + if (backend && backend->isSynchronous()) _q_startOperation(); else QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection); -- cgit v0.12 From be4d3182e48dcae70837f26d76dd449d914e8cb3 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Fri, 28 Jan 2011 16:32:33 +0200 Subject: Fix generated mif file cleaning in symbian-abld Mif file cleaning was incorrectly done at distclean phase. Task-number: QTBUG-16893 Reviewed-by: axis --- mkspecs/features/symbian/application_icon.prf | 2 +- qmake/generators/symbian/symmake_abld.cpp | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/mkspecs/features/symbian/application_icon.prf b/mkspecs/features/symbian/application_icon.prf index b6be89b..06f5b31 100644 --- a/mkspecs/features/symbian/application_icon.prf +++ b/mkspecs/features/symbian/application_icon.prf @@ -71,7 +71,7 @@ contains(CONFIG, no_icon) { mifconv.depends = $$ICON PRE_TARGETDEPS += $$mifconv.target QMAKE_EXTRA_TARGETS += mifconv - QMAKE_DISTCLEAN += $$mifconv.target + QMAKE_CLEAN += $$mifconv.target } # Rules to use generated MIF file from symbian resources RSS_RULES.number_of_icons = $$size(ICON_backslashed) diff --git a/qmake/generators/symbian/symmake_abld.cpp b/qmake/generators/symbian/symmake_abld.cpp index 5729e26..b582257 100644 --- a/qmake/generators/symbian/symmake_abld.cpp +++ b/qmake/generators/symbian/symmake_abld.cpp @@ -190,6 +190,7 @@ void SymbianAbldMakefileGenerator::writeWrapperMakefile(QFile& wrapperFile, bool t << "QMAKE = " << var("QMAKE_QMAKE") << endl; t << "DEL_FILE = " << var("QMAKE_DEL_FILE") << endl; t << "DEL_DIR = " << var("QMAKE_DEL_DIR") << endl; + t << "DEL_TREE = " << var("QMAKE_DEL_TREE") << endl; t << "MOVE = " << var("QMAKE_MOVE") << endl; t << "CHK_DIR_EXISTS = " << var("QMAKE_CHK_DIR_EXISTS") << endl; t << "MKDIR = " << var("QMAKE_MKDIR") << endl; @@ -329,7 +330,8 @@ void SymbianAbldMakefileGenerator::writeWrapperMakefile(QFile& wrapperFile, bool // Note: EXTENSION_CLEAN will get called many times when doing reallyclean // This is why the "2> NUL" gets appended to generated clean targets in makefile.cpp. t << EXTENSION_CLEAN ": " COMPILER_CLEAN_TARGET << endl; - generateCleanCommands(t, dirsToClean, var("QMAKE_DEL_TREE"), "", "", ""); + generateCleanCommands(t, dirsToClean, "$(DEL_TREE)", "", "", ""); + generateCleanCommands(t, project->values("QMAKE_CLEAN"), "$(DEL_FILE)", "", "", ""); t << endl; t << PRE_TARGETDEPS_TARGET ":" -- cgit v0.12 From f5f2f4d1cda47ba67e821495da0a9707c10a708c Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Mon, 31 Jan 2011 09:36:52 +1000 Subject: Use qobject_cast rather than dynamic_cast. To complile on platforms without rtti. Reviewed-by: Michael Brasser --- src/declarative/qml/qdeclarativeenginedebug.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/declarative/qml/qdeclarativeenginedebug.cpp b/src/declarative/qml/qdeclarativeenginedebug.cpp index 3863385..8c7f3ad 100644 --- a/src/declarative/qml/qdeclarativeenginedebug.cpp +++ b/src/declarative/qml/qdeclarativeenginedebug.cpp @@ -327,7 +327,7 @@ void QDeclarativeEngineDebugServer::buildStatesList(QDeclarativeContext *ctxt, b void QDeclarativeEngineDebugServer::buildStatesList(QObject *obj) { - if (QDeclarativeState *state = dynamic_cast(obj)) { + if (QDeclarativeState *state = qobject_cast(obj)) { m_allStates.append(state); } @@ -589,7 +589,7 @@ void QDeclarativeEngineDebugServer::setBinding(int objectId, } else { // not a valid property - if (QDeclarativePropertyChanges *propertyChanges = dynamic_cast(object)) { + if (QDeclarativePropertyChanges *propertyChanges = qobject_cast(object)) { if (isLiteralValue) { propertyChanges->changeValue(propertyName, expression); } else { @@ -637,7 +637,7 @@ void QDeclarativeEngineDebugServer::resetBinding(int objectId, const QString &pr } } } else { - if (QDeclarativePropertyChanges *propertyChanges = dynamic_cast(object)) { + if (QDeclarativePropertyChanges *propertyChanges = qobject_cast(object)) { propertyChanges->removeProperty(propertyName); } } -- cgit v0.12 From 2b337d8cbe8e6646ec78b3acaad50ce108d33dc0 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Mon, 31 Jan 2011 13:29:05 +1000 Subject: Add missing versioning tests for new QtQuick 1.1 properties/methods. Task-number: QTBUG-15489 Reviewed-by: Bea Lam --- .../tst_qdeclarativeborderimage.cpp | 41 ++++++++++++++++++ .../tst_qdeclarativepositioners.cpp | 48 +++++++++++++++++++++- .../qdeclarativetext/tst_qdeclarativetext.cpp | 24 ++++++++++- .../tst_qdeclarativetextedit.cpp | 16 +++++++- .../tst_qdeclarativetextinput.cpp | 46 +++++++++++++++++++++ 5 files changed, 171 insertions(+), 4 deletions(-) diff --git a/tests/auto/declarative/qdeclarativeborderimage/tst_qdeclarativeborderimage.cpp b/tests/auto/declarative/qdeclarativeborderimage/tst_qdeclarativeborderimage.cpp index 9a9d22b..d85b92a 100644 --- a/tests/auto/declarative/qdeclarativeborderimage/tst_qdeclarativeborderimage.cpp +++ b/tests/auto/declarative/qdeclarativeborderimage/tst_qdeclarativeborderimage.cpp @@ -86,6 +86,8 @@ private slots: void invalidSciFile(); void pendingRemoteRequest(); void pendingRemoteRequest_data(); + void testQtQuick11Attributes(); + void testQtQuick11Attributes_data(); private: QDeclarativeEngine engine; @@ -380,6 +382,45 @@ void tst_qdeclarativeborderimage::pendingRemoteRequest_data() QTest::newRow("sci file") << "http://localhost/none.sci"; } +void tst_qdeclarativeborderimage::testQtQuick11Attributes() +{ + QFETCH(QString, code); + QFETCH(QString, warning); + QFETCH(QString, error); + + QDeclarativeEngine engine; + QObject *obj; + + QDeclarativeComponent valid(&engine); + valid.setData("import QtQuick 1.1; BorderImage { " + code.toUtf8() + " }", QUrl("")); + obj = valid.create(); + QVERIFY(obj); + QVERIFY(valid.errorString().isEmpty()); + delete obj; + + QDeclarativeComponent invalid(&engine); + invalid.setData("import QtQuick 1.0; BorderImage { " + code.toUtf8() + " }", QUrl("")); + QTest::ignoreMessage(QtWarningMsg, warning.toUtf8()); + obj = invalid.create(); + QCOMPARE(invalid.errorString(), error); + delete obj; +} + +void tst_qdeclarativeborderimage::testQtQuick11Attributes_data() +{ + QTest::addColumn("code"); + QTest::addColumn("warning"); + QTest::addColumn("error"); + + QTest::newRow("mirror") << "mirror: true" + << "QDeclarativeComponent: Component is not ready" + << ":1 \"BorderImage.mirror\" is not available in QtQuick 1.0.\n"; + + QTest::newRow("cache") << "cache: true" + << "QDeclarativeComponent: Component is not ready" + << ":1 \"BorderImage.cache\" is not available in QtQuick 1.0.\n"; +} + QTEST_MAIN(tst_qdeclarativeborderimage) #include "tst_qdeclarativeborderimage.moc" diff --git a/tests/auto/declarative/qdeclarativepositioners/tst_qdeclarativepositioners.cpp b/tests/auto/declarative/qdeclarativepositioners/tst_qdeclarativepositioners.cpp index 6365ce5..40e533d 100644 --- a/tests/auto/declarative/qdeclarativepositioners/tst_qdeclarativepositioners.cpp +++ b/tests/auto/declarative/qdeclarativepositioners/tst_qdeclarativepositioners.cpp @@ -87,6 +87,8 @@ private slots: void test_flow_implicit_resize(); void test_conflictinganchors(); void test_vertical_qgraphicswidget(); + void testQtQuick11Attributes(); + void testQtQuick11Attributes_data(); private: QDeclarativeView *createView(const QString &filename); }; @@ -1070,7 +1072,7 @@ void interceptWarnings(QtMsgType type, const char *msg) void tst_QDeclarativePositioners::test_conflictinganchors() { - qInstallMsgHandler(interceptWarnings); + QtMsgHandler oldMsgHandler = qInstallMsgHandler(interceptWarnings); QDeclarativeEngine engine; QDeclarativeComponent component(&engine); @@ -1151,6 +1153,7 @@ void tst_QDeclarativePositioners::test_conflictinganchors() item = qobject_cast(component.create()); QVERIFY(item); QCOMPARE(warningMessage, QString("file::2:1: QML Flow: Cannot specify anchors for items inside Flow")); + qInstallMsgHandler(oldMsgHandler); } void tst_QDeclarativePositioners::test_vertical_qgraphicswidget() @@ -1195,6 +1198,49 @@ void tst_QDeclarativePositioners::test_vertical_qgraphicswidget() delete canvas; } +void tst_QDeclarativePositioners::testQtQuick11Attributes() +{ + QFETCH(QString, code); + QFETCH(QString, warning); + QFETCH(QString, error); + + QDeclarativeEngine engine; + QObject *obj; + + QDeclarativeComponent valid(&engine); + valid.setData("import QtQuick 1.1; " + code.toUtf8(), QUrl("")); + obj = valid.create(); + QVERIFY(obj); + QVERIFY(valid.errorString().isEmpty()); + delete obj; + + QDeclarativeComponent invalid(&engine); + invalid.setData("import QtQuick 1.0; " + code.toUtf8(), QUrl("")); + QTest::ignoreMessage(QtWarningMsg, warning.toUtf8()); + obj = invalid.create(); + QCOMPARE(invalid.errorString(), error); + delete obj; +} + +void tst_QDeclarativePositioners::testQtQuick11Attributes_data() +{ + QTest::addColumn("code"); + QTest::addColumn("warning"); + QTest::addColumn("error"); + + QTest::newRow("Flow.layoutDirection") << "Flow { layoutDirection: Qt.LeftToRight }" + << "QDeclarativeComponent: Component is not ready" + << ":1 \"Flow.layoutDirection\" is not available in QtQuick 1.0.\n"; + + QTest::newRow("Row.layoutDirection") << "Row { layoutDirection: Qt.LeftToRight }" + << "QDeclarativeComponent: Component is not ready" + << ":1 \"Row.layoutDirection\" is not available in QtQuick 1.0.\n"; + + QTest::newRow("Grid.layoutDirection") << "Grid { layoutDirection: Qt.LeftToRight }" + << "QDeclarativeComponent: Component is not ready" + << ":1 \"Grid.layoutDirection\" is not available in QtQuick 1.0.\n"; +} + QDeclarativeView *tst_QDeclarativePositioners::createView(const QString &filename) { QDeclarativeView *canvas = new QDeclarativeView(0); diff --git a/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp b/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp index 8111cd2..320a6e7 100644 --- a/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp +++ b/tests/auto/declarative/qdeclarativetext/tst_qdeclarativetext.cpp @@ -470,6 +470,8 @@ void tst_qdeclarativetext::alignments() QCOMPARE(actual,expect); } #endif + + delete canvas; } //the alignment tests may be trivial o.oa @@ -962,6 +964,8 @@ void tst_qdeclarativetext::QTBUG_12291() QDeclarativeText *text = ob->findChild("text"); QVERIFY(text); QVERIFY(text->boundingRect().isValid()); + + delete canvas; } class EventSender : public QGraphicsItem @@ -1054,6 +1058,8 @@ void tst_qdeclarativetext::embeddedImages() QCOMPARE(textObject->width(), 16.0); // default size of QTextDocument broken image icon QCOMPARE(textObject->height(), 16.0); } + + delete textObject; } void tst_qdeclarativetext::lineCount() @@ -1081,6 +1087,8 @@ void tst_qdeclarativetext::lineCount() QCOMPARE(myText->lineCount(), 2); QCOMPARE(myText->truncated(), true); QCOMPARE(myText->maximumLineCount(), 2); + + delete canvas; } void tst_qdeclarativetext::lineHeight() @@ -1112,6 +1120,8 @@ void tst_qdeclarativetext::lineHeight() myText->setLineHeightMode(QDeclarativeText::PixelHeight); myText->setLineHeight(10); QCOMPARE(myText->height(), myText->lineCount() * 10.0); + + delete canvas; } void tst_qdeclarativetext::implicitSize_data() @@ -1175,9 +1185,21 @@ void tst_qdeclarativetext::testQtQuick11Attributes_data() << "QDeclarativeComponent: Component is not ready" << ":1 \"Text.maximumLineCount\" is not available in QtQuick 1.0.\n"; - QTest::newRow("truncated") << "property int foo: lineCount" + QTest::newRow("lineHeight") << "lineHeight: 2" + << "QDeclarativeComponent: Component is not ready" + << ":1 \"Text.lineHeight\" is not available in QtQuick 1.0.\n"; + + QTest::newRow("lineHeightMode") << "lineHeightMode: Text.MultiplyHeight" + << "QDeclarativeComponent: Component is not ready" + << ":1 \"Text.lineHeightMode\" is not available in QtQuick 1.0.\n"; + + QTest::newRow("lineCount") << "property int foo: lineCount" << ":1: ReferenceError: Can't find variable: lineCount" << ""; + + QTest::newRow("truncated") << "property bool foo: truncated" + << ":1: ReferenceError: Can't find variable: truncated" + << ""; } QTEST_MAIN(tst_qdeclarativetext) diff --git a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp index b1e0cb9..1364337 100644 --- a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp +++ b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp @@ -1513,14 +1513,14 @@ void tst_qdeclarativetextedit::testQtQuick11Attributes() QObject *obj; QDeclarativeComponent valid(&engine); - valid.setData("import QtQuick 1.1; Text { " + code.toUtf8() + " }", QUrl("")); + valid.setData("import QtQuick 1.1; TextEdit { " + code.toUtf8() + " }", QUrl("")); obj = valid.create(); QVERIFY(obj); QVERIFY(valid.errorString().isEmpty()); delete obj; QDeclarativeComponent invalid(&engine); - invalid.setData("import QtQuick 1.0; Text { " + code.toUtf8() + " }", QUrl("")); + invalid.setData("import QtQuick 1.0; TextEdit { " + code.toUtf8() + " }", QUrl("")); QTest::ignoreMessage(QtWarningMsg, warning.toUtf8()); obj = invalid.create(); QCOMPARE(invalid.errorString(), error); @@ -1540,6 +1540,18 @@ void tst_qdeclarativetextedit::testQtQuick11Attributes_data() QTest::newRow("lineCount") << "property int foo: lineCount" << ":1: ReferenceError: Can't find variable: lineCount" << ""; + + QTest::newRow("moveCursorSelection") << "Component.onCompleted: moveCursorSelection(0, TextEdit.SelectCharacters)" + << ":1: ReferenceError: Can't find variable: moveCursorSelection" + << ""; + + QTest::newRow("deselect") << "Component.onCompleted: deselect()" + << ":1: ReferenceError: Can't find variable: deselect" + << ""; + + QTest::newRow("onLinkActivated") << "onLinkActivated: {}" + << "QDeclarativeComponent: Component is not ready" + << ":1 \"TextEdit.onLinkActivated\" is not available in QtQuick 1.0.\n"; } QTEST_MAIN(tst_qdeclarativetextedit) diff --git a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp index 78f6693..7cdec27 100644 --- a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp +++ b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp @@ -117,6 +117,9 @@ private slots: void echoMode(); void geometrySignals(); + void testQtQuick11Attributes(); + void testQtQuick11Attributes_data(); + private: void simulateKey(QDeclarativeView *, int key); QDeclarativeView *createView(const QString &filename); @@ -1434,6 +1437,49 @@ void tst_qdeclarativetextinput::geometrySignals() delete o; } +void tst_qdeclarativetextinput::testQtQuick11Attributes() +{ + QFETCH(QString, code); + QFETCH(QString, warning); + QFETCH(QString, error); + + QDeclarativeEngine engine; + QObject *obj; + + QDeclarativeComponent valid(&engine); + valid.setData("import QtQuick 1.1; TextInput { " + code.toUtf8() + " }", QUrl("")); + obj = valid.create(); + QVERIFY(obj); + QVERIFY(valid.errorString().isEmpty()); + delete obj; + + QDeclarativeComponent invalid(&engine); + invalid.setData("import QtQuick 1.0; TextInput { " + code.toUtf8() + " }", QUrl("")); + QTest::ignoreMessage(QtWarningMsg, warning.toUtf8()); + obj = invalid.create(); + QCOMPARE(invalid.errorString(), error); + delete obj; +} + +void tst_qdeclarativetextinput::testQtQuick11Attributes_data() +{ + QTest::addColumn("code"); + QTest::addColumn("warning"); + QTest::addColumn("error"); + + QTest::newRow("canPaste") << "property bool foo: canPaste" + << ":1: ReferenceError: Can't find variable: canPaste" + << ""; + + QTest::newRow("moveCursorSelection") << "Component.onCompleted: moveCursorSelection(0, TextEdit.SelectCharacters)" + << ":1: ReferenceError: Can't find variable: moveCursorSelection" + << ""; + + QTest::newRow("deselect") << "Component.onCompleted: deselect()" + << ":1: ReferenceError: Can't find variable: deselect" + << ""; +} + QTEST_MAIN(tst_qdeclarativetextinput) #include "tst_qdeclarativetextinput.moc" -- cgit v0.12 From dc8163d64af88e1daa88c7b1bf9903a87eb3d5b0 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Mon, 31 Jan 2011 17:13:46 +0200 Subject: Make emulator deployment depend on post linking in symbian-sbsv2. Post linking output was not previously possible to deploy as there was no dependency from deployment to post linking, which meant deployment was usually attempted first. Now all post linking in project tree needs to be done before any deployment is done. Note that you can still get warnings about missing dependencies as sbsv2 checks those before it actually executes the targets. These warnings are harmless, but difficult to get rid of using a general solution, as qmake cannot make any guesses what QMAKE_POST_LINK handling might output. Task-number: QTBUG-17037 Reviewed-by: axis --- mkspecs/symbian-sbsv2/flm/qt/qmake_emulator_deployment.flm | 8 ++++---- mkspecs/symbian-sbsv2/flm/qt/qmake_post_link.flm | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/mkspecs/symbian-sbsv2/flm/qt/qmake_emulator_deployment.flm b/mkspecs/symbian-sbsv2/flm/qt/qmake_emulator_deployment.flm index db91f7f..39ab0f0 100644 --- a/mkspecs/symbian-sbsv2/flm/qt/qmake_emulator_deployment.flm +++ b/mkspecs/symbian-sbsv2/flm/qt/qmake_emulator_deployment.flm @@ -11,6 +11,9 @@ SINGLETON:=$(call sanitise,TARGET_$(DEPLOY_TARGET)) CLEAN_TARGET:= +# Deployment dependencies collection target for post link operations +all_qmake_emulator_deployment_dependencies:: + define qmake_emulator_deployment $(ALLTARGET):: $(1) @@ -19,7 +22,7 @@ $(SINGLETON):=1 CLEAN_TARGET:=$(1) -$(1): $(2) +$(1): $(2) all_qmake_emulator_deployment_dependencies $(call startrule,qmake_emulator_deployment) \ $(GNUCP) --remove-destination --no-preserve=mode $(2) "$$@" && \ $(GNUCHMOD) a+rw "$$@" \ @@ -32,6 +35,3 @@ $(call makepath,$(dir $(DEPLOY_TARGET))) $(eval $(call GenerateStandardCleanTarget,$(CLEAN_TARGET),'')) endif - - - diff --git a/mkspecs/symbian-sbsv2/flm/qt/qmake_post_link.flm b/mkspecs/symbian-sbsv2/flm/qt/qmake_post_link.flm index ae53741..0312d14 100644 --- a/mkspecs/symbian-sbsv2/flm/qt/qmake_post_link.flm +++ b/mkspecs/symbian-sbsv2/flm/qt/qmake_post_link.flm @@ -18,6 +18,8 @@ define command_fixer THE_COMMAND:=$(POST_LINK_CMD) endef +all_qmake_emulator_deployment_dependencies:: $(POST_LINK_TARGET) + define qmake_post_link $(ALLTARGET):: $(POST_LINK_TARGET) -- cgit v0.12 From ba63becc13221ca6538fb40c790275465dd47703 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Fri, 28 Jan 2011 15:58:37 +1000 Subject: Add a mouseSelectionMode property to TextEdit and TextInput. Adds an option to do per word selection when selectByMouse is true. Also changes the selection behavior so that the first word selected remains selected when the direction of the selection changes which is more consistent with other implementations including the existing per word selection in QTextEdit. Task-number: QTBUG-16283 Reviewed-by: Martin Jones --- .../graphicsitems/qdeclarativetextedit.cpp | 84 +++-- .../graphicsitems/qdeclarativetextedit_p.h | 5 + .../graphicsitems/qdeclarativetextedit_p_p.h | 3 +- .../graphicsitems/qdeclarativetextinput.cpp | 90 +++--- .../graphicsitems/qdeclarativetextinput_p.h | 5 + .../graphicsitems/qdeclarativetextinput_p_p.h | 2 + src/gui/text/qtextcontrol.cpp | 27 +- src/gui/text/qtextcontrol_p.h | 5 +- src/gui/text/qtextcontrol_p_p.h | 2 + .../data/mouseselectionmode_characters.qml | 8 + .../data/mouseselectionmode_default.qml | 7 + .../data/mouseselectionmode_words.qml | 8 + .../tst_qdeclarativetextedit.cpp | 349 ++++++++++++++++---- .../data/mouseselectionmode_characters.qml | 8 + .../data/mouseselectionmode_default.qml | 7 + .../data/mouseselectionmode_words.qml | 8 + .../tst_qdeclarativetextinput.cpp | 352 +++++++++++++++++---- 17 files changed, 778 insertions(+), 192 deletions(-) create mode 100644 tests/auto/declarative/qdeclarativetextedit/data/mouseselectionmode_characters.qml create mode 100644 tests/auto/declarative/qdeclarativetextedit/data/mouseselectionmode_default.qml create mode 100644 tests/auto/declarative/qdeclarativetextedit/data/mouseselectionmode_words.qml create mode 100644 tests/auto/declarative/qdeclarativetextinput/data/mouseselectionmode_characters.qml create mode 100644 tests/auto/declarative/qdeclarativetextinput/data/mouseselectionmode_default.qml create mode 100644 tests/auto/declarative/qdeclarativetextinput/data/mouseselectionmode_words.qml diff --git a/src/declarative/graphicsitems/qdeclarativetextedit.cpp b/src/declarative/graphicsitems/qdeclarativetextedit.cpp index 959d655..f63e4cb 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextedit.cpp @@ -653,9 +653,7 @@ void QDeclarativeTextEdit::moveCursorSelection(int pos) selected (the 6th and 7th characters). The same sequence with TextEdit.SelectWords will extend the selection start to a word boundary - before or on position 5 and extend the selection end to a word boundary past position 9, and - then if there is a word boundary between position 7 and 8 retract the selection end to that - boundary. If there is whitespace at position 7 the selection will be retracted further. + before or on position 5 and extend the selection end to a word boundary on or past position 9. */ void QDeclarativeTextEdit::moveCursorSelection(int pos, SelectionMode mode) { @@ -665,48 +663,43 @@ void QDeclarativeTextEdit::moveCursorSelection(int pos, SelectionMode mode) return; if (mode == SelectCharacters) { cursor.setPosition(pos, QTextCursor::KeepAnchor); - } else if (cursor.anchor() < pos) { - cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor); - cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor); - if (cursor.position() == cursor.anchor()) { - cursor.movePosition(QTextCursor::NextWord, QTextCursor::MoveAnchor); + } else if (cursor.anchor() < pos || (cursor.anchor() == pos && cursor.position() < pos)) { + if (cursor.anchor() > cursor.position()) { + cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor); + cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::KeepAnchor); + if (cursor.position() == cursor.anchor()) + cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::MoveAnchor); + else + cursor.setPosition(cursor.position(), QTextCursor::MoveAnchor); } else { - cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::MoveAnchor); + cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor); cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::MoveAnchor); } + cursor.setPosition(pos, QTextCursor::KeepAnchor); cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::KeepAnchor); - if (cursor.position() == pos) { - cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::KeepAnchor); + if (cursor.position() != pos) cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor); - - if (cursor.anchor() > cursor.position()) - cursor.setPosition(pos, QTextCursor::MoveAnchor); - } else { - cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor); - } - } else if (cursor.anchor() > pos) { - cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor); - cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::KeepAnchor); - if (cursor.position() == cursor.anchor()) { - cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::MoveAnchor); + } else if (cursor.anchor() > pos || (cursor.anchor() == pos && cursor.position() > pos)) { + if (cursor.anchor() < cursor.position()) { + cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor); cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::MoveAnchor); } else { - cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::MoveAnchor); + cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor); + cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor); + cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor); + if (cursor.position() != cursor.anchor()) { + cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor); + cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::MoveAnchor); + } } + cursor.setPosition(pos, QTextCursor::KeepAnchor); cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor); - if (cursor.position() == pos) { - cursor.movePosition(QTextCursor::NextWord, QTextCursor::KeepAnchor); - - if (cursor.anchor() < cursor.position()) - cursor.setPosition(pos, QTextCursor::MoveAnchor); - } else { + if (cursor.position() != pos) { cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor); cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::KeepAnchor); } - } else { - cursor.setPosition(pos, QTextCursor::MoveAnchor); } d->control->setTextCursor(cursor); } @@ -986,6 +979,35 @@ void QDeclarativeTextEdit::setSelectByMouse(bool on) } +/*! + \qmlproperty enum TextEdit::mouseSelectionMode + \since Quick 1.1 + + Specifies how text should be selected using a mouse. + + \list + \o TextEdit.SelectCharacters - The selection is updated with individual characters. (Default) + \o TextEdit.SelectWords - The selection is updated with whole words. + \endlist + + This property only applies when \l selectByMouse is true. +*/ + +QDeclarativeTextEdit::SelectionMode QDeclarativeTextEdit::mouseSelectionMode() const +{ + Q_D(const QDeclarativeTextEdit); + return d->mouseSelectionMode; +} + +void QDeclarativeTextEdit::setMouseSelectionMode(SelectionMode mode) +{ + Q_D(QDeclarativeTextEdit); + if (d->mouseSelectionMode != mode) { + d->mouseSelectionMode = mode; + d->control->setWordSelectionEnabled(mode == SelectWords); + emit mouseSelectionModeChanged(mode); + } +} /*! \qmlproperty bool TextEdit::readOnly diff --git a/src/declarative/graphicsitems/qdeclarativetextedit_p.h b/src/declarative/graphicsitems/qdeclarativetextedit_p.h index db3cb2d..7785a7a 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextedit_p.h @@ -92,6 +92,7 @@ class Q_AUTOTEST_EXPORT QDeclarativeTextEdit : public QDeclarativeImplicitSizePa Q_PROPERTY(qreal textMargin READ textMargin WRITE setTextMargin NOTIFY textMarginChanged) Q_PROPERTY(Qt::InputMethodHints inputMethodHints READ inputMethodHints WRITE setInputMethodHints) Q_PROPERTY(bool selectByMouse READ selectByMouse WRITE setSelectByMouse NOTIFY selectByMouseChanged) + Q_PROPERTY(SelectionMode mouseSelectionMode READ mouseSelectionMode WRITE setMouseSelectionMode NOTIFY mouseSelectionModeChanged REVISION 1) Q_PROPERTY(bool canPaste READ canPaste NOTIFY canPasteChanged REVISION 1) public: @@ -186,6 +187,9 @@ public: bool selectByMouse() const; void setSelectByMouse(bool); + SelectionMode mouseSelectionMode() const; + void setMouseSelectionMode(SelectionMode mode); + bool canPaste() const; virtual void componentComplete(); @@ -235,6 +239,7 @@ Q_SIGNALS: void persistentSelectionChanged(bool isPersistentSelection); void textMarginChanged(qreal textMargin); void selectByMouseChanged(bool selectByMouse); + Q_REVISION(1) void mouseSelectionModeChanged(SelectionMode mode); Q_REVISION(1) void linkActivated(const QString &link); Q_REVISION(1) void canPasteChanged(); diff --git a/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h b/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h index 98b3c6d..111cc02 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h @@ -73,7 +73,7 @@ public: showInputPanelOnFocus(true), clickCausedFocus(false), persistentSelection(true), requireImplicitWidth(false), textMargin(0.0), lastSelectionStart(0), lastSelectionEnd(0), cursorComponent(0), cursor(0), format(QDeclarativeTextEdit::AutoText), document(0), wrapMode(QDeclarativeTextEdit::NoWrap), - selectByMouse(false), canPaste(false), + mouseSelectionMode(QDeclarativeTextEdit::SelectCharacters), selectByMouse(false), canPaste(false), yoff(0) { #ifdef Q_OS_SYMBIAN @@ -121,6 +121,7 @@ public: QTextDocument *document; QTextControl *control; QDeclarativeTextEdit::WrapMode wrapMode; + QDeclarativeTextEdit::SelectionMode mouseSelectionMode; int lineCount; bool selectByMouse; bool canPaste; diff --git a/src/declarative/graphicsitems/qdeclarativetextinput.cpp b/src/declarative/graphicsitems/qdeclarativetextinput.cpp index 3d2466d..9e62291 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextinput.cpp @@ -1022,7 +1022,7 @@ void QDeclarativeTextInput::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { Q_D(QDeclarativeTextInput); if (d->selectByMouse) { - d->control->moveCursor(d->xToPos(event->pos().x()), true); + moveCursorSelection(d->xToPos(event->pos().x()), d->mouseSelectionMode); event->setAccepted(true); } else { QDeclarativePaintedItem::mouseMoveEvent(event); @@ -1348,6 +1348,35 @@ void QDeclarativeTextInput::setSelectByMouse(bool on) } } +/*! + \qmlproperty enum TextInput::mouseSelectionMode + \since Quick 1.1 + + Specifies how text should be selected using a mouse. + + \list + \o TextInput.SelectCharacters - The selection is updated with individual characters. (Default) + \o TextInput.SelectWords - The selection is updated with whole words. + \endlist + + This property only applies when \l selectByMouse is true. +*/ + +QDeclarativeTextInput::SelectionMode QDeclarativeTextInput::mouseSelectionMode() const +{ + Q_D(const QDeclarativeTextInput); + return d->mouseSelectionMode; +} + +void QDeclarativeTextInput::setMouseSelectionMode(SelectionMode mode) +{ + Q_D(QDeclarativeTextInput); + if (d->mouseSelectionMode != mode) { + d->mouseSelectionMode = mode; + emit mouseSelectionModeChanged(mode); + } +} + bool QDeclarativeTextInput::canPaste() const { Q_D(const QDeclarativeTextInput); @@ -1397,9 +1426,7 @@ void QDeclarativeTextInput::moveCursorSelection(int position) selected (the 6th and 7th characters). The same sequence with TextInput.SelectWords will extend the selection start to a word boundary - before or on position 5 and extend the selection end to a word boundary past position 9, and - then if there is a word boundary between position 7 and 8 retract the selection end to that - boundary. If there is whitespace at position 7 the selection will be retracted further. + before or on position 5 and extend the selection end to a word boundary on or past position 9. */ void QDeclarativeTextInput::moveCursorSelection(int pos, SelectionMode mode) { @@ -1408,6 +1435,7 @@ void QDeclarativeTextInput::moveCursorSelection(int pos, SelectionMode mode) if (mode == SelectCharacters) { d->control->moveCursor(pos, true); } else if (pos != d->control->cursor()){ + const int cursor = d->control->cursor(); int anchor; if (!d->control->hasSelectedText()) anchor = d->control->cursor(); @@ -1416,55 +1444,39 @@ void QDeclarativeTextInput::moveCursorSelection(int pos, SelectionMode mode) else anchor = d->control->selectionStart(); - if (anchor < pos) { + if (anchor < pos || (anchor == pos && cursor < pos)) { QTextBoundaryFinder finder(QTextBoundaryFinder::Word, d->control->text()); finder.setPosition(anchor); - if (!(finder.boundaryReasons() & QTextBoundaryFinder::StartWord)) { - finder.toNextBoundary(); - if (finder.boundaryReasons() != QTextBoundaryFinder::StartWord) - finder.toPreviousBoundary(); + const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons(); + if (!(reasons & QTextBoundaryFinder::StartWord) + || ((reasons & QTextBoundaryFinder::EndWord) && anchor > cursor)) { + finder.toPreviousBoundary(); } anchor = finder.position(); finder.setPosition(pos); - if (!(finder.boundaryReasons() & QTextBoundaryFinder::EndWord)) { - finder.toPreviousBoundary(); - if (finder.boundaryReasons() != QTextBoundaryFinder::EndWord) - finder.toNextBoundary(); - } - int cursor = finder.position(); + if (!finder.isAtBoundary()) + finder.toNextBoundary(); - if (anchor < cursor) - d->control->setSelection(anchor, cursor - anchor); - else - d->control->moveCursor(pos, false); - - } else if (anchor > pos) { + d->control->setSelection(anchor, finder.position() - anchor); + } else if (anchor > pos || (anchor == pos && cursor > pos)) { QTextBoundaryFinder finder(QTextBoundaryFinder::Word, d->control->text()); - finder.setPosition(anchor); - if (!(finder.boundaryReasons() & QTextBoundaryFinder::EndWord)) { - finder.toPreviousBoundary(); - if (finder.boundaryReasons() != QTextBoundaryFinder::EndWord) - finder.toNextBoundary(); + + const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons(); + if (!(reasons & QTextBoundaryFinder::EndWord) + || ((reasons & QTextBoundaryFinder::StartWord) && anchor < cursor)) { + finder.toNextBoundary(); } + anchor = finder.position(); finder.setPosition(pos); - if (!(finder.boundaryReasons() & QTextBoundaryFinder::StartWord)) { - finder.toNextBoundary(); - if (finder.boundaryReasons() != QTextBoundaryFinder::StartWord) - finder.toPreviousBoundary(); - } - int cursor = finder.position(); - - if (anchor > cursor) - d->control->setSelection(anchor, cursor - anchor); - else - d->control->moveCursor(pos, false); - } else { - d->control->moveCursor(pos, false); + if (!finder.isAtBoundary()) + finder.toPreviousBoundary(); + + d->control->setSelection(anchor, finder.position() - anchor); } } } diff --git a/src/declarative/graphicsitems/qdeclarativetextinput_p.h b/src/declarative/graphicsitems/qdeclarativetextinput_p.h index 543f7a8..63d0e53 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextinput_p.h @@ -95,6 +95,7 @@ class Q_AUTOTEST_EXPORT QDeclarativeTextInput : public QDeclarativeImplicitSizeP Q_PROPERTY(QString displayText READ displayText NOTIFY displayTextChanged) Q_PROPERTY(bool autoScroll READ autoScroll WRITE setAutoScroll NOTIFY autoScrollChanged) Q_PROPERTY(bool selectByMouse READ selectByMouse WRITE setSelectByMouse NOTIFY selectByMouseChanged) + Q_PROPERTY(SelectionMode mouseSelectionMode READ mouseSelectionMode WRITE setMouseSelectionMode NOTIFY mouseSelectionModeChanged REVISION 1) Q_PROPERTY(bool canPaste READ canPaste NOTIFY canPasteChanged REVISION 1) public: @@ -192,6 +193,9 @@ public: bool selectByMouse() const; void setSelectByMouse(bool); + SelectionMode mouseSelectionMode() const; + void setMouseSelectionMode(SelectionMode mode); + bool hasAcceptableInput() const; void drawContents(QPainter *p,const QRect &r); @@ -225,6 +229,7 @@ Q_SIGNALS: void activeFocusOnPressChanged(bool activeFocusOnPress); void autoScrollChanged(bool autoScroll); void selectByMouseChanged(bool selectByMouse); + Q_REVISION(1) void mouseSelectionModeChanged(SelectionMode mode); Q_REVISION(1) void canPasteChanged(); protected: diff --git a/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h b/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h index 1f45c11..7a0086e 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h @@ -73,6 +73,7 @@ public: QDeclarativeTextInputPrivate() : control(new QLineControl(QString())), color((QRgb)0), style(QDeclarativeText::Normal), styleColor((QRgb)0), hAlign(QDeclarativeTextInput::AlignLeft), + mouseSelectionMode(QDeclarativeTextInput::SelectCharacters), hscroll(0), oldScroll(0), focused(false), focusOnPress(true), showInputPanelOnFocus(true), clickCausedFocus(false), cursorVisible(false), autoScroll(true), selectByMouse(false), canPaste(false) @@ -114,6 +115,7 @@ public: QDeclarativeText::TextStyle style; QColor styleColor; QDeclarativeTextInput::HAlignment hAlign; + QDeclarativeTextInput::SelectionMode mouseSelectionMode; QPointer cursorComponent; QPointer cursorItem; diff --git a/src/gui/text/qtextcontrol.cpp b/src/gui/text/qtextcontrol.cpp index 030e196..e380b37 100644 --- a/src/gui/text/qtextcontrol.cpp +++ b/src/gui/text/qtextcontrol.cpp @@ -129,7 +129,8 @@ QTextControlPrivate::QTextControlPrivate() isEnabled(true), hadSelectionOnMousePress(false), ignoreUnusedNavigationEvents(false), - openExternalLinks(false) + openExternalLinks(false), + wordSelectionEnabled(false) {} bool QTextControlPrivate::cursorMoveKeyEvent(QKeyEvent *e) @@ -1544,11 +1545,16 @@ void QTextControlPrivate::mousePressEvent(QEvent *e, Qt::MouseButton button, con } #endif if (modifiers == Qt::ShiftModifier) { + if (wordSelectionEnabled && !selectedWordOnDoubleClick.hasSelection()) { + selectedWordOnDoubleClick = cursor; + selectedWordOnDoubleClick.select(QTextCursor::WordUnderCursor); + } + if (selectedBlockOnTrippleClick.hasSelection()) extendBlockwiseSelection(cursorPos); else if (selectedWordOnDoubleClick.hasSelection()) extendWordwiseSelection(cursorPos, pos.x()); - else + else if (wordSelectionEnabled) setCursorPosition(cursorPos, QTextCursor::KeepAnchor); } else { @@ -1626,6 +1632,11 @@ void QTextControlPrivate::mouseMoveEvent(Qt::MouseButtons buttons, const QPointF if (newCursorPos == -1) return; + if (wordSelectionEnabled && !selectedWordOnDoubleClick.hasSelection()) { + selectedWordOnDoubleClick = cursor; + selectedWordOnDoubleClick.select(QTextCursor::WordUnderCursor); + } + if (selectedBlockOnTrippleClick.hasSelection()) extendBlockwiseSelection(newCursorPos); else if (selectedWordOnDoubleClick.hasSelection()) @@ -2343,6 +2354,18 @@ bool QTextControl::isDragEnabled() const return d->dragEnabled; } +void QTextControl::setWordSelectionEnabled(bool enabled) +{ + Q_D(QTextControl); + d->wordSelectionEnabled = enabled; +} + +bool QTextControl::isWordSelectionEnabled() const +{ + Q_D(const QTextControl); + return d->wordSelectionEnabled; +} + #ifndef QT_NO_PRINTER void QTextControl::print(QPrinter *printer) const { diff --git a/src/gui/text/qtextcontrol_p.h b/src/gui/text/qtextcontrol_p.h index 9277b68..31fa843 100644 --- a/src/gui/text/qtextcontrol_p.h +++ b/src/gui/text/qtextcontrol_p.h @@ -178,6 +178,9 @@ public: void setDragEnabled(bool enabled); bool isDragEnabled() const; + bool isWordSelectionEnabled() const; + void setWordSelectionEnabled(bool enabled); + #ifndef QT_NO_PRINTER void print(QPrinter *printer) const; #endif @@ -186,8 +189,6 @@ public: virtual QRectF blockBoundingRect(const QTextBlock &block) const; QAbstractTextDocumentLayout::PaintContext getPaintContext(QWidget *widget) const; - - public Q_SLOTS: void setPlainText(const QString &text); void setHtml(const QString &text); diff --git a/src/gui/text/qtextcontrol_p_p.h b/src/gui/text/qtextcontrol_p_p.h index d7463ca..ecd13ea 100644 --- a/src/gui/text/qtextcontrol_p_p.h +++ b/src/gui/text/qtextcontrol_p_p.h @@ -211,6 +211,8 @@ public: bool ignoreUnusedNavigationEvents; bool openExternalLinks; + bool wordSelectionEnabled; + QString linkToCopy; void _q_copyLink(); void _q_updateBlock(const QTextBlock &); diff --git a/tests/auto/declarative/qdeclarativetextedit/data/mouseselectionmode_characters.qml b/tests/auto/declarative/qdeclarativetextedit/data/mouseselectionmode_characters.qml new file mode 100644 index 0000000..5784e19 --- /dev/null +++ b/tests/auto/declarative/qdeclarativetextedit/data/mouseselectionmode_characters.qml @@ -0,0 +1,8 @@ +import QtQuick 1.1 + +TextEdit { + focus: true + text: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + selectByMouse: true + mouseSelectionMode: TextEdit.SelectCharacters +} diff --git a/tests/auto/declarative/qdeclarativetextedit/data/mouseselectionmode_default.qml b/tests/auto/declarative/qdeclarativetextedit/data/mouseselectionmode_default.qml new file mode 100644 index 0000000..1e5f4aa --- /dev/null +++ b/tests/auto/declarative/qdeclarativetextedit/data/mouseselectionmode_default.qml @@ -0,0 +1,7 @@ +import QtQuick 1.1 + +TextEdit { + focus: true + text: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + selectByMouse: true +} diff --git a/tests/auto/declarative/qdeclarativetextedit/data/mouseselectionmode_words.qml b/tests/auto/declarative/qdeclarativetextedit/data/mouseselectionmode_words.qml new file mode 100644 index 0000000..4b25f2f --- /dev/null +++ b/tests/auto/declarative/qdeclarativetextedit/data/mouseselectionmode_words.qml @@ -0,0 +1,8 @@ +import QtQuick 1.1 + +TextEdit { + focus: true + text: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + selectByMouse: true + mouseSelectionMode: TextEdit.SelectWords +} diff --git a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp index 1364337..b82aca8 100644 --- a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp +++ b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp @@ -112,8 +112,12 @@ private slots: void selection(); void moveCursorSelection_data(); void moveCursorSelection(); + void moveCursorSelectionSequence_data(); + void moveCursorSelectionSequence(); void mouseSelection_data(); void mouseSelection(); + void mouseSelectionMode_data(); + void mouseSelectionMode(); void dragMouseSelection(); void inputMethodHints(); @@ -786,91 +790,113 @@ void tst_qdeclarativetextedit::moveCursorSelection_data() QTest::newRow("jum()ped|characters") << standard[0] << 23 << 23 << QDeclarativeTextEdit::SelectCharacters << 23 << 23 << true; - QTest::newRow("(t)he|words") + QTest::newRow("<(t)he>|words") << standard[0] << 0 << 1 << QDeclarativeTextEdit::SelectWords << 0 << 3 << true; - QTest::newRow("do(g)|words") + QTest::newRow("|words") << standard[0] << 43 << 44 << QDeclarativeTextEdit::SelectWords << 41 << 44 << true; - QTest::newRow("jum(p)ed|words") + QTest::newRow("|words") << standard[0] << 23 << 24 << QDeclarativeTextEdit::SelectWords << 20 << 26 << true; - QTest::newRow("jumped( )over|words") - << standard[0] << 26 << 27 << QDeclarativeTextEdit::SelectWords << 27 << 27 << false; - QTest::newRow("jumped( )over|words,reversed") - << standard[0] << 27 << 26 << QDeclarativeTextEdit::SelectWords << 26 << 26 << false; - QTest::newRow("(the )|words") - << standard[0] << 0 << 4 << QDeclarativeTextEdit::SelectWords << 0 << 3 << true; - QTest::newRow("( dog)|words") - << standard[0] << 40 << 44 << QDeclarativeTextEdit::SelectWords << 41 << 44 << true; - QTest::newRow("( jumped )|words") - << standard[0] << 19 << 27 << QDeclarativeTextEdit::SelectWords << 20 << 26 << true; - QTest::newRow("th(e qu)ick|words") + QTest::newRow("over|words") + << standard[0] << 26 << 27 << QDeclarativeTextEdit::SelectWords << 20 << 27 << false; + QTest::newRow("jumped<( )over>|words,reversed") + << standard[0] << 27 << 26 << QDeclarativeTextEdit::SelectWords << 26 << 31 << false; + QTest::newRow("<(the )>quick|words") + << standard[0] << 0 << 4 << QDeclarativeTextEdit::SelectWords << 0 << 4 << false; + QTest::newRow("<(the )quick>|words,reversed") + << standard[0] << 4 << 0 << QDeclarativeTextEdit::SelectWords << 0 << 9 << false; + QTest::newRow("|words") + << standard[0] << 40 << 44 << QDeclarativeTextEdit::SelectWords << 36 << 44 << false; + QTest::newRow("lazy<( dog)>|words,reversed") + << standard[0] << 44 << 40 << QDeclarativeTextEdit::SelectWords << 40 << 44 << false; + QTest::newRow("over|words") + << standard[0] << 19 << 27 << QDeclarativeTextEdit::SelectWords << 16 << 27 << false; + QTest::newRow("fox<( jumped )over>|words,reversed") + << standard[0] << 27 << 19 << QDeclarativeTextEdit::SelectWords << 19 << 31 << false; + QTest::newRow("|words") << standard[0] << 2 << 6 << QDeclarativeTextEdit::SelectWords << 0 << 9 << true; - QTest::newRow("la(zy d)og|words") + QTest::newRow("") << standard[0] << 38 << 42 << QDeclarativeTextEdit::SelectWords << 36 << 44 << true; - QTest::newRow("jum(ped ov)er|words") + QTest::newRow("|words") << standard[0] << 23 << 29 << QDeclarativeTextEdit::SelectWords << 20 << 31 << true; - QTest::newRow("()the|words") + QTest::newRow("<()>the|words") << standard[0] << 0 << 0 << QDeclarativeTextEdit::SelectWords << 0 << 0 << true; - QTest::newRow("dog()|words") + QTest::newRow("dog<()>|words") << standard[0] << 44 << 44 << QDeclarativeTextEdit::SelectWords << 44 << 44 << true; - QTest::newRow("jum()ped|words") + QTest::newRow("jum<()>ped|words") << standard[0] << 23 << 23 << QDeclarativeTextEdit::SelectWords << 23 << 23 << true; - QTest::newRow("Hello(,) |words") + QTest::newRow("Hello<(,)> |words") << standard[2] << 5 << 6 << QDeclarativeTextEdit::SelectWords << 5 << 6 << true; - QTest::newRow("Hello(, )|words") - << standard[2] << 5 << 7 << QDeclarativeTextEdit::SelectWords << 5 << 6 << true; - QTest::newRow("Hel(lo, )|words") - << standard[2] << 3 << 7 << QDeclarativeTextEdit::SelectWords << 0 << 6 << true; - QTest::newRow("Hel(lo),|words") + QTest::newRow("Hello<(, )>world|words") + << standard[2] << 5 << 7 << QDeclarativeTextEdit::SelectWords << 5 << 7 << false; + QTest::newRow("Hello<(, )world>|words,reversed") + << standard[2] << 7 << 5 << QDeclarativeTextEdit::SelectWords << 5 << 12 << false; + QTest::newRow("world|words") + << standard[2] << 3 << 7 << QDeclarativeTextEdit::SelectWords << 0 << 7 << false; + QTest::newRow("|words,reversed") + << standard[2] << 7 << 3 << QDeclarativeTextEdit::SelectWords << 0 << 12 << false; + QTest::newRow(",|words") << standard[2] << 3 << 5 << QDeclarativeTextEdit::SelectWords << 0 << 5 << true; - QTest::newRow("Hello(),|words") + QTest::newRow("Hello<()>,|words") << standard[2] << 5 << 5 << QDeclarativeTextEdit::SelectWords << 5 << 5 << true; - QTest::newRow("Hello,()|words") + QTest::newRow("Hello,<()>|words") << standard[2] << 6 << 6 << QDeclarativeTextEdit::SelectWords << 6 << 6 << true; - QTest::newRow("Hello,( )|words") - << standard[2] << 6 << 7 << QDeclarativeTextEdit::SelectWords << 7 << 7 << false; - QTest::newRow("Hello,( )|words") - << standard[2] << 7 << 6 << QDeclarativeTextEdit::SelectWords << 6 << 6 << false; - QTest::newRow("Hello,( world)|words") - << standard[2] << 6 << 12 << QDeclarativeTextEdit::SelectWords << 7 << 12 << true; - QTest::newRow("Hello,( world!)|words") - << standard[2] << 6 << 13 << QDeclarativeTextEdit::SelectWords << 7 << 13 << true; - QTest::newRow("Hello(, world!)|words") + QTest::newRow("Hello<,( )>world|words") + << standard[2] << 6 << 7 << QDeclarativeTextEdit::SelectWords << 5 << 7 << false; + QTest::newRow("Hello,<( )world>|words,reversed") + << standard[2] << 7 << 6 << QDeclarativeTextEdit::SelectWords << 6 << 12 << false; + QTest::newRow("Hello<,( world)>|words") + << standard[2] << 6 << 12 << QDeclarativeTextEdit::SelectWords << 5 << 12 << false; + QTest::newRow("Hello,<( world)>|words,reversed") + << standard[2] << 12 << 6 << QDeclarativeTextEdit::SelectWords << 6 << 12 << false; + QTest::newRow("Hello<,( world!)>|words") + << standard[2] << 6 << 13 << QDeclarativeTextEdit::SelectWords << 5 << 13 << false; + QTest::newRow("Hello,<( world!)>|words,reversed") + << standard[2] << 13 << 6 << QDeclarativeTextEdit::SelectWords << 6 << 13 << false; + QTest::newRow("Hello<(, world!)>|words") << standard[2] << 5 << 13 << QDeclarativeTextEdit::SelectWords << 5 << 13 << true; - QTest::newRow("world(!)|words") + QTest::newRow("world<(!)>|words") << standard[2] << 12 << 13 << QDeclarativeTextEdit::SelectWords << 12 << 13 << true; - QTest::newRow("world!())|words") + QTest::newRow("world!<()>)|words") << standard[2] << 13 << 13 << QDeclarativeTextEdit::SelectWords << 13 << 13 << true; - QTest::newRow("world()!)|words") + QTest::newRow("world<()>!)|words") << standard[2] << 12 << 12 << QDeclarativeTextEdit::SelectWords << 12 << 12 << true; - QTest::newRow("(,)olleH |words") + QTest::newRow("<(,)>olleH |words") << standard[3] << 7 << 8 << QDeclarativeTextEdit::SelectWords << 7 << 8 << true; - QTest::newRow("( ,)olleH|words") - << standard[3] << 6 << 8 << QDeclarativeTextEdit::SelectWords << 7 << 8 << true; - QTest::newRow("( ,ol)leH|words") - << standard[3] << 6 << 10 << QDeclarativeTextEdit::SelectWords << 7 << 13 << true; - QTest::newRow(",(ol)leH,|words") + QTest::newRow("olleH|words") + << standard[3] << 6 << 8 << QDeclarativeTextEdit::SelectWords << 1 << 8 << false; + QTest::newRow("dlrow<( ,)>olleH|words,reversed") + << standard[3] << 8 << 6 << QDeclarativeTextEdit::SelectWords << 6 << 8 << false; + QTest::newRow("|words") + << standard[3] << 6 << 10 << QDeclarativeTextEdit::SelectWords << 1 << 13 << false; + QTest::newRow("dlrow<( ,ol)leH>|words,reversed") + << standard[3] << 10 << 6 << QDeclarativeTextEdit::SelectWords << 6 << 13 << false; + QTest::newRow(",<(ol)leH>,|words") << standard[3] << 8 << 10 << QDeclarativeTextEdit::SelectWords << 8 << 13 << true; - QTest::newRow(",()olleH|words") + QTest::newRow(",<()>olleH|words") << standard[3] << 8 << 8 << QDeclarativeTextEdit::SelectWords << 8 << 8 << true; - QTest::newRow("(),olleH|words") + QTest::newRow("<()>,olleH|words") << standard[3] << 7 << 7 << QDeclarativeTextEdit::SelectWords << 7 << 7 << true; - QTest::newRow("( ),olleH|words") - << standard[3] << 6 << 7 << QDeclarativeTextEdit::SelectWords << 7 << 7 << false; - QTest::newRow("( ),olleH|words,reversed") - << standard[3] << 7 << 6 << QDeclarativeTextEdit::SelectWords << 6 << 6 << false; - QTest::newRow("(dlrow ),olleH|words") - << standard[3] << 1 << 7 << QDeclarativeTextEdit::SelectWords << 1 << 6 << true; - QTest::newRow("(!dlrow ),olleH|words") - << standard[3] << 0 << 7 << QDeclarativeTextEdit::SelectWords << 0 << 6 << true; + QTest::newRow(",olleH|words") + << standard[3] << 6 << 7 << QDeclarativeTextEdit::SelectWords << 1 << 7 << false; + QTest::newRow("dlrow<( ),>olleH|words,reversed") + << standard[3] << 7 << 6 << QDeclarativeTextEdit::SelectWords << 6 << 8 << false; + QTest::newRow("<(dlrow )>,olleH|words") + << standard[3] << 1 << 7 << QDeclarativeTextEdit::SelectWords << 1 << 7 << false; + QTest::newRow("<(dlrow ),>olleH|words,reversed") + << standard[3] << 7 << 1 << QDeclarativeTextEdit::SelectWords << 1 << 8 << false; + QTest::newRow("<(!dlrow )>,olleH|words") + << standard[3] << 0 << 7 << QDeclarativeTextEdit::SelectWords << 0 << 7 << false; + QTest::newRow("<(!dlrow ),>olleH|words,reversed") + << standard[3] << 7 << 0 << QDeclarativeTextEdit::SelectWords << 0 << 8 << false; QTest::newRow("(!dlrow ,)olleH|words") << standard[3] << 0 << 8 << QDeclarativeTextEdit::SelectWords << 0 << 8 << true; - QTest::newRow("(!)dlrow|words") + QTest::newRow("<(!)>dlrow|words") << standard[3] << 0 << 1 << QDeclarativeTextEdit::SelectWords << 0 << 1 << true; - QTest::newRow("()!dlrow|words") + QTest::newRow("<()>!dlrow|words") << standard[3] << 0 << 0 << QDeclarativeTextEdit::SelectWords << 0 << 0 << true; - QTest::newRow("!()dlrow|words") + QTest::newRow("!<()>dlrow|words") << standard[3] << 1 << 1 << QDeclarativeTextEdit::SelectWords << 1 << 1 << true; } @@ -893,6 +919,7 @@ void tst_qdeclarativetextedit::moveCursorSelection() texteditObject->setCursorPosition(cursorPosition); texteditObject->moveCursorSelection(movePosition, mode); + QCOMPARE(texteditObject->selectedText(), testStr.mid(selectionStart, selectionEnd - selectionStart)); QCOMPARE(texteditObject->selectionStart(), selectionStart); QCOMPARE(texteditObject->selectionEnd(), selectionEnd); @@ -900,11 +927,168 @@ void tst_qdeclarativetextedit::moveCursorSelection() texteditObject->setCursorPosition(movePosition); texteditObject->moveCursorSelection(cursorPosition, mode); + QCOMPARE(texteditObject->selectedText(), testStr.mid(selectionStart, selectionEnd - selectionStart)); QCOMPARE(texteditObject->selectionStart(), selectionStart); QCOMPARE(texteditObject->selectionEnd(), selectionEnd); } } +void tst_qdeclarativetextedit::moveCursorSelectionSequence_data() +{ + QTest::addColumn("testStr"); + QTest::addColumn("cursorPosition"); + QTest::addColumn("movePosition1"); + QTest::addColumn("movePosition2"); + QTest::addColumn("selection1Start"); + QTest::addColumn("selection1End"); + QTest::addColumn("selection2Start"); + QTest::addColumn("selection2End"); + + QTest::newRow("the { f^ox} jumped|ltr") + << standard[0] + << 9 << 13 << 17 + << 4 << 15 + << 4 << 19; + QTest::newRow("the quick<( {bro)wn> f^ox} jumped|rtl") + << standard[0] + << 13 << 9 << 17 + << 9 << 15 + << 10 << 19; + QTest::newRow("the { ^}fox jumped|ltr") + << standard[0] + << 9 << 13 << 16 + << 4 << 15 + << 4 << 16; + QTest::newRow("the quick<( {bro)wn> ^}fox jumped|rtl") + << standard[0] + << 13 << 9 << 16 + << 9 << 15 + << 10 << 16; + QTest::newRow("the {} fox jumped|ltr") + << standard[0] + << 9 << 13 << 15 + << 4 << 15 + << 4 << 15; + QTest::newRow("the quick<( {bro)wn^>} f^ox jumped|rtl") + << standard[0] + << 13 << 9 << 15 + << 9 << 15 + << 10 << 15; + QTest::newRow("the { fox|ltr") + << standard[0] + << 9 << 13 << 10 + << 4 << 15 + << 4 << 10; + QTest::newRow("the quick<(^ {^bro)wn>} fox|rtl") + << standard[0] + << 13 << 9 << 10 + << 9 << 15 + << 10 << 15; + QTest::newRow("the { fox|ltr") + << standard[0] + << 9 << 13 << 9 + << 4 << 15 + << 4 << 9; + QTest::newRow("the quick{<(^ bro)wn>} fox|rtl") + << standard[0] + << 13 << 9 << 9 + << 9 << 15 + << 9 << 15; + QTest::newRow("the { fox|ltr") + << standard[0] + << 9 << 13 << 7 + << 4 << 15 + << 4 << 9; + QTest::newRow("the { fox|rtl") + << standard[0] + << 13 << 9 << 7 + << 9 << 15 + << 4 << 15; + QTest::newRow("the {<^quick}( bro)wn> fox|ltr") + << standard[0] + << 9 << 13 << 4 + << 4 << 15 + << 4 << 9; + QTest::newRow("the {<^quick}( bro)wn> fox|rtl") + << standard[0] + << 13 << 9 << 4 + << 9 << 15 + << 4 << 15; + QTest::newRow("the{^ fox|ltr") + << standard[0] + << 9 << 13 << 3 + << 4 << 15 + << 3 << 9; + QTest::newRow("the{^ fox|rtl") + << standard[0] + << 13 << 9 << 3 + << 9 << 15 + << 3 << 15; + QTest::newRow("{t^he fox|ltr") + << standard[0] + << 9 << 13 << 1 + << 4 << 15 + << 0 << 9; + QTest::newRow("{t^he fox|rtl") + << standard[0] + << 13 << 9 << 1 + << 9 << 15 + << 0 << 15; + + QTest::newRow("{, w^orld}!|ltr") + << standard[2] + << 2 << 4 << 8 + << 0 << 5 + << 0 << 12; + QTest::newRow("{, w^orld}!|rtl") + << standard[2] + << 4 << 2 << 8 + << 0 << 5 + << 0 << 12; + + QTest::newRow("!{dlro^w ,}|ltr") + << standard[3] + << 9 << 11 << 5 + << 8 << 13 + << 1 << 13; + QTest::newRow("!{dlro^w ,}|rtl") + << standard[3] + << 11 << 9 << 5 + << 8 << 13 + << 1 << 13; +} + +void tst_qdeclarativetextedit::moveCursorSelectionSequence() +{ + QFETCH(QString, testStr); + QFETCH(int, cursorPosition); + QFETCH(int, movePosition1); + QFETCH(int, movePosition2); + QFETCH(int, selection1Start); + QFETCH(int, selection1End); + QFETCH(int, selection2Start); + QFETCH(int, selection2End); + + QString componentStr = "import QtQuick 1.1\nTextEdit { text: \""+ testStr +"\"; }"; + QDeclarativeComponent texteditComponent(&engine); + texteditComponent.setData(componentStr.toLatin1(), QUrl()); + QDeclarativeTextEdit *texteditObject = qobject_cast(texteditComponent.create()); + QVERIFY(texteditObject != 0); + + texteditObject->setCursorPosition(cursorPosition); + + texteditObject->moveCursorSelection(movePosition1, QDeclarativeTextEdit::SelectWords); + QCOMPARE(texteditObject->selectedText(), testStr.mid(selection1Start, selection1End - selection1Start)); + QCOMPARE(texteditObject->selectionStart(), selection1Start); + QCOMPARE(texteditObject->selectionEnd(), selection1End); + + texteditObject->moveCursorSelection(movePosition2, QDeclarativeTextEdit::SelectWords); + QCOMPARE(texteditObject->selectedText(), testStr.mid(selection2Start, selection2End - selection2Start)); + QCOMPARE(texteditObject->selectionStart(), selection2Start); + QCOMPARE(texteditObject->selectionEnd(), selection2End); +} + + void tst_qdeclarativetextedit::mouseSelection_data() { QTest::addColumn("qmlfile"); @@ -995,6 +1179,55 @@ void tst_qdeclarativetextedit::dragMouseSelection() QVERIFY(str1 != str2); // Verify the second press and drag is a new selection and doesn't not the first moved. } +void tst_qdeclarativetextedit::mouseSelectionMode_data() +{ + QTest::addColumn("qmlfile"); + QTest::addColumn("selectWords"); + + // import installed + QTest::newRow("SelectWords") << SRCDIR "/data/mouseselectionmode_words.qml" << true; + QTest::newRow("SelectCharacters") << SRCDIR "/data/mouseselectionmode_characters.qml" << false; + QTest::newRow("default") << SRCDIR "/data/mouseselectionmode_default.qml" << false; +} + +void tst_qdeclarativetextedit::mouseSelectionMode() +{ + QFETCH(QString, qmlfile); + QFETCH(bool, selectWords); + + QString text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + QDeclarativeView *canvas = createView(qmlfile); + + canvas->show(); + QApplication::setActiveWindow(canvas); + QTest::qWaitForWindowShown(canvas); + QTRY_COMPARE(QApplication::activeWindow(), static_cast(canvas)); + + QVERIFY(canvas->rootObject() != 0); + QDeclarativeTextEdit *textEditObject = qobject_cast(canvas->rootObject()); + QVERIFY(textEditObject != 0); + + // press-and-drag-and-release from x1 to x2 + int x1 = 10; + int x2 = 70; + int y = textEditObject->height()/2; + QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y))); + //QTest::mouseMove(canvas->viewport(), canvas->mapFromScene(QPoint(x2,y))); // doesn't work + QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(canvas->viewport(), &mv); + QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y))); + QString str = textEditObject->selectedText(); + if (selectWords) { + QCOMPARE(str, text); + } else { + QVERIFY(str.length() > 3); + QVERIFY(str != text); + } + + delete canvas; +} + void tst_qdeclarativetextedit::inputMethodHints() { QDeclarativeView *canvas = createView(SRCDIR "/data/inputmethodhints.qml"); diff --git a/tests/auto/declarative/qdeclarativetextinput/data/mouseselectionmode_characters.qml b/tests/auto/declarative/qdeclarativetextinput/data/mouseselectionmode_characters.qml new file mode 100644 index 0000000..0ffc6ff --- /dev/null +++ b/tests/auto/declarative/qdeclarativetextinput/data/mouseselectionmode_characters.qml @@ -0,0 +1,8 @@ +import QtQuick 1.1 + +TextInput { + focus: true + text: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + selectByMouse: true + mouseSelectionMode: TextInput.SelectCharacters +} diff --git a/tests/auto/declarative/qdeclarativetextinput/data/mouseselectionmode_default.qml b/tests/auto/declarative/qdeclarativetextinput/data/mouseselectionmode_default.qml new file mode 100644 index 0000000..87c174b --- /dev/null +++ b/tests/auto/declarative/qdeclarativetextinput/data/mouseselectionmode_default.qml @@ -0,0 +1,7 @@ +import QtQuick 1.1 + +TextInput { + focus: true + text: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + selectByMouse: true +} diff --git a/tests/auto/declarative/qdeclarativetextinput/data/mouseselectionmode_words.qml b/tests/auto/declarative/qdeclarativetextinput/data/mouseselectionmode_words.qml new file mode 100644 index 0000000..df69a7d --- /dev/null +++ b/tests/auto/declarative/qdeclarativetextinput/data/mouseselectionmode_words.qml @@ -0,0 +1,8 @@ +import QtQuick 1.1 + +TextInput { + focus: true + text: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + selectByMouse: true + mouseSelectionMode: TextInput.SelectWords +} diff --git a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp index 7cdec27..675367c 100644 --- a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp +++ b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp @@ -91,7 +91,11 @@ private slots: void selection(); void moveCursorSelection_data(); void moveCursorSelection(); + void moveCursorSelectionSequence_data(); + void moveCursorSelectionSequence(); void dragMouseSelection(); + void mouseSelectionMode_data(); + void mouseSelectionMode(); void horizontalAlignment_data(); void horizontalAlignment(); @@ -462,91 +466,115 @@ void tst_qdeclarativetextinput::moveCursorSelection_data() QTest::newRow("jum()ped|characters") << standard[0] << 23 << 23 << QDeclarativeTextInput::SelectCharacters << 23 << 23 << true; - QTest::newRow("(t)he|words") + QTest::newRow("<(t)he>|words") << standard[0] << 0 << 1 << QDeclarativeTextInput::SelectWords << 0 << 3 << true; - QTest::newRow("do(g)|words") + QTest::newRow("|words") << standard[0] << 43 << 44 << QDeclarativeTextInput::SelectWords << 41 << 44 << true; - QTest::newRow("jum(p)ed|words") + QTest::newRow("|words") << standard[0] << 23 << 24 << QDeclarativeTextInput::SelectWords << 20 << 26 << true; - QTest::newRow("jumped( )over|words") - << standard[0] << 26 << 27 << QDeclarativeTextInput::SelectWords << 27 << 27 << false; - QTest::newRow("jumped( )over|words,reversed") - << standard[0] << 27 << 26 << QDeclarativeTextInput::SelectWords << 26 << 26 << false; - QTest::newRow("(the )|words") - << standard[0] << 0 << 4 << QDeclarativeTextInput::SelectWords << 0 << 3 << true; - QTest::newRow("( dog)|words") - << standard[0] << 40 << 44 << QDeclarativeTextInput::SelectWords << 41 << 44 << true; - QTest::newRow("( jumped )|words") - << standard[0] << 19 << 27 << QDeclarativeTextInput::SelectWords << 20 << 26 << true; - QTest::newRow("th(e qu)ick|words") + QTest::newRow("over|words,ltr") + << standard[0] << 26 << 27 << QDeclarativeTextInput::SelectWords << 20 << 27 << false; + QTest::newRow("jumped<( )over>|words,rtl") + << standard[0] << 27 << 26 << QDeclarativeTextInput::SelectWords << 26 << 31 << false; + QTest::newRow("<(the )>quick|words,ltr") + << standard[0] << 0 << 4 << QDeclarativeTextInput::SelectWords << 0 << 4 << false; + QTest::newRow("<(the )quick>|words,rtl") + << standard[0] << 4 << 0 << QDeclarativeTextInput::SelectWords << 0 << 9 << false; + QTest::newRow("|words,ltr") + << standard[0] << 40 << 44 << QDeclarativeTextInput::SelectWords << 36 << 44 << false; + QTest::newRow("lazy<( dog)>|words,rtl") + << standard[0] << 44 << 40 << QDeclarativeTextInput::SelectWords << 40 << 44 << false; + QTest::newRow("over|words,ltr") + << standard[0] << 19 << 27 << QDeclarativeTextInput::SelectWords << 16 << 27 << false; + QTest::newRow("fox<( jumped )over>|words,rtl") + << standard[0] << 27 << 19 << QDeclarativeTextInput::SelectWords << 19 << 31 << false; + QTest::newRow("|words") << standard[0] << 2 << 6 << QDeclarativeTextInput::SelectWords << 0 << 9 << true; - QTest::newRow("la(zy d)og|words") + QTest::newRow("") << standard[0] << 38 << 42 << QDeclarativeTextInput::SelectWords << 36 << 44 << true; - QTest::newRow("jum(ped ov)er|words") + QTest::newRow("|words") << standard[0] << 23 << 29 << QDeclarativeTextInput::SelectWords << 20 << 31 << true; - QTest::newRow("()the|words") + QTest::newRow("<()>the|words") << standard[0] << 0 << 0 << QDeclarativeTextInput::SelectWords << 0 << 0 << true; - QTest::newRow("dog()|words") + QTest::newRow("dog<()>|words") << standard[0] << 44 << 44 << QDeclarativeTextInput::SelectWords << 44 << 44 << true; - QTest::newRow("jum()ped|words") + QTest::newRow("jum<()>ped|words") << standard[0] << 23 << 23 << QDeclarativeTextInput::SelectWords << 23 << 23 << true; - QTest::newRow("Hello(,) |words") + QTest::newRow("Hello<(,)> |words") << standard[2] << 5 << 6 << QDeclarativeTextInput::SelectWords << 5 << 6 << true; - QTest::newRow("Hello(, )|words") - << standard[2] << 5 << 7 << QDeclarativeTextInput::SelectWords << 5 << 6 << true; - QTest::newRow("Hel(lo, )|words") - << standard[2] << 3 << 7 << QDeclarativeTextInput::SelectWords << 0 << 6 << true; - QTest::newRow("Hel(lo),|words") + QTest::newRow("Hello<(, )>world|words,ltr") + << standard[2] << 5 << 7 << QDeclarativeTextInput::SelectWords << 5 << 7 << false; + QTest::newRow("Hello<(, )world>|words,rtl") + << standard[2] << 7 << 5 << QDeclarativeTextInput::SelectWords << 5 << 12 << false; + QTest::newRow("world|words,ltr") + << standard[2] << 3 << 7 << QDeclarativeTextInput::SelectWords << 0 << 7 << false; + QTest::newRow("|words,rtl") + << standard[2] << 7 << 3 << QDeclarativeTextInput::SelectWords << 0 << 12 << false; + QTest::newRow(",|words") << standard[2] << 3 << 5 << QDeclarativeTextInput::SelectWords << 0 << 5 << true; - QTest::newRow("Hello(),|words") + QTest::newRow("Hello<()>,|words") << standard[2] << 5 << 5 << QDeclarativeTextInput::SelectWords << 5 << 5 << true; - QTest::newRow("Hello,()|words") + QTest::newRow("Hello,<()>|words") << standard[2] << 6 << 6 << QDeclarativeTextInput::SelectWords << 6 << 6 << true; - QTest::newRow("Hello,( )|words") - << standard[2] << 6 << 7 << QDeclarativeTextInput::SelectWords << 7 << 7 << false; - QTest::newRow("Hello,( )|words,reversed") - << standard[2] << 7 << 6 << QDeclarativeTextInput::SelectWords << 6 << 6 << false; - QTest::newRow("Hello,( world)|words") - << standard[2] << 6 << 12 << QDeclarativeTextInput::SelectWords << 7 << 12 << true; - QTest::newRow("Hello,( world!)|words") - << standard[2] << 6 << 13 << QDeclarativeTextInput::SelectWords << 7 << 13 << true; - QTest::newRow("Hello(, world!)|words") + QTest::newRow("Hello<,( )>world|words,ltr") + << standard[2] << 6 << 7 << QDeclarativeTextInput::SelectWords << 5 << 7 << false; + QTest::newRow("Hello,<( )world>|words,rtl") + << standard[2] << 7 << 6 << QDeclarativeTextInput::SelectWords << 6 << 12 << false; + QTest::newRow("Hello<,( world)>|words,ltr") + << standard[2] << 6 << 12 << QDeclarativeTextInput::SelectWords << 5 << 12 << false; + QTest::newRow("Hello,<( world)>|words,rtl") + << standard[2] << 12 << 6 << QDeclarativeTextInput::SelectWords << 6 << 12 << false; + QTest::newRow("Hello<,( world!)>|words,ltr") + << standard[2] << 6 << 13 << QDeclarativeTextInput::SelectWords << 5 << 13 << false; + QTest::newRow("Hello,<( world!)>|words,rtl") + << standard[2] << 13 << 6 << QDeclarativeTextInput::SelectWords << 6 << 13 << false; + QTest::newRow("Hello<(, world!)>|words") << standard[2] << 5 << 13 << QDeclarativeTextInput::SelectWords << 5 << 13 << true; - QTest::newRow("world(!)|words") - << standard[2] << 12 << 13 << QDeclarativeTextInput::SelectWords << 12 << 13 << true; - QTest::newRow("world!())|words") + // Fails due to an issue with QTextBoundaryFinder and punctuation at the end of strings. + // QTBUG-11365 + // QTest::newRow("world<(!)>|words") + // << standard[2] << 12 << 13 << QDeclarativeTextInput::SelectWords << 12 << 13 << true; + QTest::newRow("world!<()>)|words") << standard[2] << 13 << 13 << QDeclarativeTextInput::SelectWords << 13 << 13 << true; - QTest::newRow("world()!)|words") + QTest::newRow("world<()>!)|words") << standard[2] << 12 << 12 << QDeclarativeTextInput::SelectWords << 12 << 12 << true; - QTest::newRow("(,)olleH |words") + QTest::newRow("<(,)>olleH |words") << standard[3] << 7 << 8 << QDeclarativeTextInput::SelectWords << 7 << 8 << true; - QTest::newRow("( ,)olleH|words") - << standard[3] << 6 << 8 << QDeclarativeTextInput::SelectWords << 7 << 8 << true; - QTest::newRow("( ,ol)leH|words") - << standard[3] << 6 << 10 << QDeclarativeTextInput::SelectWords << 7 << 13 << true; - QTest::newRow(",(ol)leH,|words") + QTest::newRow("olleH|words,ltr") + << standard[3] << 6 << 8 << QDeclarativeTextInput::SelectWords << 1 << 8 << false; + QTest::newRow("dlrow<( ,)>olleH|words,rtl") + << standard[3] << 8 << 6 << QDeclarativeTextInput::SelectWords << 6 << 8 << false; + QTest::newRow("|words,ltr") + << standard[3] << 6 << 10 << QDeclarativeTextInput::SelectWords << 1 << 13 << false; + QTest::newRow("dlrow<( ,ol)leH>|words,rtl") + << standard[3] << 10 << 6 << QDeclarativeTextInput::SelectWords << 6 << 13 << false; + QTest::newRow(",<(ol)leH>,|words") << standard[3] << 8 << 10 << QDeclarativeTextInput::SelectWords << 8 << 13 << true; - QTest::newRow(",()olleH|words") + QTest::newRow(",<()>olleH|words") << standard[3] << 8 << 8 << QDeclarativeTextInput::SelectWords << 8 << 8 << true; - QTest::newRow("(),olleH|words") + QTest::newRow("<()>,olleH|words") << standard[3] << 7 << 7 << QDeclarativeTextInput::SelectWords << 7 << 7 << true; - QTest::newRow("( ),olleH|words") - << standard[3] << 6 << 7 << QDeclarativeTextInput::SelectWords << 7 << 7 << false; - QTest::newRow("( ),olleH|words,reversed") - << standard[3] << 7 << 6 << QDeclarativeTextInput::SelectWords << 6 << 6 << false; - QTest::newRow("(dlrow ),olleH|words") - << standard[3] << 1 << 7 << QDeclarativeTextInput::SelectWords << 1 << 6 << true; - QTest::newRow("(!dlrow ),olleH|words") - << standard[3] << 0 << 7 << QDeclarativeTextInput::SelectWords << 0 << 6 << true; + QTest::newRow(",olleH|words,ltr") + << standard[3] << 6 << 7 << QDeclarativeTextInput::SelectWords << 1 << 7 << false; + QTest::newRow("dlrow<( ),>olleH|words,rtl") + << standard[3] << 7 << 6 << QDeclarativeTextInput::SelectWords << 6 << 8 << false; + QTest::newRow("<(dlrow )>,olleH|words,ltr") + << standard[3] << 1 << 7 << QDeclarativeTextInput::SelectWords << 1 << 7 << false; + QTest::newRow("<(dlrow ),>olleH|words,rtl") + << standard[3] << 7 << 1 << QDeclarativeTextInput::SelectWords << 1 << 8 << false; + QTest::newRow("<(!dlrow )>,olleH|words,ltr") + << standard[3] << 0 << 7 << QDeclarativeTextInput::SelectWords << 0 << 7 << false; + QTest::newRow("<(!dlrow ),>olleH|words,rtl") + << standard[3] << 7 << 0 << QDeclarativeTextInput::SelectWords << 0 << 8 << false; QTest::newRow("(!dlrow ,)olleH|words") << standard[3] << 0 << 8 << QDeclarativeTextInput::SelectWords << 0 << 8 << true; - QTest::newRow("(!)dlrow|words") + QTest::newRow("<(!)>dlrow|words") << standard[3] << 0 << 1 << QDeclarativeTextInput::SelectWords << 0 << 1 << true; - QTest::newRow("()!dlrow|words") + QTest::newRow("<()>!dlrow|words") << standard[3] << 0 << 0 << QDeclarativeTextInput::SelectWords << 0 << 0 << true; - QTest::newRow("!()dlrow|words") + QTest::newRow("!<()>dlrow|words") << standard[3] << 1 << 1 << QDeclarativeTextInput::SelectWords << 1 << 1 << true; } @@ -569,6 +597,7 @@ void tst_qdeclarativetextinput::moveCursorSelection() textinputObject->setCursorPosition(cursorPosition); textinputObject->moveCursorSelection(movePosition, mode); + QCOMPARE(textinputObject->selectedText(), testStr.mid(selectionStart, selectionEnd - selectionStart)); QCOMPARE(textinputObject->selectionStart(), selectionStart); QCOMPARE(textinputObject->selectionEnd(), selectionEnd); @@ -576,11 +605,167 @@ void tst_qdeclarativetextinput::moveCursorSelection() textinputObject->setCursorPosition(movePosition); textinputObject->moveCursorSelection(cursorPosition, mode); + QCOMPARE(textinputObject->selectedText(), testStr.mid(selectionStart, selectionEnd - selectionStart)); QCOMPARE(textinputObject->selectionStart(), selectionStart); QCOMPARE(textinputObject->selectionEnd(), selectionEnd); } } +void tst_qdeclarativetextinput::moveCursorSelectionSequence_data() +{ + QTest::addColumn("testStr"); + QTest::addColumn("cursorPosition"); + QTest::addColumn("movePosition1"); + QTest::addColumn("movePosition2"); + QTest::addColumn("selection1Start"); + QTest::addColumn("selection1End"); + QTest::addColumn("selection2Start"); + QTest::addColumn("selection2End"); + + QTest::newRow("the { f^ox} jumped|ltr") + << standard[0] + << 9 << 13 << 17 + << 4 << 15 + << 4 << 19; + QTest::newRow("the quick<( {bro)wn> f^ox} jumped|rtl") + << standard[0] + << 13 << 9 << 17 + << 9 << 15 + << 10 << 19; + QTest::newRow("the { ^}fox jumped|ltr") + << standard[0] + << 9 << 13 << 16 + << 4 << 15 + << 4 << 16; + QTest::newRow("the quick<( {bro)wn> ^}fox jumped|rtl") + << standard[0] + << 13 << 9 << 16 + << 9 << 15 + << 10 << 16; + QTest::newRow("the {} fox jumped|ltr") + << standard[0] + << 9 << 13 << 15 + << 4 << 15 + << 4 << 15; + QTest::newRow("the quick<( {bro)wn^>} f^ox jumped|rtl") + << standard[0] + << 13 << 9 << 15 + << 9 << 15 + << 10 << 15; + QTest::newRow("the { fox|ltr") + << standard[0] + << 9 << 13 << 10 + << 4 << 15 + << 4 << 10; + QTest::newRow("the quick<( {^bro)wn>} fox|rtl") + << standard[0] + << 13 << 9 << 10 + << 9 << 15 + << 10 << 15; + QTest::newRow("the { fox|ltr") + << standard[0] + << 9 << 13 << 9 + << 4 << 15 + << 4 << 9; + QTest::newRow("the quick{<(^ bro)wn>} fox|rtl") + << standard[0] + << 13 << 9 << 9 + << 9 << 15 + << 9 << 15; + QTest::newRow("the { fox|ltr") + << standard[0] + << 9 << 13 << 7 + << 4 << 15 + << 4 << 9; + QTest::newRow("the { fox|rtl") + << standard[0] + << 13 << 9 << 7 + << 9 << 15 + << 4 << 15; + QTest::newRow("the {<^quick}( bro)wn> fox|ltr") + << standard[0] + << 9 << 13 << 4 + << 4 << 15 + << 4 << 9; + QTest::newRow("the {<^quick}( bro)wn> fox|rtl") + << standard[0] + << 13 << 9 << 4 + << 9 << 15 + << 4 << 15; + QTest::newRow("the{^ fox|ltr") + << standard[0] + << 9 << 13 << 3 + << 4 << 15 + << 3 << 9; + QTest::newRow("the{^ fox|rtl") + << standard[0] + << 13 << 9 << 3 + << 9 << 15 + << 3 << 15; + QTest::newRow("{t^he fox|ltr") + << standard[0] + << 9 << 13 << 1 + << 4 << 15 + << 0 << 9; + QTest::newRow("{t^he fox|rtl") + << standard[0] + << 13 << 9 << 1 + << 9 << 15 + << 0 << 15; + + QTest::newRow("{, w^orld}!|ltr") + << standard[2] + << 2 << 4 << 8 + << 0 << 5 + << 0 << 12; + QTest::newRow("{, w^orld}!|rtl") + << standard[2] + << 4 << 2 << 8 + << 0 << 5 + << 0 << 12; + + QTest::newRow("!{dlro^w ,}|ltr") + << standard[3] + << 9 << 11 << 5 + << 8 << 13 + << 1 << 13; + QTest::newRow("!{dlro^w ,}|rtl") + << standard[3] + << 11 << 9 << 5 + << 8 << 13 + << 1 << 13; +} + +void tst_qdeclarativetextinput::moveCursorSelectionSequence() +{ + QFETCH(QString, testStr); + QFETCH(int, cursorPosition); + QFETCH(int, movePosition1); + QFETCH(int, movePosition2); + QFETCH(int, selection1Start); + QFETCH(int, selection1End); + QFETCH(int, selection2Start); + QFETCH(int, selection2End); + + QString componentStr = "import QtQuick 1.1\nTextInput { text: \""+ testStr +"\"; }"; + QDeclarativeComponent textinputComponent(&engine); + textinputComponent.setData(componentStr.toLatin1(), QUrl()); + QDeclarativeTextInput *textinputObject = qobject_cast(textinputComponent.create()); + QVERIFY(textinputObject != 0); + + textinputObject->setCursorPosition(cursorPosition); + + textinputObject->moveCursorSelection(movePosition1, QDeclarativeTextInput::SelectWords); + QCOMPARE(textinputObject->selectedText(), testStr.mid(selection1Start, selection1End - selection1Start)); + QCOMPARE(textinputObject->selectionStart(), selection1Start); + QCOMPARE(textinputObject->selectionEnd(), selection1End); + + textinputObject->moveCursorSelection(movePosition2, QDeclarativeTextInput::SelectWords); + QCOMPARE(textinputObject->selectedText(), testStr.mid(selection2Start, selection2End - selection2Start)); + QCOMPARE(textinputObject->selectionStart(), selection2Start); + QCOMPARE(textinputObject->selectionEnd(), selection2End); +} + void tst_qdeclarativetextinput::dragMouseSelection() { QString qmlfile = SRCDIR "/data/mouseselection_true.qml"; @@ -626,6 +811,55 @@ void tst_qdeclarativetextinput::dragMouseSelection() delete canvas; } +void tst_qdeclarativetextinput::mouseSelectionMode_data() +{ + QTest::addColumn("qmlfile"); + QTest::addColumn("selectWords"); + + // import installed + QTest::newRow("SelectWords") << SRCDIR "/data/mouseselectionmode_words.qml" << true; + QTest::newRow("SelectCharacters") << SRCDIR "/data/mouseselectionmode_characters.qml" << false; + QTest::newRow("default") << SRCDIR "/data/mouseselectionmode_default.qml" << false; +} + +void tst_qdeclarativetextinput::mouseSelectionMode() +{ + QFETCH(QString, qmlfile); + QFETCH(bool, selectWords); + + QString text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + QDeclarativeView *canvas = createView(qmlfile); + + canvas->show(); + QApplication::setActiveWindow(canvas); + QTest::qWaitForWindowShown(canvas); + QTRY_COMPARE(QApplication::activeWindow(), static_cast(canvas)); + + QVERIFY(canvas->rootObject() != 0); + QDeclarativeTextInput *textInputObject = qobject_cast(canvas->rootObject()); + QVERIFY(textInputObject != 0); + + // press-and-drag-and-release from x1 to x2 + int x1 = 10; + int x2 = 70; + int y = textInputObject->height()/2; + QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x1,y))); + //QTest::mouseMove(canvas->viewport(), canvas->mapFromScene(QPoint(x2,y))); // doesn't work + QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(x2,y)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(canvas->viewport(), &mv); + QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(x2,y))); + QString str = textInputObject->selectedText(); + if (selectWords) { + QCOMPARE(str, text); + } else { + QVERIFY(str.length() > 3); + QVERIFY(str != text); + } + + delete canvas; +} + void tst_qdeclarativetextinput::horizontalAlignment_data() { QTest::addColumn("hAlign"); -- cgit v0.12 From fc7f72b663ec934d2d7e41645cb3ca94b96ae6d6 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Tue, 1 Feb 2011 11:23:53 +1000 Subject: Clarify that IntValidator performs locale specific validation. Task-number: QTBUG-16873 Reviewed-by: Martin Jones --- src/declarative/graphicsitems/qdeclarativetextinput.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/declarative/graphicsitems/qdeclarativetextinput.cpp b/src/declarative/graphicsitems/qdeclarativetextinput.cpp index 9e62291..012d408 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextinput.cpp @@ -613,6 +613,11 @@ void QDeclarativeTextInput::setAutoScroll(bool b) \ingroup qml-basic-visual-elements This element provides a validator for integer values. + + IntValidator uses the \l {QLocale::setDefault()}{default locale} to interpret the number and + will accept locale specific digits, group separators, and positive and negative signs. In + addition, IntValidator is always guaranteed to accept a number formatted according to the "C" + locale. */ /*! \qmlproperty int IntValidator::top -- cgit v0.12 From c7c2036d6f5136dd2dd000258f0e49cd155fe072 Mon Sep 17 00:00:00 2001 From: juhvu Date: Tue, 1 Feb 2011 11:58:37 +1000 Subject: Froze Symbian def files for QtQuick11. Reviewed-by: Martin Jones --- src/s60installs/bwins/QtCoreu.def | 2 + src/s60installs/bwins/QtDeclarativeu.def | 119 +++++++++++++++++++--------- src/s60installs/bwins/QtGuiu.def | 40 ++++++++++ src/s60installs/bwins/QtScriptu.def | 2 + src/s60installs/eabi/QtCoreu.def | 2 + src/s60installs/eabi/QtDeclarativeu.def | 128 ++++++++++++++++++++----------- src/s60installs/eabi/QtGuiu.def | 35 +++++++++ src/s60installs/eabi/QtScriptu.def | 2 + tools/qml/qdeclarativetester.cpp | 5 ++ 9 files changed, 251 insertions(+), 84 deletions(-) diff --git a/src/s60installs/bwins/QtCoreu.def b/src/s60installs/bwins/QtCoreu.def index 872142d..b82f6e5 100644 --- a/src/s60installs/bwins/QtCoreu.def +++ b/src/s60installs/bwins/QtCoreu.def @@ -4487,4 +4487,6 @@ EXPORTS ?queueDeferredActiveObjectsCompletion@QEventDispatcherSymbian@@QAEXXZ @ 4486 NONAME ; void QEventDispatcherSymbian::queueDeferredActiveObjectsCompletion(void) ?reactivateDeferredActiveObjects@QEventDispatcherSymbian@@UAEXXZ @ 4487 NONAME ; void QEventDispatcherSymbian::reactivateDeferredActiveObjects(void) ?symbianCommandLine@QCoreApplicationPrivate@@SAPAVCApaCommandLine@@XZ @ 4488 NONAME ; class CApaCommandLine * QCoreApplicationPrivate::symbianCommandLine(void) + ?revision@QMetaProperty@@QBEHXZ @ 4489 NONAME ; int QMetaProperty::revision(void) const + ?revision@QMetaMethod@@QBEHXZ @ 4490 NONAME ; int QMetaMethod::revision(void) const diff --git a/src/s60installs/bwins/QtDeclarativeu.def b/src/s60installs/bwins/QtDeclarativeu.def index 9e88df7..a287def 100644 --- a/src/s60installs/bwins/QtDeclarativeu.def +++ b/src/s60installs/bwins/QtDeclarativeu.def @@ -52,7 +52,7 @@ EXPORTS ?isDesignable@QMetaPropertyBuilder@@QBE_NXZ @ 51 NONAME ABSENT ; bool QMetaPropertyBuilder::isDesignable(void) const ?tr@QDeclarativeStateGroup@@SA?AVQString@@PBD0H@Z @ 52 NONAME ; class QString QDeclarativeStateGroup::tr(char const *, char const *, int) ?errors@QDeclarativeView@@QBE?AV?$QList@VQDeclarativeError@@@@XZ @ 53 NONAME ; class QList QDeclarativeView::errors(void) const - ??0QPacket@@QAE@ABV0@@Z @ 54 NONAME ABSENT ; QPacket::QPacket(class QPacket const &) + ??0QPacket@@QAE@ABV0@@Z @ 54 NONAME ; QPacket::QPacket(class QPacket const &) ??1QDeclarativeDebugObjectExpressionWatch@@UAE@XZ @ 55 NONAME ABSENT ; QDeclarativeDebugObjectExpressionWatch::~QDeclarativeDebugObjectExpressionWatch(void) ?status@QDeclarativePixmap@@QBE?AW4Status@1@XZ @ 56 NONAME ; enum QDeclarativePixmap::Status QDeclarativePixmap::status(void) const ?bottom@QDeclarativeAnchors@@QBE?AVQDeclarativeAnchorLine@@XZ @ 57 NONAME ABSENT ; class QDeclarativeAnchorLine QDeclarativeAnchors::bottom(void) const @@ -69,7 +69,7 @@ EXPORTS ??0Variant@QDeclarativeParser@@QAE@ABVQString@@@Z @ 68 NONAME ; QDeclarativeParser::Variant::Variant(class QString const &) ?paintedSizeChanged@QDeclarativeText@@IAEXXZ @ 69 NONAME ABSENT ; void QDeclarativeText::paintedSizeChanged(void) ??1QDeclarativeDebugClient@@UAE@XZ @ 70 NONAME ABSENT ; QDeclarativeDebugClient::~QDeclarativeDebugClient(void) - ?trUtf8@QPacketProtocol@@SA?AVQString@@PBD0@Z @ 71 NONAME ABSENT ; class QString QPacketProtocol::trUtf8(char const *, char const *) + ?trUtf8@QPacketProtocol@@SA?AVQString@@PBD0@Z @ 71 NONAME ; class QString QPacketProtocol::trUtf8(char const *, char const *) ?trUtf8@QDeclarativeListModel@@SA?AVQString@@PBD0@Z @ 72 NONAME ABSENT ; class QString QDeclarativeListModel::trUtf8(char const *, char const *) ?qt_metacast@QDeclarativeState@@UAEPAXPBD@Z @ 73 NONAME ; void * QDeclarativeState::qt_metacast(char const *) ??1QDeclarativeDebugContextReference@@QAE@XZ @ 74 NONAME ABSENT ; QDeclarativeDebugContextReference::~QDeclarativeDebugContextReference(void) @@ -126,7 +126,7 @@ EXPORTS ?addToObject@QDeclarativeAbstractBinding@@QAEXPAVQObject@@@Z @ 125 NONAME ABSENT ; void QDeclarativeAbstractBinding::addToObject(class QObject *) ?trUtf8@QDeclarativeView@@SA?AVQString@@PBD0H@Z @ 126 NONAME ; class QString QDeclarativeView::trUtf8(char const *, char const *, int) ?d_func@QDeclarativeAnchors@@AAEPAVQDeclarativeAnchorsPrivate@@XZ @ 127 NONAME ABSENT ; class QDeclarativeAnchorsPrivate * QDeclarativeAnchors::d_func(void) - ??1QPacket@@UAE@XZ @ 128 NONAME ABSENT ; QPacket::~QPacket(void) + ??1QPacket@@UAE@XZ @ 128 NONAME ; QPacket::~QPacket(void) ?top@QDeclarativeScaleGrid@@QBEHXZ @ 129 NONAME ABSENT ; int QDeclarativeScaleGrid::top(void) const ?setExpression@QDeclarativeExpression@@QAEXABVQString@@@Z @ 130 NONAME ; void QDeclarativeExpression::setExpression(class QString const &) ??1QDeclarativeDebugEngineReference@@QAE@XZ @ 131 NONAME ABSENT ; QDeclarativeDebugEngineReference::~QDeclarativeDebugEngineReference(void) @@ -252,7 +252,7 @@ EXPORTS ??4QDeclarativeDomValueLiteral@@QAEAAV0@ABV0@@Z @ 251 NONAME ABSENT ; class QDeclarativeDomValueLiteral & QDeclarativeDomValueLiteral::operator=(class QDeclarativeDomValueLiteral const &) ?setScript@QDeclarativeScriptString@@QAEXABVQString@@@Z @ 252 NONAME ; void QDeclarativeScriptString::setScript(class QString const &) ?requestImage@QDeclarativeImageProvider@@UAE?AVQImage@@ABVQString@@PAVQSize@@ABV4@@Z @ 253 NONAME ; class QImage QDeclarativeImageProvider::requestImage(class QString const &, class QSize *, class QSize const &) - ?qt_metacast@QPacketProtocol@@UAEPAXPBD@Z @ 254 NONAME ABSENT ; void * QPacketProtocol::qt_metacast(char const *) + ?qt_metacast@QPacketProtocol@@UAEPAXPBD@Z @ 254 NONAME ; void * QPacketProtocol::qt_metacast(char const *) ?addMetaObject@QMetaObjectBuilder@@QAEXPBUQMetaObject@@V?$QFlags@W4AddMember@QMetaObjectBuilder@@@@@Z @ 255 NONAME ABSENT ; void QMetaObjectBuilder::addMetaObject(struct QMetaObject const *, class QFlags) ?trUtf8@QDeclarativeRectangle@@SA?AVQString@@PBD0H@Z @ 256 NONAME ABSENT ; class QString QDeclarativeRectangle::trUtf8(char const *, char const *, int) ?qt_metacast@QDeclarativeText@@UAEPAXPBD@Z @ 257 NONAME ABSENT ; void * QDeclarativeText::qt_metacast(char const *) @@ -263,7 +263,7 @@ EXPORTS ?create@QDeclarativeType@@QBEPAVQObject@@XZ @ 262 NONAME ABSENT ; class QObject * QDeclarativeType::create(void) const ?metaObject@QDeclarativeDebugExpressionQuery@@UBEPBUQMetaObject@@XZ @ 263 NONAME ABSENT ; struct QMetaObject const * QDeclarativeDebugExpressionQuery::metaObject(void) const ?engine@QDeclarativeView@@QBEPAVQDeclarativeEngine@@XZ @ 264 NONAME ; class QDeclarativeEngine * QDeclarativeView::engine(void) const - ?readyRead@QPacketProtocol@@IAEXXZ @ 265 NONAME ABSENT ; void QPacketProtocol::readyRead(void) + ?readyRead@QPacketProtocol@@IAEXXZ @ 265 NONAME ; void QPacketProtocol::readyRead(void) ?qt_metacall@QDeclarativeValueType@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 266 NONAME ABSENT ; int QDeclarativeValueType::qt_metacall(enum QMetaObject::Call, int, void * *) ?propertyType@QDeclarativePropertyPrivate@@QBEHXZ @ 267 NONAME ABSENT ; int QDeclarativePropertyPrivate::propertyType(void) const ?inputMethodQuery@QDeclarativeItem@@MBE?AVQVariant@@W4InputMethodQuery@Qt@@@Z @ 268 NONAME ; class QVariant QDeclarativeItem::inputMethodQuery(enum Qt::InputMethodQuery) const @@ -310,7 +310,7 @@ EXPORTS ?setSmooth@QDeclarativeItem@@QAEX_N@Z @ 309 NONAME ; void QDeclarativeItem::setSmooth(bool) ?value@QDeclarativeDebugPropertyReference@@QBE?AVQVariant@@XZ @ 310 NONAME ABSENT ; class QVariant QDeclarativeDebugPropertyReference::value(void) const ?resources@QDeclarativeItemPrivate@@QAE?AV?$QDeclarativeListProperty@VQObject@@@@XZ @ 311 NONAME ; class QDeclarativeListProperty QDeclarativeItemPrivate::resources(void) - ?clear@QPacketProtocol@@QAEXXZ @ 312 NONAME ABSENT ; void QPacketProtocol::clear(void) + ?clear@QPacketProtocol@@QAEXXZ @ 312 NONAME ; void QPacketProtocol::clear(void) ?setState@QDeclarativeItemPrivate@@QAEXABVQString@@@Z @ 313 NONAME ; void QDeclarativeItemPrivate::setState(class QString const &) ??4QDeclarativeDebugPropertyReference@@QAEAAV0@ABV0@@Z @ 314 NONAME ABSENT ; class QDeclarativeDebugPropertyReference & QDeclarativeDebugPropertyReference::operator=(class QDeclarativeDebugPropertyReference const &) ?metaObject@QDeclarativeView@@UBEPBUQMetaObject@@XZ @ 315 NONAME ; struct QMetaObject const * QDeclarativeView::metaObject(void) const @@ -377,7 +377,7 @@ EXPORTS ?status@QDeclarativeView@@QBE?AW4Status@1@XZ @ 376 NONAME ; enum QDeclarativeView::Status QDeclarativeView::status(void) const ??0QDeclarativeEngineDebug@@QAE@PAVQDeclarativeDebugConnection@@PAVQObject@@@Z @ 377 NONAME ABSENT ; QDeclarativeEngineDebug::QDeclarativeEngineDebug(class QDeclarativeDebugConnection *, class QObject *) ?create@QDeclarativeComponent@@UAEPAVQObject@@PAVQDeclarativeContext@@@Z @ 378 NONAME ; class QObject * QDeclarativeComponent::create(class QDeclarativeContext *) - ??_EQPacket@@UAE@I@Z @ 379 NONAME ABSENT ; QPacket::~QPacket(unsigned int) + ??_EQPacket@@UAE@I@Z @ 379 NONAME ; QPacket::~QPacket(unsigned int) ?trUtf8@QDeclarativeScaleGrid@@SA?AVQString@@PBD0H@Z @ 380 NONAME ABSENT ; class QString QDeclarativeScaleGrid::trUtf8(char const *, char const *, int) ?isResettable@QDeclarativeProperty@@QBE_NXZ @ 381 NONAME ; bool QDeclarativeProperty::isResettable(void) const ?isList@QDeclarativeCustomParserProperty@@QBE_NXZ @ 382 NONAME ; bool QDeclarativeCustomParserProperty::isList(void) const @@ -428,7 +428,7 @@ EXPORTS ?line@QDeclarativeError@@QBEHXZ @ 427 NONAME ; int QDeclarativeError::line(void) const ?heightValid@QDeclarativeItem@@IBE_NXZ @ 428 NONAME ; bool QDeclarativeItem::heightValid(void) const ??1QDeclarativeOpenMetaObject@@UAE@XZ @ 429 NONAME ABSENT ; QDeclarativeOpenMetaObject::~QDeclarativeOpenMetaObject(void) - ??0QPacket@@QAE@XZ @ 430 NONAME ABSENT ; QPacket::QPacket(void) + ??0QPacket@@QAE@XZ @ 430 NONAME ; QPacket::QPacket(void) ?trUtf8@QDeclarativePropertyMap@@SA?AVQString@@PBD0H@Z @ 431 NONAME ; class QString QDeclarativePropertyMap::trUtf8(char const *, char const *, int) ?trUtf8@QDeclarativeEngine@@SA?AVQString@@PBD0H@Z @ 432 NONAME ; class QString QDeclarativeEngine::trUtf8(char const *, char const *, int) ??0QDeclarativeDebugEngineReference@@QAE@XZ @ 433 NONAME ABSENT ; QDeclarativeDebugEngineReference::QDeclarativeDebugEngineReference(void) @@ -485,7 +485,7 @@ EXPORTS ?staticMetaObject@QDeclarativeDebugService@@2UQMetaObject@@B @ 484 NONAME ABSENT ; struct QMetaObject const QDeclarativeDebugService::staticMetaObject ?topMargin@QDeclarativeAnchors@@QBEMXZ @ 485 NONAME ABSENT ; float QDeclarativeAnchors::topMargin(void) const ??0QDeclarativeDebugExpressionQuery@@AAE@PAVQObject@@@Z @ 486 NONAME ABSENT ; QDeclarativeDebugExpressionQuery::QDeclarativeDebugExpressionQuery(class QObject *) - ??0QPacket@@IAE@ABVQByteArray@@@Z @ 487 NONAME ABSENT ; QPacket::QPacket(class QByteArray const &) + ??0QPacket@@IAE@ABVQByteArray@@@Z @ 487 NONAME ; QPacket::QPacket(class QByteArray const &) ?implicitSize@QDeclarativePixmap@@QBEABVQSize@@XZ @ 488 NONAME ; class QSize const & QDeclarativePixmap::implicitSize(void) const ?setFlags@QMetaObjectBuilder@@QAEXV?$QFlags@W4MetaObjectFlag@QMetaObjectBuilder@@@@@Z @ 489 NONAME ABSENT ; void QMetaObjectBuilder::setFlags(class QFlags) ?horizontalCenterChanged@QDeclarativeAnchors@@IAEXXZ @ 490 NONAME ABSENT ; void QDeclarativeAnchors::horizontalCenterChanged(void) @@ -502,7 +502,7 @@ EXPORTS ?qmlAttachedPropertiesObject@@YAPAVQObject@@PAHPBV1@PBUQMetaObject@@_N@Z @ 501 NONAME ; class QObject * qmlAttachedPropertiesObject(int *, class QObject const *, struct QMetaObject const *, bool) ??_EQDeclarativeDebugClient@@UAE@I@Z @ 502 NONAME ABSENT ; QDeclarativeDebugClient::~QDeclarativeDebugClient(unsigned int) ??4QDeclarativeDomComponent@@QAEAAV0@ABV0@@Z @ 503 NONAME ABSENT ; class QDeclarativeDomComponent & QDeclarativeDomComponent::operator=(class QDeclarativeDomComponent const &) - ?tr@QPacketProtocol@@SA?AVQString@@PBD0@Z @ 504 NONAME ABSENT ; class QString QPacketProtocol::tr(char const *, char const *) + ?tr@QPacketProtocol@@SA?AVQString@@PBD0@Z @ 504 NONAME ; class QString QPacketProtocol::tr(char const *, char const *) ?setFont@QDeclarativeText@@QAEXABVQFont@@@Z @ 505 NONAME ABSENT ; void QDeclarativeText::setFont(class QFont const &) ?fromChanged@QDeclarativeTransition@@IAEXXZ @ 506 NONAME ; void QDeclarativeTransition::fromChanged(void) ?addMethod@QMetaObjectBuilder@@QAE?AVQMetaMethodBuilder@@ABVQMetaMethod@@@Z @ 507 NONAME ABSENT ; class QMetaMethodBuilder QMetaObjectBuilder::addMethod(class QMetaMethod const &) @@ -610,7 +610,7 @@ EXPORTS ??0QDeclarativeListReference@@QAE@PAVQObject@@PBDPAVQDeclarativeEngine@@@Z @ 609 NONAME ; QDeclarativeListReference::QDeclarativeListReference(class QObject *, char const *, class QDeclarativeEngine *) ?setData@QListModelInterface@@UAE_NHABV?$QHash@HVQVariant@@@@@Z @ 610 NONAME ABSENT ; bool QListModelInterface::setData(int, class QHash const &) ??0QDeclarativePen@@QAE@PAVQObject@@@Z @ 611 NONAME ABSENT ; QDeclarativePen::QDeclarativePen(class QObject *) - ?trUtf8@QPacketProtocol@@SA?AVQString@@PBD0H@Z @ 612 NONAME ABSENT ; class QString QPacketProtocol::trUtf8(char const *, char const *, int) + ?trUtf8@QPacketProtocol@@SA?AVQString@@PBD0H@Z @ 612 NONAME ; class QString QPacketProtocol::trUtf8(char const *, char const *, int) ?setContextObject@QDeclarativeContext@@QAEXPAVQObject@@@Z @ 613 NONAME ; void QDeclarativeContext::setContextObject(class QObject *) ??_EQDeclarativeState@@UAE@I@Z @ 614 NONAME ; QDeclarativeState::~QDeclarativeState(unsigned int) ?expression@QDeclarativeExpression@@QBE?AVQString@@XZ @ 615 NONAME ; class QString QDeclarativeExpression::expression(void) const @@ -668,7 +668,7 @@ EXPORTS ?setStdCppSet@QMetaPropertyBuilder@@QAEX_N@Z @ 667 NONAME ABSENT ; void QMetaPropertyBuilder::setStdCppSet(bool) ??0QDeclarativeItemPrivate@@QAE@XZ @ 668 NONAME ; QDeclarativeItemPrivate::QDeclarativeItemPrivate(void) ??0QDeclarativeDebugService@@QAE@ABVQString@@PAVQObject@@@Z @ 669 NONAME ABSENT ; QDeclarativeDebugService::QDeclarativeDebugService(class QString const &, class QObject *) - ?load@QDeclarativePixmap@@QAEXPAVQDeclarativeEngine@@ABVQUrl@@_N@Z @ 670 NONAME ; void QDeclarativePixmap::load(class QDeclarativeEngine *, class QUrl const &, bool) + ?load@QDeclarativePixmap@@QAEXPAVQDeclarativeEngine@@ABVQUrl@@_N@Z @ 670 NONAME ABSENT ; void QDeclarativePixmap::load(class QDeclarativeEngine *, class QUrl const &, bool) ??_EQPacketAutoSend@@UAE@I@Z @ 671 NONAME ABSENT ; QPacketAutoSend::~QPacketAutoSend(unsigned int) ?saveValueType@QDeclarativePropertyPrivate@@SA?AVQByteArray@@PBUQMetaObject@@H0H@Z @ 672 NONAME ABSENT ; class QByteArray QDeclarativePropertyPrivate::saveValueType(struct QMetaObject const *, int, struct QMetaObject const *, int) ?resetHeight@QDeclarativeItem@@QAEXXZ @ 673 NONAME ; void QDeclarativeItem::resetHeight(void) @@ -688,7 +688,7 @@ EXPORTS ?d_func@QDeclarativeDebugClient@@AAEPAVQDeclarativeDebugClientPrivate@@XZ @ 687 NONAME ABSENT ; class QDeclarativeDebugClientPrivate * QDeclarativeDebugClient::d_func(void) ??1QDeclarativeType@@AAE@XZ @ 688 NONAME ABSENT ; QDeclarativeType::~QDeclarativeType(void) ?colorFromString@QDeclarativeStringConverters@@YA?AVQColor@@ABVQString@@PA_N@Z @ 689 NONAME ABSENT ; class QColor QDeclarativeStringConverters::colorFromString(class QString const &, bool *) - ??_EQPacketProtocol@@UAE@I@Z @ 690 NONAME ABSENT ; QPacketProtocol::~QPacketProtocol(unsigned int) + ??_EQPacketProtocol@@UAE@I@Z @ 690 NONAME ; QPacketProtocol::~QPacketProtocol(unsigned int) ?tr@QDeclarativeListModel@@SA?AVQString@@PBD0@Z @ 691 NONAME ABSENT ; class QString QDeclarativeListModel::tr(char const *, char const *) ??0QDeclarativePixmap@@QAE@XZ @ 692 NONAME ; QDeclarativePixmap::QDeclarativePixmap(void) ??0QDeclarativeDebugObjectReference@@QAE@XZ @ 693 NONAME ABSENT ; QDeclarativeDebugObjectReference::QDeclarativeDebugObjectReference(void) @@ -704,7 +704,7 @@ EXPORTS ??4QDeclarativeDomDocument@@QAEAAV0@ABV0@@Z @ 703 NONAME ABSENT ; class QDeclarativeDomDocument & QDeclarativeDomDocument::operator=(class QDeclarativeDomDocument const &) ??0QDeclarativeOpenMetaObject@@QAE@PAVQObject@@PAVQDeclarativeOpenMetaObjectType@@_N@Z @ 704 NONAME ABSENT ; QDeclarativeOpenMetaObject::QDeclarativeOpenMetaObject(class QObject *, class QDeclarativeOpenMetaObjectType *, bool) ?trUtf8@QDeclarativeExpression@@SA?AVQString@@PBD0@Z @ 705 NONAME ; class QString QDeclarativeExpression::trUtf8(char const *, char const *) - ??0QPacketProtocol@@QAE@PAVQIODevice@@PAVQObject@@@Z @ 706 NONAME ABSENT ; QPacketProtocol::QPacketProtocol(class QIODevice *, class QObject *) + ??0QPacketProtocol@@QAE@PAVQIODevice@@PAVQObject@@@Z @ 706 NONAME; QPacketProtocol::QPacketProtocol(class QIODevice *, class QObject *) ??1QDeclarativeListReference@@QAE@XZ @ 707 NONAME ; QDeclarativeListReference::~QDeclarativeListReference(void) ?clearError@QDeclarativeExpression@@QAEXXZ @ 708 NONAME ; void QDeclarativeExpression::clearError(void) ?setLineNumber@QDeclarativeDebugFileReference@@QAEXH@Z @ 709 NONAME ABSENT ; void QDeclarativeDebugFileReference::setLineNumber(int) @@ -757,7 +757,7 @@ EXPORTS ??4QDeclarativeDomValueBinding@@QAEAAV0@ABV0@@Z @ 756 NONAME ABSENT ; class QDeclarativeDomValueBinding & QDeclarativeDomValueBinding::operator=(class QDeclarativeDomValueBinding const &) ??0QDeclarativeExpression@@QAE@XZ @ 757 NONAME ; QDeclarativeExpression::QDeclarativeExpression(void) ?paint@QDeclarativeItem@@UAEXPAVQPainter@@PBVQStyleOptionGraphicsItem@@PAVQWidget@@@Z @ 758 NONAME ; void QDeclarativeItem::paint(class QPainter *, class QStyleOptionGraphicsItem const *, class QWidget *) - ?send@QPacketProtocol@@QAE?AVQPacketAutoSend@@XZ @ 759 NONAME ABSENT ; class QPacketAutoSend QPacketProtocol::send(void) + ?send@QPacketProtocol@@QAE?AVQPacketAutoSend@@XZ @ 759 NONAME ; class QPacketAutoSend QPacketProtocol::send(void) ?countChanged@QDeclarativeListModel@@IAEXXZ @ 760 NONAME ABSENT ; void QDeclarativeListModel::countChanged(void) ??0QDeclarativeGridScaledImage@@QAE@PAVQIODevice@@@Z @ 761 NONAME ABSENT ; QDeclarativeGridScaledImage::QDeclarativeGridScaledImage(class QIODevice *) ??_EQDeclarativeBinding@@UAE@I@Z @ 762 NONAME ABSENT ; QDeclarativeBinding::~QDeclarativeBinding(unsigned int) @@ -776,7 +776,7 @@ EXPORTS ?hasNotifySignal@QDeclarativeProperty@@QBE_NXZ @ 775 NONAME ; bool QDeclarativeProperty::hasNotifySignal(void) const ?create@QDeclarativeType@@QBEXPAPAVQObject@@PAPAXI@Z @ 776 NONAME ABSENT ; void QDeclarativeType::create(class QObject * *, void * *, unsigned int) const ?reversible@QDeclarativeTransition@@QBE_NXZ @ 777 NONAME ; bool QDeclarativeTransition::reversible(void) const - ?invalidPacket@QPacketProtocol@@IAEXXZ @ 778 NONAME ABSENT ; void QPacketProtocol::invalidPacket(void) + ?invalidPacket@QPacketProtocol@@IAEXXZ @ 778 NONAME ; void QPacketProtocol::invalidPacket(void) ??0QDeclarativeDebugObjectReference@@QAE@H@Z @ 779 NONAME ABSENT ; QDeclarativeDebugObjectReference::QDeclarativeDebugObjectReference(int) ?superClass@QMetaObjectBuilder@@QBEPBUQMetaObject@@XZ @ 780 NONAME ABSENT ; struct QMetaObject const * QMetaObjectBuilder::superClass(void) const ?isValid@QDeclarativeListReference@@QBE_NXZ @ 781 NONAME ; bool QDeclarativeListReference::isValid(void) const @@ -813,7 +813,7 @@ EXPORTS ??_EQDeclarativeDebugQuery@@UAE@I@Z @ 812 NONAME ABSENT ; QDeclarativeDebugQuery::~QDeclarativeDebugQuery(unsigned int) ?update@QDeclarativeAbstractBinding@@QAEXXZ @ 813 NONAME ABSENT ; void QDeclarativeAbstractBinding::update(void) ?tr@QDeclarativeBehavior@@SA?AVQString@@PBD0H@Z @ 814 NONAME ABSENT ; class QString QDeclarativeBehavior::tr(char const *, char const *, int) - ?read@QPacketProtocol@@QAE?AVQPacket@@XZ @ 815 NONAME ABSENT ; class QPacket QPacketProtocol::read(void) + ?read@QPacketProtocol@@QAE?AVQPacket@@XZ @ 815 NONAME ; class QPacket QPacketProtocol::read(void) ?setParentItem@QDeclarativeItem@@QAEXPAV1@@Z @ 816 NONAME ; void QDeclarativeItem::setParentItem(class QDeclarativeItem *) ?qmlAttachedProperties@QDeclarativeComponent@@SAPAVQDeclarativeComponentAttached@@PAVQObject@@@Z @ 817 NONAME ; class QDeclarativeComponentAttached * QDeclarativeComponent::qmlAttachedProperties(class QObject *) ??0QDeclarativeView@@QAE@ABVQUrl@@PAVQWidget@@@Z @ 818 NONAME ; QDeclarativeView::QDeclarativeView(class QUrl const &, class QWidget *) @@ -821,7 +821,7 @@ EXPORTS ??_EQDeclarativeView@@UAE@I@Z @ 820 NONAME ; QDeclarativeView::~QDeclarativeView(unsigned int) ?trUtf8@QDeclarativeStateGroup@@SA?AVQString@@PBD0H@Z @ 821 NONAME ; class QString QDeclarativeStateGroup::trUtf8(char const *, char const *, int) ?tag@QMetaMethodBuilder@@QBE?AVQByteArray@@XZ @ 822 NONAME ABSENT ; class QByteArray QMetaMethodBuilder::tag(void) const - ?getStaticMetaObject@QPacketProtocol@@SAABUQMetaObject@@XZ @ 823 NONAME ABSENT ; struct QMetaObject const & QPacketProtocol::getStaticMetaObject(void) + ?getStaticMetaObject@QPacketProtocol@@SAABUQMetaObject@@XZ @ 823 NONAME ; struct QMetaObject const & QPacketProtocol::getStaticMetaObject(void) ?setContext@QDeclarativeScriptString@@QAEXPAVQDeclarativeContext@@@Z @ 824 NONAME ; void QDeclarativeScriptString::setContext(class QDeclarativeContext *) ?addImageProvider@QDeclarativeEngine@@QAEXABVQString@@PAVQDeclarativeImageProvider@@@Z @ 825 NONAME ; void QDeclarativeEngine::addImageProvider(class QString const &, class QDeclarativeImageProvider *) ?d_func@QDeclarativeStateGroup@@ABEPBVQDeclarativeStateGroupPrivate@@XZ @ 826 NONAME ; class QDeclarativeStateGroupPrivate const * QDeclarativeStateGroup::d_func(void) const @@ -1013,7 +1013,7 @@ EXPORTS ?agent@QDeclarativeListModel@@QAEPAVQDeclarativeListModelWorkerAgent@@XZ @ 1012 NONAME ABSENT ; class QDeclarativeListModelWorkerAgent * QDeclarativeListModel::agent(void) ?engine@QDeclarativeExpression@@QBEPAVQDeclarativeEngine@@XZ @ 1013 NONAME ; class QDeclarativeEngine * QDeclarativeExpression::engine(void) const ??_EQDeclarativeDebugWatch@@UAE@I@Z @ 1014 NONAME ABSENT ; QDeclarativeDebugWatch::~QDeclarativeDebugWatch(unsigned int) - ?isEmpty@QPacket@@QBE_NXZ @ 1015 NONAME ABSENT ; bool QPacket::isEmpty(void) const + ?isEmpty@QPacket@@QBE_NXZ @ 1015 NONAME ; bool QPacket::isEmpty(void) const ?qmlType@QDeclarativeMetaType@@SAPAVQDeclarativeType@@PBUQMetaObject@@@Z @ 1016 NONAME ABSENT ; class QDeclarativeType * QDeclarativeMetaType::qmlType(struct QMetaObject const *) ?setFill@QDeclarativeAnchors@@QAEXPAVQGraphicsObject@@@Z @ 1017 NONAME ABSENT ; void QDeclarativeAnchors::setFill(class QGraphicsObject *) ?setHAlign@QDeclarativeText@@QAEXW4HAlignment@1@@Z @ 1018 NONAME ABSENT ; void QDeclarativeText::setHAlign(enum QDeclarativeText::HAlignment) @@ -1029,7 +1029,7 @@ EXPORTS ?staticMetaObject@QDeclarativeText@@2UQMetaObject@@B @ 1028 NONAME ABSENT ; struct QMetaObject const QDeclarativeText::staticMetaObject ?color@QDeclarativeRectangle@@QBE?AVQColor@@XZ @ 1029 NONAME ABSENT ; class QColor QDeclarativeRectangle::color(void) const ?isEnabled@QDeclarativeDebugClient@@QBE_NXZ @ 1030 NONAME ABSENT ; bool QDeclarativeDebugClient::isEnabled(void) const - ?send@QPacketProtocol@@QAEXABVQPacket@@@Z @ 1031 NONAME ABSENT ; void QPacketProtocol::send(class QPacket const &) + ?send@QPacketProtocol@@QAEXABVQPacket@@@Z @ 1031 NONAME ; void QPacketProtocol::send(class QPacket const &) ?width@QDeclarativePixmap@@QBEHXZ @ 1032 NONAME ; int QDeclarativePixmap::width(void) const ?error@QDeclarativeCustomParser@@IAEXABVQDeclarativeCustomParserNode@@ABVQString@@@Z @ 1033 NONAME ; void QDeclarativeCustomParser::error(class QDeclarativeCustomParserNode const &, class QString const &) ?defaultProperty@QDeclarativeMetaType@@SA?AVQMetaProperty@@PBUQMetaObject@@@Z @ 1034 NONAME ABSENT ; class QMetaProperty QDeclarativeMetaType::defaultProperty(struct QMetaObject const *) @@ -1043,7 +1043,7 @@ EXPORTS ?trUtf8@QDeclarativeAnchors@@SA?AVQString@@PBD0@Z @ 1042 NONAME ABSENT ; class QString QDeclarativeAnchors::trUtf8(char const *, char const *) ?getStaticMetaObject@QDeclarativeValueType@@SAABUQMetaObject@@XZ @ 1043 NONAME ABSENT ; struct QMetaObject const & QDeclarativeValueType::getStaticMetaObject(void) ?valueChanged@QDeclarativePropertyMap@@IAEXABVQString@@ABVQVariant@@@Z @ 1044 NONAME ; void QDeclarativePropertyMap::valueChanged(class QString const &, class QVariant const &) - ?staticMetaObject@QPacketProtocol@@2UQMetaObject@@B @ 1045 NONAME ABSENT ; struct QMetaObject const QPacketProtocol::staticMetaObject + ?staticMetaObject@QPacketProtocol@@2UQMetaObject@@B @ 1045 NONAME ; struct QMetaObject const QPacketProtocol::staticMetaObject ?tr@QDeclarativeListModel@@SA?AVQString@@PBD0H@Z @ 1046 NONAME ABSENT ; class QString QDeclarativeListModel::tr(char const *, char const *, int) ??0QDeclarativeScriptString@@QAE@XZ @ 1047 NONAME ; QDeclarativeScriptString::QDeclarativeScriptString(void) ?tr@QListModelInterface@@SA?AVQString@@PBD0@Z @ 1048 NONAME ABSENT ; class QString QListModelInterface::tr(char const *, char const *) @@ -1088,7 +1088,7 @@ EXPORTS ?resetWidth@QDeclarativeItemPrivate@@UAEXXZ @ 1087 NONAME ; void QDeclarativeItemPrivate::resetWidth(void) ??AQDeclarativeOpenMetaObject@@QAEAAVQVariant@@ABVQByteArray@@@Z @ 1088 NONAME ABSENT ; class QVariant & QDeclarativeOpenMetaObject::operator[](class QByteArray const &) ?bottom@QDeclarativeItemPrivate@@QBE?AVQDeclarativeAnchorLine@@XZ @ 1089 NONAME ; class QDeclarativeAnchorLine QDeclarativeItemPrivate::bottom(void) const - ?device@QPacketProtocol@@QAEPAVQIODevice@@XZ @ 1090 NONAME ABSENT ; class QIODevice * QPacketProtocol::device(void) + ?device@QPacketProtocol@@QAEPAVQIODevice@@XZ @ 1090 NONAME ; class QIODevice * QPacketProtocol::device(void) ?trUtf8@QDeclarativeStateGroup@@SA?AVQString@@PBD0@Z @ 1091 NONAME ; class QString QDeclarativeStateGroup::trUtf8(char const *, char const *) ?variantFromString@QDeclarativeStringConverters@@YA?AVQVariant@@ABVQString@@HPA_N@Z @ 1092 NONAME ABSENT ; class QVariant QDeclarativeStringConverters::variantFromString(class QString const &, int, bool *) ?metaObject@QDeclarativeComponent@@UBEPBUQMetaObject@@XZ @ 1093 NONAME ; struct QMetaObject const * QDeclarativeComponent::metaObject(void) const @@ -1110,7 +1110,7 @@ EXPORTS ??0QDeclarativeDebugFileReference@@QAE@XZ @ 1109 NONAME ABSENT ; QDeclarativeDebugFileReference::QDeclarativeDebugFileReference(void) ?mapFromItem@QDeclarativeItem@@QBE?AVQScriptValue@@ABV2@MM@Z @ 1110 NONAME ; class QScriptValue QDeclarativeItem::mapFromItem(class QScriptValue const &, float, float) const ?trUtf8@QDeclarativeStateOperation@@SA?AVQString@@PBD0H@Z @ 1111 NONAME ; class QString QDeclarativeStateOperation::trUtf8(char const *, char const *, int) - ?tr@QPacketProtocol@@SA?AVQString@@PBD0H@Z @ 1112 NONAME ABSENT ; class QString QPacketProtocol::tr(char const *, char const *, int) + ?tr@QPacketProtocol@@SA?AVQString@@PBD0H@Z @ 1112 NONAME ; class QString QPacketProtocol::tr(char const *, char const *, int) ?d_func@QDeclarativeAnchors@@ABEPBVQDeclarativeAnchorsPrivate@@XZ @ 1113 NONAME ABSENT ; class QDeclarativeAnchorsPrivate const * QDeclarativeAnchors::d_func(void) const ?setNotifySignal@QMetaPropertyBuilder@@QAEXABVQMetaMethodBuilder@@@Z @ 1114 NONAME ABSENT ; void QMetaPropertyBuilder::setNotifySignal(class QMetaMethodBuilder const &) ?enabled@QDeclarativeBehavior@@QBE_NXZ @ 1115 NONAME ABSENT ; bool QDeclarativeBehavior::enabled(void) const @@ -1132,7 +1132,7 @@ EXPORTS ?noCreationReason@QDeclarativeType@@QBE?AVQString@@XZ @ 1131 NONAME ABSENT ; class QString QDeclarativeType::noCreationReason(void) const ?setUrl@QDeclarativeDebugFileReference@@QAEXABVQUrl@@@Z @ 1132 NONAME ABSENT ; void QDeclarativeDebugFileReference::setUrl(class QUrl const &) ??1QDeclarativeCustomParserProperty@@QAE@XZ @ 1133 NONAME ; QDeclarativeCustomParserProperty::~QDeclarativeCustomParserProperty(void) - ??1QPacketProtocol@@UAE@XZ @ 1134 NONAME ABSENT ; QPacketProtocol::~QPacketProtocol(void) + ??1QPacketProtocol@@UAE@XZ @ 1134 NONAME ; QPacketProtocol::~QPacketProtocol(void) ??1QDeclarativeAbstractBinding@@MAE@XZ @ 1135 NONAME ABSENT ; QDeclarativeAbstractBinding::~QDeclarativeAbstractBinding(void) ?indexOfEnumerator@QMetaObjectBuilder@@QAEHABVQByteArray@@@Z @ 1136 NONAME ABSENT ; int QMetaObjectBuilder::indexOfEnumerator(class QByteArray const &) ?qt_metacast@QDeclarativePen@@UAEPAXPBD@Z @ 1137 NONAME ABSENT ; void * QDeclarativePen::qt_metacast(char const *) @@ -1222,7 +1222,7 @@ EXPORTS ?statusChanged@QDeclarativeComponent@@IAEXW4Status@1@@Z @ 1221 NONAME ; void QDeclarativeComponent::statusChanged(enum QDeclarativeComponent::Status) ?setTarget@QDeclarativeBinding@@QAEXABVQDeclarativeProperty@@@Z @ 1222 NONAME ABSENT ; void QDeclarativeBinding::setTarget(class QDeclarativeProperty const &) ?imageProvider@QDeclarativeEngine@@QBEPAVQDeclarativeImageProvider@@ABVQString@@@Z @ 1223 NONAME ; class QDeclarativeImageProvider * QDeclarativeEngine::imageProvider(class QString const &) const - ?packetsAvailable@QPacketProtocol@@QBE_JXZ @ 1224 NONAME ABSENT ; long long QPacketProtocol::packetsAvailable(void) const + ?packetsAvailable@QPacketProtocol@@QBE_JXZ @ 1224 NONAME ; long long QPacketProtocol::packetsAvailable(void) const ?state@QDeclarativeDebugWatch@@QBE?AW4State@1@XZ @ 1225 NONAME ABSENT ; enum QDeclarativeDebugWatch::State QDeclarativeDebugWatch::state(void) const ?attachedPropertiesFuncById@QDeclarativeMetaType@@SAP6APAVQObject@@PAV2@@ZH@Z @ 1226 NONAME ABSENT ; class QObject * (*)(class QObject *) QDeclarativeMetaType::attachedPropertiesFuncById(int) ?resetBaseline@QDeclarativeAnchors@@QAEXXZ @ 1227 NONAME ABSENT ; void QDeclarativeAnchors::resetBaseline(void) @@ -1341,7 +1341,7 @@ EXPORTS ?implicitWidth@QDeclarativeItem@@QBEMXZ @ 1340 NONAME ; float QDeclarativeItem::implicitWidth(void) const ?metaObject@QDeclarativeContext@@UBEPBUQMetaObject@@XZ @ 1341 NONAME ; struct QMetaObject const * QDeclarativeContext::metaObject(void) const ??0QDeclarativeContext@@AAE@PAVQDeclarativeContextData@@@Z @ 1342 NONAME ; QDeclarativeContext::QDeclarativeContext(class QDeclarativeContextData *) - ?maximumPacketSize@QPacketProtocol@@QBEHXZ @ 1343 NONAME ABSENT ; int QPacketProtocol::maximumPacketSize(void) const + ?maximumPacketSize@QPacketProtocol@@QBEHXZ @ 1343 NONAME ; int QPacketProtocol::maximumPacketSize(void) const ??_EQDeclarativeDebuggerStatus@@UAE@I@Z @ 1344 NONAME ABSENT ; QDeclarativeDebuggerStatus::~QDeclarativeDebuggerStatus(unsigned int) ?error@QDeclarativeCustomParser@@IAEXABVQString@@@Z @ 1345 NONAME ; void QDeclarativeCustomParser::error(class QString const &) ?messageReceived@QDeclarativeDebugService@@MAEXABVQByteArray@@@Z @ 1346 NONAME ABSENT ; void QDeclarativeDebugService::messageReceived(class QByteArray const &) @@ -1389,12 +1389,12 @@ EXPORTS ?setEnabled@QDeclarativeDebugClient@@QAEX_N@Z @ 1388 NONAME ABSENT ; void QDeclarativeDebugClient::setEnabled(bool) ??1QMetaObjectBuilder@@UAE@XZ @ 1389 NONAME ABSENT ; QMetaObjectBuilder::~QMetaObjectBuilder(void) ?tr@QDeclarativeStateOperation@@SA?AVQString@@PBD0@Z @ 1390 NONAME ; class QString QDeclarativeStateOperation::tr(char const *, char const *) - ?clear@QPacket@@QAEXXZ @ 1391 NONAME ABSENT ; void QPacket::clear(void) + ?clear@QPacket@@QAEXXZ @ 1391 NONAME ; void QPacket::clear(void) ?getStaticMetaObject@QDeclarativeDebugClient@@SAABUQMetaObject@@XZ @ 1392 NONAME ABSENT ; struct QMetaObject const & QDeclarativeDebugClient::getStaticMetaObject(void) ??0QDeclarativeDomList@@QAE@ABV0@@Z @ 1393 NONAME ABSENT ; QDeclarativeDomList::QDeclarativeDomList(class QDeclarativeDomList const &) ?gridTop@QDeclarativeGridScaledImage@@QBEHXZ @ 1394 NONAME ABSENT ; int QDeclarativeGridScaledImage::gridTop(void) const ?setUrl@QDeclarativeError@@QAEXABVQUrl@@@Z @ 1395 NONAME ; void QDeclarativeError::setUrl(class QUrl const &) - ?setMaximumPacketSize@QPacketProtocol@@QAEHH@Z @ 1396 NONAME ABSENT ; int QPacketProtocol::setMaximumPacketSize(int) + ?setMaximumPacketSize@QPacketProtocol@@QAEHH@Z @ 1396 NONAME ; int QPacketProtocol::setMaximumPacketSize(int) ??_EQDeclarativeAction@@QAE@I@Z @ 1397 NONAME ABSENT ; QDeclarativeAction::~QDeclarativeAction(unsigned int) ?trUtf8@QDeclarativeDebugWatch@@SA?AVQString@@PBD0@Z @ 1398 NONAME ABSENT ; class QString QDeclarativeDebugWatch::trUtf8(char const *, char const *) ?read@QDeclarativeProperty@@SA?AVQVariant@@PAVQObject@@ABVQString@@@Z @ 1399 NONAME ; class QVariant QDeclarativeProperty::read(class QObject *, class QString const &) @@ -1472,7 +1472,7 @@ EXPORTS ?signalExpression@QDeclarativePropertyPrivate@@SAPAVQDeclarativeExpression@@ABVQDeclarativeProperty@@@Z @ 1471 NONAME ABSENT ; class QDeclarativeExpression * QDeclarativePropertyPrivate::signalExpression(class QDeclarativeProperty const &) ?networkAccessManagerFactory@QDeclarativeEngine@@QBEPAVQDeclarativeNetworkAccessManagerFactory@@XZ @ 1472 NONAME ; class QDeclarativeNetworkAccessManagerFactory * QDeclarativeEngine::networkAccessManagerFactory(void) const ?isStringList@Variant@QDeclarativeParser@@QBE_NXZ @ 1473 NONAME ; bool QDeclarativeParser::Variant::isStringList(void) const - ?packetWritten@QPacketProtocol@@IAEXXZ @ 1474 NONAME ABSENT ; void QPacketProtocol::packetWritten(void) + ?packetWritten@QPacketProtocol@@IAEXXZ @ 1474 NONAME ; void QPacketProtocol::packetWritten(void) ?getStaticMetaObject@QDeclarativeDebugObjectQuery@@SAABUQMetaObject@@XZ @ 1475 NONAME ABSENT ; struct QMetaObject const & QDeclarativeDebugObjectQuery::getStaticMetaObject(void) ?isSignalProperty@QDeclarativeProperty@@QBE_NXZ @ 1476 NONAME ; bool QDeclarativeProperty::isSignalProperty(void) const ?d_func@QDeclarativeDebugService@@AAEPAVQDeclarativeDebugServicePrivate@@XZ @ 1477 NONAME ABSENT ; class QDeclarativeDebugServicePrivate * QDeclarativeDebugService::d_func(void) @@ -1488,7 +1488,7 @@ EXPORTS ?qt_metacast@QDeclarativePropertyMap@@UAEPAXPBD@Z @ 1487 NONAME ; void * QDeclarativePropertyMap::qt_metacast(char const *) ?classBegin@QDeclarativeAnchors@@QAEXXZ @ 1488 NONAME ABSENT ; void QDeclarativeAnchors::classBegin(void) ?color@QDeclarativeText@@QBE?AVQColor@@XZ @ 1489 NONAME ABSENT ; class QColor QDeclarativeText::color(void) const - ?metaObject@QPacketProtocol@@UBEPBUQMetaObject@@XZ @ 1490 NONAME ABSENT ; struct QMetaObject const * QPacketProtocol::metaObject(void) const + ?metaObject@QPacketProtocol@@UBEPBUQMetaObject@@XZ @ 1490 NONAME ; struct QMetaObject const * QPacketProtocol::metaObject(void) const ??4QDeclarativeGridScaledImage@@QAEAAV0@ABV0@@Z @ 1491 NONAME ABSENT ; class QDeclarativeGridScaledImage & QDeclarativeGridScaledImage::operator=(class QDeclarativeGridScaledImage const &) ?tr@QDeclarativeScaleGrid@@SA?AVQString@@PBD0@Z @ 1492 NONAME ABSENT ; class QString QDeclarativeScaleGrid::tr(char const *, char const *) ??1QDeclarativeScriptString@@QAE@XZ @ 1493 NONAME ; QDeclarativeScriptString::~QDeclarativeScriptString(void) @@ -1619,7 +1619,7 @@ EXPORTS ?metaObject@QDeclarativeItem@@UBEPBUQMetaObject@@XZ @ 1618 NONAME ; struct QMetaObject const * QDeclarativeItem::metaObject(void) const ?clear@QDeclarativeAbstractBinding@@IAEXXZ @ 1619 NONAME ABSENT ; void QDeclarativeAbstractBinding::clear(void) ?start@QDeclarativeItemPrivate@@SAXAAVQElapsedTimer@@@Z @ 1620 NONAME ; void QDeclarativeItemPrivate::start(class QElapsedTimer &) - ?load@QDeclarativePixmap@@QAEXPAVQDeclarativeEngine@@ABVQUrl@@ABVQSize@@_N@Z @ 1621 NONAME ; void QDeclarativePixmap::load(class QDeclarativeEngine *, class QUrl const &, class QSize const &, bool) + ?load@QDeclarativePixmap@@QAEXPAVQDeclarativeEngine@@ABVQUrl@@ABVQSize@@_N@Z @ 1621 NONAME ABSENT ; void QDeclarativePixmap::load(class QDeclarativeEngine *, class QUrl const &, class QSize const &, bool) ?stringToRule@QDeclarativeGridScaledImage@@CA?AW4TileMode@QDeclarativeBorderImage@@ABVQString@@@Z @ 1622 NONAME ABSENT ; enum QDeclarativeBorderImage::TileMode QDeclarativeGridScaledImage::stringToRule(class QString const &) ?setHorizontalCenter@QDeclarativeAnchors@@QAEXABVQDeclarativeAnchorLine@@@Z @ 1623 NONAME ABSENT ; void QDeclarativeAnchors::setHorizontalCenter(class QDeclarativeAnchorLine const &) ?setFocus@QDeclarativeItem@@QAEX_N@Z @ 1624 NONAME ; void QDeclarativeItem::setFocus(bool) @@ -1631,7 +1631,7 @@ EXPORTS ??0QDeclarativeContext@@AAE@PAVQDeclarativeEngine@@_N@Z @ 1630 NONAME ; QDeclarativeContext::QDeclarativeContext(class QDeclarativeEngine *, bool) ?initialValue@QDeclarativeOpenMetaObject@@UAE?AVQVariant@@H@Z @ 1631 NONAME ABSENT ; class QVariant QDeclarativeOpenMetaObject::initialValue(int) ?tr@QDeclarativeView@@SA?AVQString@@PBD0@Z @ 1632 NONAME ; class QString QDeclarativeView::tr(char const *, char const *) - ?qt_metacall@QPacketProtocol@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 1633 NONAME ABSENT ; int QPacketProtocol::qt_metacall(enum QMetaObject::Call, int, void * *) + ?qt_metacall@QPacketProtocol@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 1633 NONAME ; int QPacketProtocol::qt_metacall(enum QMetaObject::Call, int, void * *) ??0QDeclarativeItem@@QAE@PAV0@@Z @ 1634 NONAME ; QDeclarativeItem::QDeclarativeItem(class QDeclarativeItem *) ?hasDebuggingClient@QDeclarativeDebugService@@SA_NXZ @ 1635 NONAME ABSENT ; bool QDeclarativeDebugService::hasDebuggingClient(void) ?staticMetaObject@QDeclarativeContext@@2UQMetaObject@@B @ 1636 NONAME ; struct QMetaObject const QDeclarativeContext::staticMetaObject @@ -1645,15 +1645,15 @@ EXPORTS ??_EQDeclarativePropertyChanges@@UAE@I@Z @ 1644 NONAME ABSENT ; QDeclarativePropertyChanges::~QDeclarativePropertyChanges(unsigned int) ?setObject@QDeclarativePropertyChanges@@QAEXPAVQObject@@@Z @ 1645 NONAME ABSENT ; void QDeclarativePropertyChanges::setObject(class QObject *) ?staticMetaObject@QDeclarativePropertyChanges@@2UQMetaObject@@B @ 1646 NONAME ABSENT ; struct QMetaObject const QDeclarativePropertyChanges::staticMetaObject - ?removeEntryFromRevertList@QDeclarativeState@@QAE_NPAVQObject@@ABVQByteArray@@@Z @ 1647 NONAME ; bool QDeclarativeState::removeEntryFromRevertList(class QObject *, class QByteArray const &) + ?removeEntryFromRevertList@QDeclarativeState@@QAE_NPAVQObject@@ABVQByteArray@@@Z @ 1647 NONAME ABSENT ; bool QDeclarativeState::removeEntryFromRevertList(class QObject *, class QByteArray const &) ?restoreEntryValues@QDeclarativePropertyChanges@@QBE_NXZ @ 1648 NONAME ABSENT ; bool QDeclarativePropertyChanges::restoreEntryValues(void) const ?setRestoreEntryValues@QDeclarativePropertyChanges@@QAEX_N@Z @ 1649 NONAME ABSENT ; void QDeclarativePropertyChanges::setRestoreEntryValues(bool) ?changeValue@QDeclarativePropertyChanges@@QAEXABVQByteArray@@ABVQVariant@@@Z @ 1650 NONAME ABSENT ; void QDeclarativePropertyChanges::changeValue(class QByteArray const &, class QVariant const &) ?metaObject@QDeclarativePropertyChanges@@UBEPBUQMetaObject@@XZ @ 1651 NONAME ABSENT ; struct QMetaObject const * QDeclarativePropertyChanges::metaObject(void) const ?data_clear@QDeclarativeItemPrivate@@SAXPAV?$QDeclarativeListProperty@VQObject@@@@@Z @ 1652 NONAME ; void QDeclarativeItemPrivate::data_clear(class QDeclarativeListProperty *) - ?containsPropertyInRevertList@QDeclarativeState@@QBE_NPAVQObject@@ABVQByteArray@@@Z @ 1653 NONAME ; bool QDeclarativeState::containsPropertyInRevertList(class QObject *, class QByteArray const &) const + ?containsPropertyInRevertList@QDeclarativeState@@QBE_NPAVQObject@@ABVQByteArray@@@Z @ 1653 NONAME ABSENT ; bool QDeclarativeState::containsPropertyInRevertList(class QObject *, class QByteArray const &) const ?containsValue@QDeclarativePropertyChanges@@QBE_NABVQByteArray@@@Z @ 1654 NONAME ABSENT ; bool QDeclarativePropertyChanges::containsValue(class QByteArray const &) const - ?bindingInRevertList@QDeclarativeState@@QBEPAVQDeclarativeAbstractBinding@@PAVQObject@@ABVQByteArray@@@Z @ 1655 NONAME ; class QDeclarativeAbstractBinding * QDeclarativeState::bindingInRevertList(class QObject *, class QByteArray const &) const + ?bindingInRevertList@QDeclarativeState@@QBEPAVQDeclarativeAbstractBinding@@PAVQObject@@ABVQByteArray@@@Z @ 1655 NONAME ABSENT ; class QDeclarativeAbstractBinding * QDeclarativeState::bindingInRevertList(class QObject *, class QByteArray const &) const ?d_func@QDeclarativePropertyChanges@@ABEPBVQDeclarativePropertyChangesPrivate@@XZ @ 1656 NONAME ABSENT ; class QDeclarativePropertyChangesPrivate const * QDeclarativePropertyChanges::d_func(void) const ?containsProperty@QDeclarativePropertyChanges@@QBE_NABVQByteArray@@@Z @ 1657 NONAME ABSENT ; bool QDeclarativePropertyChanges::containsProperty(class QByteArray const &) const ?trUtf8@QDeclarativePropertyChanges@@SA?AVQString@@PBD0H@Z @ 1658 NONAME ABSENT ; class QString QDeclarativePropertyChanges::trUtf8(char const *, char const *, int) @@ -1677,17 +1677,17 @@ EXPORTS ?addEntriesToRevertList@QDeclarativeState@@QAEXABV?$QList@VQDeclarativeAction@@@@@Z @ 1676 NONAME ; void QDeclarativeState::addEntriesToRevertList(class QList const &) ?expression@QDeclarativePropertyChanges@@QBE?AVQString@@ABVQByteArray@@@Z @ 1677 NONAME ABSENT ; class QString QDeclarativePropertyChanges::expression(class QByteArray const &) const ?object@QDeclarativePropertyChanges@@QBEPAVQObject@@XZ @ 1678 NONAME ABSENT ; class QObject * QDeclarativePropertyChanges::object(void) const - ?valueInRevertList@QDeclarativeState@@QBE?AVQVariant@@PAVQObject@@ABVQByteArray@@@Z @ 1679 NONAME ; class QVariant QDeclarativeState::valueInRevertList(class QObject *, class QByteArray const &) const + ?valueInRevertList@QDeclarativeState@@QBE?AVQVariant@@PAVQObject@@ABVQByteArray@@@Z @ 1679 NONAME ABSENT ; class QVariant QDeclarativeState::valueInRevertList(class QObject *, class QByteArray const &) const ?removeAllEntriesFromRevertList@QDeclarativeState@@QAEXPAVQObject@@@Z @ 1680 NONAME ; void QDeclarativeState::removeAllEntriesFromRevertList(class QObject *) ?d_func@QDeclarativeStateOperation@@AAEPAVQDeclarativeStateOperationPrivate@@XZ @ 1681 NONAME ; class QDeclarativeStateOperationPrivate * QDeclarativeStateOperation::d_func(void) - ?changeValueInRevertList@QDeclarativeState@@QAE_NPAVQObject@@ABVQByteArray@@ABVQVariant@@@Z @ 1682 NONAME ; bool QDeclarativeState::changeValueInRevertList(class QObject *, class QByteArray const &, class QVariant const &) + ?changeValueInRevertList@QDeclarativeState@@QAE_NPAVQObject@@ABVQByteArray@@ABVQVariant@@@Z @ 1682 NONAME ABSENT ; bool QDeclarativeState::changeValueInRevertList(class QObject *, class QByteArray const &, class QVariant const &) ?setIsExplicit@QDeclarativePropertyChanges@@QAEX_N@Z @ 1683 NONAME ABSENT ; void QDeclarativePropertyChanges::setIsExplicit(bool) ?isStateActive@QDeclarativeState@@QBE_NXZ @ 1684 NONAME ; bool QDeclarativeState::isStateActive(void) const ?data_count@QDeclarativeItemPrivate@@SAHPAV?$QDeclarativeListProperty@VQObject@@@@@Z @ 1685 NONAME ; int QDeclarativeItemPrivate::data_count(class QDeclarativeListProperty *) ?removeProperty@QDeclarativePropertyChanges@@QAEXABVQByteArray@@@Z @ 1686 NONAME ABSENT ; void QDeclarativePropertyChanges::removeProperty(class QByteArray const &) ?data_at@QDeclarativeItemPrivate@@SAPAVQObject@@PAV?$QDeclarativeListProperty@VQObject@@@@H@Z @ 1687 NONAME ; class QObject * QDeclarativeItemPrivate::data_at(class QDeclarativeListProperty *, int) ?tr@QDeclarativePropertyChanges@@SA?AVQString@@PBD0@Z @ 1688 NONAME ABSENT ; class QString QDeclarativePropertyChanges::tr(char const *, char const *) - ?changeBindingInRevertList@QDeclarativeState@@QAE_NPAVQObject@@ABVQByteArray@@PAVQDeclarativeAbstractBinding@@@Z @ 1689 NONAME ; bool QDeclarativeState::changeBindingInRevertList(class QObject *, class QByteArray const &, class QDeclarativeAbstractBinding *) + ?changeBindingInRevertList@QDeclarativeState@@QAE_NPAVQObject@@ABVQByteArray@@PAVQDeclarativeAbstractBinding@@@Z @ 1689 NONAME ABSENT ; bool QDeclarativeState::changeBindingInRevertList(class QObject *, class QByteArray const &, class QDeclarativeAbstractBinding *) ?getStaticMetaObject@QDeclarativePropertyChanges@@SAABUQMetaObject@@XZ @ 1690 NONAME ABSENT ; struct QMetaObject const & QDeclarativePropertyChanges::getStaticMetaObject(void) ?weakPointer@QDeclarativeAbstractBinding@@QAE?AV?$QWeakPointer@VQDeclarativeAbstractBinding@@@@XZ @ 1691 NONAME ABSENT ; class QWeakPointer QDeclarativeAbstractBinding::weakPointer(void) ?getStaticMetaObject@QDeclarativeScriptAction@@SAABUQMetaObject@@XZ @ 1692 NONAME ABSENT ; struct QMetaObject const & QDeclarativeScriptAction::getStaticMetaObject(void) @@ -1840,4 +1840,47 @@ EXPORTS ?qt_metacall@QDeclarativeAbstractAnimation@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 1839 NONAME ABSENT ; int QDeclarativeAbstractAnimation::qt_metacall(enum QMetaObject::Call, int, void * *) ?enableDebugging@QDeclarativeDebugHelper@@SAXXZ @ 1840 NONAME ; void QDeclarativeDebugHelper::enableDebugging(void) ?connect@QDeclarativePropertyPrivate@@SA_NPBVQObject@@H0HHPAH@Z @ 1841 NONAME ABSENT ; bool QDeclarativePropertyPrivate::connect(class QObject const *, int, class QObject const *, int, int, int *) + ?qt_metacall@QDeclarativeDebugServer@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 1842 NONAME ; int QDeclarativeDebugServer::qt_metacall(enum QMetaObject::Call, int, void * *) + ?implicitHeight@QDeclarativeItemPrivate@@UBEMXZ @ 1843 NONAME ; float QDeclarativeItemPrivate::implicitHeight(void) const + ?instance@QDeclarativeDebugServer@@SAPAV1@XZ @ 1844 NONAME ; class QDeclarativeDebugServer * QDeclarativeDebugServer::instance(void) + ?addService@QDeclarativeDebugServer@@QAE_NPAVQDeclarativeDebugService@@@Z @ 1845 NONAME ; bool QDeclarativeDebugServer::addService(class QDeclarativeDebugService *) + ?containsPropertyInRevertList@QDeclarativeState@@QBE_NPAVQObject@@ABVQString@@@Z @ 1846 NONAME ; bool QDeclarativeState::containsPropertyInRevertList(class QObject *, class QString const &) const + ?data@QPacket@@QBE?AVQByteArray@@XZ @ 1847 NONAME ; class QByteArray QPacket::data(void) const + ?removeService@QDeclarativeDebugServer@@QAE_NPAVQDeclarativeDebugService@@@Z @ 1848 NONAME ; bool QDeclarativeDebugServer::removeService(class QDeclarativeDebugService *) + ?serviceNames@QDeclarativeDebugServer@@QBE?AVQStringList@@XZ @ 1849 NONAME ; class QStringList QDeclarativeDebugServer::serviceNames(void) const + ??_EQDeclarativeDebugServer@@UAE@I@Z @ 1850 NONAME ; QDeclarativeDebugServer::~QDeclarativeDebugServer(unsigned int) + ?staticMetaObject@QDeclarativeDebugServer@@2UQMetaObject@@B @ 1851 NONAME ; struct QMetaObject const QDeclarativeDebugServer::staticMetaObject + ?services@QDeclarativeDebugServer@@QBE?AV?$QList@PAVQDeclarativeDebugService@@@@XZ @ 1852 NONAME ; class QList QDeclarativeDebugServer::services(void) const + ?rewriteBinding@QDeclarativeCustomParser@@IAEHABVQString@@ABVQByteArray@@@Z @ 1853 NONAME ; int QDeclarativeCustomParser::rewriteBinding(class QString const &, class QByteArray const &) + ?changeValueInRevertList@QDeclarativeState@@QAE_NPAVQObject@@ABVQString@@ABVQVariant@@@Z @ 1854 NONAME ; bool QDeclarativeState::changeValueInRevertList(class QObject *, class QString const &, class QVariant const &) + ?load@QDeclarativePixmap@@QAEXPAVQDeclarativeEngine@@ABVQUrl@@ABVQSize@@V?$QFlags@W4Option@QDeclarativePixmap@@@@@Z @ 1855 NONAME ; void QDeclarativePixmap::load(class QDeclarativeEngine *, class QUrl const &, class QSize const &, class QFlags) + ?implicitHeightChanged@QDeclarativeItemPrivate@@UAEXXZ @ 1856 NONAME ; void QDeclarativeItemPrivate::implicitHeightChanged(void) + ?implicitWidthChanged@QDeclarativeItem@@IAEXXZ @ 1857 NONAME ; void QDeclarativeItem::implicitWidthChanged(void) + ?implicitWidthChanged@QDeclarativeItemPrivate@@UAEXXZ @ 1858 NONAME ; void QDeclarativeItemPrivate::implicitWidthChanged(void) + ?trUtf8@QDeclarativeDebugServer@@SA?AVQString@@PBD0H@Z @ 1859 NONAME ; class QString QDeclarativeDebugServer::trUtf8(char const *, char const *, int) + ?implicitHeightChanged@QDeclarativeItem@@IAEXXZ @ 1860 NONAME ; void QDeclarativeItem::implicitHeightChanged(void) + ?load@QDeclarativePixmap@@QAEXPAVQDeclarativeEngine@@ABVQUrl@@V?$QFlags@W4Option@QDeclarativePixmap@@@@@Z @ 1861 NONAME ; void QDeclarativePixmap::load(class QDeclarativeEngine *, class QUrl const &, class QFlags) + ?trUtf8@QDeclarativeDebugServer@@SA?AVQString@@PBD0@Z @ 1862 NONAME ; class QString QDeclarativeDebugServer::trUtf8(char const *, char const *) + ??_EQDeclarativeDebugServerConnection@@UAE@I@Z @ 1863 NONAME ; QDeclarativeDebugServerConnection::~QDeclarativeDebugServerConnection(unsigned int) + ?receiveMessage@QDeclarativeDebugServer@@QAEXABVQByteArray@@@Z @ 1864 NONAME ; void QDeclarativeDebugServer::receiveMessage(class QByteArray const &) + ??0QDeclarativeDebugServer@@AAE@XZ @ 1865 NONAME ; QDeclarativeDebugServer::QDeclarativeDebugServer(void) + ?tr@QDeclarativeDebugServer@@SA?AVQString@@PBD0@Z @ 1866 NONAME ; class QString QDeclarativeDebugServer::tr(char const *, char const *) + ??1QDeclarativeDebugServer@@UAE@XZ @ 1867 NONAME ; QDeclarativeDebugServer::~QDeclarativeDebugServer(void) + ?sendMessage@QDeclarativeDebugServer@@QAEXPAVQDeclarativeDebugService@@ABVQByteArray@@@Z @ 1868 NONAME ; void QDeclarativeDebugServer::sendMessage(class QDeclarativeDebugService *, class QByteArray const &) + ??1QDeclarativeDebugServerConnection@@UAE@XZ @ 1869 NONAME ; QDeclarativeDebugServerConnection::~QDeclarativeDebugServerConnection(void) + ?qt_metacast@QDeclarativeDebugServer@@UAEPAXPBD@Z @ 1870 NONAME ; void * QDeclarativeDebugServer::qt_metacast(char const *) + ?hasDebuggingClient@QDeclarativeDebugServer@@QBE_NXZ @ 1871 NONAME ; bool QDeclarativeDebugServer::hasDebuggingClient(void) const + ?bindingInRevertList@QDeclarativeState@@QBEPAVQDeclarativeAbstractBinding@@PAVQObject@@ABVQString@@@Z @ 1872 NONAME ; class QDeclarativeAbstractBinding * QDeclarativeState::bindingInRevertList(class QObject *, class QString const &) const + ?getStaticMetaObject@QDeclarativeDebugServer@@SAABUQMetaObject@@XZ @ 1873 NONAME ; struct QMetaObject const & QDeclarativeDebugServer::getStaticMetaObject(void) + ?metaObject@QDeclarativeDebugServer@@UBEPBUQMetaObject@@XZ @ 1874 NONAME ; struct QMetaObject const * QDeclarativeDebugServer::metaObject(void) const + ?d_func@QDeclarativeDebugServer@@ABEPBVQDeclarativeDebugServerPrivate@@XZ @ 1875 NONAME ; class QDeclarativeDebugServerPrivate const * QDeclarativeDebugServer::d_func(void) const + ??0QDeclarativeExpression@@IAE@PAVQDeclarativeContextData@@PAVQObject@@ABVQScriptValue@@AAVQDeclarativeExpressionPrivate@@@Z @ 1876 NONAME ; QDeclarativeExpression::QDeclarativeExpression(class QDeclarativeContextData *, class QObject *, class QScriptValue const &, class QDeclarativeExpressionPrivate &) + ?createObject@QDeclarativeComponent@@IAE?AVQScriptValue@@PAVQObject@@ABV2@@Z @ 1877 NONAME ; class QScriptValue QDeclarativeComponent::createObject(class QObject *, class QScriptValue const &) + ?changeBindingInRevertList@QDeclarativeState@@QAE_NPAVQObject@@ABVQString@@PAVQDeclarativeAbstractBinding@@@Z @ 1878 NONAME ; bool QDeclarativeState::changeBindingInRevertList(class QObject *, class QString const &, class QDeclarativeAbstractBinding *) + ??0QDeclarativeDebugServerConnection@@QAE@XZ @ 1879 NONAME ; QDeclarativeDebugServerConnection::QDeclarativeDebugServerConnection(void) + ?valueInRevertList@QDeclarativeState@@QBE?AVQVariant@@PAVQObject@@ABVQString@@@Z @ 1880 NONAME ; class QVariant QDeclarativeState::valueInRevertList(class QObject *, class QString const &) const + ?removeEntryFromRevertList@QDeclarativeState@@QAE_NPAVQObject@@ABVQString@@@Z @ 1881 NONAME ; bool QDeclarativeState::removeEntryFromRevertList(class QObject *, class QString const &) + ?d_func@QDeclarativeDebugServer@@AAEPAVQDeclarativeDebugServerPrivate@@XZ @ 1882 NONAME ; class QDeclarativeDebugServerPrivate * QDeclarativeDebugServer::d_func(void) + ?tr@QDeclarativeDebugServer@@SA?AVQString@@PBD0H@Z @ 1883 NONAME ; class QString QDeclarativeDebugServer::tr(char const *, char const *, int) + ?implicitWidth@QDeclarativeItemPrivate@@UBEMXZ @ 1884 NONAME ; float QDeclarativeItemPrivate::implicitWidth(void) const diff --git a/src/s60installs/bwins/QtGuiu.def b/src/s60installs/bwins/QtGuiu.def index bf4d99f..6a2bcb9 100644 --- a/src/s60installs/bwins/QtGuiu.def +++ b/src/s60installs/bwins/QtGuiu.def @@ -12908,4 +12908,44 @@ EXPORTS ?resetCursorBlinkTimer@QLineControl@@QAEXXZ @ 12907 NONAME ; void QLineControl::resetCursorBlinkTimer(void) ?setSubFocus@QGraphicsItemPrivate@@QAEXPAVQGraphicsItem@@0@Z @ 12908 NONAME ; void QGraphicsItemPrivate::setSubFocus(class QGraphicsItem *, class QGraphicsItem *) ?clearSubFocus@QGraphicsItemPrivate@@QAEXPAVQGraphicsItem@@0@Z @ 12909 NONAME ; void QGraphicsItemPrivate::clearSubFocus(class QGraphicsItem *, class QGraphicsItem *) + ?hitTest@QTextDocumentLayout@@UBEHABVQPointF@@W4HitTestAccuracy@Qt@@@Z @ 12910 NONAME ; int QTextDocumentLayout::hitTest(class QPointF const &, enum Qt::HitTestAccuracy) const + ?positionInlineObject@QTextDocumentLayout@@MAEXVQTextInlineObject@@HABVQTextFormat@@@Z @ 12911 NONAME ; void QTextDocumentLayout::positionInlineObject(class QTextInlineObject, int, class QTextFormat const &) + ?timerEvent@QTextDocumentLayout@@MAEXPAVQTimerEvent@@@Z @ 12912 NONAME ; void QTextDocumentLayout::timerEvent(class QTimerEvent *) + ?draw@QTextDocumentLayout@@UAEXPAVQPainter@@ABUPaintContext@QAbstractTextDocumentLayout@@@Z @ 12913 NONAME ; void QTextDocumentLayout::draw(class QPainter *, struct QAbstractTextDocumentLayout::PaintContext const &) + ?documentSize@QTextDocumentLayout@@UBE?AVQSizeF@@XZ @ 12914 NONAME ; class QSizeF QTextDocumentLayout::documentSize(void) const + ?drawInlineObject@QTextDocumentLayout@@MAEXPAVQPainter@@ABVQRectF@@VQTextInlineObject@@HABVQTextFormat@@@Z @ 12915 NONAME ; void QTextDocumentLayout::drawInlineObject(class QPainter *, class QRectF const &, class QTextInlineObject, int, class QTextFormat const &) + ?resizeInlineObject@QTextDocumentLayout@@MAEXVQTextInlineObject@@HABVQTextFormat@@@Z @ 12916 NONAME ; void QTextDocumentLayout::resizeInlineObject(class QTextInlineObject, int, class QTextFormat const &) + ?dynamicDocumentSize@QTextDocumentLayout@@QBE?AVQSizeF@@XZ @ 12917 NONAME ; class QSizeF QTextDocumentLayout::dynamicDocumentSize(void) const + ?metaObject@QTextDocumentLayout@@UBEPBUQMetaObject@@XZ @ 12918 NONAME ; struct QMetaObject const * QTextDocumentLayout::metaObject(void) const + ?getStaticMetaObject@QTextDocumentLayout@@SAABUQMetaObject@@XZ @ 12919 NONAME ; struct QMetaObject const & QTextDocumentLayout::getStaticMetaObject(void) + ?blockBoundingRect@QTextDocumentLayout@@UBE?AVQRectF@@ABVQTextBlock@@@Z @ 12920 NONAME ; class QRectF QTextDocumentLayout::blockBoundingRect(class QTextBlock const &) const + ?qt_metacall@QTextDocumentLayout@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 12921 NONAME ; int QTextDocumentLayout::qt_metacall(enum QMetaObject::Call, int, void * *) + ?d_func@QTextDocumentLayout@@AAEPAVQTextDocumentLayoutPrivate@@XZ @ 12922 NONAME ; class QTextDocumentLayoutPrivate * QTextDocumentLayout::d_func(void) + ?isDragEnabled@QTextControl@@QBE_NXZ @ 12923 NONAME ; bool QTextControl::isDragEnabled(void) const + ?staticMetaObject@QTextDocumentLayout@@2UQMetaObject@@B @ 12924 NONAME ; struct QMetaObject const QTextDocumentLayout::staticMetaObject + ?qt_metacast@QTextDocumentLayout@@UAEPAXPBD@Z @ 12925 NONAME ; void * QTextDocumentLayout::qt_metacast(char const *) + ?documentChanged@QTextDocumentLayout@@MAEXHHH@Z @ 12926 NONAME ; void QTextDocumentLayout::documentChanged(int, int, int) + ??1QTextDocumentLayout@@UAE@XZ @ 12927 NONAME ; QTextDocumentLayout::~QTextDocumentLayout(void) + ?layoutStatus@QTextDocumentLayout@@QBEHXZ @ 12928 NONAME ; int QTextDocumentLayout::layoutStatus(void) const + ?setDragEnabled@QTextControl@@QAEX_N@Z @ 12929 NONAME ; void QTextControl::setDragEnabled(bool) + ?d_func@QTextDocumentLayout@@ABEPBVQTextDocumentLayoutPrivate@@XZ @ 12930 NONAME ; class QTextDocumentLayoutPrivate const * QTextDocumentLayout::d_func(void) const + ?idealWidth@QTextDocumentLayout@@QBEMXZ @ 12931 NONAME ; float QTextDocumentLayout::idealWidth(void) const + ?setFixedColumnWidth@QTextDocumentLayout@@QAEXH@Z @ 12932 NONAME ; void QTextDocumentLayout::setFixedColumnWidth(int) + ?cursorWidth@QTextDocumentLayout@@QBEHXZ @ 12933 NONAME ; int QTextDocumentLayout::cursorWidth(void) const + ?trUtf8@QTextDocumentLayout@@SA?AVQString@@PBD0H@Z @ 12934 NONAME ; class QString QTextDocumentLayout::trUtf8(char const *, char const *, int) + ?pageCount@QTextDocumentLayout@@UBEHXZ @ 12935 NONAME ; int QTextDocumentLayout::pageCount(void) const + ?setViewport@QTextDocumentLayout@@QAEXABVQRectF@@@Z @ 12936 NONAME ; void QTextDocumentLayout::setViewport(class QRectF const &) + ?contentHasAlignment@QTextDocumentLayout@@QBE_NXZ @ 12937 NONAME ; bool QTextDocumentLayout::contentHasAlignment(void) const + ?tr@QTextDocumentLayout@@SA?AVQString@@PBD0@Z @ 12938 NONAME ; class QString QTextDocumentLayout::tr(char const *, char const *) + ?setLineHeight@QTextDocumentLayout@@IAEXMW4LineHeightMode@1@@Z @ 12939 NONAME ; void QTextDocumentLayout::setLineHeight(float, enum QTextDocumentLayout::LineHeightMode) + ?tr@QTextDocumentLayout@@SA?AVQString@@PBD0H@Z @ 12940 NONAME ; class QString QTextDocumentLayout::tr(char const *, char const *, int) + ?trUtf8@QTextDocumentLayout@@SA?AVQString@@PBD0@Z @ 12941 NONAME ; class QString QTextDocumentLayout::trUtf8(char const *, char const *) + ?frameBoundingRect@QTextDocumentLayout@@UBE?AVQRectF@@PAVQTextFrame@@@Z @ 12942 NONAME ; class QRectF QTextDocumentLayout::frameBoundingRect(class QTextFrame *) const + ?setCursorWidth@QTextDocumentLayout@@QAEXH@Z @ 12943 NONAME ; void QTextDocumentLayout::setCursorWidth(int) + ??_EQTextDocumentLayout@@UAE@I@Z @ 12944 NONAME ; QTextDocumentLayout::~QTextDocumentLayout(unsigned int) + ??0QTextDocumentLayout@@QAE@PAVQTextDocument@@@Z @ 12945 NONAME ; QTextDocumentLayout::QTextDocumentLayout(class QTextDocument *) + ?doLayout@QTextDocumentLayout@@AAE?AVQRectF@@HHH@Z @ 12946 NONAME ; class QRectF QTextDocumentLayout::doLayout(int, int, int) + ?ensureLayouted@QTextDocumentLayout@@QAEXM@Z @ 12947 NONAME ; void QTextDocumentLayout::ensureLayouted(float) + ?layoutFinished@QTextDocumentLayout@@AAEXXZ @ 12948 NONAME ; void QTextDocumentLayout::layoutFinished(void) + ?dynamicPageCount@QTextDocumentLayout@@QBEHXZ @ 12949 NONAME ; int QTextDocumentLayout::dynamicPageCount(void) const diff --git a/src/s60installs/bwins/QtScriptu.def b/src/s60installs/bwins/QtScriptu.def index 9d998ca..02a0819 100644 --- a/src/s60installs/bwins/QtScriptu.def +++ b/src/s60installs/bwins/QtScriptu.def @@ -403,4 +403,6 @@ EXPORTS ??0Value@QScriptDeclarativeClass@@QAE@PAVQScriptContext@@H@Z @ 402 NONAME ; QScriptDeclarativeClass::Value::Value(class QScriptContext *, int) ??0PersistentIdentifier@QScriptDeclarativeClass@@AAE@PAVQScriptEnginePrivate@@@Z @ 403 NONAME ; QScriptDeclarativeClass::PersistentIdentifier::PersistentIdentifier(class QScriptEnginePrivate *) ?compare@QScriptDeclarativeClass@@UAE_NPAUObject@1@0@Z @ 404 NONAME ; bool QScriptDeclarativeClass::compare(struct QScriptDeclarativeClass::Object *, struct QScriptDeclarativeClass::Object *) + ?toString@PersistentIdentifier@QScriptDeclarativeClass@@QBE?AVQString@@XZ @ 405 NONAME ; class QString QScriptDeclarativeClass::PersistentIdentifier::toString(void) const + ?startsWithUpper@QScriptDeclarativeClass@@QAE_NABQAX@Z @ 406 NONAME ; bool QScriptDeclarativeClass::startsWithUpper(void * const const &) diff --git a/src/s60installs/eabi/QtCoreu.def b/src/s60installs/eabi/QtCoreu.def index 5815b28..fce55dd 100644 --- a/src/s60installs/eabi/QtCoreu.def +++ b/src/s60installs/eabi/QtCoreu.def @@ -3715,4 +3715,6 @@ EXPORTS _ZN24QAbstractDeclarativeData17objectNameChangedE @ 3714 NONAME DATA 4 _ZN23QEventDispatcherSymbian36queueDeferredActiveObjectsCompletionEv @ 3715 NONAME _ZN23QCoreApplicationPrivate18symbianCommandLineEv @ 3716 NONAME + _ZNK11QMetaMethod8revisionEv @ 3717 NONAME + _ZNK13QMetaProperty8revisionEv @ 3718 NONAME diff --git a/src/s60installs/eabi/QtDeclarativeu.def b/src/s60installs/eabi/QtDeclarativeu.def index 1f69061..fe2a7a1 100644 --- a/src/s60installs/eabi/QtDeclarativeu.def +++ b/src/s60installs/eabi/QtDeclarativeu.def @@ -19,24 +19,24 @@ EXPORTS _ZN15QPacketAutoSendD0Ev @ 18 NONAME ABSENT _ZN15QPacketAutoSendD1Ev @ 19 NONAME ABSENT _ZN15QPacketAutoSendD2Ev @ 20 NONAME ABSENT - _ZN15QPacketProtocol11qt_metacallEN11QMetaObject4CallEiPPv @ 21 NONAME ABSENT - _ZN15QPacketProtocol11qt_metacastEPKc @ 22 NONAME ABSENT - _ZN15QPacketProtocol13invalidPacketEv @ 23 NONAME ABSENT - _ZN15QPacketProtocol13packetWrittenEv @ 24 NONAME ABSENT - _ZN15QPacketProtocol16staticMetaObjectE @ 25 NONAME DATA 16 ABSENT - _ZN15QPacketProtocol19getStaticMetaObjectEv @ 26 NONAME ABSENT - _ZN15QPacketProtocol20setMaximumPacketSizeEi @ 27 NONAME ABSENT - _ZN15QPacketProtocol4readEv @ 28 NONAME ABSENT - _ZN15QPacketProtocol4sendERK7QPacket @ 29 NONAME ABSENT - _ZN15QPacketProtocol4sendEv @ 30 NONAME ABSENT - _ZN15QPacketProtocol5clearEv @ 31 NONAME ABSENT - _ZN15QPacketProtocol6deviceEv @ 32 NONAME ABSENT - _ZN15QPacketProtocol9readyReadEv @ 33 NONAME ABSENT - _ZN15QPacketProtocolC1EP9QIODeviceP7QObject @ 34 NONAME ABSENT - _ZN15QPacketProtocolC2EP9QIODeviceP7QObject @ 35 NONAME ABSENT - _ZN15QPacketProtocolD0Ev @ 36 NONAME ABSENT - _ZN15QPacketProtocolD1Ev @ 37 NONAME ABSENT - _ZN15QPacketProtocolD2Ev @ 38 NONAME ABSENT + _ZN15QPacketProtocol11qt_metacallEN11QMetaObject4CallEiPPv @ 21 NONAME + _ZN15QPacketProtocol11qt_metacastEPKc @ 22 NONAME + _ZN15QPacketProtocol13invalidPacketEv @ 23 NONAME + _ZN15QPacketProtocol13packetWrittenEv @ 24 NONAME + _ZN15QPacketProtocol16staticMetaObjectE @ 25 NONAME DATA 16 + _ZN15QPacketProtocol19getStaticMetaObjectEv @ 26 NONAME + _ZN15QPacketProtocol20setMaximumPacketSizeEi @ 27 NONAME + _ZN15QPacketProtocol4readEv @ 28 NONAME + _ZN15QPacketProtocol4sendERK7QPacket @ 29 NONAME + _ZN15QPacketProtocol4sendEv @ 30 NONAME + _ZN15QPacketProtocol5clearEv @ 31 NONAME + _ZN15QPacketProtocol6deviceEv @ 32 NONAME + _ZN15QPacketProtocol9readyReadEv @ 33 NONAME + _ZN15QPacketProtocolC1EP9QIODeviceP7QObject @ 34 NONAME + _ZN15QPacketProtocolC2EP9QIODeviceP7QObject @ 35 NONAME + _ZN15QPacketProtocolD0Ev @ 36 NONAME + _ZN15QPacketProtocolD1Ev @ 37 NONAME + _ZN15QPacketProtocolD2Ev @ 38 NONAME _ZN16QDeclarativeInfoC1EP23QDeclarativeInfoPrivate @ 39 NONAME _ZN16QDeclarativeInfoC1ERKS_ @ 40 NONAME _ZN16QDeclarativeInfoC2EP23QDeclarativeInfoPrivate @ 41 NONAME @@ -241,8 +241,8 @@ EXPORTS _ZN18QDeclarativePixmap23connectDownloadProgressEP7QObjecti @ 240 NONAME _ZN18QDeclarativePixmap4loadEP18QDeclarativeEngineRK4QUrl @ 241 NONAME _ZN18QDeclarativePixmap4loadEP18QDeclarativeEngineRK4QUrlRK5QSize @ 242 NONAME - _ZN18QDeclarativePixmap4loadEP18QDeclarativeEngineRK4QUrlRK5QSizeb @ 243 NONAME - _ZN18QDeclarativePixmap4loadEP18QDeclarativeEngineRK4QUrlb @ 244 NONAME + _ZN18QDeclarativePixmap4loadEP18QDeclarativeEngineRK4QUrlRK5QSizeb @ 243 NONAME ABSENT + _ZN18QDeclarativePixmap4loadEP18QDeclarativeEngineRK4QUrlb @ 244 NONAME ABSENT _ZN18QDeclarativePixmap5clearEP7QObject @ 245 NONAME _ZN18QDeclarativePixmap5clearEv @ 246 NONAME _ZN18QDeclarativePixmap9setPixmapERK7QPixmap @ 247 NONAME @@ -1059,20 +1059,20 @@ EXPORTS _ZN39QDeclarativeNetworkAccessManagerFactoryD0Ev @ 1058 NONAME _ZN39QDeclarativeNetworkAccessManagerFactoryD1Ev @ 1059 NONAME _ZN39QDeclarativeNetworkAccessManagerFactoryD2Ev @ 1060 NONAME - _ZN7QPacket5clearEv @ 1061 NONAME ABSENT - _ZN7QPacketC1ERK10QByteArray @ 1062 NONAME ABSENT - _ZN7QPacketC1ERKS_ @ 1063 NONAME ABSENT - _ZN7QPacketC1Ev @ 1064 NONAME ABSENT - _ZN7QPacketC2ERK10QByteArray @ 1065 NONAME ABSENT - _ZN7QPacketC2ERKS_ @ 1066 NONAME ABSENT - _ZN7QPacketC2Ev @ 1067 NONAME ABSENT - _ZN7QPacketD0Ev @ 1068 NONAME ABSENT - _ZN7QPacketD1Ev @ 1069 NONAME ABSENT - _ZN7QPacketD2Ev @ 1070 NONAME ABSENT + _ZN7QPacket5clearEv @ 1061 NONAME + _ZN7QPacketC1ERK10QByteArray @ 1062 NONAME + _ZN7QPacketC1ERKS_ @ 1063 NONAME + _ZN7QPacketC1Ev @ 1064 NONAME + _ZN7QPacketC2ERK10QByteArray @ 1065 NONAME + _ZN7QPacketC2ERKS_ @ 1066 NONAME + _ZN7QPacketC2Ev @ 1067 NONAME + _ZN7QPacketD0Ev @ 1068 NONAME + _ZN7QPacketD1Ev @ 1069 NONAME + _ZN7QPacketD2Ev @ 1070 NONAME _ZNK15QDeclarativePen10metaObjectEv @ 1071 NONAME ABSENT - _ZNK15QPacketProtocol10metaObjectEv @ 1072 NONAME ABSENT - _ZNK15QPacketProtocol16packetsAvailableEv @ 1073 NONAME ABSENT - _ZNK15QPacketProtocol17maximumPacketSizeEv @ 1074 NONAME ABSENT + _ZNK15QPacketProtocol10metaObjectEv @ 1072 NONAME + _ZNK15QPacketProtocol16packetsAvailableEv @ 1073 NONAME + _ZNK15QPacketProtocol17maximumPacketSizeEv @ 1074 NONAME _ZNK16QDeclarativeItem10metaObjectEv @ 1075 NONAME _ZNK16QDeclarativeItem10parentItemEv @ 1076 NONAME _ZNK16QDeclarativeItem10widthValidEv @ 1077 NONAME @@ -1524,10 +1524,10 @@ EXPORTS _ZNK36QDeclarativeDomValueValueInterceptor6objectEv @ 1523 NONAME ABSENT _ZNK38QDeclarativeDebugObjectExpressionWatch10expressionEv @ 1524 NONAME ABSENT _ZNK38QDeclarativeDebugObjectExpressionWatch10metaObjectEv @ 1525 NONAME ABSENT - _ZNK7QPacket7isEmptyEv @ 1526 NONAME ABSENT + _ZNK7QPacket7isEmptyEv @ 1526 NONAME _ZTI15QDeclarativePen @ 1527 NONAME ABSENT _ZTI15QPacketAutoSend @ 1528 NONAME ABSENT - _ZTI15QPacketProtocol @ 1529 NONAME ABSENT + _ZTI15QPacketProtocol @ 1529 NONAME _ZTI16QDeclarativeItem @ 1530 NONAME _ZTI16QDeclarativeText @ 1531 NONAME ABSENT _ZTI16QDeclarativeView @ 1532 NONAME @@ -1574,10 +1574,10 @@ EXPORTS _ZTI36QDeclarativePropertyValueInterceptor @ 1573 NONAME _ZTI38QDeclarativeDebugObjectExpressionWatch @ 1574 NONAME ABSENT _ZTI39QDeclarativeNetworkAccessManagerFactory @ 1575 NONAME - _ZTI7QPacket @ 1576 NONAME ABSENT + _ZTI7QPacket @ 1576 NONAME _ZTV15QDeclarativePen @ 1577 NONAME ABSENT _ZTV15QPacketAutoSend @ 1578 NONAME ABSENT - _ZTV15QPacketProtocol @ 1579 NONAME ABSENT + _ZTV15QPacketProtocol @ 1579 NONAME _ZTV16QDeclarativeItem @ 1580 NONAME _ZTV16QDeclarativeText @ 1581 NONAME ABSENT _ZTV16QDeclarativeView @ 1582 NONAME @@ -1623,7 +1623,7 @@ EXPORTS _ZTV36QDeclarativePropertyValueInterceptor @ 1622 NONAME _ZTV38QDeclarativeDebugObjectExpressionWatch @ 1623 NONAME ABSENT _ZTV39QDeclarativeNetworkAccessManagerFactory @ 1624 NONAME - _ZTV7QPacket @ 1625 NONAME ABSENT + _ZTV7QPacket @ 1625 NONAME _ZThn16_N16QDeclarativeItem10classBeginEv @ 1626 NONAME _ZThn16_N16QDeclarativeItem17componentCompleteEv @ 1627 NONAME _ZThn16_N16QDeclarativeItemD0Ev @ 1628 NONAME @@ -1677,9 +1677,9 @@ EXPORTS _ZN23QDeclarativeEngineDebug10newObjectsEv @ 1676 NONAME ABSENT _ZN17QDeclarativeState20addEntryToRevertListERK18QDeclarativeAction @ 1677 NONAME _ZN17QDeclarativeState22addEntriesToRevertListERK5QListI18QDeclarativeActionE @ 1678 NONAME - _ZN17QDeclarativeState23changeValueInRevertListEP7QObjectRK10QByteArrayRK8QVariant @ 1679 NONAME - _ZN17QDeclarativeState25changeBindingInRevertListEP7QObjectRK10QByteArrayP27QDeclarativeAbstractBinding @ 1680 NONAME - _ZN17QDeclarativeState25removeEntryFromRevertListEP7QObjectRK10QByteArray @ 1681 NONAME + _ZN17QDeclarativeState23changeValueInRevertListEP7QObjectRK10QByteArrayRK8QVariant @ 1679 NONAME ABSENT + _ZN17QDeclarativeState25changeBindingInRevertListEP7QObjectRK10QByteArrayP27QDeclarativeAbstractBinding @ 1680 NONAME ABSENT + _ZN17QDeclarativeState25removeEntryFromRevertListEP7QObjectRK10QByteArray @ 1681 NONAME ABSENT _ZN17QDeclarativeState30removeAllEntriesFromRevertListEP7QObject @ 1682 NONAME _ZN23QDeclarativeItemPrivate10data_clearEP24QDeclarativeListPropertyI7QObjectE @ 1683 NONAME _ZN23QDeclarativeItemPrivate10data_countEP24QDeclarativeListPropertyI7QObjectE @ 1684 NONAME @@ -1706,9 +1706,9 @@ EXPORTS _ZN27QDeclarativePropertyChangesD1Ev @ 1705 NONAME ABSENT _ZN27QDeclarativePropertyChangesD2Ev @ 1706 NONAME ABSENT _ZNK17QDeclarativeState13isStateActiveEv @ 1707 NONAME - _ZNK17QDeclarativeState17valueInRevertListEP7QObjectRK10QByteArray @ 1708 NONAME - _ZNK17QDeclarativeState19bindingInRevertListEP7QObjectRK10QByteArray @ 1709 NONAME - _ZNK17QDeclarativeState28containsPropertyInRevertListEP7QObjectRK10QByteArray @ 1710 NONAME + _ZNK17QDeclarativeState17valueInRevertListEP7QObjectRK10QByteArray @ 1708 NONAME ABSENT + _ZNK17QDeclarativeState19bindingInRevertListEP7QObjectRK10QByteArray @ 1709 NONAME ABSENT + _ZNK17QDeclarativeState28containsPropertyInRevertListEP7QObjectRK10QByteArray @ 1710 NONAME ABSENT _ZNK26QDeclarativeStateOperation5stateEv @ 1711 NONAME _ZNK27QDeclarativePropertyChanges10expressionERK10QByteArray @ 1712 NONAME ABSENT _ZNK27QDeclarativePropertyChanges10isExplicitEv @ 1713 NONAME ABSENT @@ -1747,8 +1747,8 @@ EXPORTS _ZN21QDeclarativeListModelC1EPKS_P32QDeclarativeListModelWorkerAgent @ 1746 NONAME ABSENT _ZN21QDeclarativeListModelC2EPKS_P32QDeclarativeListModelWorkerAgent @ 1747 NONAME ABSENT _ZNK21QDeclarativeListModel14inWorkerThreadEv @ 1748 NONAME ABSENT - _ZN23QDeclarativeDebugHelper15getScriptEngineEP18QDeclarativeEngine @ 1749 NONAME ABSENT - _ZN23QDeclarativeDebugHelper26setAnimationSlowDownFactorEf @ 1750 NONAME ABSENT + _ZN23QDeclarativeDebugHelper15getScriptEngineEP18QDeclarativeEngine @ 1749 NONAME + _ZN23QDeclarativeDebugHelper26setAnimationSlowDownFactorEf @ 1750 NONAME _ZN17QDeclarativeTimer10classBeginEv @ 1751 NONAME ABSENT _ZN17QDeclarativeTimer10setRunningEb @ 1752 NONAME ABSENT _ZN17QDeclarativeTimer11qt_metacallEN11QMetaObject4CallEiPPv @ 1753 NONAME ABSENT @@ -1885,4 +1885,40 @@ EXPORTS _ZThn8_N29QDeclarativeAbstractAnimationD1Ev @ 1884 NONAME ABSENT _ZN23QDeclarativeDebugHelper15enableDebuggingEv @ 1885 NONAME _ZN27QDeclarativePropertyPrivate7connectEPK7QObjectiS2_iiPi @ 1886 NONAME ABSENT + _ZN16QDeclarativeItem20implicitWidthChangedEv @ 1887 NONAME + _ZN16QDeclarativeItem21implicitHeightChangedEv @ 1888 NONAME + _ZN17QDeclarativeState23changeValueInRevertListEP7QObjectRK7QStringRK8QVariant @ 1889 NONAME + _ZN17QDeclarativeState25changeBindingInRevertListEP7QObjectRK7QStringP27QDeclarativeAbstractBinding @ 1890 NONAME + _ZN17QDeclarativeState25removeEntryFromRevertListEP7QObjectRK7QString @ 1891 NONAME + _ZN18QDeclarativePixmap4loadEP18QDeclarativeEngineRK4QUrl6QFlagsINS_6OptionEE @ 1892 NONAME + _ZN18QDeclarativePixmap4loadEP18QDeclarativeEngineRK4QUrlRK5QSize6QFlagsINS_6OptionEE @ 1893 NONAME + _ZN21QDeclarativeComponent12createObjectEP7QObjectRK12QScriptValue @ 1894 NONAME + _ZN22QDeclarativeExpressionC1EP23QDeclarativeContextDataP7QObjectRK12QScriptValueR29QDeclarativeExpressionPrivate @ 1895 NONAME + _ZN22QDeclarativeExpressionC2EP23QDeclarativeContextDataP7QObjectRK12QScriptValueR29QDeclarativeExpressionPrivate @ 1896 NONAME + _ZN23QDeclarativeDebugServer10addServiceEP24QDeclarativeDebugService @ 1897 NONAME + _ZN23QDeclarativeDebugServer11qt_metacallEN11QMetaObject4CallEiPPv @ 1898 NONAME + _ZN23QDeclarativeDebugServer11qt_metacastEPKc @ 1899 NONAME + _ZN23QDeclarativeDebugServer11sendMessageEP24QDeclarativeDebugServiceRK10QByteArray @ 1900 NONAME + _ZN23QDeclarativeDebugServer13removeServiceEP24QDeclarativeDebugService @ 1901 NONAME + _ZN23QDeclarativeDebugServer14receiveMessageERK10QByteArray @ 1902 NONAME + _ZN23QDeclarativeDebugServer16staticMetaObjectE @ 1903 NONAME DATA 16 + _ZN23QDeclarativeDebugServer19getStaticMetaObjectEv @ 1904 NONAME + _ZN23QDeclarativeDebugServer8instanceEv @ 1905 NONAME + _ZN23QDeclarativeDebugServerC1Ev @ 1906 NONAME + _ZN23QDeclarativeDebugServerC2Ev @ 1907 NONAME + _ZN23QDeclarativeItemPrivate20implicitWidthChangedEv @ 1908 NONAME + _ZN23QDeclarativeItemPrivate21implicitHeightChangedEv @ 1909 NONAME + _ZN24QDeclarativeCustomParser14rewriteBindingERK7QStringRK10QByteArray @ 1910 NONAME + _ZNK17QDeclarativeState17valueInRevertListEP7QObjectRK7QString @ 1911 NONAME + _ZNK17QDeclarativeState19bindingInRevertListEP7QObjectRK7QString @ 1912 NONAME + _ZNK17QDeclarativeState28containsPropertyInRevertListEP7QObjectRK7QString @ 1913 NONAME + _ZNK23QDeclarativeDebugServer10metaObjectEv @ 1914 NONAME + _ZNK23QDeclarativeDebugServer12serviceNamesEv @ 1915 NONAME + _ZNK23QDeclarativeDebugServer18hasDebuggingClientEv @ 1916 NONAME + _ZNK23QDeclarativeDebugServer8servicesEv @ 1917 NONAME + _ZNK23QDeclarativeItemPrivate13implicitWidthEv @ 1918 NONAME + _ZNK23QDeclarativeItemPrivate14implicitHeightEv @ 1919 NONAME + _ZNK7QPacket4dataEv @ 1920 NONAME + _ZTI23QDeclarativeDebugServer @ 1921 NONAME + _ZTV23QDeclarativeDebugServer @ 1922 NONAME diff --git a/src/s60installs/eabi/QtGuiu.def b/src/s60installs/eabi/QtGuiu.def index 48976a1..d552931 100644 --- a/src/s60installs/eabi/QtGuiu.def +++ b/src/s60installs/eabi/QtGuiu.def @@ -12108,4 +12108,39 @@ EXPORTS _ZN20QGraphicsItemPrivate11setSubFocusEP13QGraphicsItemS1_ @ 12107 NONAME _ZN20QGraphicsItemPrivate13clearSubFocusEP13QGraphicsItemS1_ @ 12108 NONAME _ZN12QLineControl21resetCursorBlinkTimerEv @ 12109 NONAME + _ZN12QTextControl14setDragEnabledEb @ 12110 NONAME + _ZN19QTextDocumentLayout10timerEventEP11QTimerEvent @ 12111 NONAME + _ZN19QTextDocumentLayout11qt_metacallEN11QMetaObject4CallEiPPv @ 12112 NONAME + _ZN19QTextDocumentLayout11qt_metacastEPKc @ 12113 NONAME + _ZN19QTextDocumentLayout11setViewportERK6QRectF @ 12114 NONAME + _ZN19QTextDocumentLayout13setLineHeightEfNS_14LineHeightModeE @ 12115 NONAME + _ZN19QTextDocumentLayout14ensureLayoutedEf @ 12116 NONAME + _ZN19QTextDocumentLayout14layoutFinishedEv @ 12117 NONAME + _ZN19QTextDocumentLayout14setCursorWidthEi @ 12118 NONAME + _ZN19QTextDocumentLayout15documentChangedEiii @ 12119 NONAME + _ZN19QTextDocumentLayout16drawInlineObjectEP8QPainterRK6QRectF17QTextInlineObjectiRK11QTextFormat @ 12120 NONAME + _ZN19QTextDocumentLayout16staticMetaObjectE @ 12121 NONAME DATA 16 + _ZN19QTextDocumentLayout18resizeInlineObjectE17QTextInlineObjectiRK11QTextFormat @ 12122 NONAME + _ZN19QTextDocumentLayout19getStaticMetaObjectEv @ 12123 NONAME + _ZN19QTextDocumentLayout19setFixedColumnWidthEi @ 12124 NONAME + _ZN19QTextDocumentLayout20positionInlineObjectE17QTextInlineObjectiRK11QTextFormat @ 12125 NONAME + _ZN19QTextDocumentLayout4drawEP8QPainterRKN27QAbstractTextDocumentLayout12PaintContextE @ 12126 NONAME + _ZN19QTextDocumentLayout8doLayoutEiii @ 12127 NONAME + _ZN19QTextDocumentLayoutC1EP13QTextDocument @ 12128 NONAME + _ZN19QTextDocumentLayoutC2EP13QTextDocument @ 12129 NONAME + _ZNK12QTextControl13isDragEnabledEv @ 12130 NONAME + _ZNK19QTextDocumentLayout10idealWidthEv @ 12131 NONAME + _ZNK19QTextDocumentLayout10metaObjectEv @ 12132 NONAME + _ZNK19QTextDocumentLayout11cursorWidthEv @ 12133 NONAME + _ZNK19QTextDocumentLayout12documentSizeEv @ 12134 NONAME + _ZNK19QTextDocumentLayout12layoutStatusEv @ 12135 NONAME + _ZNK19QTextDocumentLayout16dynamicPageCountEv @ 12136 NONAME + _ZNK19QTextDocumentLayout17blockBoundingRectERK10QTextBlock @ 12137 NONAME + _ZNK19QTextDocumentLayout17frameBoundingRectEP10QTextFrame @ 12138 NONAME + _ZNK19QTextDocumentLayout19contentHasAlignmentEv @ 12139 NONAME + _ZNK19QTextDocumentLayout19dynamicDocumentSizeEv @ 12140 NONAME + _ZNK19QTextDocumentLayout7hitTestERK7QPointFN2Qt15HitTestAccuracyE @ 12141 NONAME + _ZNK19QTextDocumentLayout9pageCountEv @ 12142 NONAME + _ZTI19QTextDocumentLayout @ 12143 NONAME + _ZTV19QTextDocumentLayout @ 12144 NONAME diff --git a/src/s60installs/eabi/QtScriptu.def b/src/s60installs/eabi/QtScriptu.def index b26f9c7..f7da892 100644 --- a/src/s60installs/eabi/QtScriptu.def +++ b/src/s60installs/eabi/QtScriptu.def @@ -441,4 +441,6 @@ EXPORTS _ZN25QScriptEngineAgentPrivate18didReachBreakpointERKN5QTJSC17DebuggerCallFrameEii @ 440 NONAME _ZNK23QScriptDeclarativeClass12supportsCallEv @ 441 NONAME _ZNK23QScriptDeclarativeClass5Value13toScriptValueEP13QScriptEngine @ 442 NONAME + _ZN23QScriptDeclarativeClass15startsWithUpperERKPv @ 443 NONAME + _ZNK23QScriptDeclarativeClass20PersistentIdentifier8toStringEv @ 444 NONAME diff --git a/tools/qml/qdeclarativetester.cpp b/tools/qml/qdeclarativetester.cpp index 3f4be57..11f81fc 100644 --- a/tools/qml/qdeclarativetester.cpp +++ b/tools/qml/qdeclarativetester.cpp @@ -48,7 +48,10 @@ #include #include #include +#include +#ifndef Q_OS_SYMBIAN #include +#endif QT_BEGIN_NAMESPACE @@ -266,7 +269,9 @@ void QDeclarativeTester::save() void QDeclarativeTester::updateCurrentTime(int msec) { +#ifndef Q_OS_SYMBIAN QDeclarativeItemPrivate::setConsistentTime(msec); +#endif if (!testscript && msec > 16 && options & QDeclarativeViewer::Snapshot) return; -- cgit v0.12 From 88b072b3644cfd960367096ae0103e8ddef0d06d Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Tue, 1 Feb 2011 13:09:44 +1000 Subject: PinchArea sometimes failed. Almost always failed on Mac and could fail on other systems due to QDeclarativePinchEvent::m_accepted not being initialized. Task-number: QTBUG-15491 Reviewed-by: Bea Lam --- .../graphicsitems/qdeclarativepincharea.cpp | 5 ++++- .../graphicsitems/qdeclarativepincharea_p.h | 2 +- .../graphicsitems/qdeclarativepincharea_p_p.h | 2 +- .../tst_qdeclarativepincharea.cpp | 24 ---------------------- 4 files changed, 6 insertions(+), 27 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativepincharea.cpp b/src/declarative/graphicsitems/qdeclarativepincharea.cpp index 436099e..eae83f6 100644 --- a/src/declarative/graphicsitems/qdeclarativepincharea.cpp +++ b/src/declarative/graphicsitems/qdeclarativepincharea.cpp @@ -312,6 +312,7 @@ void QDeclarativePinchArea::updatePinch() pe.setPoint1(d->lastPoint1); pe.setPoint2(d->lastPoint2); emit pinchFinished(&pe); + d->pinchStartDist = 0; if (d->pinch && d->pinch->target()) d->pinch->setActive(false); } @@ -363,7 +364,9 @@ void QDeclarativePinchArea::updatePinch() if (pe.accepted()) { d->inPinch = true; d->stealMouse = true; - grabMouse(); + QGraphicsScene *s = scene(); + if (s && s->mouseGrabberItem() != this) + grabMouse(); setKeepMouseGrab(true); if (d->pinch && d->pinch->target()) { d->pinchStartPos = pinch()->target()->pos(); diff --git a/src/declarative/graphicsitems/qdeclarativepincharea_p.h b/src/declarative/graphicsitems/qdeclarativepincharea_p.h index cd5423d..6d04708 100644 --- a/src/declarative/graphicsitems/qdeclarativepincharea_p.h +++ b/src/declarative/graphicsitems/qdeclarativepincharea_p.h @@ -207,7 +207,7 @@ class Q_AUTOTEST_EXPORT QDeclarativePinchEvent : public QObject public: QDeclarativePinchEvent(QPointF c, qreal s, qreal a, qreal r) - : QObject(), m_center(c), m_scale(s), m_angle(a), m_rotation(r) {} + : QObject(), m_center(c), m_scale(s), m_angle(a), m_rotation(r), m_accepted(true) {} QPointF center() const { return m_center; } QPointF startCenter() const { return m_startCenter; } diff --git a/src/declarative/graphicsitems/qdeclarativepincharea_p_p.h b/src/declarative/graphicsitems/qdeclarativepincharea_p_p.h index b1cdf68..5641e35 100644 --- a/src/declarative/graphicsitems/qdeclarativepincharea_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativepincharea_p_p.h @@ -68,7 +68,7 @@ class QDeclarativePinchAreaPrivate : public QDeclarativeItemPrivate public: QDeclarativePinchAreaPrivate() : absorb(true), stealMouse(false), inPinch(false) - , pinchRejected(false), pinch(0) + , pinchRejected(false), pinch(0), pinchStartDist(0) { } diff --git a/tests/auto/declarative/qdeclarativepincharea/tst_qdeclarativepincharea.cpp b/tests/auto/declarative/qdeclarativepincharea/tst_qdeclarativepincharea.cpp index b7e7a99..f175033 100644 --- a/tests/auto/declarative/qdeclarativepincharea/tst_qdeclarativepincharea.cpp +++ b/tests/auto/declarative/qdeclarativepincharea/tst_qdeclarativepincharea.cpp @@ -228,14 +228,8 @@ void tst_QDeclarativePinchArea::scale() p2 += QPoint(10,10); QTest::touchEvent(vp).move(0, p1).move(1, p2); -#ifdef Q_OS_MAC - QEXPECT_FAIL("", "todo on mac", Continue); -#endif QCOMPARE(root->property("scale").toReal(), 1.5); QCOMPARE(root->property("center").toPointF(), QPointF(40, 40)); // blackrect is at 50,50 -#ifdef Q_OS_MAC - QEXPECT_FAIL("", "todo on mac", Continue); -#endif QCOMPARE(blackRect->scale(), 1.5); // scale beyond bound @@ -243,9 +237,6 @@ void tst_QDeclarativePinchArea::scale() p2 += QPoint(50,50); QTest::touchEvent(vp).move(0, p1).move(1, p2); -#ifdef Q_OS_MAC - QEXPECT_FAIL("", "todo on mac", Continue); -#endif QCOMPARE(blackRect->scale(), 2.0); QTest::touchEvent(vp).release(0, p1).release(1, p2); @@ -292,18 +283,9 @@ void tst_QDeclarativePinchArea::pan() p2 += QPoint(10,10); QTest::touchEvent(vp).move(0, p1).move(1, p2); -#ifdef Q_OS_MAC - QEXPECT_FAIL("", "todo mac", Continue); -#endif QCOMPARE(root->property("center").toPointF(), QPointF(60, 60)); // blackrect is at 50,50 -#ifdef Q_OS_MAC - QEXPECT_FAIL("", "todo mac", Continue); -#endif QCOMPARE(blackRect->x(), 60.0); -#ifdef Q_OS_MAC - QEXPECT_FAIL("", "todo mac", Continue); -#endif QCOMPARE(blackRect->y(), 60.0); // pan x beyond bound @@ -311,13 +293,7 @@ void tst_QDeclarativePinchArea::pan() p2 += QPoint(100,100); QTest::touchEvent(vp).move(0, p1).move(1, p2); -#ifdef Q_OS_MAC - QEXPECT_FAIL("", "todo mac", Continue); -#endif QCOMPARE(blackRect->x(), 140.0); -#ifdef Q_OS_MAC - QEXPECT_FAIL("", "todo mac", Continue); -#endif QCOMPARE(blackRect->y(), 160.0); QTest::touchEvent(vp).release(0, p1).release(1, p2); -- cgit v0.12 From 0e456bf74dfea10c0f5c164eb5a920e4661a91b2 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Tue, 1 Feb 2011 13:15:28 +0100 Subject: Fix a crash when undoing form layout In a rare case when breaking a layout might make widgets overlap, the internal heuristic failed when recreating an original layout during undo. Some widgets were removed from the grid. The patch fixes this heuristic (makes sure we don't remove other widgets). Creating a form layout from overlapping widgets works better now. Reviewed-by: Friedemann Kleint Task-number: QTCREATORBUG-3616 --- tools/designer/src/lib/shared/layout.cpp | 22 ++++++++++++++-------- tools/designer/src/lib/shared/qlayout_widget.cpp | 3 +-- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/tools/designer/src/lib/shared/layout.cpp b/tools/designer/src/lib/shared/layout.cpp index c9ffe71..9fe438b 100644 --- a/tools/designer/src/lib/shared/layout.cpp +++ b/tools/designer/src/lib/shared/layout.cpp @@ -996,13 +996,23 @@ bool Grid::shrinkFormLayoutSpans() for (WidgetSet::const_iterator it = widgets.constBegin(); it != cend ; ++it) { QWidget *w = *it; int row, col, rowspan, colspan; - locateWidget(w, row, col, rowspan, colspan); + if (!locateWidget(w, row, col, rowspan, colspan)) + qDebug("ooops, widget '%s' does not fit in layout", w->objectName().toUtf8().constData()); const int maxColSpan = col == 0 ? 2 : 1; const int newColSpan = qMin(colspan, maxColSpan); const int newRowSpan = qMin(rowspan, maxRowSpan); if (newColSpan != colspan || newRowSpan != rowspan) { - setCells(QRect(col, row, colspan, rowspan), 0); - setCells(QRect(col, row, newColSpan, newRowSpan), w); + // in case like this: + // W1 W1 + // W1 W2 + // do: + // W1 0 + // 0 W2 + for (int i = row; i < row + rowspan - 1; i++) + for (int j = col; j < col + colspan - 1; j++) + if (i > row + newColSpan - 1 || j > col + newRowSpan - 1) + if (cell(i, j) == w) + setCell(i, j, 0); shrunk = true; } } @@ -1177,11 +1187,7 @@ void GridLayout::doLayout() if (const Spacer *spacer = qobject_cast(w)) alignment = spacer->alignment(); - if (rs * cs == 1) { - addWidgetToGrid(layout, w, r, c, 1, 1, alignment); - } else { - addWidgetToGrid(layout, w, r, c, rs, cs, alignment); - } + addWidgetToGrid(layout, w, r, c, rs, cs, alignment); w->show(); } else { diff --git a/tools/designer/src/lib/shared/qlayout_widget.cpp b/tools/designer/src/lib/shared/qlayout_widget.cpp index 20db606..4debb5e 100644 --- a/tools/designer/src/lib/shared/qlayout_widget.cpp +++ b/tools/designer/src/lib/shared/qlayout_widget.cpp @@ -1181,8 +1181,7 @@ QRect LayoutHelper::itemInfo(QLayout *lt, const QWidget *widget) const } else { for (int c = 0; c < FormLayoutColumns; c++) { const QFormLayout::ItemRole role = c == 0 ? QFormLayout::LabelRole : QFormLayout::FieldRole; - if (widgets[c]) { - Q_ASSERT(BoxLayoutHelper::findItemOfWidget(items, widgets[c])); + if (widgets[c] && BoxLayoutHelper::findItemOfWidget(items, widgets[c])) { formLayout->setWidget(r, role, widgets[c]); } else { formLayout->setItem(r, role, createFormSpacer()); -- cgit v0.12 From bb84c5ef4f620af659395b66e6ed792a380b9a1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Tue, 1 Feb 2011 15:17:53 +0100 Subject: Don't ignore source-text when generating qsTrId translations for QML Reviewed-by: ossi --- tests/auto/linguist/lupdate/testdata/good/parseqml/main.qml | 3 +++ tests/auto/linguist/lupdate/testdata/good/parseqml/project.ts.result | 5 +++++ tools/linguist/lupdate/qdeclarative.cpp | 2 +- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/tests/auto/linguist/lupdate/testdata/good/parseqml/main.qml b/tests/auto/linguist/lupdate/testdata/good/parseqml/main.qml index 768a4e2..c966fa1 100644 --- a/tests/auto/linguist/lupdate/testdata/good/parseqml/main.qml +++ b/tests/auto/linguist/lupdate/testdata/good/parseqml/main.qml @@ -93,5 +93,8 @@ QtObject { //: qsTrId() with comment, meta-data and plurals. //~ well-tested True qsTrId("qtn_bar_baz", 10); + + //% "Source text" + qsTrId("qtn_baz_biz"); } } diff --git a/tests/auto/linguist/lupdate/testdata/good/parseqml/project.ts.result b/tests/auto/linguist/lupdate/testdata/good/parseqml/project.ts.result index 7dac8cb..4843902 100644 --- a/tests/auto/linguist/lupdate/testdata/good/parseqml/project.ts.result +++ b/tests/auto/linguist/lupdate/testdata/good/parseqml/project.ts.result @@ -27,6 +27,11 @@ True + + + Source text + + BarContext diff --git a/tools/linguist/lupdate/qdeclarative.cpp b/tools/linguist/lupdate/qdeclarative.cpp index b85b1a7..1c1e9ad 100644 --- a/tools/linguist/lupdate/qdeclarative.cpp +++ b/tools/linguist/lupdate/qdeclarative.cpp @@ -225,7 +225,7 @@ protected: const QString id = literal->value->asString(); bool plural = node->arguments->next; - TranslatorMessage msg(QString(), QString(), + TranslatorMessage msg(QString(), sourcetext, QString(), QString(), m_fileName, node->firstSourceLocation().startLine, QStringList(), TranslatorMessage::Unfinished, plural); -- cgit v0.12 From e09cd7062bb50067eb2d2db9197eb9d4ee170360 Mon Sep 17 00:00:00 2001 From: juhvu Date: Wed, 2 Feb 2011 10:16:16 +1000 Subject: Froze two more symbols and fixed compilation error (QtQuick11). Reviewed-by: Martin Jones --- src/declarative/util/qdeclarativestate_p.h | 4 ++-- src/s60installs/bwins/QtGuiu.def | 2 ++ src/s60installs/eabi/QtGuiu.def | 2 ++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/declarative/util/qdeclarativestate_p.h b/src/declarative/util/qdeclarativestate_p.h index 45e6e8d..60d0e0b 100644 --- a/src/declarative/util/qdeclarativestate_p.h +++ b/src/declarative/util/qdeclarativestate_p.h @@ -45,7 +45,7 @@ #include #include #include -#include +#include #include QT_BEGIN_HEADER @@ -76,7 +76,7 @@ public: QVariant toValue; QDeclarativeAbstractBinding *fromBinding; - QDeclarativeAbstractBinding::Pointer toBinding; + QWeakPointer toBinding; QDeclarativeActionEvent *event; //strictly for matching diff --git a/src/s60installs/bwins/QtGuiu.def b/src/s60installs/bwins/QtGuiu.def index 6a2bcb9..adf2b3c 100644 --- a/src/s60installs/bwins/QtGuiu.def +++ b/src/s60installs/bwins/QtGuiu.def @@ -12948,4 +12948,6 @@ EXPORTS ?ensureLayouted@QTextDocumentLayout@@QAEXM@Z @ 12947 NONAME ; void QTextDocumentLayout::ensureLayouted(float) ?layoutFinished@QTextDocumentLayout@@AAEXXZ @ 12948 NONAME ; void QTextDocumentLayout::layoutFinished(void) ?dynamicPageCount@QTextDocumentLayout@@QBEHXZ @ 12949 NONAME ; int QTextDocumentLayout::dynamicPageCount(void) const + ?setWordSelectionEnabled@QTextControl@@QAEX_N@Z @ 12950 NONAME ; void QTextControl::setWordSelectionEnabled(bool) + ?isWordSelectionEnabled@QTextControl@@QBE_NXZ @ 12951 NONAME ; bool QTextControl::isWordSelectionEnabled(void) const diff --git a/src/s60installs/eabi/QtGuiu.def b/src/s60installs/eabi/QtGuiu.def index d552931..564f530 100644 --- a/src/s60installs/eabi/QtGuiu.def +++ b/src/s60installs/eabi/QtGuiu.def @@ -12143,4 +12143,6 @@ EXPORTS _ZNK19QTextDocumentLayout9pageCountEv @ 12142 NONAME _ZTI19QTextDocumentLayout @ 12143 NONAME _ZTV19QTextDocumentLayout @ 12144 NONAME + _ZN12QTextControl23setWordSelectionEnabledEb @ 12145 NONAME + _ZNK12QTextControl22isWordSelectionEnabledEv @ 12146 NONAME -- cgit v0.12 From 501180c6fbed0857126da2bb0ff1f17ee35472c6 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Wed, 2 Feb 2011 11:20:29 +1000 Subject: Make sure we update Loader size if item size changes after creation. Task-number: QTBUG-17114 Reviewed-by: Bea Lam --- src/declarative/graphicsitems/qdeclarativeloader.cpp | 7 ++++++- .../qdeclarativeloader/data/QTBUG_17114.qml | 18 ++++++++++++++++++ .../qdeclarativeloader/tst_qdeclarativeloader.cpp | 13 +++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 tests/auto/declarative/qdeclarativeloader/data/QTBUG_17114.qml diff --git a/src/declarative/graphicsitems/qdeclarativeloader.cpp b/src/declarative/graphicsitems/qdeclarativeloader.cpp index 562ef08..6c1f1be 100644 --- a/src/declarative/graphicsitems/qdeclarativeloader.cpp +++ b/src/declarative/graphicsitems/qdeclarativeloader.cpp @@ -59,8 +59,13 @@ QDeclarativeLoaderPrivate::~QDeclarativeLoaderPrivate() void QDeclarativeLoaderPrivate::itemGeometryChanged(QDeclarativeItem *resizeItem, const QRectF &newGeometry, const QRectF &oldGeometry) { - if (resizeItem == item) + if (resizeItem == item) { + if (!updatingSize && newGeometry.width() != oldGeometry.width()) + itemWidthValid = true; + if (!updatingSize && newGeometry.height() != oldGeometry.height()) + itemHeightValid = true; _q_updateSize(false); + } QDeclarativeItemChangeListener::itemGeometryChanged(resizeItem, newGeometry, oldGeometry); } diff --git a/tests/auto/declarative/qdeclarativeloader/data/QTBUG_17114.qml b/tests/auto/declarative/qdeclarativeloader/data/QTBUG_17114.qml new file mode 100644 index 0000000..8a49733 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeloader/data/QTBUG_17114.qml @@ -0,0 +1,18 @@ +import QtQuick 1.1 + +Rectangle { + property real loaderWidth: loader.width + property real loaderHeight: loader.height + width: 200 + height: 200 + + Loader { + id: loader + sourceComponent: Item { + property real iwidth: 32 + property real iheight: 32 + width: iwidth + height: iheight + } + } +} diff --git a/tests/auto/declarative/qdeclarativeloader/tst_qdeclarativeloader.cpp b/tests/auto/declarative/qdeclarativeloader/tst_qdeclarativeloader.cpp index 42746e8..f5218c7 100644 --- a/tests/auto/declarative/qdeclarativeloader/tst_qdeclarativeloader.cpp +++ b/tests/auto/declarative/qdeclarativeloader/tst_qdeclarativeloader.cpp @@ -91,6 +91,7 @@ private slots: void creationContext(); void QTBUG_16928(); void implicitSize(); + void QTBUG_17114(); private: QDeclarativeEngine engine; @@ -619,6 +620,18 @@ void tst_QDeclarativeLoader::implicitSize() delete item; } +void tst_QDeclarativeLoader::QTBUG_17114() +{ + QDeclarativeComponent component(&engine, TEST_FILE("QTBUG_17114.qml")); + QDeclarativeItem *item = qobject_cast(component.create()); + QVERIFY(item); + + QCOMPARE(item->property("loaderWidth").toReal(), 32.); + QCOMPARE(item->property("loaderHeight").toReal(), 32.); + + delete item; +} + QTEST_MAIN(tst_QDeclarativeLoader) #include "tst_qdeclarativeloader.moc" -- cgit v0.12 From 634589cdcdeb608352e17007360c5fb7d916a527 Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Mon, 31 Jan 2011 16:56:38 +1000 Subject: Improve docs on Item::visible and Item::opacity Task-number: QTBUG-16973 --- src/declarative/graphicsitems/qdeclarativeitem.cpp | 43 +++++++++++++++++----- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativeitem.cpp b/src/declarative/graphicsitems/qdeclarativeitem.cpp index e1c138f..ac5d55c 100644 --- a/src/declarative/graphicsitems/qdeclarativeitem.cpp +++ b/src/declarative/graphicsitems/qdeclarativeitem.cpp @@ -1911,11 +1911,26 @@ void QDeclarativeItem::setClip(bool c) /*! \qmlproperty bool Item::visible - Whether the item is visible. By default this is true. + This property holds whether the item is visible. By default this is true. - \note visible is not linked to actual visibility; if an item - moves off screen, or the opacity changes to 0, this will - not affect the visible property. + Setting this property directly affects the \c visible value of child + items. When set to \c false, the \c visible values of all child items also + become \c false. When set to \c true, the \c visible values of child items + are returned to \c true, unless they have explicitly been set to \c false. + + (Because of this flow-on behavior, using the \c visible property may not + have the intended effect if a property binding should only respond to + explicit property changes. In such cases it may be better to use the + \l opacity property instead.) + + Setting this property to \c false automatically causes \l focus to be set + to \c false, and this item will longer receive mouse and keyboard events. + (In contrast, setting the \l opacity to 0 does not affect the \l focus + property and the receiving of key events.) + + \note This property's value is only affected by changes to this property or + the parent's \c visible property. It does not change, for example, if this + item moves off-screen, or if the \l opacity changes to 0. */ @@ -2289,13 +2304,15 @@ void QDeclarativeItem::setBaselineOffset(qreal offset) /*! \qmlproperty real Item::opacity - The opacity of the item. Opacity is specified as a number between 0 - (fully transparent) and 1 (fully opaque). The default is 1. + This property holds the opacity of the item. Opacity is specified as a + number between 0 (fully transparent) and 1 (fully opaque). The default is 1. - Opacity is an \e inherited attribute. That is, the opacity is - also applied individually to child items. In almost all cases this - is what you want, but in some cases (like the following example) - it may produce undesired results. + When this property is set, the specified opacity is also applied + individually to child items. In almost all cases this is what you want, + but in some cases it may produce undesired results. For example in the + second set of rectangles below, the red rectangle has specified an opacity + of 0.5, which affects the opacity of its blue child rectangle even though + the child has not specified an opacity. \table \row @@ -2330,6 +2347,12 @@ void QDeclarativeItem::setBaselineOffset(qreal offset) } \endqml \endtable + + If an item's opacity is set to 0, the item will no longer receive mouse + events, but will continue to receive key events and will retain the keyboard + \l focus if it has been set. (In contrast, setting the \l visible property + to \c false stops both mouse and keyboard events, and also removes focus + from the item.) */ /*! -- cgit v0.12 From 08a3db6efd9fa48701491f9e8a8070e825a132f5 Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Mon, 31 Jan 2011 17:22:06 +1000 Subject: update What's New for QtQuick 1.1 and AnimatedImage docs --- doc/src/declarative/whatsnew.qdoc | 18 ++++++++++++++---- .../graphicsitems/qdeclarativeanimatedimage.cpp | 9 +++++++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/doc/src/declarative/whatsnew.qdoc b/doc/src/declarative/whatsnew.qdoc index 4b94d51..f4359f9 100644 --- a/doc/src/declarative/whatsnew.qdoc +++ b/doc/src/declarative/whatsnew.qdoc @@ -69,7 +69,7 @@ Added the following properties and methods: \o moveCursorSelection(int pos, SelectionMode mode) to enable selection by word \endlist -\section2 Image and BorderImage +\section2 Image, BorderImage and AnimatedImage Added the following properties: \list @@ -109,21 +109,31 @@ Added the following properties: \section2 Repeater -Added the following methods: +Added the following methods and signal handlers: \list \o onItemAdded() \o onItemRemoved() -\o itemAt() +\o itemAt(int index) \endlist +\section2 Component + +The createObject() method now accepts a map of initial property values for the created object. + \section2 Qt -Added the following properties: +Added the following properties and methods: \list \o application.layoutDirection \o application.active \endlist +\section2 Other changes + +\list +\o Functions can be assigned to properties from JavaScript to create property bindings +\endlist + \section1 Qt 4.7.1 diff --git a/src/declarative/graphicsitems/qdeclarativeanimatedimage.cpp b/src/declarative/graphicsitems/qdeclarativeanimatedimage.cpp index f62e374..27bb6a2 100644 --- a/src/declarative/graphicsitems/qdeclarativeanimatedimage.cpp +++ b/src/declarative/graphicsitems/qdeclarativeanimatedimage.cpp @@ -87,6 +87,15 @@ QT_BEGIN_NAMESPACE */ /*! + \qmlproperty bool AnimatedImage::cache + \since Quick 1.1 + + Specifies whether the image should be cached. The default value is + true. Setting \a cache to false is useful when dealing with large images, + to make sure that they aren't cached at the expense of small 'ui element' images. +*/ + +/*! \qmlproperty bool AnimatedImage::mirror \since Quick 1.1 -- cgit v0.12 From 0ee4b2f32a539ee5dc1c08a838f6584ca9d896d4 Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Tue, 1 Feb 2011 16:10:01 +1000 Subject: Add initial size to ListView in FolderListModel example Plus other minor doc changes --- doc/src/examples/qml-folderlistmodel.qdoc | 7 ++++++- doc/src/snippets/declarative/folderlistmodel.qml | 12 ++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/doc/src/examples/qml-folderlistmodel.qdoc b/doc/src/examples/qml-folderlistmodel.qdoc index c9d248e..0a01ce0 100644 --- a/doc/src/examples/qml-folderlistmodel.qdoc +++ b/doc/src/examples/qml-folderlistmodel.qdoc @@ -41,10 +41,15 @@ making the model available to QML. \section1 Usage from QML -The type we are creating can be used from QML like this: +The FolderListModel can be used from QML like this: \snippet doc/src/snippets/declarative/folderlistmodel.qml 0 +This displays a list of all subfolders and QML files in the current folder. + +The FolderListModel \c folder property can be set to change the folder that +is currently displayed. + \section1 Defining the Model We are subclassing QAbstractListModel which will allow us to give data to QML and diff --git a/doc/src/snippets/declarative/folderlistmodel.qml b/doc/src/snippets/declarative/folderlistmodel.qml index 3bddefb..8aeb72c 100644 --- a/doc/src/snippets/declarative/folderlistmodel.qml +++ b/doc/src/snippets/declarative/folderlistmodel.qml @@ -43,15 +43,19 @@ import QtQuick 1.0 import Qt.labs.folderlistmodel 1.0 ListView { + width: 200; height: 400 + FolderListModel { - id: foldermodel + id: folderModel nameFilters: ["*.qml"] } + Component { - id: filedelegate + id: fileDelegate Text { text: fileName } } - model: foldermodel - delegate: filedelegate + + model: folderModel + delegate: fileDelegate } //![0] -- cgit v0.12 From a3010164fd904f4efe2dadb3df699004edaabd95 Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Tue, 1 Feb 2011 16:20:27 +1000 Subject: Move Qt.application docs into Qt global object page Previously it was documented as a separate 'Application' element Reviewed-by: Martin Jones --- doc/src/declarative/qmlviewer.qdoc | 3 ++ doc/src/snippets/declarative/application.qml | 14 +++--- src/declarative/qml/qdeclarativeengine.cpp | 60 ++++++++++++++++++++++-- src/declarative/util/qdeclarativeapplication.cpp | 53 ++------------------- 4 files changed, 69 insertions(+), 61 deletions(-) diff --git a/doc/src/declarative/qmlviewer.qdoc b/doc/src/declarative/qmlviewer.qdoc index cfb762c..585b402 100644 --- a/doc/src/declarative/qmlviewer.qdoc +++ b/doc/src/declarative/qmlviewer.qdoc @@ -192,6 +192,9 @@ Rectangle { } \endqml +\note Since Qt Quick 1.1 this information is accessible outside of the QML Viewer, +through the \c active property of the \l {QML:Qt::application}{Qt.application} object. + \row \o \c runtime.orientation diff --git a/doc/src/snippets/declarative/application.qml b/doc/src/snippets/declarative/application.qml index 2820ff2..06f83f2 100644 --- a/doc/src/snippets/declarative/application.qml +++ b/doc/src/snippets/declarative/application.qml @@ -42,12 +42,12 @@ import QtQuick 1.1 Rectangle { - width: 300; height: 55 - color: Qt.application.active ? "white" : "lightgray" - Text { - text: "Application " + (Qt.application.active ? "active" : "inactive") - opacity: Qt.application.active ? 1.0 : 0.5 - anchors.centerIn: parent - } + width: 300; height: 55 + color: Qt.application.active ? "white" : "lightgray" + Text { + text: "Application " + (Qt.application.active ? "active" : "inactive") + opacity: Qt.application.active ? 1.0 : 0.5 + anchors.centerIn: parent + } } //! [document] diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp index e3be599..890f500 100644 --- a/src/declarative/qml/qdeclarativeengine.cpp +++ b/src/declarative/qml/qdeclarativeengine.cpp @@ -204,8 +204,9 @@ void QDeclarativeEnginePrivate::defineModule() \brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files. -The \c Qt object is not a QML element; it cannot be instantiated. It is a global object -with enums and functions. To use it, call the members of the global \c Qt object directly. +The \c Qt object is a global object with utility functions, properties and enums. + +It is not instantiable; to use it, call the members of the global \c Qt object directly. For example: \qml @@ -220,8 +221,8 @@ Text { \section1 Enums -The Qt object contains enums that declared into Qt's Meta-Object System. For example, you can access -the \c Leftbutton member of the \c Qt::MouseButton enum with \c Qt.LeftButton. +The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access +the \l Qt::LeftButton and \l Qt::RightButton enum values as \c Qt.LeftButton and \c Qt.RightButton. \section1 Types @@ -263,6 +264,57 @@ of their use. \endlist */ + +/*! + \qmlproperty object QML:Qt::application + \since QtQuick 1.1 + + The \c application object provides access to global application state + properties shared by many QML components. + + Its properties are: + + \table + \row + \o \c application.active + \o + This read-only property indicates whether the application is the top-most and focused + application, and the user is able to interact with the application. The property + is false when the application is in the background, the device keylock or screen + saver is active, the screen backlight is turned off, or the global system dialog + is being displayed on top of the application. It can be used for stopping and + pausing animations, timers and active processing of data in order to save device + battery power and free device memory and processor load when the application is not + active. + + \row + \o \c application.layoutDirection + \o + This read-only property can be used to query the default layout direction of the + application. On system start-up, the default layout direction depends on the + application's language. The property has a value of \c Qt.RightToLeft in locales + where text and graphic elements are read from right to left, and \c Qt.LeftToRight + where the reading direction flows from left to right. You can bind to this + property to customize your application layouts to support both layout directions. + + Possible values are: + + \list + \o Qt.LeftToRight - Text and graphics elements should be positioned + from left to right. + \o Qt.RightToLeft - Text and graphics elements should be positioned + from right to left. + \endlist + \endtable + + The following example uses the \c application object to indicate + whether the application is currently active: + + \snippet doc/src/snippets/declarative/application.qml document + +*/ + + /*! \qmlmethod object Qt::include(string url, jsobject callback) diff --git a/src/declarative/util/qdeclarativeapplication.cpp b/src/declarative/util/qdeclarativeapplication.cpp index 7ecce1e..e0f6df2 100644 --- a/src/declarative/util/qdeclarativeapplication.cpp +++ b/src/declarative/util/qdeclarativeapplication.cpp @@ -55,22 +55,9 @@ public: Qt::LayoutDirection layoutDirection; }; -/*! - \qmlclass Application QDeclarativeApplication - \since QtQuick 1.1 - \ingroup qml-utility-elements - \brief The Application element provides access to global application - state properties shared by many QML components. - - These properties include application activity property \c active, - and default layout direction property \c layoutDirection. - - \section1 Example Usage - - The following example shows the simplest usage of the Application element. - - \snippet doc/src/snippets/declarative/application.qml document - +/* + This object and its properties are documented as part of the Qt object, + in qdeclarativengine.cpp */ QDeclarativeApplication::QDeclarativeApplication(QObject *parent) : QObject(*new QDeclarativeApplicationPrivate(), parent) @@ -83,46 +70,12 @@ QDeclarativeApplication::~QDeclarativeApplication() { } -/*! - \qmlproperty bool Application::active - - This property indicates whether the application is the top-most and focused - application, and user is able to interact with the application. The property - is false when the application is on the background, device keylock or screen - saver is active, the screen backlight is turned off, or global system dialog - is being displayed on top of the application. It can be used for stopping and - pausing animations, timers, active processing of data to save device battery - and free device memory and processor load when the application is not active. - This property is readonly. - -*/ bool QDeclarativeApplication::active() const { Q_D(const QDeclarativeApplication); return d->active; } -/*! - \qmlproperty enumeration Application::layoutDirection - - This property can be used to query the default layout direction of the - application. On system start-up, the default layout direction depends on the - application's language. The property has a value Qt.RightToLeft in locales - where text and graphic elements are read from right to left, and Qt.LeftToRight - where the reading direction flows from left to right. You can bind to the - property to customize your application layouts to support both layout - directions. This property is readonly. - - Possible values are: - - \list - \o Qt.LeftToRight - Text and graphics elements should be positioned - from left to right. - \o Qt.RightToLeft - Text and graphics elements should be positioned - from right to left. - \endlist - -*/ Qt::LayoutDirection QDeclarativeApplication::layoutDirection() const { Q_D(const QDeclarativeApplication); -- cgit v0.12 From 49df52abc004419f35bb6b508fb681c028a7c679 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Wed, 2 Feb 2011 13:20:11 +1000 Subject: Avoid index-out-of bounds related crash in Grid Task-number: QTBUG-16959 Reviewed-by: Martin Jones --- .../graphicsitems/qdeclarativepositioners.cpp | 2 +- .../qdeclarativepositioners/data/repeatertest.qml | 20 +++++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativepositioners.cpp b/src/declarative/graphicsitems/qdeclarativepositioners.cpp index 9450647..4560d32 100644 --- a/src/declarative/graphicsitems/qdeclarativepositioners.cpp +++ b/src/declarative/graphicsitems/qdeclarativepositioners.cpp @@ -939,7 +939,7 @@ void QDeclarativeGrid::doPositioning(QSizeF *contentSize) if (i==0) maxColWidth << 0; - if (childIndex == positionedItems.count()) + if (childIndex == visibleItems.count()) break; const PositionedItem &child = visibleItems.at(childIndex++); diff --git a/tests/auto/declarative/qdeclarativepositioners/data/repeatertest.qml b/tests/auto/declarative/qdeclarativepositioners/data/repeatertest.qml index 1cba598..f93ce67 100644 --- a/tests/auto/declarative/qdeclarativepositioners/data/repeatertest.qml +++ b/tests/auto/declarative/qdeclarativepositioners/data/repeatertest.qml @@ -12,9 +12,27 @@ Item { height: 50 z: {if(index == 0){2;}else if(index == 1){1;} else{3;}} objectName: {if(index == 0){"one";}else if(index == 1){"two";} else{"three";}} - } } } } + + //This crashed once (QTBUG-16959) because the repeater ended up on the end of the list + //If this grid just instantiates without crashing, then it has not regressed. + Grid { + id: grid + rows: 2 + flow: Grid.TopToBottom + + Repeater { + model: 13 + Rectangle { + color: "goldenrod" + width: 100 + height: 100 + radius: 10 + border.width: 1 + } + } + } } -- cgit v0.12 From 13d59acef59952e07d98c2947c25da33418c2465 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Wed, 2 Feb 2011 14:01:04 +1000 Subject: Changing header or footer failed to delete the previous. Also ensure that the view is repositioned if the change of header results in the view being out of bounds. Task-number: QTBUG-16522 Reviewed-by: Michael Brasser --- .../graphicsitems/qdeclarativegridview.cpp | 8 ++++++ .../graphicsitems/qdeclarativelistview.cpp | 8 ++++++ .../qdeclarativegridview/data/footer.qml | 8 ++++++ .../qdeclarativegridview/data/header.qml | 8 ++++++ .../tst_qdeclarativegridview.cpp | 30 ++++++++++++++++++++++ .../qdeclarativelistview/data/footer.qml | 8 ++++++ .../qdeclarativelistview/data/header.qml | 9 ++++++- .../tst_qdeclarativelistview.cpp | 30 ++++++++++++++++++++++ 8 files changed, 108 insertions(+), 1 deletion(-) diff --git a/src/declarative/graphicsitems/qdeclarativegridview.cpp b/src/declarative/graphicsitems/qdeclarativegridview.cpp index 6a6ff64..9aade98 100644 --- a/src/declarative/graphicsitems/qdeclarativegridview.cpp +++ b/src/declarative/graphicsitems/qdeclarativegridview.cpp @@ -1779,6 +1779,9 @@ void QDeclarativeGridView::setFooter(QDeclarativeComponent *footer) Q_D(QDeclarativeGridView); if (d->footerComponent != footer) { if (d->footer) { + if (scene()) + scene()->removeItem(d->footer->item); + d->footer->item->deleteLater(); delete d->footer; d->footer = 0; } @@ -1786,6 +1789,7 @@ void QDeclarativeGridView::setFooter(QDeclarativeComponent *footer) if (isComponentComplete()) { d->updateFooter(); d->updateGrid(); + d->fixupPosition(); } emit footerChanged(); } @@ -1811,6 +1815,9 @@ void QDeclarativeGridView::setHeader(QDeclarativeComponent *header) Q_D(QDeclarativeGridView); if (d->headerComponent != header) { if (d->header) { + if (scene()) + scene()->removeItem(d->header->item); + d->header->item->deleteLater(); delete d->header; d->header = 0; } @@ -1819,6 +1826,7 @@ void QDeclarativeGridView::setHeader(QDeclarativeComponent *header) d->updateHeader(); d->updateFooter(); d->updateGrid(); + d->fixupPosition(); } emit headerChanged(); } diff --git a/src/declarative/graphicsitems/qdeclarativelistview.cpp b/src/declarative/graphicsitems/qdeclarativelistview.cpp index cbc4311..075c3af 100644 --- a/src/declarative/graphicsitems/qdeclarativelistview.cpp +++ b/src/declarative/graphicsitems/qdeclarativelistview.cpp @@ -2232,6 +2232,9 @@ void QDeclarativeListView::setFooter(QDeclarativeComponent *footer) Q_D(QDeclarativeListView); if (d->footerComponent != footer) { if (d->footer) { + if (scene()) + scene()->removeItem(d->footer->item); + d->footer->item->deleteLater(); delete d->footer; d->footer = 0; } @@ -2241,6 +2244,7 @@ void QDeclarativeListView::setFooter(QDeclarativeComponent *footer) if (isComponentComplete()) { d->updateFooter(); d->updateViewport(); + d->fixupPosition(); } emit footerChanged(); } @@ -2266,6 +2270,9 @@ void QDeclarativeListView::setHeader(QDeclarativeComponent *header) Q_D(QDeclarativeListView); if (d->headerComponent != header) { if (d->header) { + if (scene()) + scene()->removeItem(d->header->item); + d->header->item->deleteLater(); delete d->header; d->header = 0; } @@ -2276,6 +2283,7 @@ void QDeclarativeListView::setHeader(QDeclarativeComponent *header) d->updateHeader(); d->updateFooter(); d->updateViewport(); + d->fixupPosition(); } emit headerChanged(); } diff --git a/tests/auto/declarative/qdeclarativegridview/data/footer.qml b/tests/auto/declarative/qdeclarativegridview/data/footer.qml index ad69a25..b41e2ac 100644 --- a/tests/auto/declarative/qdeclarativegridview/data/footer.qml +++ b/tests/auto/declarative/qdeclarativegridview/data/footer.qml @@ -1,6 +1,9 @@ import QtQuick 1.0 Rectangle { + function changeFooter() { + grid.footer = footer2 + } width: 240 height: 320 color: "#ffffff" @@ -29,4 +32,9 @@ Rectangle { delegate: myDelegate footer: Text { objectName: "footer"; text: "Footer"; height: 30 } } + + Component { + id: footer2 + Text { objectName: "footer2"; text: "Footer 2"; height: 20 } + } } diff --git a/tests/auto/declarative/qdeclarativegridview/data/header.qml b/tests/auto/declarative/qdeclarativegridview/data/header.qml index 99baacd..f39da55 100644 --- a/tests/auto/declarative/qdeclarativegridview/data/header.qml +++ b/tests/auto/declarative/qdeclarativegridview/data/header.qml @@ -1,6 +1,9 @@ import QtQuick 1.0 Rectangle { + function changeHeader() { + grid.header = header2 + } width: 240 height: 320 color: "#ffffff" @@ -29,4 +32,9 @@ Rectangle { delegate: myDelegate header: Text { objectName: "header"; text: "Header"; height: 30 } } + + Component { + id: header2 + Text { objectName: "header2"; text: "Header 2"; height: 20 } + } } diff --git a/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp b/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp index a6a8b90..82a1a4a 100644 --- a/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp +++ b/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp @@ -1370,12 +1370,27 @@ void tst_QDeclarativeGridView::footer() QVERIFY(footer); QCOMPARE(footer->y(), 180.0); + QCOMPARE(footer->height(), 30.0); model.removeItem(2); QTRY_COMPARE(footer->y(), 120.0); model.clear(); QTRY_COMPARE(footer->y(), 0.0); + + for (int i = 0; i < 30; i++) + model.addItem("Item" + QString::number(i), ""); + + QMetaObject::invokeMethod(canvas->rootObject(), "changeFooter"); + + footer = findItem(contentItem, "footer"); + QVERIFY(!footer); + footer = findItem(contentItem, "footer2"); + QVERIFY(footer); + + QCOMPARE(footer->y(), 0.0); + QCOMPARE(footer->height(), 20.0); + QCOMPARE(gridview->contentY(), 0.0); } void tst_QDeclarativeGridView::header() @@ -1402,6 +1417,7 @@ void tst_QDeclarativeGridView::header() QVERIFY(header); QCOMPARE(header->y(), 0.0); + QCOMPARE(header->height(), 30.0); QCOMPARE(gridview->contentY(), 0.0); QDeclarativeItem *item = findItem(contentItem, "wrapper", 0); @@ -1410,6 +1426,20 @@ void tst_QDeclarativeGridView::header() model.clear(); QTRY_COMPARE(header->y(), 0.0); + + for (int i = 0; i < 30; i++) + model.addItem("Item" + QString::number(i), ""); + + QMetaObject::invokeMethod(canvas->rootObject(), "changeHeader"); + + header = findItem(contentItem, "header"); + QVERIFY(!header); + header = findItem(contentItem, "header2"); + QVERIFY(header); + + QCOMPARE(header->y(), 0.0); + QCOMPARE(header->height(), 20.0); + QCOMPARE(gridview->contentY(), 0.0); } void tst_QDeclarativeGridView::indexAt() diff --git a/tests/auto/declarative/qdeclarativelistview/data/footer.qml b/tests/auto/declarative/qdeclarativelistview/data/footer.qml index 4cbd33b..33e04f1 100644 --- a/tests/auto/declarative/qdeclarativelistview/data/footer.qml +++ b/tests/auto/declarative/qdeclarativelistview/data/footer.qml @@ -1,6 +1,9 @@ import QtQuick 1.0 Rectangle { + function changeFooter() { + list.footer = footer2 + } width: 240 height: 320 color: "#ffffff" @@ -27,4 +30,9 @@ Rectangle { delegate: myDelegate footer: Text { objectName: "footer"; text: "Footer"; height: 30 } } + + Component { + id: footer2 + Text { objectName: "footer2"; text: "Footer 2"; height: 20 } + } } diff --git a/tests/auto/declarative/qdeclarativelistview/data/header.qml b/tests/auto/declarative/qdeclarativelistview/data/header.qml index 6da996e..38cdd6e 100644 --- a/tests/auto/declarative/qdeclarativelistview/data/header.qml +++ b/tests/auto/declarative/qdeclarativelistview/data/header.qml @@ -1,6 +1,9 @@ import QtQuick 1.0 Rectangle { + function changeHeader() { + list.header = header2 + } width: 240 height: 320 color: "#ffffff" @@ -26,6 +29,10 @@ Rectangle { snapMode: ListView.SnapToItem model: testModel delegate: myDelegate - header: Text { objectName: "header"; text: "Header"; height: 10 } + header: Text { objectName: "header"; text: "Header"; height: 20 } + } + Component { + id: header2 + Text { objectName: "header2"; text: "Header 2"; height: 10 } } } diff --git a/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp b/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp index 4fff071..86b68ca 100644 --- a/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp +++ b/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp @@ -1736,12 +1736,27 @@ void tst_QDeclarativeListView::header() QDeclarativeText *header = findItem(contentItem, "header"); QVERIFY(header); QCOMPARE(header->y(), 0.0); + QCOMPARE(header->height(), 20.0); QCOMPARE(listview->contentY(), 0.0); model.clear(); QTRY_COMPARE(header->y(), 0.0); + for (int i = 0; i < 30; i++) + model.addItem("Item" + QString::number(i), ""); + + QMetaObject::invokeMethod(canvas->rootObject(), "changeHeader"); + + header = findItem(contentItem, "header"); + QVERIFY(!header); + header = findItem(contentItem, "header2"); + QVERIFY(header); + + QCOMPARE(header->y(), 0.0); + QCOMPARE(header->height(), 10.0); + QCOMPARE(listview->contentY(), 0.0); + delete canvas; } { @@ -1796,6 +1811,7 @@ void tst_QDeclarativeListView::footer() QDeclarativeText *footer = findItem(contentItem, "footer"); QVERIFY(footer); QCOMPARE(footer->y(), 60.0); + QCOMPARE(footer->height(), 30.0); model.removeItem(1); QTRY_COMPARE(footer->y(), 40.0); @@ -1803,6 +1819,20 @@ void tst_QDeclarativeListView::footer() model.clear(); QTRY_COMPARE(footer->y(), 0.0); + for (int i = 0; i < 30; i++) + model.addItem("Item" + QString::number(i), ""); + + QMetaObject::invokeMethod(canvas->rootObject(), "changeFooter"); + + footer = findItem(contentItem, "footer"); + QVERIFY(!footer); + footer = findItem(contentItem, "footer2"); + QVERIFY(footer); + + QCOMPARE(footer->y(), 0.0); + QCOMPARE(footer->height(), 20.0); + QCOMPARE(listview->contentY(), 0.0); + delete canvas; } -- cgit v0.12 From ac5e89a2fd94c4eb45e79e2c19b3ef5e9b240cb9 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Wed, 2 Feb 2011 16:06:36 +1000 Subject: Make Flickable's wheel handling more like QAbstractScrollArea. Vertical scrolling should only affect vertical movement, and horizontal scrolling should only affect horizontal movement. Task-number: QTBUG-7369 Reviewed-by: Martin Jones --- .../graphicsitems/qdeclarativeflickable.cpp | 4 +-- .../qdeclarativeflickable/data/wheel.qml | 21 ++++++++++++ .../tst_qdeclarativeflickable.cpp | 39 ++++++++++++++++++++++ 3 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 tests/auto/declarative/qdeclarativeflickable/data/wheel.qml diff --git a/src/declarative/graphicsitems/qdeclarativeflickable.cpp b/src/declarative/graphicsitems/qdeclarativeflickable.cpp index ba5e12c..87578b4 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable.cpp +++ b/src/declarative/graphicsitems/qdeclarativeflickable.cpp @@ -876,7 +876,7 @@ void QDeclarativeFlickable::wheelEvent(QGraphicsSceneWheelEvent *event) Q_D(QDeclarativeFlickable); if (!d->interactive) { QDeclarativeItem::wheelEvent(event); - } else if (yflick()) { + } else if (yflick() && event->orientation() == Qt::Vertical) { if (event->delta() > 0) d->vData.velocity = qMax(event->delta() - d->vData.smoothVelocity.value(), qreal(250.0)); else @@ -888,7 +888,7 @@ void QDeclarativeFlickable::wheelEvent(QGraphicsSceneWheelEvent *event) movementStarting(); } event->accept(); - } else if (xflick()) { + } else if (xflick() && event->orientation() == Qt::Horizontal) { if (event->delta() > 0) d->hData.velocity = qMax(event->delta() - d->hData.smoothVelocity.value(), qreal(250.0)); else diff --git a/tests/auto/declarative/qdeclarativeflickable/data/wheel.qml b/tests/auto/declarative/qdeclarativeflickable/data/wheel.qml new file mode 100644 index 0000000..6ea81b2 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeflickable/data/wheel.qml @@ -0,0 +1,21 @@ +import QtQuick 1.1 + +Rectangle { + width: 400 + height: 400 + color: "gray" + + Flickable { + id: flick + objectName: "flick" + anchors.fill: parent + contentWidth: 800 + contentHeight: 800 + + Rectangle { + width: flick.contentWidth + height: flick.contentHeight + color: "red" + } + } +} diff --git a/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp b/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp index ae1e99e..f4bec8f 100644 --- a/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp +++ b/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -74,6 +75,7 @@ private slots: void returnToBounds(); void testQtQuick11Attributes(); void testQtQuick11Attributes_data(); + void wheel(); private: QDeclarativeEngine engine; @@ -373,6 +375,43 @@ void tst_qdeclarativeflickable::testQtQuick11Attributes_data() } +void tst_qdeclarativeflickable::wheel() +{ + QDeclarativeView *canvas = new QDeclarativeView; + canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/wheel.qml")); + canvas->show(); + canvas->setFocus(); + QVERIFY(canvas->rootObject() != 0); + + QDeclarativeFlickable *flick = canvas->rootObject()->findChild("flick"); + QVERIFY(flick != 0); + + QGraphicsScene *scene = canvas->scene(); + QGraphicsSceneWheelEvent event(QEvent::GraphicsSceneWheel); + event.setScenePos(QPointF(200, 200)); + event.setDelta(-120); + event.setOrientation(Qt::Vertical); + event.setAccepted(false); + QApplication::sendEvent(scene, &event); + + QTRY_VERIFY(flick->contentY() > 0); + QVERIFY(flick->contentX() == 0); + + flick->setContentY(0); + QVERIFY(flick->contentY() == 0); + + event.setScenePos(QPointF(200, 200)); + event.setDelta(-120); + event.setOrientation(Qt::Horizontal); + event.setAccepted(false); + QApplication::sendEvent(scene, &event); + + QTRY_VERIFY(flick->contentX() > 0); + QVERIFY(flick->contentY() == 0); + + delete canvas; +} + template T *tst_qdeclarativeflickable::findItem(QGraphicsObject *parent, const QString &objectName) -- cgit v0.12 From ebc0ad51ab319aefd88939963ecf172867b36f5a Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Wed, 2 Feb 2011 16:24:50 +1000 Subject: Export QDeclarativeRefCount so that symbian compiles. --- src/declarative/qml/qdeclarativerefcount_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/declarative/qml/qdeclarativerefcount_p.h b/src/declarative/qml/qdeclarativerefcount_p.h index 868cdc4..b896e5f 100644 --- a/src/declarative/qml/qdeclarativerefcount_p.h +++ b/src/declarative/qml/qdeclarativerefcount_p.h @@ -61,7 +61,7 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) -class Q_AUTOTEST_EXPORT QDeclarativeRefCount +class Q_DECLARATIVE_EXPORT QDeclarativeRefCount { public: QDeclarativeRefCount(); -- cgit v0.12 From e44f8f098c8213e7f2b50c6a9b8c222b3a23b6a9 Mon Sep 17 00:00:00 2001 From: Kalle Juhani Lehtonen Date: Wed, 2 Feb 2011 18:44:53 +1000 Subject: Update QDeclarative DEF files for Symbian Reviewed-by: Martin Jones --- src/s60installs/bwins/QtDeclarativeu.def | 7 ++++++- src/s60installs/eabi/QtDeclarativeu.def | 9 +++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/s60installs/bwins/QtDeclarativeu.def b/src/s60installs/bwins/QtDeclarativeu.def index a287def..7d0a83e 100644 --- a/src/s60installs/bwins/QtDeclarativeu.def +++ b/src/s60installs/bwins/QtDeclarativeu.def @@ -704,7 +704,7 @@ EXPORTS ??4QDeclarativeDomDocument@@QAEAAV0@ABV0@@Z @ 703 NONAME ABSENT ; class QDeclarativeDomDocument & QDeclarativeDomDocument::operator=(class QDeclarativeDomDocument const &) ??0QDeclarativeOpenMetaObject@@QAE@PAVQObject@@PAVQDeclarativeOpenMetaObjectType@@_N@Z @ 704 NONAME ABSENT ; QDeclarativeOpenMetaObject::QDeclarativeOpenMetaObject(class QObject *, class QDeclarativeOpenMetaObjectType *, bool) ?trUtf8@QDeclarativeExpression@@SA?AVQString@@PBD0@Z @ 705 NONAME ; class QString QDeclarativeExpression::trUtf8(char const *, char const *) - ??0QPacketProtocol@@QAE@PAVQIODevice@@PAVQObject@@@Z @ 706 NONAME; QPacketProtocol::QPacketProtocol(class QIODevice *, class QObject *) + ??0QPacketProtocol@@QAE@PAVQIODevice@@PAVQObject@@@Z @ 706 NONAME ; QPacketProtocol::QPacketProtocol(class QIODevice *, class QObject *) ??1QDeclarativeListReference@@QAE@XZ @ 707 NONAME ; QDeclarativeListReference::~QDeclarativeListReference(void) ?clearError@QDeclarativeExpression@@QAEXXZ @ 708 NONAME ; void QDeclarativeExpression::clearError(void) ?setLineNumber@QDeclarativeDebugFileReference@@QAEXH@Z @ 709 NONAME ABSENT ; void QDeclarativeDebugFileReference::setLineNumber(int) @@ -1883,4 +1883,9 @@ EXPORTS ?d_func@QDeclarativeDebugServer@@AAEPAVQDeclarativeDebugServerPrivate@@XZ @ 1882 NONAME ; class QDeclarativeDebugServerPrivate * QDeclarativeDebugServer::d_func(void) ?tr@QDeclarativeDebugServer@@SA?AVQString@@PBD0H@Z @ 1883 NONAME ; class QString QDeclarativeDebugServer::tr(char const *, char const *, int) ?implicitWidth@QDeclarativeItemPrivate@@UBEMXZ @ 1884 NONAME ; float QDeclarativeItemPrivate::implicitWidth(void) const + ??_EQDeclarativeRefCount@@UAE@I@Z @ 1885 NONAME ; QDeclarativeRefCount::~QDeclarativeRefCount(unsigned int) + ??0QDeclarativeRefCount@@QAE@XZ @ 1886 NONAME ; QDeclarativeRefCount::QDeclarativeRefCount(void) + ??1QDeclarativeRefCount@@UAE@XZ @ 1887 NONAME ; QDeclarativeRefCount::~QDeclarativeRefCount(void) + ?addref@QDeclarativeRefCount@@QAEXXZ @ 1888 NONAME ; void QDeclarativeRefCount::addref(void) + ?release@QDeclarativeRefCount@@QAEXXZ @ 1889 NONAME ; void QDeclarativeRefCount::release(void) diff --git a/src/s60installs/eabi/QtDeclarativeu.def b/src/s60installs/eabi/QtDeclarativeu.def index fe2a7a1..95180d4 100644 --- a/src/s60installs/eabi/QtDeclarativeu.def +++ b/src/s60installs/eabi/QtDeclarativeu.def @@ -1921,4 +1921,13 @@ EXPORTS _ZNK7QPacket4dataEv @ 1920 NONAME _ZTI23QDeclarativeDebugServer @ 1921 NONAME _ZTV23QDeclarativeDebugServer @ 1922 NONAME + _ZN20QDeclarativeRefCount6addrefEv @ 1923 NONAME + _ZN20QDeclarativeRefCount7releaseEv @ 1924 NONAME + _ZN20QDeclarativeRefCountC1Ev @ 1925 NONAME + _ZN20QDeclarativeRefCountC2Ev @ 1926 NONAME + _ZN20QDeclarativeRefCountD0Ev @ 1927 NONAME + _ZN20QDeclarativeRefCountD1Ev @ 1928 NONAME + _ZN20QDeclarativeRefCountD2Ev @ 1929 NONAME + _ZTI20QDeclarativeRefCount @ 1930 NONAME + _ZTV20QDeclarativeRefCount @ 1931 NONAME -- cgit v0.12 From 9fa392cdb528db0bb5073892484c809e99ae27b3 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Wed, 2 Feb 2011 09:27:53 +0100 Subject: Revert "Restore Qt 4.6 behaviour: exec() always enters the event loop." This reverts commit 2e72a8b19ea6c674fb4777860dac50faa5d387e6. The behavour in Qt 4.6 was wrong. And even if it was not documented, it is too late to change the behaviour back at this point. The tests for QEventLoop and QCoreApplication have not been reverted Reviewed-by: Brad --- src/corelib/thread/qthread.cpp | 5 +- tests/auto/qthread/tst_qthread.cpp | 191 +++++++++++-------------------------- 2 files changed, 58 insertions(+), 138 deletions(-) diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp index f4bfa5d..f368192 100644 --- a/src/corelib/thread/qthread.cpp +++ b/src/corelib/thread/qthread.cpp @@ -482,7 +482,10 @@ int QThread::exec() Q_D(QThread); QMutexLocker locker(&d->mutex); d->data->quitNow = false; - d->exited = false; + if (d->exited) { + d->exited = false; + return d->returnCode; + } locker.unlock(); QEventLoop eventLoop; diff --git a/tests/auto/qthread/tst_qthread.cpp b/tests/auto/qthread/tst_qthread.cpp index c7036e4..e6bf9ce 100644 --- a/tests/auto/qthread/tst_qthread.cpp +++ b/tests/auto/qthread/tst_qthread.cpp @@ -86,7 +86,6 @@ private slots: void start(); void terminate(); void quit(); - void execAfterQuit(); void wait(); void started(); void finished(); @@ -266,34 +265,6 @@ public: } }; -class ExecAfterQuitThreadHelper: public QObject -{ - Q_OBJECT - QThread *thr; -public: - ExecAfterQuitThreadHelper(QThread *thr) : thr(thr) {} -public slots: - void doIt() { thr->exit(0); } -}; - -class ExecAfterQuitThread: public QThread -{ -public: - int returnValue; - void run() - { - ExecAfterQuitThreadHelper obj(this); - - QMetaObject::invokeMethod(&obj, "doIt", Qt::QueuedConnection); - exit(1); - - // returnValue will be either 0 or 1, depending on which of the two - // above take effect. The correct value is 0, since exit(1) before - // exec() should have no effect - returnValue = exec(); - } -}; - tst_QThread::tst_QThread() { @@ -453,52 +424,34 @@ void tst_QThread::stackSize() void tst_QThread::exit() { - { - Exit_Thread thread; - thread.object = new Exit_Object; - thread.object->moveToThread(&thread); - thread.code = 42; - thread.result = 0; - QVERIFY(!thread.isFinished()); - QVERIFY(!thread.isRunning()); - - QMutexLocker locker(&thread.mutex); - thread.start(); - QVERIFY(thread.isRunning()); - QVERIFY(!thread.isFinished()); - // but the thread is not running the event loop yet (the mutex is locked) - - // start the event loop - thread.cond.wait(locker.mutex()); - - // the Exit_Object above will cause the thread to exit - QVERIFY(thread.wait(five_minutes)); - QVERIFY(thread.isFinished()); - QVERIFY(!thread.isRunning()); - QCOMPARE(thread.result, thread.code); - delete thread.object; - } + Exit_Thread thread; + thread.object = new Exit_Object; + thread.object->moveToThread(&thread); + thread.code = 42; + thread.result = 0; + QVERIFY(!thread.isFinished()); + QVERIFY(!thread.isRunning()); + QMutexLocker locker(&thread.mutex); + thread.start(); + QVERIFY(thread.isRunning()); + QVERIFY(!thread.isFinished()); + thread.cond.wait(locker.mutex()); + QVERIFY(thread.wait(five_minutes)); + QVERIFY(thread.isFinished()); + QVERIFY(!thread.isRunning()); + QCOMPARE(thread.result, thread.code); + delete thread.object; - { - Exit_Thread thread2; - thread2.object = 0; - thread2.code = 53; - thread2.result = 0; - QMutexLocker locker2(&thread2.mutex); - thread2.start(); - - // the mutex is locked, so the thread has *not* started running the event loop yet - // this will do nothing: - thread2.exit(thread2.code); - - // the thread will now start running - thread2.cond.wait(locker2.mutex()); - - // this will cause it to exit now - thread2.exit(++thread2.code); - QVERIFY(thread2.wait(five_minutes)); - QCOMPARE(thread2.result, thread2.code); - } + Exit_Thread thread2; + thread2.object = 0; + thread2.code = 53; + thread2.result = 0; + QMutexLocker locker2(&thread2.mutex); + thread2.start(); + thread2.exit(thread2.code); + thread2.cond.wait(locker2.mutex()); + QVERIFY(thread2.wait(five_minutes)); + QCOMPARE(thread2.result, thread2.code); } void tst_QThread::start() @@ -545,59 +498,32 @@ void tst_QThread::terminate() void tst_QThread::quit() { - // very similar to exit() above - { - Quit_Thread thread; - thread.object = new Quit_Object; - thread.object->moveToThread(&thread); - thread.result = -1; - QVERIFY(!thread.isFinished()); - QVERIFY(!thread.isRunning()); - - // start the thread, but keep the event loop from starting - // (while the mutex is locked) - QMutexLocker locker(&thread.mutex); - thread.start(); - QVERIFY(thread.isRunning()); - QVERIFY(!thread.isFinished()); - - // unlock the mutex and let the event loop run - // the Quit_Object above will cause the thread to quit - thread.cond.wait(locker.mutex()); - QVERIFY(thread.wait(five_minutes)); - QVERIFY(thread.isFinished()); - QVERIFY(!thread.isRunning()); - QCOMPARE(thread.result, 0); - delete thread.object; - } - - { - Quit_Thread thread2; - thread2.object = 0; - thread2.result = -1; - - // start the thread, but keep the event loop from starting - // (while the mutex is locked) - QMutexLocker locker2(&thread2.mutex); - thread2.start(); - thread2.quit(); // does nothing, the event loop is not running! - - // unlock the mutex and let the event loop run - thread2.cond.wait(locker2.mutex()); - - // there's no Quit_Object so it won't quit on its own - thread2.quit(); - QVERIFY(thread2.wait(five_minutes)); - QCOMPARE(thread2.result, 0); - } -} - -void tst_QThread::execAfterQuit() -{ - ExecAfterQuitThread thread; + Quit_Thread thread; + thread.object = new Quit_Object; + thread.object->moveToThread(&thread); + thread.result = -1; + QVERIFY(!thread.isFinished()); + QVERIFY(!thread.isRunning()); + QMutexLocker locker(&thread.mutex); thread.start(); - QVERIFY(thread.wait()); - QCOMPARE(thread.returnValue, 0); + QVERIFY(thread.isRunning()); + QVERIFY(!thread.isFinished()); + thread.cond.wait(locker.mutex()); + QVERIFY(thread.wait(five_minutes)); + QVERIFY(thread.isFinished()); + QVERIFY(!thread.isRunning()); + QCOMPARE(thread.result, 0); + delete thread.object; + + Quit_Thread thread2; + thread2.object = 0; + thread2.result = -1; + QMutexLocker locker2(&thread2.mutex); + thread2.start(); + thread2.quit(); + thread2.cond.wait(locker2.mutex()); + QVERIFY(thread2.wait(five_minutes)); + QCOMPARE(thread2.result, 0); } void tst_QThread::wait() @@ -1068,17 +994,8 @@ void tst_QThread::QTBUG15378_exitAndExec() Thread thread; thread.value = 0; thread.start(); - thread.exit(42); // will do nothing, this value should not appear - thread.sem1.release(); //should enter the first loop - - Exit_Object *exit_object = new Exit_Object; - exit_object->code = 556; - exit_object->thread = &thread; - QMetaObject::invokeMethod(exit_object, "slot", Qt::QueuedConnection); - exit_object->deleteLater(); - exit_object->moveToThread(&thread); // should exit the first loop - exit_object = 0; - + thread.exit(556); + thread.sem1.release(); //should exit the first loop thread.sem2.acquire(); int v = thread.value; QCOMPARE(v, 556); -- cgit v0.12 From 216b29f0c976405c718c7bb8e24699d368baac7e Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Wed, 2 Feb 2011 10:03:51 +0100 Subject: document that QThread::exit will exit future event loops Reviewed-by: Brad --- src/corelib/thread/qthread.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp index f368192..8223cff 100644 --- a/src/corelib/thread/qthread.cpp +++ b/src/corelib/thread/qthread.cpp @@ -509,10 +509,12 @@ int QThread::exec() Note that unlike the C library function of the same name, this function \e does return to the caller -- it is event processing - that stops. - - This function does nothing if the thread does not have an event - loop. + that stops. + + No QEventLoops will be started anymore in this thread until + QThread::exec() has been called again. If the eventloop in QThread::exec() + is not running then the next call to QThread::exec() will also return + immediately. \sa quit() QEventLoop */ -- cgit v0.12 From 186a9f967394d554ce99b8a3313cbc679b54c7c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Tue, 1 Feb 2011 17:12:11 +0100 Subject: Fixed es2 configure when both EGL/egl.h and GLES/egl.h are present. Change e0c2861976e06658a1d651941310407c15b0bcde fixed es1 configure by only picking EGL/egl.h if GLES/egl.h is not found. This broke es2 configure on platforms where both EGL/egl.h and GLES/egl.h are present, by picking GLES/egl.h instead of EGL/egl.h, which implicitly pulled in the GLES/gl.h header as well, causing inconsistent declarations due to both GLES2/gl2.h and GLES/gl.h getting included. Instead, we need to prioritize depending on whether we're using es1 or es2. For es1, we prefer GLES/egl.h, and for es2, we prefer EGL/egl.h. If only one of the headers is found we still use it unconditionally, to preserve the existing behaviour and minimize the risk of breaking other platforms. Reviewed-by: Ritt Konstantin Reviewed-by: Marius Storm-Olsen --- configure | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/configure b/configure index dfbf9bd..5e8ef17 100755 --- a/configure +++ b/configure @@ -6056,19 +6056,28 @@ if [ "$PLATFORM_QWS" = "yes" ]; then fi # QWS +EGL_VARIANT=none # EGL Support if [ "$PLATFORM_X11" = "yes" -o "$PLATFORM_QWS" = "yes" ]; then if [ "$CFG_EGL" != "no" ]; then # detect EGL support - if "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" "config.tests/unix/egl4gles1" "EGL (GLES/egl.h)" $L_FLAGS $I_FLAGS $l_FLAGS; then - # EGL specified by QMAKE_*_EGL, included with - CFG_EGL=yes - CFG_EGL_GLES_INCLUDES=yes - elif "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" "config.tests/unix/egl" "EGL (EGL/egl.h)" $L_FLAGS $I_FLAGS $l_FLAGS; then + if "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" "config.tests/unix/egl" "EGL (EGL/egl.h)" $L_FLAGS $I_FLAGS $l_FLAGS; then # EGL specified by QMAKE_*_EGL, included with + EGL_VARIANT=regular CFG_EGL=yes - CFG_EGL_GLES_INCLUDES=no - else + fi + + # Prefer this variant for ES1 + if [ "$CFG_OPENGL" = "es1" -o "$EGL_VARIANT" = "none" ]; then + if "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" "config.tests/unix/egl4gles1" "EGL (GLES/egl.h)" $L_FLAGS $I_FLAGS $l_FLAGS; then + # EGL specified by QMAKE_*_EGL, included with + EGL_VARIANT=gles + CFG_EGL=yes + CFG_EGL_GLES_INCLUDES=yes + fi + fi + + if [ "$EGL_VARIANT" = "none" ]; then if [ "$CFG_EGL" = "yes" ]; then echo "The EGL functionality test failed!" echo " EGL is required for OpenGL ES to manage contexts & surfaces." -- cgit v0.12 From 5ad8cd48a1ed3be183c0af8698491b039f0054e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Tue, 1 Feb 2011 17:59:54 +0100 Subject: Prevent recursion when creating window surface. If we can't access the qt_gl_share_widget() we should just create a raster window surface. This might happen when creating the share widget itself leads to creation of a window surface (which isn't really going to be used anyways). Reviewed-by: Michael Dominic K --- src/plugins/graphicssystems/meego/qmeegographicssystem.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp b/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp index 20b092e..a70d232 100644 --- a/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp +++ b/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -75,7 +76,12 @@ QMeeGoGraphicsSystem::~QMeeGoGraphicsSystem() QWindowSurface* QMeeGoGraphicsSystem::createWindowSurface(QWidget *widget) const { - QGLShareContextScope ctx(qt_gl_share_widget()->context()); + QGLWidget *shareWidget = qt_gl_share_widget(); + + if (!shareWidget) + return new QRasterWindowSurface(widget); + + QGLShareContextScope ctx(shareWidget->context()); QMeeGoGraphicsSystem::surfaceWasCreated = true; QWindowSurface *surface = new QGLWindowSurface(widget); -- cgit v0.12 From 4d38013cfc3058e36de1b6a6c20653ef2688a92b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Tue, 1 Feb 2011 17:57:10 +0100 Subject: Fixed missing text when using static text items in GL 2 engine. When the context is destroyed and recreated, we end up with a new glyph cache, but we only recreate the vertex arrays for the very first static text item. We need to keep track of the glyph cache in each text item, so that we can recreate the vertex arrays and re-populate the cache accordingly. As the pointer might be the same after the glyph cache is recreated, we need to use serial numbers instead. We also need to re-create the cache when the context pointer has been invalidated, so that the static text items also get invalidated, and the texture glyph cache gets repopulated. Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 13 ++++++++----- src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp | 3 +++ src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h | 3 +++ 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index ad2852e..cda31e5 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -1489,7 +1489,7 @@ namespace { { public: QOpenGLStaticTextUserData() - : QStaticTextUserData(OpenGLUserData), cacheSize(0, 0) + : QStaticTextUserData(OpenGLUserData), cacheSize(0, 0), cacheSerialNumber(0) { } @@ -1501,6 +1501,7 @@ namespace { QGL2PEXVertexArray vertexCoordinateArray; QGL2PEXVertexArray textureCoordinateArray; QFontEngineGlyphCache::Type glyphType; + int cacheSerialNumber; }; } @@ -1518,12 +1519,10 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp QGLTextureGlyphCache *cache = (QGLTextureGlyphCache *) staticTextItem->fontEngine()->glyphCache(ctx, glyphType, QTransform()); - if (!cache || cache->cacheType() != glyphType) { + if (!cache || cache->cacheType() != glyphType || cache->context() == 0) { cache = new QGLTextureGlyphCache(ctx, glyphType, QTransform()); staticTextItem->fontEngine()->setGlyphCache(ctx, cache); recreateVertexArrays = true; - } else if (cache->context() == 0) { // Old context has been destroyed, new context has same ptr value - cache->setContext(ctx); } if (staticTextItem->userDataNeedsUpdate) { @@ -1534,8 +1533,11 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp recreateVertexArrays = true; } else { QOpenGLStaticTextUserData *userData = static_cast(staticTextItem->userData()); - if (userData->glyphType != glyphType) + if (userData->glyphType != glyphType) { recreateVertexArrays = true; + } else if (userData->cacheSerialNumber != cache->serialNumber()) { + recreateVertexArrays = true; + } } // We only need to update the cache with new glyphs if we are actually going to recreate the vertex arrays. @@ -1580,6 +1582,7 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp } userData->glyphType = glyphType; + userData->cacheSerialNumber = cache->serialNumber(); // Use cache if backend optimizations is turned on vertexCoordinates = &userData->vertexCoordinateArray; diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp index 58c78ec..312d66f 100644 --- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp +++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp @@ -52,12 +52,15 @@ QT_BEGIN_NAMESPACE extern Q_GUI_EXPORT bool qt_cleartype_enabled; #endif +QBasicAtomicInt qgltextureglyphcache_serial_number = Q_BASIC_ATOMIC_INITIALIZER(1); + QGLTextureGlyphCache::QGLTextureGlyphCache(QGLContext *context, QFontEngineGlyphCache::Type type, const QTransform &matrix) : QImageTextureGlyphCache(type, matrix) , ctx(0) , m_width(0) , m_height(0) , m_filterMode(Nearest) + , m_serialNumber(qgltextureglyphcache_serial_number.fetchAndAddRelaxed(1)) { setContext(context); } diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h b/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h index 1c1b7c4..2eb4e65 100644 --- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h +++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h @@ -83,6 +83,8 @@ public: inline void setPaintEnginePrivate(QGL2PaintEngineExPrivate *p) { pex = p; } + inline int serialNumber() const { return m_serialNumber; } + enum FilterMode { Nearest, Linear @@ -140,6 +142,7 @@ private: QGLShaderProgram *m_program; FilterMode m_filterMode; + int m_serialNumber; }; QT_END_NAMESPACE -- cgit v0.12 From 5b89e67619d15e817a81c8f39072a210c7cd5f4c Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Wed, 2 Feb 2011 13:40:59 +0200 Subject: Fix few QFileDialog static method issues in Symbian^3 - The selected file path now uses slashes instead of Symbian native backslashes as directory separator. - If default file is specified in dir parameter of getSaveFileName in addition to directory, that will be used as default suggested filename. - Clarified documentation a bit. Task-number: QTBUG-17135 Reviewed-by: Janne Koskinen --- src/gui/dialogs/qfiledialog.cpp | 2 +- src/gui/dialogs/qfiledialog_symbian.cpp | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/gui/dialogs/qfiledialog.cpp b/src/gui/dialogs/qfiledialog.cpp index 5ff8d1e..27c58a5 100644 --- a/src/gui/dialogs/qfiledialog.cpp +++ b/src/gui/dialogs/qfiledialog.cpp @@ -1770,7 +1770,7 @@ QString QFileDialog::getOpenFileName(QWidget *parent, On Symbian^3 the parameter \a selectedFilter has no meaning and the \a options parameter is only used to define if the native file dialog is - used. + used. On Symbian^3, this function can only return a single filename. \warning Do not delete \a parent during the execution of the dialog. If you want to do this, you should create the dialog yourself using one of the diff --git a/src/gui/dialogs/qfiledialog_symbian.cpp b/src/gui/dialogs/qfiledialog_symbian.cpp index e7197bd..b8ea5e5 100644 --- a/src/gui/dialogs/qfiledialog_symbian.cpp +++ b/src/gui/dialogs/qfiledialog_symbian.cpp @@ -140,11 +140,13 @@ static QString launchSymbianDialog(const QString dialogCaption, const QString st CleanupStack::PushL(extensionFilter); extensionFilter->setFilter(filter); select = AknCommonDialogsDynMem::RunSelectDlgLD(types, target, - startFolder, NULL, NULL, titlePtr, extensionFilter); + startFolder, 0, 0, titlePtr, extensionFilter); CleanupStack::Pop(extensionFilter); } else if (dialogMode == DialogSave) { + QString defaultFileName = QFileDialogPrivate::initialSelection(startDirectory); + target = qt_QString2TPtrC(defaultFileName); select = AknCommonDialogsDynMem::RunSaveDlgLD(types, target, - startFolder, NULL, NULL, titlePtr); + startFolder, 0, 0, titlePtr); } else if (dialogMode == DialogFolder) { select = AknCommonDialogsDynMem::RunFolderSelectDlgLD(types, target, startFolder, 0, 0, titlePtr, NULL, NULL); @@ -160,8 +162,10 @@ static QString launchSymbianDialog(const QString dialogCaption, const QString st startFolder = qt_QString2TPtrC(dir); } } - if (select) - selection.append(qt_TDesC2QString(target)); + if (select) { + QFileInfo fi(qt_TDesC2QString(target)); + selection = fi.absoluteFilePath(); + } #endif return selection; } -- cgit v0.12 From 31492cc049a8dfe7f52748922a88f117499d62a3 Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Wed, 26 Jan 2011 08:43:34 +0100 Subject: Fixes memory leaks in QX11Embed We should XFree the values returned from XGetWindowProperty. Task-number: QTBUG-16597 Reviewed-by: Ritt Konstantin --- src/gui/kernel/qx11embed_x11.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/gui/kernel/qx11embed_x11.cpp b/src/gui/kernel/qx11embed_x11.cpp index aba42f2..710f607 100644 --- a/src/gui/kernel/qx11embed_x11.cpp +++ b/src/gui/kernel/qx11embed_x11.cpp @@ -415,8 +415,9 @@ static Bool functor(Display *display, XEvent *event, XPointer arg) status = XGetWindowProperty(display, data->id, ATOM(WM_STATE), 0, 2, False, ATOM(WM_STATE), &ret, &format, &nitems, &after, &retval ); if (status == Success && ret == ATOM(WM_STATE) && format == 32 && nitems > 0) { - long *state = (long *)retval; - if (state[0] == WithdrawnState) { + long state = *(long *)retval; + XFree(retval); + if (state == WithdrawnState) { data->clearedWmState = true; return true; } @@ -833,6 +834,8 @@ bool QX11EmbedWidget::x11Event(XEvent *event) XUnmapWindow(x11Info().display(), internalWinId()); } } + if (prop_return) + XFree(prop_return); } } -- cgit v0.12 From 17ee918b2cd2bb012a538b721bbd888677072614 Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Wed, 2 Feb 2011 12:54:20 +0100 Subject: Carefull free the data from XGetWindowProperty on X11. Make sure we free the data correctly in case of error. Task-number: QTBUG-16616 Patch-by: Juuso Pakarinen Reviewed-by: Ritt Konstantin --- src/gui/kernel/qwidget_x11.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/gui/kernel/qwidget_x11.cpp b/src/gui/kernel/qwidget_x11.cpp index 9893478..28eb3f0 100644 --- a/src/gui/kernel/qwidget_x11.cpp +++ b/src/gui/kernel/qwidget_x11.cpp @@ -444,6 +444,7 @@ static QVector getNetWmState(QWidget *w) && actualType == XA_ATOM && actualFormat == 32) { returnValue.resize(bytesLeft / 4); XFree((char*) propertyData); + propertyData = 0; // fetch all data if (XGetWindowProperty(X11->display, w->internalWinId(), ATOM(_NET_WM_STATE), 0, @@ -458,7 +459,8 @@ static QVector getNetWmState(QWidget *w) if (!returnValue.isEmpty()) { memcpy(returnValue.data(), propertyData, returnValue.size() * sizeof(Atom)); } - XFree((char*) propertyData); + if (propertyData) + XFree((char*) propertyData); } return returnValue; -- cgit v0.12 From 7987d4cfd3ce86c20a55b5661a5221f12246b27e Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Wed, 2 Feb 2011 11:31:20 +0100 Subject: Fix QMutex can deadlock when calling tryLock in the unix code, if the QMutexPrivate::wait() with a timeout expires in the same moment that the mutex is released, wakeup would be set, but would be then ignored. (reset to false quickly after) If we waken up between the timeout and the re-aquisition of the internal mutex, we consider that the mutex has been locked. Reviewed-by: brad Task-number: QTBUG-16115 --- src/corelib/thread/qmutex_unix.cpp | 5 ++++- tests/auto/qmutex/tst_qmutex.cpp | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/corelib/thread/qmutex_unix.cpp b/src/corelib/thread/qmutex_unix.cpp index 41d87a7..dd7e5d1 100644 --- a/src/corelib/thread/qmutex_unix.cpp +++ b/src/corelib/thread/qmutex_unix.cpp @@ -94,8 +94,11 @@ bool QMutexPrivate::wait(int timeout) errorCode = pthread_cond_timedwait(&cond, &mutex, &ti); } if (errorCode) { - if (errorCode == ETIMEDOUT) + if (errorCode == ETIMEDOUT) { + if (wakeup) + errorCode = 0; break; + } report_error(errorCode, "QMutex::lock()", "cv wait"); } } diff --git a/tests/auto/qmutex/tst_qmutex.cpp b/tests/auto/qmutex/tst_qmutex.cpp index 3c4c767..ea983cb 100644 --- a/tests/auto/qmutex/tst_qmutex.cpp +++ b/tests/auto/qmutex/tst_qmutex.cpp @@ -67,6 +67,7 @@ private slots: void lock_unlock_locked_tryLock(); void stressTest(); void tryLockRace(); + void qtbug16115_trylock(); }; static const int iterations = 100; @@ -464,5 +465,42 @@ void tst_QMutex::tryLockRace() TryLockRaceThread::mutex.unlock(); } +static volatile int qtbug16115_trylock_counter; + +void tst_QMutex::qtbug16115_trylock() +{ + //Used to deadlock on unix + struct TrylockThread : QThread { + TrylockThread(QMutex &mut) : mut(mut) {} + QMutex &mut; + void run() { + for (int i = 0; i < 1000000; ++i) { + if (mut.tryLock(0)) { + Q_ASSERT((++qtbug16115_trylock_counter) == 1); + Q_ASSERT((--qtbug16115_trylock_counter) == 0); + mut.unlock(); + } + } + } + }; + QMutex mut; + TrylockThread t1(mut); + TrylockThread t2(mut); + TrylockThread t3(mut); + t1.start(); + t2.start(); + t3.start(); + + for (int i = 0; i < 1000000; ++i) { + mut.lock(); + Q_ASSERT((++qtbug16115_trylock_counter) == 1); + Q_ASSERT((--qtbug16115_trylock_counter) == 0); + mut.unlock(); + } + t1.wait(); + t2.wait(); + t3.wait(); +} + QTEST_MAIN(tst_QMutex) #include "tst_qmutex.moc" -- cgit v0.12 From cf2f23225414893a7b061fadbde4739165f0c554 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Wed, 2 Feb 2011 15:58:14 +0200 Subject: Fix qt.sis platform dependencies for Symbian^3 builds. Symbian^3 build of qt.sis is not compatible with pre-Symbian^3 devices, so remove the platform dependencies to said devices. Task-number: QTBUG-17150 Reviewed-by: Janne Koskinen --- src/s60installs/s60installs.pro | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/s60installs/s60installs.pro b/src/s60installs/s60installs.pro index 3b705ad..5c89338 100644 --- a/src/s60installs/s60installs.pro +++ b/src/s60installs/s60installs.pro @@ -77,13 +77,19 @@ symbian: { "ENDIF" \ " \"$$bearerStubZ\" - \"c:$$replace(QT_PLUGINS_BASE_DIR,/,\\)\\bearer\\qsymbianbearer$${QT_LIBINFIX}.qtplugin\" } else { + # Restrict deployment to Symbian3 and later platforms + default_deployment.pkg_prerules -= pkg_platform_dependencies + platform_dependency_rules.pkg_prerules = \ + "[0x20022E6D],0,0,0,{\"S60ProductID\"}" \ + "[0x20032DE7],0,0,0,{\"S60ProductID\"}" + # No need to deploy plugins for older platform versions when building on Symbian3 or later qts60plugindeployment = \ " \"$$pluginLocations/qts60plugin_5_0$${QT_LIBINFIX}.dll\" - \"c:\\sys\\bin\\qts60plugin_5_0$${QT_LIBINFIX}.dll\"" bearer_plugin.sources = $$QT_BUILD_TREE/plugins/bearer/qsymbianbearer$${QT_LIBINFIX}.dll bearer_plugin.path = c:$$QT_PLUGINS_BASE_DIR/bearer - DEPLOYMENT += bearer_plugin + DEPLOYMENT += bearer_plugin platform_dependency_rules } qtlibraries.pkg_postrules += qts60plugindeployment @@ -183,10 +189,6 @@ symbian: { contains(QT_CONFIG, openvg) { qtlibraries.sources += $$QMAKE_LIBDIR_QT/QtOpenVG$${QT_LIBINFIX}.dll graphicssystems_plugins.sources += $$QT_BUILD_TREE/plugins/graphicssystems/qvggraphicssystem$${QT_LIBINFIX}.dll - # OpenVG requires Symbian^3 or later - pkg_platform_dependencies = \ - "[0x20022E6D],0,0,0,{\"S60ProductID\"}" \ - "[0x20032DE7],0,0,0,{\"S60ProductID\"}" } contains(QT_CONFIG, opengl) { -- cgit v0.12 From bb6d0f75d4a5d3dadb5e0134aa0270bcab61f205 Mon Sep 17 00:00:00 2001 From: kranthi Date: Wed, 2 Feb 2011 16:57:45 +0200 Subject: Fix for QTBUG-17035 Reviewed-by: Aaron McCarthy Task-number: QTBUG-17035 --- src/plugins/bearer/icd/qnetworksession_impl.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plugins/bearer/icd/qnetworksession_impl.cpp b/src/plugins/bearer/icd/qnetworksession_impl.cpp index 6d578d3..af5d85e 100644 --- a/src/plugins/bearer/icd/qnetworksession_impl.cpp +++ b/src/plugins/bearer/icd/qnetworksession_impl.cpp @@ -125,9 +125,6 @@ static QString get_network_interface(); void QNetworkSessionPrivateImpl::iapStateChanged(const QString& iapid, uint icd_connection_state) { - if ((publicConfig.type() == QNetworkConfiguration::UserChoice) && opened) { - updateIdentifier(iapid); - } if (((publicConfig.type() == QNetworkConfiguration::UserChoice) && (activeConfig.identifier() == iapid)) || @@ -149,6 +146,9 @@ void QNetworkSessionPrivateImpl::iapStateChanged(const QString& iapid, uint icd_ break; } } + if (publicConfig.type() == QNetworkConfiguration::UserChoice) { + updateIdentifier(iapid); + } } void QNetworkSessionPrivateImpl::cleanupSession(void) -- cgit v0.12 From 1ee195424a5f1430b08929c79f7f5d118a814212 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 3 Feb 2011 11:24:30 +1000 Subject: Correct assert --- src/declarative/qml/qdeclarativeengine_p.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/declarative/qml/qdeclarativeengine_p.h b/src/declarative/qml/qdeclarativeengine_p.h index 1cc9dc5..88b4e80 100644 --- a/src/declarative/qml/qdeclarativeengine_p.h +++ b/src/declarative/qml/qdeclarativeengine_p.h @@ -374,9 +374,8 @@ The returned cache is not referenced, so if it is to be stored, call addref(). QDeclarativePropertyCache *QDeclarativeEnginePrivate::cache(QDeclarativeType *type, int minorVersion, QDeclarativeError &error) { Q_ASSERT(type); - Q_ASSERT(minorVersion >= 0); - if (!type->containsRevisionedAttributes()) + if (minorVersion == -1 || !type->containsRevisionedAttributes()) return cache(type->metaObject()); QDeclarativePropertyCache *rv = typePropertyCache.value(qMakePair(type, minorVersion)); -- cgit v0.12 From 20af4d6777f827eb347ee6c167f67cc2d5dad0a5 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Thu, 3 Feb 2011 13:08:01 +1000 Subject: On windows xp using a higher port makes the declarativedebug* tests work I know not why... Reviewed-by: Aaron Kennedy --- .../qdeclarativedebugclient/tst_qdeclarativedebugclient.cpp | 6 +++--- .../qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/auto/declarative/qdeclarativedebugclient/tst_qdeclarativedebugclient.cpp b/tests/auto/declarative/qdeclarativedebugclient/tst_qdeclarativedebugclient.cpp index e3f0349..c182893 100644 --- a/tests/auto/declarative/qdeclarativedebugclient/tst_qdeclarativedebugclient.cpp +++ b/tests/auto/declarative/qdeclarativedebugclient/tst_qdeclarativedebugclient.cpp @@ -76,7 +76,7 @@ void tst_QDeclarativeDebugClient::initTestCase() QTest::ignoreMessage(QtWarningMsg, "Qml debugging is enabled. Only use this in a safe environment!"); QDeclarativeDebugHelper::enableDebugging(); - QTest::ignoreMessage(QtWarningMsg, "QDeclarativeDebugServer: Waiting for connection on port 3770..."); + QTest::ignoreMessage(QtWarningMsg, "QDeclarativeDebugServer: Waiting for connection on port 13770..."); new QDeclarativeEngine(this); m_conn = new QDeclarativeDebugConnection(this); @@ -84,7 +84,7 @@ void tst_QDeclarativeDebugClient::initTestCase() QDeclarativeDebugTestClient client("tst_QDeclarativeDebugClient::handshake()", m_conn); QDeclarativeDebugTestService service("tst_QDeclarativeDebugClient::handshake()"); - m_conn->connectToHost("127.0.0.1", 3770); + m_conn->connectToHost("127.0.0.1", 13770); QTest::ignoreMessage(QtWarningMsg, "QDeclarativeDebugServer: Connection established"); bool ok = m_conn->waitForConnected(); @@ -149,7 +149,7 @@ int main(int argc, char *argv[]) char **_argv = new char*[_argc]; for (int i = 0; i < argc; ++i) _argv[i] = argv[i]; - _argv[_argc - 1] = "-qmljsdebugger=port:3770"; + _argv[_argc - 1] = "-qmljsdebugger=port:13770"; QApplication app(_argc, _argv); tst_QDeclarativeDebugClient tc; diff --git a/tests/auto/declarative/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp b/tests/auto/declarative/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp index a7e5f20..0911a83 100644 --- a/tests/auto/declarative/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp +++ b/tests/auto/declarative/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp @@ -79,11 +79,11 @@ void tst_QDeclarativeDebugService::initTestCase() QTest::ignoreMessage(QtWarningMsg, "Qml debugging is enabled. Only use this in a safe environment!"); QDeclarativeDebugHelper::enableDebugging(); - QTest::ignoreMessage(QtWarningMsg, "QDeclarativeDebugServer: Waiting for connection on port 3769..."); + QTest::ignoreMessage(QtWarningMsg, "QDeclarativeDebugServer: Waiting for connection on port 13769..."); new QDeclarativeEngine(this); m_conn = new QDeclarativeDebugConnection(this); - m_conn->connectToHost("127.0.0.1", 3769); + m_conn->connectToHost("127.0.0.1", 13769); QTest::ignoreMessage(QtWarningMsg, "QDeclarativeDebugServer: Connection established"); bool ok = m_conn->waitForConnected(); @@ -193,7 +193,7 @@ int main(int argc, char *argv[]) char **_argv = new char*[_argc]; for (int i = 0; i < argc; ++i) _argv[i] = argv[i]; - _argv[_argc - 1] = "-qmljsdebugger=port:3769"; + _argv[_argc - 1] = "-qmljsdebugger=port:13769"; QApplication app(_argc, _argv); tst_QDeclarativeDebugService tc; -- cgit v0.12 From 663f836f58e6588a7f99849d52f8f7e6c9c81bb7 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 3 Feb 2011 14:21:21 +1000 Subject: Correct error message Task-number: QTBUG-17091 --- src/declarative/qml/qdeclarativecompiler.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp index a0236c0..0554897 100644 --- a/src/declarative/qml/qdeclarativecompiler.cpp +++ b/src/declarative/qml/qdeclarativecompiler.cpp @@ -1354,7 +1354,11 @@ bool QDeclarativeCompiler::buildSignal(QDeclarativeParser::Property *prop, QDecl Q_ASSERT(obj->type != -1); const QList &resolvedTypes = unit->resolvedTypes(); const QDeclarativeTypeData::TypeReference &type = resolvedTypes.at(obj->type); - COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(QString::fromUtf8(obj->className)).arg(QString::fromUtf8(prop->name)).arg(QString::fromUtf8(type.type->module())).arg(type.majorVersion).arg(type.minorVersion)); + if (type.type) { + COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(QString::fromUtf8(obj->className)).arg(QString::fromUtf8(prop->name)).arg(QString::fromUtf8(type.type->module())).arg(type.majorVersion).arg(type.minorVersion)); + } else { + COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available due to component versioning.").arg(QString::fromUtf8(obj->className)).arg(QString::fromUtf8(prop->name))); + } } // If the "on" name doesn't resolve into a signal, try it as a @@ -1471,7 +1475,11 @@ bool QDeclarativeCompiler::buildProperty(QDeclarativeParser::Property *prop, if (prop->index == -1 && notInRevision) { const QList &resolvedTypes = unit->resolvedTypes(); const QDeclarativeTypeData::TypeReference &type = resolvedTypes.at(obj->type); - COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(QString::fromUtf8(obj->className)).arg(QString::fromUtf8(prop->name)).arg(QString::fromUtf8(type.type->module())).arg(type.majorVersion).arg(type.minorVersion)); + if (type.type) { + COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(QString::fromUtf8(obj->className)).arg(QString::fromUtf8(prop->name)).arg(QString::fromUtf8(type.type->module())).arg(type.majorVersion).arg(type.minorVersion)); + } else { + COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available due to component versioning.").arg(QString::fromUtf8(obj->className)).arg(QString::fromUtf8(prop->name))); + } } if (prop->index != -1) { -- cgit v0.12 From d87e2627cbc3f818e23c9c80b03cc665e5f3d444 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Thu, 3 Feb 2011 14:59:56 +1000 Subject: Don't accept input methods when a TextEdit or TextInput is read only. Neither would open a software input panel or allow text entry while read only, but on Symbian at least the text input mode indicator was still displayed giving the appearance of being able to enter text. Task-number: QT-4497 Reviewed-by: Damian Jansen --- src/declarative/graphicsitems/qdeclarativetextedit.cpp | 1 + src/declarative/graphicsitems/qdeclarativetextinput.cpp | 1 + .../qdeclarativetextedit/tst_qdeclarativetextedit.cpp | 10 ++++++++++ .../qdeclarativetextinput/tst_qdeclarativetextinput.cpp | 10 ++++++++++ 4 files changed, 22 insertions(+) diff --git a/src/declarative/graphicsitems/qdeclarativetextedit.cpp b/src/declarative/graphicsitems/qdeclarativetextedit.cpp index f63e4cb..17354eb 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextedit.cpp @@ -1023,6 +1023,7 @@ void QDeclarativeTextEdit::setReadOnly(bool r) if (r == isReadOnly()) return; + setFlag(QGraphicsItem::ItemAcceptsInputMethod, !r); Qt::TextInteractionFlags flags = Qt::LinksAccessibleByMouse; if (r) { diff --git a/src/declarative/graphicsitems/qdeclarativetextinput.cpp b/src/declarative/graphicsitems/qdeclarativetextinput.cpp index 012d408..57e60ac 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextinput.cpp @@ -377,6 +377,7 @@ void QDeclarativeTextInput::setReadOnly(bool ro) if (d->control->isReadOnly() == ro) return; + setFlag(QGraphicsItem::ItemAcceptsInputMethod, !ro); d->control->setReadOnly(ro); emit readOnlyChanged(ro); diff --git a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp index b82aca8..7d5101c 100644 --- a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp +++ b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp @@ -1676,6 +1676,16 @@ void tst_qdeclarativetextedit::openInputPanelOnFocus() QApplication::processEvents(); QVERIFY(view.inputContext() == 0); QVERIFY(!view.testAttribute(Qt::WA_InputMethodEnabled)); + + // input method should not be enabled + // if TextEdit is read only. + edit.setReadOnly(true); + ic.openInputPanelReceived = false; + edit.setFocus(true); + QApplication::processEvents(); + QCOMPARE(ic.openInputPanelReceived, false); + QVERIFY(view.inputContext() == 0); + QVERIFY(!view.testAttribute(Qt::WA_InputMethodEnabled)); } void tst_qdeclarativetextedit::geometrySignals() diff --git a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp index 675367c..42a0659 100644 --- a/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp +++ b/tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp @@ -1605,6 +1605,16 @@ void tst_qdeclarativetextinput::openInputPanelOnFocus() QApplication::processEvents(); QVERIFY(view.inputContext() == 0); QVERIFY(!view.testAttribute(Qt::WA_InputMethodEnabled)); + + // input method should not be enabled + // if TextEdit is read only. + input.setReadOnly(true); + ic.openInputPanelReceived = false; + input.setFocus(true); + QApplication::processEvents(); + QCOMPARE(ic.openInputPanelReceived, false); + QVERIFY(view.inputContext() == 0); + QVERIFY(!view.testAttribute(Qt::WA_InputMethodEnabled)); } class MyTextInput : public QDeclarativeTextInput -- cgit v0.12 From 940d30e9cd76e9b98dd04c2e25a27b6a90bb34b9 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Thu, 3 Feb 2011 13:06:04 +0200 Subject: My changes 4.7.2 Reviewed-by: TrustMe --- dist/changes-4.7.2 | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/dist/changes-4.7.2 b/dist/changes-4.7.2 index 0d93052..d351856 100644 --- a/dist/changes-4.7.2 +++ b/dist/changes-4.7.2 @@ -134,8 +134,63 @@ Qt for Symbian specify which Internet Access Point should be used for streaming. - QNetworkProxyFactory - * [QTBUG-13857] Added systemProxyForQuery() for Symbian, allowing - network proxies configured on the device to be used by applications. + * [QTBUG-13857] Added systemProxyForQuery() for Symbian, allowing + network proxies configured on the device to be used by applications. + + - QApplication + * [QTBUG-15915] Fix crash when creating more than one QApplication in single test case. + + - QDesktopWidget + * [QTBUG-16095] Resize event for QDesktopWidget was sent too early. + + - QFileDialog + * [QTBUG-16204] Fix using QFileDialog statics in Symbian. + + - QDialog + * [QTBUG-16277] Fix fullscreen/Maximized dialog misplacement in Symbian. + + - QSystemSemaphore + * [QTBUG-16615] Fix QSystemSemaphore handle management issues in Symbian. + + - QLineEdit + * [QTBUG-16238] Fix one character displacement for cursor in line edits. + + - qmake & mkspecs + * [QT-4193] Only add ICON for application projects in symbianpkgrules.pri + * [QTBUG-13159] Allow pkg_prerules and pkg_postrules to be targeted to separate files. + * [QTBUG-13367] Make default application deployment removable & added .flags modifier + support for DEPLOYMENT items in Symbian. + * [QTBUG-14280] Implement support for DEPLOYMENT.display_name in Symbian. + * [QTBUG-13917] Localize .loc and .pkg content based on TRANSLATIONS. + * [QTBUG-15159] Use include(original mkspec) instead of copying of mkspec to default. + * [QTBUG-15393] Resolve EPOCROOT in qt.conf using same logic as in .pro. + * [QTBUG-15501] Fix symbian-mmp.conf include path. + * [QTBUG-15539] Use parent class function to generate Makefile headers in Symbian. + * [QTBUG-14472] Add NetworkServices capability automatically for network apps + * [QTBUG-14736] Add libinfix support for QML plugins in Symbian. + * [QT-4375] Fix incorrect file name case for OpenGL libraries in symbian.conf. + * [QTBUG-16172] Use relative include instead of absolute in default qmake.conf. + * [QTBUG-16221] Fix libinfixed usage in Symbian when def files are used. + * [QTBUG-16261] Fix infinite loop in qmake when reading malformed .ts files. + * [QTBUG-16298] Ignore static_and_shared in Symbian builds. + * [QTBUG-13769] Generate freeze targets in Symbian. + * [QTBUG-16691] Remove toolcheck from generic clean targets for symbian-sbsv2. + * [QT-4476] Fixed UTF-8 application names in device application menu in Symbian. + * [QTBUG-16753] Improved QMAKE_POST_LINK support in symbian-sbsv2. + * [QTBUG-16881] Fix QMAKE_POST_LINK in Symbian for targets with special characters. + * [QTBUG-16888] No longer replace dash and dot in TARGET with underscore in Symbian. + * Fix partial upgrade package UID for libinfixed Qt. + * Cleaned up sis_targets.prf. + + - Tool scripts + * [QTBUG-13886] Disallow patching capabilities of executables. + * [QTBUG-13891] Add Location as self signable capability in patch_capabilities.pl. + * [QTBUG-15561] Only patch package content that is necessary for self-signing. + * Fix epocroot handling in createpackage.pl script. + * Unify epocroot usage in createpackage and patch_capabilities scripts. + + - qtmain.lib + * [QTBUG-14735] Use qtmain.lib to provide entry point for all Symbian applications. Qt for Embedded Linux --------------------- @@ -165,6 +220,9 @@ Qt for Windows CE - Linguist * baz + - qmake + * [QTBUG-14357] Make qmake to pass all UTF-8 characters unchanged through parser. + **************************************************************************** * Important Behavior Changes * **************************************************************************** -- cgit v0.12 From 822151edc065dc89ed331e91e02fb8014ef3ecee Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Thu, 3 Feb 2011 15:33:41 +0200 Subject: Remove dependencies to pre-Symbian3 platforms from Symbian3 packages Qt applications built against Symbian3 SDK will not run on older devices, so remove the platform dependency to those devices so that the user will get a proper warning if he tries to install incompatible software to an older device. Task-number: QTBUG-17187 Reviewed-by: Janne Koskinen --- mkspecs/features/symbian/default_post.prf | 14 ++++++++------ src/s60installs/s60installs.pro | 8 +------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/mkspecs/features/symbian/default_post.prf b/mkspecs/features/symbian/default_post.prf index ec6ecd0..126981e 100644 --- a/mkspecs/features/symbian/default_post.prf +++ b/mkspecs/features/symbian/default_post.prf @@ -53,14 +53,16 @@ isEmpty(TARGET.UID2) { } } -# Supports S60 3.1, 3.2, 5.0, Symbian^3, and Symbian^4 by default +# Supports Symbian^3 and Symbian^4 by default and also S60 3.1, 3.2, and 5.0 if built against any of those. platform_product_id = S60ProductID platform_product_id = $$addLanguageDependentPkgItem(platform_product_id) pkg_platform_dependencies = \ "; Default HW/platform dependencies" \ - "[0x102032BE],0,0,0,{$$platform_product_id}" \ - "[0x102752AE],0,0,0,{$$platform_product_id}" \ - "[0x1028315F],0,0,0,{$$platform_product_id}" \ "[0x20022E6D],0,0,0,{$$platform_product_id}" \ - "[0x20032DE7],0,0,0,{$$platform_product_id}" \ - " " + "[0x20032DE7],0,0,0,{$$platform_product_id}" +contains(S60_VERSION, 3.1)|contains(S60_VERSION, 3.2)|contains(S60_VERSION, 5.0) { + pkg_platform_dependencies += \ + "[0x102032BE],0,0,0,{$$platform_product_id}" \ + "[0x102752AE],0,0,0,{$$platform_product_id}" \ + "[0x1028315F],0,0,0,{$$platform_product_id}" +} diff --git a/src/s60installs/s60installs.pro b/src/s60installs/s60installs.pro index 5c89338..c282b1e 100644 --- a/src/s60installs/s60installs.pro +++ b/src/s60installs/s60installs.pro @@ -77,19 +77,13 @@ symbian: { "ENDIF" \ " \"$$bearerStubZ\" - \"c:$$replace(QT_PLUGINS_BASE_DIR,/,\\)\\bearer\\qsymbianbearer$${QT_LIBINFIX}.qtplugin\" } else { - # Restrict deployment to Symbian3 and later platforms - default_deployment.pkg_prerules -= pkg_platform_dependencies - platform_dependency_rules.pkg_prerules = \ - "[0x20022E6D],0,0,0,{\"S60ProductID\"}" \ - "[0x20032DE7],0,0,0,{\"S60ProductID\"}" - # No need to deploy plugins for older platform versions when building on Symbian3 or later qts60plugindeployment = \ " \"$$pluginLocations/qts60plugin_5_0$${QT_LIBINFIX}.dll\" - \"c:\\sys\\bin\\qts60plugin_5_0$${QT_LIBINFIX}.dll\"" bearer_plugin.sources = $$QT_BUILD_TREE/plugins/bearer/qsymbianbearer$${QT_LIBINFIX}.dll bearer_plugin.path = c:$$QT_PLUGINS_BASE_DIR/bearer - DEPLOYMENT += bearer_plugin platform_dependency_rules + DEPLOYMENT += bearer_plugin } qtlibraries.pkg_postrules += qts60plugindeployment -- cgit v0.12 From 0401781da17f949c0d42d176266ff47ed59b0793 Mon Sep 17 00:00:00 2001 From: axis Date: Tue, 1 Feb 2011 09:44:42 +0100 Subject: Fixed library casing. RevBy: Trust me --- src/plugins/phonon/mmf/mmf.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/phonon/mmf/mmf.pro b/src/plugins/phonon/mmf/mmf.pro index de00c9e..a9e5746 100644 --- a/src/plugins/phonon/mmf/mmf.pro +++ b/src/plugins/phonon/mmf/mmf.pro @@ -128,7 +128,7 @@ symbian { LIBS += -lAudioEqualizerEffect -lBassBoostEffect -lDistanceAttenuationEffect -lDopplerbase -lEffectBase -lEnvironmentalReverbEffect -lListenerDopplerEffect -lListenerLocationEffect -lListenerOrientationEffect -lLocationBase -lLoudnessEffect -lOrientationBase -lSourceDopplerEffect -lSourceLocationEffect -lSourceOrientationEffect -lStereoWideningEffect # This is to allow IAP to be specified - LIBS += -lCommDb + LIBS += -lcommdb # This is needed for having the .qtplugin file properly created on Symbian. QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/phonon_backend -- cgit v0.12 From 1f904ce8553f4d8a64ac793fe09e3b8cedb8bddf Mon Sep 17 00:00:00 2001 From: axis Date: Tue, 1 Feb 2011 09:45:23 +0100 Subject: Fixed wrong static library extension on Symbian. After commit a1ba5568da6c57e, which moved the extension definitions from the symbian-makefile.conf to symbian.conf, the QMAKE_EXTENSION_STATICLIB was wrong because unix.conf was included later and overwrote it. Turns out we don't need unix.conf, so I just removed it. RevBy: Trust me --- mkspecs/common/symbian/symbian-makefile.conf | 2 -- 1 file changed, 2 deletions(-) diff --git a/mkspecs/common/symbian/symbian-makefile.conf b/mkspecs/common/symbian/symbian-makefile.conf index 0360615..e51de1d 100644 --- a/mkspecs/common/symbian/symbian-makefile.conf +++ b/mkspecs/common/symbian/symbian-makefile.conf @@ -19,8 +19,6 @@ QMAKE_ELF2E32_FLAGS = --dlldata \ --compressionmethod bytepair \ --unpaged -include(../../common/unix.conf) - QMAKE_PREFIX_SHLIB = CONFIG *= no_plugin_name_prefix QMAKE_PREFIX_STATICLIB = -- cgit v0.12 From 0c494b2c3d05a00f0cb167daed24730a2cc5815e Mon Sep 17 00:00:00 2001 From: axis Date: Thu, 3 Feb 2011 15:37:05 +0100 Subject: Fixed wrong casing of a Symbian library. RevBy: Trust me --- demos/qmediaplayer/qmediaplayer.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demos/qmediaplayer/qmediaplayer.pro b/demos/qmediaplayer/qmediaplayer.pro index d283ec8..fbf06d2 100644 --- a/demos/qmediaplayer/qmediaplayer.pro +++ b/demos/qmediaplayer/qmediaplayer.pro @@ -33,7 +33,7 @@ symbian { include($$QT_SOURCE_TREE/demos/symbianpkgrules.pri) - LIBS += -lCommDb + LIBS += -lcommdb TARGET.CAPABILITY="NetworkServices" } -- cgit v0.12 From 5ee75c4a483405180788b5a4986dce2cf9360d86 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Thu, 3 Feb 2011 21:05:16 +0100 Subject: Added a configuration variable for the QML documentation file prefix. This required a certain amount of refactoring to make the new variable visible to the relevant parts of the code. I also moved the fullDocumentLocation() function into the HtmlGenerator class, where it belongs. Task-number: QTBUG-17071 --- tools/qdoc3/config.h | 1 + tools/qdoc3/doc/qdoc-manual.qdoc | 21 +++++ tools/qdoc3/generator.cpp | 16 ++++ tools/qdoc3/generator.h | 2 + tools/qdoc3/helpprojectwriter.cpp | 32 ++++---- tools/qdoc3/htmlgenerator.cpp | 147 +++++++++++++++++++++++++++++++++- tools/qdoc3/htmlgenerator.h | 1 + tools/qdoc3/node.cpp | 2 +- tools/qdoc3/pagegenerator.cpp | 8 +- tools/qdoc3/tree.cpp | 162 +++----------------------------------- 10 files changed, 217 insertions(+), 175 deletions(-) diff --git a/tools/qdoc3/config.h b/tools/qdoc3/config.h index bc2b6a2..9ebc0f8 100644 --- a/tools/qdoc3/config.h +++ b/tools/qdoc3/config.h @@ -148,6 +148,7 @@ class Config #define CONFIG_OUTPUTENCODING "outputencoding" #define CONFIG_OUTPUTLANGUAGE "outputlanguage" #define CONFIG_OUTPUTFORMATS "outputformats" +#define CONFIG_OUTPUTPREFIXES "outputprefixes" #define CONFIG_PROJECT "project" #define CONFIG_QHP "qhp" #define CONFIG_QUOTINGINFORMATION "quotinginformation" diff --git a/tools/qdoc3/doc/qdoc-manual.qdoc b/tools/qdoc3/doc/qdoc-manual.qdoc index adf92fe..7290c0e 100644 --- a/tools/qdoc3/doc/qdoc-manual.qdoc +++ b/tools/qdoc3/doc/qdoc-manual.qdoc @@ -7069,6 +7069,8 @@ \l {22-qdoc-configuration-generalvariables.html#outputdir}{outputdir}, \l {22-qdoc-configuration-generalvariables.html#outputformats} {outputformats}, + \l {22-qdoc-configuration-generalvariables.html#outputprefixes} + {outputprefixes}, \l {22-qdoc-configuration-generalvariables.html#slow}{slow}, \l {22-qdoc-configuration-generalvariables.html#sourcedirs}{sourcedirs}, \l {22-qdoc-configuration-generalvariables.html#sources}{sources}, @@ -7155,6 +7157,8 @@ \l {22-qdoc-configuration-generalvariables.html#outputdir}{outputdir}, \l {22-qdoc-configuration-generalvariables.html#outputformats} {outputformats}, + \l {22-qdoc-configuration-generalvariables.html#outputprefixes} + {outputprefixes}, \l {22-qdoc-configuration-generalvariables.html#slow}{slow}, \l {22-qdoc-configuration-generalvariables.html#sourcedirs}{sourcedirs}, \l {22-qdoc-configuration-generalvariables.html#sources}{sources}, @@ -7796,6 +7800,23 @@ the default format, and doesn't need to be specified. \row + \o \bold outputprefixes \target outputprefixes + \o \bold {The \c outputprefixes variable specifies a mapping between + types of files and the prefixes to prepend to the HTML file names + in the generated documentation.} + + For example: + + \code + outputprefixes = QML + outputprefixes.QML = qt-components- + \endcode + + Be default, files containing the API documentation for QML elements + or components are prefixed with "qml-". In the above example, the + prefix "qt-components-" is used instead. + + \row \o \bold qhp \target qhp \o \bold{The \c qhp variable is used to define the information to be written out to Qt Help Project (\c{qhp}) files.} diff --git a/tools/qdoc3/generator.cpp b/tools/qdoc3/generator.cpp index 276eab4..b4768db 100644 --- a/tools/qdoc3/generator.cpp +++ b/tools/qdoc3/generator.cpp @@ -43,7 +43,9 @@ generator.cpp */ #include +#ifdef DEBUG_MULTIPLE_QDOCCONF_FILES #include +#endif #include "codemarker.h" #include "config.h" #include "doc.h" @@ -73,6 +75,7 @@ QStringList Generator::styleFiles; QStringList Generator::styleDirs; QString Generator::outDir; QString Generator::project; +QHash Generator::outputPrefixes; static void singularPlural(Text& text, const NodeList& nodes) { @@ -272,6 +275,14 @@ void Generator::initialize(const Config &config) } project = config.getString(CONFIG_PROJECT); + + QStringList prefixes = config.getStringList(CONFIG_OUTPUTPREFIXES); + if (!prefixes.isEmpty()) { + foreach (QString prefix, prefixes) + outputPrefixes[prefix] = config.getString( + CONFIG_OUTPUTPREFIXES + Config::dot + prefix); + } else + outputPrefixes[QLatin1String("QML")] = QLatin1String("qml-"); } void Generator::terminate() @@ -1259,4 +1270,9 @@ QString Generator::fullName(const Node *node, return marker->plainFullName(node, relative); } +QString Generator::outputPrefix(const QString &nodeType) +{ + return outputPrefixes[nodeType]; +} + QT_END_NAMESPACE diff --git a/tools/qdoc3/generator.h b/tools/qdoc3/generator.h index 8378d07..4482313 100644 --- a/tools/qdoc3/generator.h +++ b/tools/qdoc3/generator.h @@ -148,6 +148,7 @@ class Generator static QString trimmedTrailing(const QString &string); static bool matchAhead(const Atom *atom, Atom::Type expectedAtomType); static void supplementAlsoList(const Node *node, QList &alsoList); + static QString outputPrefix(const QString &nodeType); private: void generateReimplementedFrom(const FunctionNode *func, @@ -198,6 +199,7 @@ class Generator static QStringList styleDirs; static QString outDir; static QString project; + static QHash outputPrefixes; }; QT_END_NAMESPACE diff --git a/tools/qdoc3/helpprojectwriter.cpp b/tools/qdoc3/helpprojectwriter.cpp index 386ce20..f2e2f04 100644 --- a/tools/qdoc3/helpprojectwriter.cpp +++ b/tools/qdoc3/helpprojectwriter.cpp @@ -214,7 +214,7 @@ QStringList HelpProjectWriter::keywordDetails(const Node *node) const details << node->name(); details << node->name(); } - details << tree->fullDocumentLocation(node); + details << HtmlGenerator::fullDocumentLocation(node); return details; } @@ -274,12 +274,12 @@ bool HelpProjectWriter::generateSection(HelpProject &project, case Node::Class: project.keywords.append(keywordDetails(node)); - project.files.insert(tree->fullDocumentLocation(node)); + project.files.insert(HtmlGenerator::fullDocumentLocation(node)); break; case Node::Namespace: project.keywords.append(keywordDetails(node)); - project.files.insert(tree->fullDocumentLocation(node)); + project.files.insert(HtmlGenerator::fullDocumentLocation(node)); break; case Node::Enum: @@ -299,7 +299,7 @@ bool HelpProjectWriter::generateSection(HelpProject &project, details << item.name(); // "name" details << item.name(); // "id" } - details << tree->fullDocumentLocation(node); + details << HtmlGenerator::fullDocumentLocation(node); project.keywords.append(details); } } @@ -330,7 +330,7 @@ bool HelpProjectWriter::generateSection(HelpProject &project, if (node->relates()) { project.memberStatus[node->relates()].insert(node->status()); - project.files.insert(tree->fullDocumentLocation(node->relates())); + project.files.insert(HtmlGenerator::fullDocumentLocation(node->relates())); } else if (node->parent()) project.memberStatus[node->parent()].insert(node->status()); } @@ -344,7 +344,7 @@ bool HelpProjectWriter::generateSection(HelpProject &project, // Use the location of any associated enum node in preference // to that of the typedef. if (enumNode) - typedefDetails[2] = tree->fullDocumentLocation(enumNode); + typedefDetails[2] = HtmlGenerator::fullDocumentLocation(enumNode); project.keywords.append(typedefDetails); } @@ -364,11 +364,11 @@ bool HelpProjectWriter::generateSection(HelpProject &project, QStringList details; details << keyword->string() << keyword->string() - << tree->fullDocumentLocation(node) + "#" + Doc::canonicalTitle(keyword->string()); + << HtmlGenerator::fullDocumentLocation(node) + "#" + Doc::canonicalTitle(keyword->string()); project.keywords.append(details); } else fakeNode->doc().location().warning( - tr("Bad keyword in %1").arg(tree->fullDocumentLocation(node)) + tr("Bad keyword in %1").arg(HtmlGenerator::fullDocumentLocation(node)) ); } } @@ -382,16 +382,16 @@ bool HelpProjectWriter::generateSection(HelpProject &project, QStringList details; details << title << title - << tree->fullDocumentLocation(node) + "#" + Doc::canonicalTitle(title); + << HtmlGenerator::fullDocumentLocation(node) + "#" + Doc::canonicalTitle(title); project.keywords.append(details); } else fakeNode->doc().location().warning( - tr("Bad contents item in %1").arg(tree->fullDocumentLocation(node)) + tr("Bad contents item in %1").arg(HtmlGenerator::fullDocumentLocation(node)) ); } } */ - project.files.insert(tree->fullDocumentLocation(node)); + project.files.insert(HtmlGenerator::fullDocumentLocation(node)); } break; } @@ -470,7 +470,7 @@ void HelpProjectWriter::generate(const Tree *tre) void HelpProjectWriter::writeNode(HelpProject &project, QXmlStreamWriter &writer, const Node *node) { - QString href = tree->fullDocumentLocation(node); + QString href = HtmlGenerator::fullDocumentLocation(node); QString objName = node->name(); switch (node->type()) { @@ -613,12 +613,12 @@ void HelpProjectWriter::generateProject(HelpProject &project) writer.writeStartElement("toc"); writer.writeStartElement("section"); - QString indexPath = tree->fullDocumentLocation(tree->findFakeNodeByTitle(project.indexTitle)); + QString indexPath = HtmlGenerator::fullDocumentLocation(tree->findFakeNodeByTitle(project.indexTitle)); if (indexPath.isEmpty()) indexPath = "index.html"; writer.writeAttribute("ref", HtmlGenerator::cleanRef(indexPath)); writer.writeAttribute("title", project.indexTitle); - project.files.insert(tree->fullDocumentLocation(rootNode)); + project.files.insert(HtmlGenerator::fullDocumentLocation(rootNode)); generateSections(project, writer, rootNode); @@ -656,7 +656,7 @@ void HelpProjectWriter::generateProject(HelpProject &project) const FakeNode *page = tree->findFakeNodeByTitle(atom->string()); writer.writeStartElement("section"); - QString indexPath = tree->fullDocumentLocation(page); + QString indexPath = HtmlGenerator::fullDocumentLocation(page); writer.writeAttribute("ref", HtmlGenerator::cleanRef(indexPath)); writer.writeAttribute("title", atom->string()); project.files.insert(indexPath); @@ -681,7 +681,7 @@ void HelpProjectWriter::generateProject(HelpProject &project) if (!name.isEmpty()) { writer.writeStartElement("section"); - QString indexPath = tree->fullDocumentLocation(tree->findFakeNodeByTitle(subproject.indexTitle)); + QString indexPath = HtmlGenerator::fullDocumentLocation(tree->findFakeNodeByTitle(subproject.indexTitle)); writer.writeAttribute("ref", HtmlGenerator::cleanRef(indexPath)); writer.writeAttribute("title", subproject.title); project.files.insert(indexPath); diff --git a/tools/qdoc3/htmlgenerator.cpp b/tools/qdoc3/htmlgenerator.cpp index 196bd44..0ff28af 100644 --- a/tools/qdoc3/htmlgenerator.cpp +++ b/tools/qdoc3/htmlgenerator.cpp @@ -4246,6 +4246,151 @@ void HtmlGenerator::generateExtractionMark(const Node *node, ExtractionMarkType } } +/*! + Returns the full document location for HTML-based documentation. + */ +QString HtmlGenerator::fullDocumentLocation(const Node *node) +{ + if (!node) + return ""; + if (!node->url().isEmpty()) + return node->url(); + + QString parentName; + QString anchorRef; + + if (node->type() == Node::Namespace) { + + // The root namespace has no name - check for this before creating + // an attribute containing the location of any documentation. + + if (!node->fileBase().isEmpty()) + parentName = node->fileBase() + ".html"; + else + return ""; + } + else if (node->type() == Node::Fake) { +#ifdef QDOC_QML + if ((node->subType() == Node::QmlClass) || + (node->subType() == Node::QmlBasicType)) { + QString fb = node->fileBase(); + if (fb.startsWith(Generator::outputPrefix(QLatin1String("QML")))) + return fb + ".html"; + else + return Generator::outputPrefix(QLatin1String("QML")) + node->fileBase() + QLatin1String(".html"); + } else +#endif + parentName = node->fileBase() + ".html"; + } + else if (node->fileBase().isEmpty()) + return ""; + + Node *parentNode = 0; + + if ((parentNode = node->relates())) + parentName = fullDocumentLocation(node->relates()); + else if ((parentNode = node->parent())) { + if (parentNode->subType() == Node::QmlPropertyGroup) { + parentNode = parentNode->parent(); + parentName = fullDocumentLocation(parentNode); + } + else + parentName = fullDocumentLocation(node->parent()); + } + + switch (node->type()) { + case Node::Class: + case Node::Namespace: + if (parentNode && !parentNode->name().isEmpty()) + parentName = parentName.replace(".html", "") + "-" + + node->fileBase().toLower() + ".html"; + else + parentName = node->fileBase() + ".html"; + break; + case Node::Function: + { + /* + Functions can be destructors, overloaded, or + have associated properties. + */ + const FunctionNode *functionNode = + static_cast(node); + + if (functionNode->metaness() == FunctionNode::Dtor) + anchorRef = "#dtor." + functionNode->name().mid(1); + + else if (functionNode->associatedProperty()) + return fullDocumentLocation(functionNode->associatedProperty()); + + else if (functionNode->overloadNumber() > 1) + anchorRef = "#" + functionNode->name() + + "-" + QString::number(functionNode->overloadNumber()); + else + anchorRef = "#" + functionNode->name(); + } + + /* + Use node->name() instead of node->fileBase() as + the latter returns the name in lower-case. For + HTML anchors, we need to preserve the case. + */ + break; + case Node::Enum: + anchorRef = "#" + node->name() + "-enum"; + break; + case Node::Typedef: + anchorRef = "#" + node->name() + "-typedef"; + break; + case Node::Property: + anchorRef = "#" + node->name() + "-prop"; + break; + case Node::QmlProperty: + anchorRef = "#" + node->name() + "-prop"; + break; + case Node::QmlSignal: + anchorRef = "#" + node->name() + "-signal"; + break; + case Node::QmlMethod: + anchorRef = "#" + node->name() + "-method"; + break; + case Node::Variable: + anchorRef = "#" + node->name() + "-var"; + break; + case Node::Target: + anchorRef = "#" + Doc::canonicalTitle(node->name()); + break; + case Node::Fake: + { + /* + Use node->fileBase() for fake nodes because they are represented + by pages whose file names are lower-case. + */ + parentName = node->fileBase(); + parentName.replace("/", "-").replace(".", "-"); + parentName += ".html"; + } + break; + default: + break; + } + + // Various objects can be compat (deprecated) or obsolete. + if (node->type() != Node::Class && node->type() != Node::Namespace) { + switch (node->status()) { + case Node::Compat: + parentName.replace(".html", "-qt3.html"); + break; + case Node::Obsolete: + parentName.replace(".html", "-obsolete.html"); + break; + default: + ; + } + } + + return parentName.toLower() + anchorRef; +} + #endif - QT_END_NAMESPACE +QT_END_NAMESPACE diff --git a/tools/qdoc3/htmlgenerator.h b/tools/qdoc3/htmlgenerator.h index 6e00ed3..eed96e7 100644 --- a/tools/qdoc3/htmlgenerator.h +++ b/tools/qdoc3/htmlgenerator.h @@ -98,6 +98,7 @@ class HtmlGenerator : public PageGenerator static QString protect(const QString &string, const QString &encoding = "ISO-8859-1"); static QString cleanRef(const QString& ref); static QString sinceTitle(int i) { return sinceTitles[i]; } + static QString fullDocumentLocation(const Node *node); protected: virtual void startText(const Node *relative, CodeMarker *marker); diff --git a/tools/qdoc3/node.cpp b/tools/qdoc3/node.cpp index a36d440..7195322 100644 --- a/tools/qdoc3/node.cpp +++ b/tools/qdoc3/node.cpp @@ -1693,7 +1693,7 @@ static QString valueType(const QString& n) read-only. The algorithm for figuring this out is long amd tedious and almost certainly will break. It currently doesn't work for qmlproperty bool PropertyChanges::explicit, - because the tokenized gets confused on "explicit" . + because the tokenizer gets confused on "explicit". */ bool QmlPropertyNode::isWritable(const Tree* tree) const { diff --git a/tools/qdoc3/pagegenerator.cpp b/tools/qdoc3/pagegenerator.cpp index 89ec6fe..d5564f7 100644 --- a/tools/qdoc3/pagegenerator.cpp +++ b/tools/qdoc3/pagegenerator.cpp @@ -206,15 +206,15 @@ QString PageGenerator::fileBase(const Node *node) const #ifdef QDOC_QML /* To avoid file name conflicts in the html directory, - we prepend "qml-" to the file name of QML element doc - files. + we prepend a prefix (by default, "qml-") to the file name of QML + element doc files. */ if ((p->subType() == Node::QmlClass) || (p->subType() == Node::QmlBasicType)) { if (!base.startsWith(QLatin1String("QML:"))) - base.prepend("qml-"); + base.prepend(outputPrefix(QLatin1String("QML"))); } -#endif +#endif if (!pp || pp->name().isEmpty() || pp->type() == Node::Fake) break; base.prepend(QLatin1Char('-')); diff --git a/tools/qdoc3/tree.cpp b/tools/qdoc3/tree.cpp index 5972b9f..eec6578 100644 --- a/tools/qdoc3/tree.cpp +++ b/tools/qdoc3/tree.cpp @@ -1226,7 +1226,7 @@ bool Tree::generateIndexSection(QXmlStreamWriter &writer, QString fullName = fullDocumentName(node); if (fullName != objName) writer.writeAttribute("fullname", fullName); - writer.writeAttribute("href", fullDocumentLocation(node)); + writer.writeAttribute("href", HtmlGenerator::fullDocumentLocation(node)); if ((node->type() != Node::Fake) && (!node->isQmlNode())) writer.writeAttribute("location", node->location().fileName()); @@ -1364,6 +1364,8 @@ bool Tree::generateIndexSection(QXmlStreamWriter &writer, { const QmlPropertyNode *qpn = static_cast(node); writer.writeAttribute("type", qpn->dataType()); + writer.writeAttribute("attached", qpn->isAttached() ? "true" : "false"); + writer.writeAttribute("writable", qpn->isWritable(this) ? "true" : "false"); } break; case Node::Property: @@ -1667,7 +1669,7 @@ void Tree::generateTagFileCompounds(QXmlStreamWriter &writer, if (node->type() == Node::Class) { writer.writeTextElement("name", fullDocumentName(node)); - writer.writeTextElement("filename", fullDocumentLocation(node)); + writer.writeTextElement("filename", HtmlGenerator::fullDocumentLocation(node)); // Classes contain information about their base classes. const ClassNode *classNode = static_cast(node); @@ -1685,7 +1687,7 @@ void Tree::generateTagFileCompounds(QXmlStreamWriter &writer, generateTagFileCompounds(writer, static_cast(node)); } else { writer.writeTextElement("name", fullDocumentName(node)); - writer.writeTextElement("filename", fullDocumentLocation(node)); + writer.writeTextElement("filename", HtmlGenerator::fullDocumentLocation(node)); // Recurse to write all members. generateTagFileMembers(writer, static_cast(node)); @@ -1806,7 +1808,7 @@ void Tree::generateTagFileMembers(QXmlStreamWriter &writer, "virtual " + functionNode->returnType()); writer.writeTextElement("name", objName); - QStringList pieces = fullDocumentLocation(node).split("#"); + QStringList pieces = HtmlGenerator::fullDocumentLocation(node).split("#"); writer.writeTextElement("anchorfile", pieces[0]); writer.writeTextElement("anchor", pieces[1]); @@ -1846,7 +1848,7 @@ void Tree::generateTagFileMembers(QXmlStreamWriter &writer, const PropertyNode *propertyNode = static_cast(node); writer.writeAttribute("type", propertyNode->dataType()); writer.writeTextElement("name", objName); - QStringList pieces = fullDocumentLocation(node).split("#"); + QStringList pieces = HtmlGenerator::fullDocumentLocation(node).split("#"); writer.writeTextElement("anchorfile", pieces[0]); writer.writeTextElement("anchor", pieces[1]); writer.writeTextElement("arglist", ""); @@ -1858,7 +1860,7 @@ void Tree::generateTagFileMembers(QXmlStreamWriter &writer, { const EnumNode *enumNode = static_cast(node); writer.writeTextElement("name", objName); - QStringList pieces = fullDocumentLocation(node).split("#"); + QStringList pieces = HtmlGenerator::fullDocumentLocation(node).split("#"); writer.writeTextElement("anchor", pieces[1]); writer.writeTextElement("arglist", ""); writer.writeEndElement(); // member @@ -1882,7 +1884,7 @@ void Tree::generateTagFileMembers(QXmlStreamWriter &writer, else writer.writeAttribute("type", ""); writer.writeTextElement("name", objName); - QStringList pieces = fullDocumentLocation(node).split("#"); + QStringList pieces = HtmlGenerator::fullDocumentLocation(node).split("#"); writer.writeTextElement("anchorfile", pieces[0]); writer.writeTextElement("anchor", pieces[1]); writer.writeTextElement("arglist", ""); @@ -1934,152 +1936,6 @@ void Tree::addExternalLink(const QString &url, const Node *relative) } /*! - Returns the full document location for HTML-based documentation. - This should be moved into the HTML generator. - */ -QString Tree::fullDocumentLocation(const Node *node) const -{ - if (!node) - return ""; - if (!node->url().isEmpty()) - return node->url(); - - QString parentName; - QString anchorRef; - - if (node->type() == Node::Namespace) { - - // The root namespace has no name - check for this before creating - // an attribute containing the location of any documentation. - - if (!node->fileBase().isEmpty()) - parentName = node->fileBase() + ".html"; - else - return ""; - } - else if (node->type() == Node::Fake) { -#ifdef QDOC_QML - if ((node->subType() == Node::QmlClass) || - (node->subType() == Node::QmlBasicType)) { - QString fb = node->fileBase(); - if (fb.startsWith(QLatin1String("qml-"))) - return fb + ".html"; - else - return "qml-" + node->fileBase() + ".html"; - } else -#endif - parentName = node->fileBase() + ".html"; - } - else if (node->fileBase().isEmpty()) - return ""; - - Node *parentNode = 0; - - if ((parentNode = node->relates())) - parentName = fullDocumentLocation(node->relates()); - else if ((parentNode = node->parent())) { - if (parentNode->subType() == Node::QmlPropertyGroup) { - parentNode = parentNode->parent(); - parentName = fullDocumentLocation(parentNode); - } - else - parentName = fullDocumentLocation(node->parent()); - } - - switch (node->type()) { - case Node::Class: - case Node::Namespace: - if (parentNode && !parentNode->name().isEmpty()) - parentName = parentName.replace(".html", "") + "-" - + node->fileBase().toLower() + ".html"; - else - parentName = node->fileBase() + ".html"; - break; - case Node::Function: - { - /* - Functions can be destructors, overloaded, or - have associated properties. - */ - const FunctionNode *functionNode = - static_cast(node); - - if (functionNode->metaness() == FunctionNode::Dtor) - anchorRef = "#dtor." + functionNode->name().mid(1); - - else if (functionNode->associatedProperty()) - return fullDocumentLocation(functionNode->associatedProperty()); - - else if (functionNode->overloadNumber() > 1) - anchorRef = "#" + functionNode->name() - + "-" + QString::number(functionNode->overloadNumber()); - else - anchorRef = "#" + functionNode->name(); - } - - /* - Use node->name() instead of node->fileBase() as - the latter returns the name in lower-case. For - HTML anchors, we need to preserve the case. - */ - break; - case Node::Enum: - anchorRef = "#" + node->name() + "-enum"; - break; - case Node::Typedef: - anchorRef = "#" + node->name() + "-typedef"; - break; - case Node::Property: - anchorRef = "#" + node->name() + "-prop"; - break; - case Node::QmlProperty: - anchorRef = "#" + node->name() + "-prop"; - break; - case Node::QmlSignal: - anchorRef = "#" + node->name() + "-signal"; - break; - case Node::QmlMethod: - anchorRef = "#" + node->name() + "-method"; - break; - case Node::Variable: - anchorRef = "#" + node->name() + "-var"; - break; - case Node::Target: - anchorRef = "#" + Doc::canonicalTitle(node->name()); - break; - case Node::Fake: - { - /* - Use node->fileBase() for fake nodes because they are represented - by pages whose file names are lower-case. - */ - parentName = node->fileBase(); - parentName.replace("/", "-").replace(".", "-"); - parentName += ".html"; - } - break; - default: - break; - } - - // Various objects can be compat (deprecated) or obsolete. - if (node->type() != Node::Class && node->type() != Node::Namespace) { - switch (node->status()) { - case Node::Compat: - parentName.replace(".html", "-qt3.html"); - break; - case Node::Obsolete: - parentName.replace(".html", "-obsolete.html"); - break; - default: - ; - } - } - - return parentName.toLower() + anchorRef; -} - -/*! Construct the full document name for \a node and return the name. */ -- cgit v0.12 From f3350644b74a37d7619d2de57f345e8d6dcb30f3 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Fri, 4 Feb 2011 16:39:49 +0100 Subject: Doc: Document display-orientation-related widget attributes. Reviewed-by: mread --- src/corelib/global/qnamespace.qdoc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index 8440542..65cd7f4 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -1252,6 +1252,13 @@ to this top level window. This attribute has no effect on non-X11 platforms. + \value WA_LockPortraitOrientation Locks the widget to a portrait orientation, + ignoring changes to the display's orientation with respect to the user. + \value WA_LockLandscapeOrientation Locks the widget to a landscape orientation, + ignoring changes to the display's orientation with respect to the user. + \value WA_AutoOrientation Causes the widget to change orientation whenever the + display changes orientation with respect to the user. + \omitvalue WA_SetLayoutDirection \omitvalue WA_InputMethodTransparent \omitvalue WA_WState_CompressKeys -- cgit v0.12 From e664bcceeeac38d19cbd6e8e1fc8883442f85e1b Mon Sep 17 00:00:00 2001 From: David Boddie Date: Fri, 4 Feb 2011 21:21:37 +0100 Subject: Fixed C++ and plain markup found in \c commands. --- tools/qdoc3/cppcodemarker.cpp | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/tools/qdoc3/cppcodemarker.cpp b/tools/qdoc3/cppcodemarker.cpp index 1b1e8f2..29f1c52 100644 --- a/tools/qdoc3/cppcodemarker.cpp +++ b/tools/qdoc3/cppcodemarker.cpp @@ -911,7 +911,7 @@ static QString untabified(const QString &in) QString CppCodeMarker::addMarkUp(const QString &in, const Node * /* relative */, - const Location & /* location */) + const Location /* &location */) { #define readChar() \ ch = (i < (int)code.length()) ? code[i++].cell() : EOF @@ -935,6 +935,7 @@ QString CppCodeMarker::addMarkUp(const QString &in, int braceDepth = 0; int parenDepth = 0; int i = 0; + int start = 0; char ch; QRegExp classRegExp("Qt?(?:[A-Z3]+[a-z][A-Za-z]*|t)"); QRegExp functionRegExp("q([A-Z][a-z]+)+"); @@ -942,7 +943,7 @@ QString CppCodeMarker::addMarkUp(const QString &in, readChar(); while (ch != EOF) { - int second = i; + int finish = i; QString tag; bool target = false; @@ -950,6 +951,7 @@ QString CppCodeMarker::addMarkUp(const QString &in, QString ident; do { ident += ch; + finish = i; readChar(); } while (isalnum(ch) || ch == '_'); @@ -970,6 +972,7 @@ QString CppCodeMarker::addMarkUp(const QString &in, } } else if (isdigit(ch)) { do { + finish = i; readChar(); } while (isalnum(ch) || ch == '.'); tag = QLatin1String("number"); @@ -992,10 +995,12 @@ QString CppCodeMarker::addMarkUp(const QString &in, case ']': case '|': case '~': + finish = i; readChar(); tag = QLatin1String("op"); break; case '"': + finish = i; readChar(); while (ch != EOF && ch != '"') { @@ -1003,19 +1008,23 @@ QString CppCodeMarker::addMarkUp(const QString &in, readChar(); readChar(); } + finish = i; readChar(); tag = QLatin1String("string"); break; case '#': + finish = i; readChar(); while (ch != EOF && ch != '\n') { if (ch == '\\') readChar(); + finish = i; readChar(); } tag = QLatin1String("preprocessor"); break; case '\'': + finish = i; readChar(); while (ch != EOF && ch != '\'') { @@ -1023,28 +1032,35 @@ QString CppCodeMarker::addMarkUp(const QString &in, readChar(); readChar(); } + finish = i; readChar(); tag = QLatin1String("char"); break; case '(': + finish = i; readChar(); parenDepth++; break; case ')': + finish = i; readChar(); parenDepth--; break; case ':': + finish = i; readChar(); if (ch == ':') { + finish = i; readChar(); tag = QLatin1String("op"); } break; case '/': + finish = i; readChar(); if (ch == '/') { do { + finish = i; readChar(); } while (ch != EOF && ch != '\n'); tag = QLatin1String("comment"); @@ -1052,6 +1068,7 @@ QString CppCodeMarker::addMarkUp(const QString &in, bool metAster = false; bool metAsterSlash = false; + finish = i; readChar(); while (!metAsterSlash) { @@ -1064,6 +1081,7 @@ QString CppCodeMarker::addMarkUp(const QString &in, metAsterSlash = true; else metAster = false; + finish = i; readChar(); } tag = QLatin1String("comment"); @@ -1072,23 +1090,24 @@ QString CppCodeMarker::addMarkUp(const QString &in, } break; case '{': + finish = i; readChar(); braceDepth++; break; case '}': + finish = i; readChar(); braceDepth--; break; default: + finish = i; readChar(); } } QString text; - if ((tag.isEmpty() || second == 1) && i == code.length()) - text = code.mid(second - 1, i - second + 1); - else - text = code.mid(second - 1, i - second); + text = code.mid(start, finish - start); + start = finish; if (!tag.isEmpty()) { out += QLatin1String("<@") + tag; -- cgit v0.12 From 7f919a56fe4e6e5e9b610361b8b0b32631c5edb1 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Sat, 5 Feb 2011 00:34:08 +0100 Subject: Fixed build breakage. --- tools/qdoc3/cppcodemarker.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qdoc3/cppcodemarker.cpp b/tools/qdoc3/cppcodemarker.cpp index 29f1c52..752d007 100644 --- a/tools/qdoc3/cppcodemarker.cpp +++ b/tools/qdoc3/cppcodemarker.cpp @@ -911,7 +911,7 @@ static QString untabified(const QString &in) QString CppCodeMarker::addMarkUp(const QString &in, const Node * /* relative */, - const Location /* &location */) + const Location & /* location */) { #define readChar() \ ch = (i < (int)code.length()) ? code[i++].cell() : EOF -- cgit v0.12 From eb5e587af8867fa57ee764441905bdf982ab43c6 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Sat, 5 Feb 2011 22:47:10 +0100 Subject: Ensured that trailing newlines are quoted and correct atoms are used. Newlines after comments at the end of files were previously omitted. An assumption about the type code being quoted caused incorrect CSS classes to be used and extra HTML elements to be used. --- tools/qdoc3/cppcodemarker.cpp | 5 ++++- tools/qdoc3/doc.cpp | 17 +++++++++++++---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/tools/qdoc3/cppcodemarker.cpp b/tools/qdoc3/cppcodemarker.cpp index 752d007..e27916b 100644 --- a/tools/qdoc3/cppcodemarker.cpp +++ b/tools/qdoc3/cppcodemarker.cpp @@ -936,6 +936,7 @@ QString CppCodeMarker::addMarkUp(const QString &in, int parenDepth = 0; int i = 0; int start = 0; + int finish = 0; char ch; QRegExp classRegExp("Qt?(?:[A-Z3]+[a-z][A-Za-z]*|t)"); QRegExp functionRegExp("q([A-Z][a-z]+)+"); @@ -943,7 +944,6 @@ QString CppCodeMarker::addMarkUp(const QString &in, readChar(); while (ch != EOF) { - int finish = i; QString tag; bool target = false; @@ -1120,7 +1120,10 @@ QString CppCodeMarker::addMarkUp(const QString &in, if (!tag.isEmpty()) out += QLatin1String(""); + } + if (start < code.length()) { + out += protect(code.mid(start)); } return out; diff --git a/tools/qdoc3/doc.cpp b/tools/qdoc3/doc.cpp index 76c47a2..a730799 100644 --- a/tools/qdoc3/doc.cpp +++ b/tools/qdoc3/doc.cpp @@ -369,6 +369,7 @@ class DocParser void appendChar(QChar ch); void appendWord(const QString &word); void appendToCode(const QString &code); + void appendToCode(const QString &code, Atom::Type defaultType); void startNewPara(); void enterPara(Atom::Type leftType = Atom::ParaLeft, Atom::Type rightType = Atom::ParaRight, @@ -1112,9 +1113,8 @@ void DocParser::parse(const QString& source, append(Atom::SnippetIdentifier, identifier); } else { - Doc::quoteFromFile(location(),quoter,snippet); - appendToCode(quoter.quoteSnippet(location(), - identifier)); + marker = Doc::quoteFromFile(location(),quoter,snippet); + appendToCode(quoter.quoteSnippet(location(), identifier), marker->atomType()); } } break; @@ -1855,7 +1855,7 @@ void DocParser::appendToCode(const QString& markedCode) { Atom::Type lastType = priv->text.lastAtom()->type(); #ifdef QDOC_QML - if (lastType != Atom::Qml) + if (lastType != Atom::Qml && lastType != Atom::Code && lastType != Atom::JavaScript) append(Atom::Qml); #else if (lastType != Atom::Code) @@ -1864,6 +1864,15 @@ void DocParser::appendToCode(const QString& markedCode) priv->text.lastAtom()->appendString(markedCode); } +void DocParser::appendToCode(const QString &markedCode, Atom::Type defaultType) +{ + Atom::Type lastType = priv->text.lastAtom()->type(); + if (lastType != Atom::Qml && lastType != Atom::Code && lastType != Atom::JavaScript) + append(defaultType, markedCode); + else + priv->text.lastAtom()->appendString(markedCode); +} + void DocParser::startNewPara() { leavePara(); -- cgit v0.12 From 776a00b3e8a29552a5db65fb539c0802654bfdff Mon Sep 17 00:00:00 2001 From: Morten Engvoldsen Date: Mon, 7 Feb 2011 11:26:57 +0100 Subject: Doc: Adding documentation on configure options for Qt configure --- doc/src/getting-started/installation.qdoc | 287 ++++++++++++++++++++++++++++++ 1 file changed, 287 insertions(+) diff --git a/doc/src/getting-started/installation.qdoc b/doc/src/getting-started/installation.qdoc index d39bb39..c906f84 100644 --- a/doc/src/getting-started/installation.qdoc +++ b/doc/src/getting-started/installation.qdoc @@ -1298,3 +1298,290 @@ We hope you will enjoy using Qt. \sa {Known Issues} */ + +/*! + \page configure-options.html + \title Configure options for Qt + \ingroup installation + \brief Brief description of available options building Qt. + + This page gives a brief description of the different options + available when building Qt using configure. To build Qt using + default options, just call configure from the command line like + showed below. If you would like to customize your build, please + use the options listed in the following tables. + + \c {.\configure.exe} + + \section2 Cross platform options: + + \table + \header \o Option \o Description \o Note + \row \o \c {-buildkey } \o Build the Qt library and plugins + using the specified \o + \row \o \c {} \o When the library loads plugins, it will only + load those that have a matching . \o + \row \o \c {-release } \o Compile and link Qt with debugging turned off. \o + \row \o \c {-debug } \o Compile and link Qt with debugging turned on. + \o Defualt value. + \row \o \c {-debug-and-release} \o Compile and link two Qt libraries, + with and without debugging turned on. \o This option denotes a default + value and needs to be evaluated. If the evaluation succeeds, the + feature is included. + \row \o \c {-opensource} \o Compile and link the Open-Source Edition + of Qt. \o + \row \o \c {-commercial } \o Compile and link the Commercial Edition + of Qt. \o + \row \o \c {-developer-build} \o Compile and link Qt with Qt developer + options including auto-tests exporting) \o + \row \o \c {-shared} \o Create and use shared Qt libraries. \o Defualt + value. + \row \o \c {-static} \o Create and use static Qt libraries. \o + \row \o \c {-ltcg} \o Use Link Time Code Generation. \o Apply to release + builds only. + \row \o \c {-no-ltcg} \o Do not use Link Time Code Generation. \o Defualt + value. + \row \o \c {-no-fast} \o Configure Qt normally by generating Makefiles for + all project files. \o Defualt value. + \row \o \c {-fast} \o Configure Qt quickly by generating Makefiles only for + library and subdirectory targets. \o All other Makefiles are created as + wrappers which will in turn run qmake. + \row \o \c {-no-exceptions} \o Disable exceptions on platforms that support + it. \o + \row \o \c {-exceptions} \o Enable exceptions on platforms that support it. + \o Defualt value. + \row \o \c {-no-accessibility} \o Do not compile Windows Active + Accessibility support. \o + \row \o \c {-accessibility} \o Compile Windows Active Accessibility + support. \o Defualt value. + \row \o \c {-no-stl} \o Do not compile STL support. \o + \row \o \c {-stl} \o Compile STL support. \o Defualt value. + \row \o \c {-no-sql-} \o Disable SQL entirely, by default + none are turned on. \o + \row \o \c {-qt-sql-} \o Enable a SQL in the Qt Library. + \o + \row \o \c {-plugin-sql-} \o Enable SQL as a plugin to be + linked to at run time. \o Available values for : mysql, psql, + oci, odbc, tds, db2, sqlite, sqlite2, ibase. Drivers marked with a + '+' during configure have been detected as available on this system. + \row \o \c {-system-sqlite} \o Use sqlite from the operating system. \o + \row \o \c {-no-qt3support} \o Disables the Qt 3 support functionality. \o + \row \o \c {-no-opengl} \o Disables OpenGL functionality \o + \row \o \c {-opengl } \o Enable OpenGL support with specified API + version. \o Available values for : desktop - Enable support for + Desktop OpenGL (Default), es1 - Enable support for OpenGL ES Common + Profile, es2 - Enable support for OpenGL ES 2.0. + \row \o \c {-no-openvg} \o Disables OpenVG functionality \o Defualt value. + \row \o \c {-openvg} \o Enables OpenVG functionality \o Requires EGL + support, typically supplied by an OpenGL or other graphics + implementation. + \row \o \c {-platform } \o The operating system and compiler you + are building on. \o The default value is %QMAKESPEC%. + \row \o \c {-xplatform } \o The operating system and compiler you + are cross compiling to. \o See the README file for a list of supported + operating systems and compilers. + \row \o \c {-qtnamespace } \o Wraps all Qt library code in + 'namespace name {..} \o + \row \o \c {-qtlibinfix } \o Renames all Qt* libs to Qt* + \o + \row \o \c {-D } \o Add an explicit define to the preprocessor. + \o + \row \o \c {-I } \o Add an explicit include path. \o + \row \o \c {-L } \o Add an explicit library path. \o + \row \o \c {-l } \o Add an explicit library name, residing + in a librarypath. \o + \row \o \c {-graphicssystem } \o Specify which graphicssystem should + be used. \o Available values for : * raster - Software rasterizer, + opengl - Using OpenGL acceleration, experimental!, openvg - Using + OpenVG acceleration, experimental! + \row \o \c {-help, -h, -?} \o Display this information. \o + \endtable + + \section2 Third Party Libraries: + \table + \header \o Option \o Description \o Note + \row \o \c {-qt-zlib} \o Use the zlib bundled with Qt. \o + \row \o \c {-system-zlib} \o Use zlib from the operating system. + \o See http://www.gzip.org/zlib + \row \o \c {-no-gif} \o Do not compile GIF reading support. + \o This option denotes a default value and needs to be evaluated. + If the evaluation succeeds, the feature is included. + \row \o \c {-qt-gif} \o Compile GIF reading support. \o See also + src/gui/image/qgifhandler_p.h + \row \o \c {-no-libpng} \o Do not compile PNG support. \o + \row \o \c {-qt-libpng} \o Use the libpng bundled with Qt. + \o This option denotes a default value and needs to be evaluated. + If the evaluation succeeds, the feature is included. + \row \o \c {-system-libpng} \o Use libpng from the operating system. + \o See http://www.libpng.org/pub/png + \row \o \c {-no-libmng} \o Do not compile MNG support. \o This option + denotes a default value and needs to be evaluated. If the evaluation + succeeds, the feature is included. + \row \o \c {-qt-libmng} \o Use the libmng bundled with Qt. \o + \row \o \c {-system-libmng} \o Use libmng from the operating system. + \o See See http://www.libmng.com + \row \o \c {-no-libtiff} \o Do not compile TIFF support. \o This option + denotes a default value and needs to be evaluated. If the evaluation + succeeds, the feature is included. + \row \o \c {-qt-libtiff} \o Use the libtiff bundled with Qt. \o + \row \o \c {-system-libtiff} \o Use libtiff from the operating system. + \o See http://www.libtiff.org + \row \o \c {-no-libjpeg} \o Do not compile JPEG support. \o This option + denotes a default value and needs to be evaluated. If the evaluation + succeeds, the feature is included. + \row \o \c {-qt-libjpeg} \o Use the libjpeg bundled with Qt. \o + \row \o \c {-system-libjpeg} \o Use libjpeg from the operating system. + \o See http://www.ijg.org. This option denotes a default value and + needs to be evaluated. If the evaluation succeeds, the feature is + included. + \endtable + + \section2 Qt for Windows only: + \table + \header \o Option \o Description \o Note + \row \o \c {-no-dsp} \o Do not generate VC++ .dsp files. \o + \row \o \c {-dsp} \o Generate VC++ .dsp files, only if spec "win32-msvc". + \o Defualt value. + \row \o \c {-no-vcproj} \o Do not generate VC++ .vcproj files. \o + \row \o \c {-vcproj} \o Generate VC++ .vcproj files, only if platform + "win32-msvc.net". \o Defualt value. + \row \o \c {-no-incredibuild-xge} \o Do not add IncrediBuild XGE distribution + commands to custom build steps. \o + \row \o \c {-incredibuild-xge} \o Add IncrediBuild XGE distribution commands + to custom build steps. This will distribute MOC and UIC steps, and other + custom buildsteps which are added to the INCREDIBUILD_XGE variable. + \o The IncrediBuild distribution commands are only added to Visual Studio + projects. This option denotes a default value and needs to be evaluated. + If the evaluation succeeds, the feature is included. + \row \o \c {-no-plugin-manifests} \o Do not embed manifests in plugins. \o + \row \o \c {-plugin-manifests} \o Embed manifests in plugins. + \o Defualt value. + \row \o \c {-no-qmake} \o Do not compile qmake. \o + \row \o \c {-qmake} \o Compile qmake. \o Defualt value + \row \o \c {-dont-process} \o Do not generate Makefiles/Project files. This + will override -no-fast if specified. \o + \row \o \c {-process} \o Generate Makefiles/Project files. \o Defualt value. + \row \o \c {-no-rtti} \o Do not compile runtime type information. \o + \row \o \c {-rtti} \o Compile runtime type information. \o Defualt value. + \row \o \c {-no-mmx} \o Do not compile with use of MMX instructions \o + \row \o \c {-mmx} \o Compile with use of MMX instructions \o This option + denotes a default value and needs to be evaluated. If the evaluation + succeeds, the feature is included. + \row \o \c {-no-3dnow} \o Do not compile with use of 3DNOW instructions \o + \row \o \c {-3dnow} \o Compile with use of 3DNOW instructions \o This + option denotes a default value and needs to be evaluated. If the + evaluation succeeds, the feature is included. + \row \o \c {-no-sse} \o Do not compile with use of SSE instructions \o + \row \o \c {-sse} \o Compile with use of SSE instructions \o This option + denotes a default value and needs to be evaluated. If the evaluation + succeeds, the feature is included. + \row \o \c {-no-sse2} \o Do not compile with use of SSE2 instructions \o + \row \o \c {-sse2} \o Compile with use of SSE2 instructions \o This option + denotes a default value and needs to be evaluated. If the evaluation + succeeds, the feature is included. + \row \o \c {-no-openssl} \o Do not compile in OpenSSL support \o + \row \o \c {-openssl} \o Compile in run-time OpenSSL support \o This option + denotes a default value and needs to be evaluated. If the evaluation + succeeds, the feature is included. + \row \o \c {-openssl-linked} \o Compile in linked OpenSSL support \o + \row \o \c {-no-dbus} \o Do not compile in D-Bus support \o + \row \o \c {-dbus} \o Compile in D-Bus support and load libdbus-1 dynamically. + \o This option denotes a default value and needs to be evaluated. + If the evaluation succeeds, the feature is included. + \row \o \c {-dbus-linked} \o Compile in D-Bus support and link to + libdbus-1 \o + \row \o \c {-no-phonon} \o Do not compile in the Phonon module \o + \row \o \c {-phonon} \o Compile the Phonon module. \o Phonon is built if a + decent C++ compiler is used. This option denotes a default value and needs + to be evaluated. If the evaluation succeeds, the feature is included. + \row \o \c {-no-phonon-backend} \o Do not compile the platform-specific + Phonon backend-plugin \o + \row \o \c {-phonon-backend} \o Compile in the platform-specific Phonon + backend-plugin \o Defualt value. + \row \o \c {-no-multimedia} \o Do not compile the multimedia module \o + \row \o \c {-multimedia} \o Compile in multimedia module \o Defualt value. + \row \o \c {-no-audio-backend} \o Do not compile in the platform audio + backend into QtMultimedia \o + \row \o \c {-audio-backend} \o Compile in the platform audio backend into + QtMultimedia \o This option denotes a default value and needs to be + evaluated. If the evaluation succeeds, the feature is included. + \row \o \c {-no-webkit} \o Do not compile in the WebKit module \o + \row \o \c {-webkit} \o Compile in the WebKit module \o WebKit is built + if a decent C++ compiler is used. This option denotes a default value + and needs to be evaluated. If the evaluation succeeds, the feature is + included. + \row \o \c {-webkit-debug} \o Compile in the WebKit module with debug + symbols. \o + \row \o \c {-no-script} \o Do not build the QtScript module. \o + \row \o \c {-script} \o Build the QtScript module. \o This option + denotes a default value and needs to be evaluated. If the evaluation + succeeds, the feature is included. + \row \o \c {-no-scripttools} \o Do not build the QtScriptTools module. \o + \row \o \c {-scripttools} \o Build the QtScriptTools module. \o This + option denotes a default value and needs to be evaluated. If the + evaluation succeeds, the feature is included. + \row \o \c {-no-declarative} \o Do not build the declarative module \o + \row \o \c {-declarative} \o Build the declarative module \o This option + denotes a default value and needs to be evaluated. If the evaluation + succeeds, the feature is included. + \row \o \c {-no-declarative-debug} \o Do not build the declarative debugging + support \o + \row \o \c {-declarative-debug} \o Build the declarative debugging support + \o Defualt value. + \row \o \c {-arch } \o Specify an architecture. \o Available values for + : * windows, windowsce, symbian, boundschecker, generic. + \row \o \c {-no-style-