diff options
68 files changed, 3103 insertions, 179 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 } } 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 } 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/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) } } 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 Binary files differnew file mode 100644 index 0000000..4014b46 --- /dev/null +++ b/examples/declarative/touchinteraction/pincharea/qt-logo.jpg diff --git a/src/declarative/debugger/qdeclarativedebugtrace.cpp b/src/declarative/debugger/qdeclarativedebugtrace.cpp index 03e2d56..314db70 100644 --- a/src/declarative/debugger/qdeclarativedebugtrace.cpp +++ b/src/declarative/debugger/qdeclarativedebugtrace.cpp @@ -43,11 +43,27 @@ #include <QtCore/qdatastream.h> #include <QtCore/qurl.h> +#include <QtCore/qtimer.h> 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")) +: QDeclarativeDebugService(QLatin1String("CanvasFrameRate")), + m_enabled(false), m_deferredSend(true) { m_timer.start(); } @@ -64,10 +80,16 @@ 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::rangeData(RangeType t, const QUrl &data) +{ + if (QDeclarativeDebugService::isDebuggingEnabled()) + traceInstance()->rangeDataImpl(t, data); } void QDeclarativeDebugTrace::endRange(RangeType t) @@ -78,45 +100,81 @@ 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); + QDeclarativeDebugData ed = {m_timer.elapsed(), (int)Event, (int)event, QString()}; + processMessage(ed); } 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); + QDeclarativeDebugData rd = {m_timer.elapsed(), (int)RangeStart, (int)range, QString()}; + processMessage(rd); } -void QDeclarativeDebugTrace::rangeDataImpl(RangeType range, const QUrl &u) +void QDeclarativeDebugTrace::rangeDataImpl(RangeType range, const QString &rData) { - 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); + QDeclarativeDebugData rd = {m_timer.elapsed(), (int)RangeData, (int)range, 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) + if (status() != Enabled || !m_enabled) return; - QByteArray data; - QDataStream ds(&data, QIODevice::WriteOnly); - ds << m_timer.elapsed() << (int)RangeEnd << (int)range; - sendMessage(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 QDeclarativeDebugData &message) +{ + if (m_deferredSend) + m_data.append(message); + else + sendMessage(message.toByteArray()); } +/* + 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).toByteArray()); + 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 704c49a..3f9b904 100644 --- a/src/declarative/debugger/qdeclarativedebugtrace_p.h +++ b/src/declarative/debugger/qdeclarativedebugtrace_p.h @@ -43,24 +43,28 @@ #define QDECLARATIVEDEBUGTRACE_P_H #include <private/qdeclarativedebugservice_p.h> -#include <QtCore/qelapsedtimer.h> +#include <private/qperformancetimer_p.h> 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,10 +74,20 @@ public: MaximumMessage }; + enum EventType { + FramePaint, + Mouse, + Key, + + MaximumEventType + }; + enum RangeType { Painting, Compiling, Creating, + Binding, //running a binding + HandlingSignal, //running a signal handler MaximumRangeType }; @@ -81,16 +95,25 @@ public: static void addEvent(EventType); static void startRange(RangeType); + static void rangeData(RangeType, const QString &); static void rangeData(RangeType, const QUrl &); static void endRange(RangeType); QDeclarativeDebugTrace(); +protected: + virtual void messageReceived(const QByteArray &); private: void addEventImpl(EventType); void startRangeImpl(RangeType); + void rangeDataImpl(RangeType, const QString &); void rangeDataImpl(RangeType, const QUrl &); void endRangeImpl(RangeType); - QElapsedTimer m_timer; + void processMessage(const QDeclarativeDebugData &); + void sendMessages(); + QPerformanceTimer m_timer; + bool m_enabled; + bool m_deferredSend; + QList<QDeclarativeDebugData> m_data; }; QT_END_NAMESPACE 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/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 c0a7d72..63b2b9a 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. @@ -226,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); @@ -290,7 +310,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())); @@ -310,6 +335,7 @@ void QDeclarativeBorderImage::load() d->progress = 1.0; emit statusChanged(d->status); emit progressChanged(d->progress); + requestFinished(); update(); } } @@ -413,7 +439,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; @@ -465,6 +496,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); @@ -514,8 +548,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(); @@ -541,6 +582,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/qdeclarativeborderimage_p.h b/src/declarative/graphicsitems/qdeclarativeborderimage_p.h index 9944cbe..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(); @@ -83,6 +86,7 @@ public: Q_SIGNALS: void horizontalTileModeChanged(); void verticalTileModeChanged(); + void sourceSizeChanged(); protected: virtual void load(); 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/src/declarative/graphicsitems/qdeclarativeimage.cpp b/src/declarative/graphicsitems/qdeclarativeimage.cpp index aa74716..68a1ecb 100644 --- a/src/declarative/graphicsitems/qdeclarativeimage.cpp +++ b/src/declarative/graphicsitems/qdeclarativeimage.cpp @@ -458,84 +458,102 @@ 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. +*/ + +/*! + \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 c3bac2d..c745635 100644 --- a/src/declarative/graphicsitems/qdeclarativeimagebase.cpp +++ b/src/declarative/graphicsitems/qdeclarativeimagebase.cpp @@ -128,6 +128,44 @@ 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::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); @@ -143,7 +181,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..b6e55ec 100644 --- a/src/declarative/graphicsitems/qdeclarativeimagebase_p.h +++ b/src/declarative/graphicsitems/qdeclarativeimagebase_p.h @@ -58,7 +58,9 @@ 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) + Q_PROPERTY(bool mirror READ mirror WRITE setMirror NOTIFY mirrorChanged) // ### VERSIONING: Only in QtQuick 1.1 public: ~QDeclarativeImageBase(); @@ -72,15 +74,23 @@ public: bool asynchronous() const; void setAsynchronous(bool); + bool cached() const; + void setCached(bool); + virtual void setSourceSize(const QSize&); QSize sourceSize() const; + virtual void setMirror(bool mirror); + bool mirror() const; + Q_SIGNALS: void sourceChanged(const QUrl &); void sourceSizeChanged(); void statusChanged(QDeclarativeImageBase::Status); 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 3d23ba9..950914f 100644 --- a/src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h @@ -70,7 +70,9 @@ public: : status(QDeclarativeImageBase::Null), progress(0.0), explicitSourceSize(false), - async(false) + async(false), + cached(true), + mirror(false) { QGraphicsItemPrivate::flags = QGraphicsItemPrivate::flags & ~QGraphicsItem::ItemHasNoContents; } @@ -82,6 +84,8 @@ public: QSize sourcesize; bool explicitSourceSize : 1; bool async : 1; + bool cached : 1; + bool mirror: 1; }; QT_END_NAMESPACE diff --git a/src/declarative/graphicsitems/qdeclarativeitem.cpp b/src/declarative/graphicsitems/qdeclarativeitem.cpp index 75e4a0b..4cf9b26 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<QDeclarativeKeyNavigationAttached>(currentItem, false); + if (attached) { + QDeclarativeItem *tempItem = qvariant_cast<QDeclarativeItem*>(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 a36ee34..7e4d157 100644 --- a/src/declarative/graphicsitems/qdeclarativeitem_p.h +++ b/src/declarative/graphicsitems/qdeclarativeitem_p.h @@ -415,6 +415,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/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<QDeclarativeViewSection>("QtQuick",1,0,"ViewSection"); qmlRegisterType<QDeclarativeVisualDataModel>("QtQuick",1,0,"VisualDataModel"); qmlRegisterType<QDeclarativeVisualItemModel>("QtQuick",1,0,"VisualItemModel"); + qmlRegisterType<QDeclarativePinchArea>("QtQuick",1,1,"PinchArea"); + qmlRegisterType<QDeclarativePinch>(); qmlRegisterType<QDeclarativeAnchors>(); qmlRegisterType<QDeclarativeKeyEvent>(); qmlRegisterType<QDeclarativeMouseEvent>(); + qmlRegisterType<QDeclarativePinchEvent>(); qmlRegisterType<QGraphicsObject>(); qmlRegisterType<QGraphicsWidget>("QtQuick",1,0,"QGraphicsWidget"); qmlRegisterExtendedType<QGraphicsWidget,QDeclarativeGraphicsWidget>("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 <QApplication> +#include <QGraphicsScene> + +#include <float.h> +#include <math.h> + +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<QTouchEvent*>(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<QDeclarativeItem*>(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<QDeclarativeItem*>(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<QDeclarativeItem*>(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<QGraphicsSceneMouseEvent *>(e)); + break; + case QEvent::TouchBegin: + case QEvent::TouchUpdate: { + QTouchEvent *touch = static_cast<QTouchEvent*>(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 <qdeclarativeitem.h> + +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 <qdatetime.h> +#include <qbasictimer.h> +#include <qevent.h> +#include <qgraphicssceneevent.h> +#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<QTouchEvent::TouchPoint> touchPoints; +}; + +QT_END_NAMESPACE + +#endif // QDECLARATIVEPINCHAREA_P_H diff --git a/src/declarative/graphicsitems/qdeclarativetextinput.cpp b/src/declarative/graphicsitems/qdeclarativetextinput.cpp index df103de..4649be8 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); diff --git a/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp b/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp index 4f5213a..dd07067 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); } diff --git a/src/declarative/qml/qdeclarativebinding.cpp b/src/declarative/qml/qdeclarativebinding.cpp index a7fbf44..309d372 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 <QVariant> #include <QtCore/qdebug.h> @@ -266,6 +267,20 @@ QDeclarativeProperty QDeclarativeBinding::property() const return d->property; } +class QDeclarativeBindingProfiler { +public: + QDeclarativeBindingProfiler(QDeclarativeBinding *bind) + { + QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Binding); + QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::Binding, bind->expression()); + } + + ~QDeclarativeBindingProfiler() + { + QDeclarativeDebugTrace::endRange(QDeclarativeDebugTrace::Binding); + } +}; + void QDeclarativeBinding::update(QDeclarativePropertyPrivate::WriteFlags flags) { Q_D(QDeclarativeBinding); @@ -274,6 +289,7 @@ void QDeclarativeBinding::update(QDeclarativePropertyPrivate::WriteFlags flags) return; if (!d->updating) { + QDeclarativeBindingProfiler prof(this); d->updating = true; bool wasDeleted = false; d->deleted = &wasDeleted; diff --git a/src/declarative/qml/qdeclarativeboundsignal.cpp b/src/declarative/qml/qdeclarativeboundsignal.cpp index 6af3e05..030fb2c 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 <QtCore/qdebug.h> @@ -165,6 +166,8 @@ 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() : "")); m_isEvaluating = true; if (!m_paramsValid) { if (!m_signal.parameterTypes().isEmpty()) @@ -180,6 +183,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/qdeclarativecompiledbindings.cpp b/src/declarative/qml/qdeclarativecompiledbindings.cpp index 5c295b9..48f8b84 100644 --- a/src/declarative/qml/qdeclarativecompiledbindings.cpp +++ b/src/declarative/qml/qdeclarativecompiledbindings.cpp @@ -54,6 +54,7 @@ #include <private/qdeclarativeanchors_p_p.h> #include <private/qdeclarativeglobal_p.h> #include <private/qdeclarativefastproperties_p.h> +#include <private/qdeclarativedebugtrace_p.h> QT_BEGIN_NAMESPACE @@ -302,7 +303,9 @@ void QDeclarativeCompiledBindingsPrivate::Binding::setEnabled(bool e, QDeclarati void QDeclarativeCompiledBindingsPrivate::Binding::update(QDeclarativePropertyPrivate::WriteFlags flags) { + QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Binding); parent->run(this, flags); + QDeclarativeDebugTrace::endRange(QDeclarativeDebugTrace::Binding); } void QDeclarativeCompiledBindingsPrivate::Binding::destroy() diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp index df428b1..4749bf8 100644 --- a/src/declarative/qml/qdeclarativecompiler.cpp +++ b/src/declarative/qml/qdeclarativecompiler.cpp @@ -1894,14 +1894,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 <Type>.<EnumValue> 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; @@ -2196,7 +2204,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); @@ -2849,13 +2865,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(binding.expression.asAST(), expression, &isSharable); quint32 length = expression.length(); quint32 pc; diff --git a/src/declarative/qml/qdeclarativecomponent.cpp b/src/declarative/qml/qdeclarativecomponent.cpp index 77fc925..a8b1c3f 100644 --- a/src/declarative/qml/qdeclarativecomponent.cpp +++ b/src/declarative/qml/qdeclarativecomponent.cpp @@ -789,8 +789,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 201e675..3a5fe66 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 <QtCore/qmetaobject.h> #include <QScriptClass> @@ -955,7 +956,8 @@ 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()); QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(data->context->engine); QDeclarativeComponentPrivate::ConstructionState state; @@ -965,6 +967,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/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 *); diff --git a/src/declarative/qml/qdeclarativerewrite.cpp b/src/declarative/qml/qdeclarativerewrite.cpp index bc9a114..219674f 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::Node *node) +{ _sharable = true; - AST::Node::acceptChild(parser.statement(), this); + AST::Node::acceptChild(node, 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,10 +85,63 @@ 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()); } +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 6f3c46e..310ef3c 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::Node *Node); virtual bool visit(AST::FunctionDeclaration *) { _sharable = false; return false; } virtual bool visit(AST::FunctionExpression *) { _sharable = false; return false; } @@ -81,7 +82,8 @@ 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); + 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; } 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; } diff --git a/src/declarative/qml/qdeclarativetypeloader.cpp b/src/declarative/qml/qdeclarativetypeloader.cpp index c015519..f42e8a7 100644 --- a/src/declarative/qml/qdeclarativetypeloader.cpp +++ b/src/declarative/qml/qdeclarativetypeloader.cpp @@ -45,6 +45,7 @@ #include <private/qdeclarativecompiler_p.h> #include <private/qdeclarativecomponent_p.h> #include <private/qdeclarativeglobal_p.h> +#include <private/qdeclarativedebugtrace_p.h> #include <QtDeclarative/qdeclarativecomponent.h> #include <QtCore/qdebug.h> @@ -895,10 +896,12 @@ 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(); m_compiledData->name = m_compiledData->url.toString(); + QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::Compiling, m_compiledData->name); QDeclarativeCompiler compiler; if (!compiler.compile(typeLoader()->engine(), this, m_compiledData)) { @@ -906,6 +909,7 @@ void QDeclarativeTypeData::compile() m_compiledData->release(); m_compiledData = 0; } + QDeclarativeDebugTrace::endRange(QDeclarativeDebugTrace::Compiling); } void QDeclarativeTypeData::resolveTypes() 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/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 <sys/time.h> +#include <unistd.h> +#include <mach/mach_time.h> +#elif defined(Q_OS_UNIX) +#include <sys/time.h> +#include <time.h> +#include <unistd.h> +#elif defined(Q_OS_SYMBIAN) +#include <e32std.h> +#include <sys/time.h> +#include <hal.h> +#elif defined(Q_OS_WIN) +#include <windows.h> +#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 <QtCore/qglobal.h> + +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/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/src/declarative/util/qdeclarativepixmapcache.cpp b/src/declarative/util/qdeclarativepixmapcache.cpp index 380d9bc..7c0a7f0 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<QDeclarativePixmapKey, QDeclarativePixmapData *>::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/src/declarative/util/qdeclarativeview.cpp b/src/declarative/util/qdeclarativeview.cpp index 0e31a20..a87ca37 100644 --- a/src/declarative/util/qdeclarativeview.cpp +++ b/src/declarative/util/qdeclarativeview.cpp @@ -77,7 +77,7 @@ extern Q_GUI_EXPORT bool qt_applefontsmoothing_enabled; class QDeclarativeScene : public QGraphicsScene { public: - QDeclarativeScene(); + QDeclarativeScene(QObject *parent = 0); protected: virtual void keyPressEvent(QKeyEvent *); @@ -88,7 +88,7 @@ protected: virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *); }; -QDeclarativeScene::QDeclarativeScene() +QDeclarativeScene::QDeclarativeScene(QObject *parent) : QGraphicsScene(parent) { } @@ -132,7 +132,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); @@ -155,8 +156,6 @@ public: QElapsedTimer frameTimer; void init(); - - QDeclarativeScene scene; }; void QDeclarativeViewPrivate::execute() @@ -234,6 +233,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} */ @@ -277,7 +279,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); @@ -286,11 +288,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 } /*! @@ -556,14 +558,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<QDeclarativeItem *>(obj)) { - d->scene.addItem(declarativeItem); + scene()->addItem(declarativeItem); d->root = declarativeItem; d->declarativeItemRoot = declarativeItem; } else if (QGraphicsObject *graphicsObject = qobject_cast<QGraphicsObject *>(obj)) { - d->scene.addItem(graphicsObject); + scene()->addItem(graphicsObject); d->root = graphicsObject; if (graphicsObject->isWidget()) { d->graphicsWidgetRoot = static_cast<QGraphicsWidget*>(graphicsObject); 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 &, diff --git a/tests/auto/declarative/qdeclarativeanimatedimage/data/hearts.gif b/tests/auto/declarative/qdeclarativeanimatedimage/data/hearts.gif Binary files differnew file mode 100644 index 0000000..cfb55f2 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeanimatedimage/data/hearts.gif 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 <private/qdeclarativerectangle_p.h> #include <private/qdeclarativeimage_p.h> #include <private/qdeclarativeanimatedimage_p.h> +#include <QSignalSpy> #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<QDeclarativeAnimatedImage *>(component.create()); + QVERIFY(anim); + + QGraphicsScene scene; + int width = anim->property("width").toInt(); + int height = anim->property("height").toInt(); + scene.addItem(qobject_cast<QGraphicsObject *>(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<QDeclarativeAnimatedImage *>(component.create()); + QVERIFY(anim); + + QGraphicsScene scene; + int width = anim->property("width").toInt(); + int height = anim->property("height").toInt(); + scene.addItem(qobject_cast<QGraphicsObject *>(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<QUrl>("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 Binary files differnew file mode 100644 index 0000000..5a31ae8 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeborderimage/data/heart200.png diff --git a/tests/auto/declarative/qdeclarativeborderimage/tst_qdeclarativeborderimage.cpp b/tests/auto/declarative/qdeclarativeborderimage/tst_qdeclarativeborderimage.cpp index 2f00f60..c22cde2 100644 --- a/tests/auto/declarative/qdeclarativeborderimage/tst_qdeclarativeborderimage.cpp +++ b/tests/auto/declarative/qdeclarativeborderimage/tst_qdeclarativeborderimage.cpp @@ -43,6 +43,8 @@ #include <QTcpServer> #include <QTcpSocket> #include <QDir> +#include <QGraphicsScene> +#include <QPainter> #include <QtDeclarative/qdeclarativeengine.h> #include <QtDeclarative/qdeclarativecomponent.h> @@ -77,6 +79,7 @@ private slots: void clearSource(); void resized(); void smooth(); + void mirror(); void tileModes(); void sciSource(); void sciSource_data(); @@ -153,6 +156,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 +197,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); @@ -214,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<QDeclarativeBorderImage*>(component.create()); + QVERIFY(obj != 0); + + int width = obj->property("width").toInt(); + int height = obj->property("height").toInt(); + + QGraphicsScene scene; + scene.addItem(qobject_cast<QGraphicsObject *>(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/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; i<qml.count(); i++) { QDeclarativeComponent component(m_engine); component.setData(qml[i], QUrl::fromLocalFile("")); @@ -635,14 +664,14 @@ void tst_QDeclarativeDebug::queryRootContexts() QCOMPARE(context.debugId(), QDeclarativeDebugService::idForObject(actualContext)); QCOMPARE(context.name(), actualContext->objectName()); - 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<QDeclarativeDebugObjectReference>(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<QDeclarativeDebugObjectReference>(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; 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 <private/qdeclarativevaluetype_p.h> #include <QtGui/qgraphicswidget.h> #include <math.h> +#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<QDeclarativeItem*>(c.create()); + QDeclarativeFlickable *obj = findItem<QDeclarativeFlickable>(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<QDeclarativeItem*>(c.create()); + QDeclarativeFlickable *obj = findItem<QDeclarativeFlickable>(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<typename T> T *tst_qdeclarativeflickable::findItem(QGraphicsObject *parent, const QString &objectName) { diff --git a/tests/auto/declarative/qdeclarativeimage/tst_qdeclarativeimage.cpp b/tests/auto/declarative/qdeclarativeimage/tst_qdeclarativeimage.cpp index 447210d..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(); @@ -124,19 +126,21 @@ void tst_qdeclarativeimage::imageSource_data() QTest::addColumn<double>("height"); QTest::addColumn<bool>("remote"); QTest::addColumn<bool>("async"); + QTest::addColumn<bool>("cached"); QTest::addColumn<QString>("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"; } @@ -147,6 +151,7 @@ void tst_qdeclarativeimage::imageSource() QFETCH(double, height); QFETCH(bool, remote); QFETCH(bool, async); + QFETCH(bool, cached); QFETCH(QString, error); TestHTTPServer server(SERVER_PORT); @@ -160,7 +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")) + " }"; + + (async ? QLatin1String("true") : QLatin1String("false")) + "; cached: " + + (cached ? QLatin1String("true") : QLatin1String("false")) + " }"; QDeclarativeComponent component(&engine); component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); QDeclarativeImage *obj = qobject_cast<QDeclarativeImage*>(component.create()); @@ -168,6 +174,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); @@ -259,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<QDeclarativeImage*>(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<QGraphicsObject *>(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<int>("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(); 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<QDeclarativeItem>(canvas->rootObject(), "item1"); + QVERIFY(item); + QVERIFY(item->hasActiveFocus()); + + // Set item 2 to not visible + item = findItem<QDeclarativeItem>(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<QDeclarativeItem>(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<QDeclarativeItem>(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<QDeclarativeItem>(canvas->rootObject(), "item1"); + QVERIFY(item); + QVERIFY(item->hasActiveFocus()); + + //Set item 3 to not visible + item = findItem<QDeclarativeItem>(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<QDeclarativeItem>(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<QDeclarativeItem>(canvas->rootObject(), "item1"); + QVERIFY(item); + QVERIFY(item->hasActiveFocus()); + + delete canvas; +} + void tst_QDeclarativeItem::smooth() { QDeclarativeComponent component(&engine); 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" 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 <QtTest/QtTest> +#include <QtTest/QSignalSpy> +#include <private/qdeclarativepincharea_p.h> +#include <private/qdeclarativerectangle_p.h> +#include <QtDeclarative/qdeclarativeview.h> +#include <QtDeclarative/qdeclarativecontext.h> + +#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<QDeclarativePinchArea*>("pincharea"); + QDeclarativePinch *pinch = pinchArea->pinch(); + QVERIFY(pinchArea != 0); + QVERIFY(pinch != 0); + + // target + QDeclarativeItem *blackRect = canvas->rootObject()->findChild<QDeclarativeItem*>("blackrect"); + QVERIFY(blackRect != 0); + QVERIFY(blackRect == pinch->target()); + QDeclarativeItem *rootItem = qobject_cast<QDeclarativeItem*>(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<QDeclarativePinchArea*>("pincharea"); + QDeclarativePinch *pinch = pinchArea->pinch(); + QVERIFY(pinchArea != 0); + QVERIFY(pinch != 0); + + QDeclarativeItem *root = qobject_cast<QDeclarativeItem*>(canvas->rootObject()); + QVERIFY(root != 0); + + // target + QDeclarativeItem *blackRect = canvas->rootObject()->findChild<QDeclarativeItem*>("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<QDeclarativePinchArea*>("pincharea"); + QDeclarativePinch *pinch = pinchArea->pinch(); + QVERIFY(pinchArea != 0); + QVERIFY(pinch != 0); + + QDeclarativeItem *root = qobject_cast<QDeclarativeItem*>(canvas->rootObject()); + QVERIFY(root != 0); + + // target + QDeclarativeItem *blackRect = canvas->rootObject()->findChild<QDeclarativeItem*>("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" 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<QDeclarativeItem*>(view->rootObject()); + QVERIFY(declarativeItem); + QVERIFY(scene.items().count() > 0); + QCOMPARE(scene.items().at(0), declarativeItem); +} + void tst_QDeclarativeView::resizemodedeclarativeitem() { QWidget window; 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 <private/qperformancetimer_p.h> +#include <QObject> +#include <qtest.h> + +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..497a556 --- /dev/null +++ b/tests/benchmarks/declarative/qperformancetimer/tst_qperformancetimer.cpp @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** 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 <private/qperformancetimer_p.h> +#include <QObject> +#include <qtest.h> + +class tst_qperformancetimer : public QObject +{ + Q_OBJECT + +public: + tst_qperformancetimer() {} + +private slots: + void all(); + void startElapsed(); + void doubleElapsed(); + void trace(); +}; + +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(); + } +} + +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" |