1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the test suite of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include <QtDeclarative/qdeclarativeengine.h>
43 #include <QtDeclarative/qdeclarativecomponent.h>
44 #include <QtQuick/qquickview.h>
45 #include <QtQuick/private/qquickrectangle_p.h>
46 #include <private/qquickimage_p.h>
47 #include <private/qquickanimatedimage_p.h>
49 #include <QtDeclarative/qdeclarativecontext.h>
51 #include "../../shared/testhttpserver.h"
52 #include "../../shared/util.h"
54 Q_DECLARE_METATYPE(QQuickImageBase::Status)
56 class tst_qquickanimatedimage : public QDeclarativeDataTest
60 tst_qquickanimatedimage() {}
68 void mirror_running();
69 void mirror_notRunning();
70 void mirror_notRunning_data();
74 void sourceSizeReadOnly();
77 void progressAndStatusChanges();
81 void tst_qquickanimatedimage::play()
83 QDeclarativeEngine engine;
84 QDeclarativeComponent component(&engine, testFileUrl("stickman.qml"));
85 QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create());
87 QVERIFY(anim->isPlaying());
92 void tst_qquickanimatedimage::pause()
94 QDeclarativeEngine engine;
95 QDeclarativeComponent component(&engine, testFileUrl("stickmanpause.qml"));
96 QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create());
98 QVERIFY(anim->isPlaying());
99 QVERIFY(anim->isPaused());
104 void tst_qquickanimatedimage::stopped()
106 QDeclarativeEngine engine;
107 QDeclarativeComponent component(&engine, testFileUrl("stickmanstopped.qml"));
108 QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create());
110 QVERIFY(!anim->isPlaying());
111 QCOMPARE(anim->currentFrame(), 0);
116 void tst_qquickanimatedimage::setFrame()
118 QDeclarativeEngine engine;
119 QDeclarativeComponent component(&engine, testFileUrl("stickmanpause.qml"));
120 QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create());
122 QVERIFY(anim->isPlaying());
123 QCOMPARE(anim->currentFrame(), 2);
128 void tst_qquickanimatedimage::frameCount()
130 QDeclarativeEngine engine;
131 QDeclarativeComponent component(&engine, testFileUrl("colors.qml"));
132 QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create());
134 QVERIFY(anim->isPlaying());
135 QCOMPARE(anim->frameCount(), 3);
140 void tst_qquickanimatedimage::mirror_running()
142 // test where mirror is set to true after animation has started
144 QQuickView *canvas = new QQuickView;
147 canvas->setSource(testFileUrl("hearts.qml"));
148 QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(canvas->rootObject());
151 int width = anim->property("width").toInt();
153 QCOMPARE(anim->currentFrame(), 0);
154 QPixmap frame0 = QPixmap::fromImage(canvas->grabFrameBuffer());
156 anim->setCurrentFrame(1);
157 QPixmap frame1 = QPixmap::fromImage(canvas->grabFrameBuffer());
159 anim->setCurrentFrame(0);
161 QSignalSpy spy(anim, SIGNAL(frameChanged()));
162 anim->setPlaying(true);
164 QTRY_VERIFY(spy.count() == 1); spy.clear();
165 anim->setProperty("mirror", true);
167 QCOMPARE(anim->currentFrame(), 1);
168 QPixmap frame1_flipped = QPixmap::fromImage(canvas->grabFrameBuffer());
170 QTRY_VERIFY(spy.count() == 1); spy.clear();
171 QCOMPARE(anim->currentFrame(), 0); // animation only has 2 frames, should cycle back to first
172 QPixmap frame0_flipped = QPixmap::fromImage(canvas->grabFrameBuffer());
174 QSKIP("Skip while QTBUG-19351 and QTBUG-19252 are not resolved");
176 QTransform transform;
177 transform.translate(width, 0).scale(-1, 1.0);
178 QPixmap frame0_expected = frame0.transformed(transform);
179 QPixmap frame1_expected = frame1.transformed(transform);
181 QCOMPARE(frame0_flipped, frame0_expected);
182 QCOMPARE(frame1_flipped, frame1_expected);
187 void tst_qquickanimatedimage::mirror_notRunning()
189 QFETCH(QUrl, fileUrl);
191 QQuickView *canvas = new QQuickView;
194 canvas->setSource(fileUrl);
195 QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(canvas->rootObject());
198 int width = anim->property("width").toInt();
199 QPixmap screenshot = QPixmap::fromImage(canvas->grabFrameBuffer());
201 QTransform transform;
202 transform.translate(width, 0).scale(-1, 1.0);
203 QPixmap expected = screenshot.transformed(transform);
205 int frame = anim->currentFrame();
206 bool playing = anim->isPlaying();
207 bool paused = anim->isPlaying();
209 anim->setProperty("mirror", true);
210 screenshot = QPixmap::fromImage(canvas->grabFrameBuffer());
212 QSKIP("Skip while QTBUG-19351 and QTBUG-19252 are not resolved");
213 QCOMPARE(screenshot, expected);
215 // mirroring should not change the current frame or playing status
216 QCOMPARE(anim->currentFrame(), frame);
217 QCOMPARE(anim->isPlaying(), playing);
218 QCOMPARE(anim->isPaused(), paused);
223 void tst_qquickanimatedimage::mirror_notRunning_data()
225 QTest::addColumn<QUrl>("fileUrl");
227 QTest::newRow("paused") << testFileUrl("stickmanpause.qml");
228 QTest::newRow("stopped") << testFileUrl("stickmanstopped.qml");
231 void tst_qquickanimatedimage::remote()
233 QFETCH(QString, fileName);
234 QFETCH(bool, paused);
236 TestHTTPServer server(14449);
237 QVERIFY(server.isValid());
238 server.serveDirectory(dataDirectory());
240 QDeclarativeEngine engine;
241 QDeclarativeComponent component(&engine, QUrl("http://127.0.0.1:14449/" + fileName));
242 QTRY_VERIFY(component.isReady());
244 QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create());
247 QTRY_VERIFY(anim->isPlaying());
249 QTRY_VERIFY(anim->isPaused());
250 QCOMPARE(anim->currentFrame(), 2);
252 QVERIFY(anim->status() != QQuickAnimatedImage::Error);
257 void tst_qquickanimatedimage::sourceSize()
259 QDeclarativeEngine engine;
260 QDeclarativeComponent component(&engine, testFileUrl("stickmanscaled.qml"));
261 QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create());
263 QCOMPARE(anim->width(),240.0);
264 QCOMPARE(anim->height(),180.0);
265 QCOMPARE(anim->sourceSize(),QSize(160,120));
270 void tst_qquickanimatedimage::sourceSizeReadOnly()
272 QDeclarativeEngine engine;
273 QDeclarativeComponent component(&engine, testFileUrl("stickmanerror1.qml"));
274 QVERIFY(component.isError());
275 QCOMPARE(component.errors().at(0).description(), QString("Invalid property assignment: \"sourceSize\" is a read-only property"));
278 void tst_qquickanimatedimage::remote_data()
280 QTest::addColumn<QString>("fileName");
281 QTest::addColumn<bool>("paused");
283 QTest::newRow("playing") << "stickman.qml" << false;
284 QTest::newRow("paused") << "stickmanpause.qml" << true;
287 void tst_qquickanimatedimage::invalidSource()
289 QDeclarativeEngine engine;
290 QDeclarativeComponent component(&engine);
291 component.setData("import QtQuick 2.0\n AnimatedImage { source: \"no-such-file.gif\" }", QUrl::fromLocalFile(""));
292 QVERIFY(component.isReady());
294 QTest::ignoreMessage(QtWarningMsg, "file::2:2: QML AnimatedImage: Error Reading Animated Image File file:no-such-file.gif");
296 QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create());
299 QVERIFY(!anim->isPlaying());
300 QVERIFY(!anim->isPaused());
301 QCOMPARE(anim->currentFrame(), 0);
302 QCOMPARE(anim->frameCount(), 0);
303 QTRY_VERIFY(anim->status() == 3);
306 void tst_qquickanimatedimage::qtbug_16520()
308 TestHTTPServer server(14449);
309 QVERIFY(server.isValid());
310 server.serveDirectory(dataDirectory());
312 QDeclarativeEngine engine;
313 QDeclarativeComponent component(&engine, testFileUrl("qtbug-16520.qml"));
314 QTRY_VERIFY(component.isReady());
316 QQuickRectangle *root = qobject_cast<QQuickRectangle *>(component.create());
318 QQuickAnimatedImage *anim = root->findChild<QQuickAnimatedImage*>("anim");
320 anim->setProperty("source", "http://127.0.0.1:14449/stickman.gif");
322 QTRY_VERIFY(anim->opacity() == 0);
323 QTRY_VERIFY(anim->opacity() == 1);
328 void tst_qquickanimatedimage::progressAndStatusChanges()
330 TestHTTPServer server(14449);
331 QVERIFY(server.isValid());
332 server.serveDirectory(dataDirectory());
334 QDeclarativeEngine engine;
335 QString componentStr = "import QtQuick 2.0\nAnimatedImage { source: srcImage }";
336 QDeclarativeContext *ctxt = engine.rootContext();
337 ctxt->setContextProperty("srcImage", testFileUrl("stickman.gif"));
338 QDeclarativeComponent component(&engine);
339 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
340 QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
342 QVERIFY(obj->status() == QQuickImage::Ready);
343 QTRY_VERIFY(obj->progress() == 1.0);
345 qRegisterMetaType<QQuickImageBase::Status>();
346 QSignalSpy sourceSpy(obj, SIGNAL(sourceChanged(const QUrl &)));
347 QSignalSpy progressSpy(obj, SIGNAL(progressChanged(qreal)));
348 QSignalSpy statusSpy(obj, SIGNAL(statusChanged(QQuickImageBase::Status)));
350 // Loading local file
351 ctxt->setContextProperty("srcImage", testFileUrl("colors.gif"));
352 QTRY_VERIFY(obj->status() == QQuickImage::Ready);
353 QTRY_VERIFY(obj->progress() == 1.0);
354 QTRY_COMPARE(sourceSpy.count(), 1);
355 QTRY_COMPARE(progressSpy.count(), 0);
356 QTRY_COMPARE(statusSpy.count(), 0);
358 // Loading remote file
359 ctxt->setContextProperty("srcImage", "http://127.0.0.1:14449/stickman.gif");
360 QTRY_VERIFY(obj->status() == QQuickImage::Loading);
361 QTRY_VERIFY(obj->progress() == 0.0);
362 QTRY_VERIFY(obj->status() == QQuickImage::Ready);
363 QTRY_VERIFY(obj->progress() == 1.0);
364 QTRY_COMPARE(sourceSpy.count(), 2);
365 QTRY_VERIFY(progressSpy.count() > 1);
366 QTRY_COMPARE(statusSpy.count(), 2);
368 ctxt->setContextProperty("srcImage", "");
369 QTRY_VERIFY(obj->status() == QQuickImage::Null);
370 QTRY_VERIFY(obj->progress() == 0.0);
371 QTRY_COMPARE(sourceSpy.count(), 3);
372 QTRY_VERIFY(progressSpy.count() > 2);
373 QTRY_COMPARE(statusSpy.count(), 3);
376 QTEST_MAIN(tst_qquickanimatedimage)
378 #include "tst_qquickanimatedimage.moc"