1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the test suite of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include <QtQml/qqmlengine.h>
43 #include <QtQml/qqmlcomponent.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 <QtQml/qqmlcontext.h>
51 #include "../../shared/testhttpserver.h"
52 #include "../../shared/util.h"
54 Q_DECLARE_METATYPE(QQuickImageBase::Status)
56 class tst_qquickanimatedimage : public QQmlDataTest
60 tst_qquickanimatedimage() {}
69 void mirror_running();
70 void mirror_notRunning();
71 void mirror_notRunning_data();
75 void sourceSizeChanges();
76 void sourceSizeReadOnly();
79 void progressAndStatusChanges();
82 void tst_qquickanimatedimage::cleanup()
85 canvas.releaseResources();
88 void tst_qquickanimatedimage::play()
91 QQmlComponent component(&engine, testFileUrl("stickman.qml"));
92 QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create());
94 QVERIFY(anim->isPlaying());
99 void tst_qquickanimatedimage::pause()
102 QQmlComponent component(&engine, testFileUrl("stickmanpause.qml"));
103 QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create());
106 QTRY_VERIFY(anim->isPaused());
107 QTRY_VERIFY(anim->isPlaying());
112 void tst_qquickanimatedimage::stopped()
115 QQmlComponent component(&engine, testFileUrl("stickmanstopped.qml"));
116 QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create());
118 QVERIFY(!anim->isPlaying());
119 QCOMPARE(anim->currentFrame(), 0);
124 void tst_qquickanimatedimage::setFrame()
127 QQmlComponent component(&engine, testFileUrl("stickmanpause.qml"));
128 QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create());
130 QVERIFY(anim->isPlaying());
131 QCOMPARE(anim->currentFrame(), 2);
136 void tst_qquickanimatedimage::frameCount()
139 QQmlComponent component(&engine, testFileUrl("colors.qml"));
140 QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create());
142 QVERIFY(anim->isPlaying());
143 QCOMPARE(anim->frameCount(), 3);
148 void tst_qquickanimatedimage::mirror_running()
150 // test where mirror is set to true after animation has started
155 canvas.setSource(testFileUrl("hearts.qml"));
156 QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(canvas.rootObject());
159 int width = anim->property("width").toInt();
161 QCOMPARE(anim->currentFrame(), 0);
162 QPixmap frame0 = QPixmap::fromImage(canvas.grabFrameBuffer());
164 anim->setCurrentFrame(1);
165 QPixmap frame1 = QPixmap::fromImage(canvas.grabFrameBuffer());
167 anim->setCurrentFrame(0);
169 QSignalSpy spy(anim, SIGNAL(frameChanged()));
170 anim->setPlaying(true);
172 QTRY_VERIFY(spy.count() == 1); spy.clear();
173 anim->setProperty("mirror", true);
175 QCOMPARE(anim->currentFrame(), 1);
176 QPixmap frame1_flipped = QPixmap::fromImage(canvas.grabFrameBuffer());
178 QTRY_VERIFY(spy.count() == 1); spy.clear();
179 QCOMPARE(anim->currentFrame(), 0); // animation only has 2 frames, should cycle back to first
180 QPixmap frame0_flipped = QPixmap::fromImage(canvas.grabFrameBuffer());
182 QSKIP("Skip while QTBUG-19351 and QTBUG-19252 are not resolved");
184 QTransform transform;
185 transform.translate(width, 0).scale(-1, 1.0);
186 QPixmap frame0_expected = frame0.transformed(transform);
187 QPixmap frame1_expected = frame1.transformed(transform);
189 QCOMPARE(frame0_flipped, frame0_expected);
190 QCOMPARE(frame1_flipped, frame1_expected);
195 void tst_qquickanimatedimage::mirror_notRunning()
197 QFETCH(QUrl, fileUrl);
202 canvas.setSource(fileUrl);
203 QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(canvas.rootObject());
206 int width = anim->property("width").toInt();
207 QPixmap screenshot = QPixmap::fromImage(canvas.grabFrameBuffer());
209 QTransform transform;
210 transform.translate(width, 0).scale(-1, 1.0);
211 QPixmap expected = screenshot.transformed(transform);
213 int frame = anim->currentFrame();
214 bool playing = anim->isPlaying();
215 bool paused = anim->isPlaying();
217 anim->setProperty("mirror", true);
218 screenshot = QPixmap::fromImage(canvas.grabFrameBuffer());
220 QCOMPARE(screenshot, expected);
222 // mirroring should not change the current frame or playing status
223 QCOMPARE(anim->currentFrame(), frame);
224 QCOMPARE(anim->isPlaying(), playing);
225 QCOMPARE(anim->isPaused(), paused);
230 void tst_qquickanimatedimage::mirror_notRunning_data()
232 QTest::addColumn<QUrl>("fileUrl");
234 QTest::newRow("paused") << testFileUrl("stickmanpause.qml");
235 QTest::newRow("stopped") << testFileUrl("stickmanstopped.qml");
238 void tst_qquickanimatedimage::remote_data()
240 QTest::addColumn<QString>("fileName");
241 QTest::addColumn<bool>("paused");
243 QTest::newRow("playing") << "stickman.qml" << false;
244 QTest::newRow("paused") << "stickmanpause.qml" << true;
247 void tst_qquickanimatedimage::remote()
249 QFETCH(QString, fileName);
250 QFETCH(bool, paused);
252 TestHTTPServer server(14449);
253 QVERIFY(server.isValid());
254 server.serveDirectory(dataDirectory());
257 QQmlComponent component(&engine, QUrl("http://127.0.0.1:14449/" + fileName));
258 QTRY_VERIFY(component.isReady());
260 QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create());
263 QTRY_VERIFY(anim->isPlaying());
265 QTRY_VERIFY(anim->isPaused());
266 QCOMPARE(anim->currentFrame(), 2);
268 QVERIFY(anim->status() != QQuickAnimatedImage::Error);
273 void tst_qquickanimatedimage::sourceSize()
276 QQmlComponent component(&engine, testFileUrl("stickmanscaled.qml"));
277 QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create());
279 QCOMPARE(anim->width(),240.0);
280 QCOMPARE(anim->height(),180.0);
281 QCOMPARE(anim->sourceSize(),QSize(160,120));
286 void tst_qquickanimatedimage::sourceSizeReadOnly()
289 QQmlComponent component(&engine, testFileUrl("stickmanerror1.qml"));
290 QVERIFY(component.isError());
291 QCOMPARE(component.errors().at(0).description(), QString("Invalid property assignment: \"sourceSize\" is a read-only property"));
294 void tst_qquickanimatedimage::invalidSource()
297 QQmlComponent component(&engine);
298 component.setData("import QtQuick 2.0\n AnimatedImage { source: \"no-such-file.gif\" }", QUrl::fromLocalFile(""));
299 QVERIFY(component.isReady());
301 QTest::ignoreMessage(QtWarningMsg, "file::2:2: QML AnimatedImage: Error Reading Animated Image File file:no-such-file.gif");
303 QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage *>(component.create());
306 QVERIFY(!anim->isPlaying());
307 QVERIFY(!anim->isPaused());
308 QCOMPARE(anim->currentFrame(), 0);
309 QCOMPARE(anim->frameCount(), 0);
310 QTRY_VERIFY(anim->status() == 3);
315 void tst_qquickanimatedimage::sourceSizeChanges()
317 TestHTTPServer server(14449);
318 QVERIFY(server.isValid());
319 server.serveDirectory(dataDirectory());
322 QQmlComponent component(&engine);
323 component.setData("import QtQuick 2.0\nAnimatedImage { source: srcImage }", QUrl::fromLocalFile(""));
324 QTRY_VERIFY(component.isReady());
325 QQmlContext *ctxt = engine.rootContext();
326 ctxt->setContextProperty("srcImage", "");
327 QQuickAnimatedImage *anim = qobject_cast<QQuickAnimatedImage*>(component.create());
330 QSignalSpy sourceSizeSpy(anim, SIGNAL(sourceSizeChanged()));
333 ctxt->setContextProperty("srcImage", QUrl(""));
334 QTRY_COMPARE(anim->status(), QQuickAnimatedImage::Null);
335 QTRY_VERIFY(sourceSizeSpy.count() == 0);
337 ctxt->setContextProperty("srcImage", testFileUrl("hearts.gif"));
338 QTRY_COMPARE(anim->status(), QQuickAnimatedImage::Ready);
339 QTRY_VERIFY(sourceSizeSpy.count() == 1);
341 ctxt->setContextProperty("srcImage", testFileUrl("hearts.gif"));
342 QTRY_COMPARE(anim->status(), QQuickAnimatedImage::Ready);
343 QTRY_VERIFY(sourceSizeSpy.count() == 1);
345 ctxt->setContextProperty("srcImage", testFileUrl("hearts_copy.gif"));
346 QTRY_COMPARE(anim->status(), QQuickAnimatedImage::Ready);
347 QTRY_VERIFY(sourceSizeSpy.count() == 1);
349 ctxt->setContextProperty("srcImage", testFileUrl("colors.gif"));
350 QTRY_COMPARE(anim->status(), QQuickAnimatedImage::Ready);
351 QTRY_VERIFY(sourceSizeSpy.count() == 2);
353 ctxt->setContextProperty("srcImage", QUrl(""));
354 QTRY_COMPARE(anim->status(), QQuickAnimatedImage::Null);
355 QTRY_VERIFY(sourceSizeSpy.count() == 3);
358 ctxt->setContextProperty("srcImage", QUrl("http://127.0.0.1:14449/hearts.gif"));
359 QTRY_COMPARE(anim->status(), QQuickAnimatedImage::Ready);
360 QTRY_VERIFY(sourceSizeSpy.count() == 4);
362 ctxt->setContextProperty("srcImage", QUrl("http://127.0.0.1:14449/hearts.gif"));
363 QTRY_COMPARE(anim->status(), QQuickAnimatedImage::Ready);
364 QTRY_VERIFY(sourceSizeSpy.count() == 4);
366 ctxt->setContextProperty("srcImage", QUrl("http://127.0.0.1:14449/hearts_copy.gif"));
367 QTRY_COMPARE(anim->status(), QQuickAnimatedImage::Ready);
368 QTRY_VERIFY(sourceSizeSpy.count() == 4);
370 ctxt->setContextProperty("srcImage", QUrl("http://127.0.0.1:14449/colors.gif"));
371 QTRY_COMPARE(anim->status(), QQuickAnimatedImage::Ready);
372 QTRY_VERIFY(sourceSizeSpy.count() == 5);
374 ctxt->setContextProperty("srcImage", QUrl(""));
375 QTRY_COMPARE(anim->status(), QQuickAnimatedImage::Null);
376 QTRY_VERIFY(sourceSizeSpy.count() == 6);
381 void tst_qquickanimatedimage::qtbug_16520()
383 TestHTTPServer server(14449);
384 QVERIFY(server.isValid());
385 server.serveDirectory(dataDirectory());
388 QQmlComponent component(&engine, testFileUrl("qtbug-16520.qml"));
389 QTRY_VERIFY(component.isReady());
391 QQuickRectangle *root = qobject_cast<QQuickRectangle *>(component.create());
393 QQuickAnimatedImage *anim = root->findChild<QQuickAnimatedImage*>("anim");
396 anim->setProperty("source", "http://127.0.0.1:14449/stickman.gif");
397 QTRY_VERIFY(anim->opacity() == 0);
398 QTRY_VERIFY(anim->opacity() == 1);
404 void tst_qquickanimatedimage::progressAndStatusChanges()
406 TestHTTPServer server(14449);
407 QVERIFY(server.isValid());
408 server.serveDirectory(dataDirectory());
411 QString componentStr = "import QtQuick 2.0\nAnimatedImage { source: srcImage }";
412 QQmlContext *ctxt = engine.rootContext();
413 ctxt->setContextProperty("srcImage", testFileUrl("stickman.gif"));
414 QQmlComponent component(&engine);
415 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
416 QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
418 QVERIFY(obj->status() == QQuickImage::Ready);
419 QTRY_VERIFY(obj->progress() == 1.0);
421 qRegisterMetaType<QQuickImageBase::Status>();
422 QSignalSpy sourceSpy(obj, SIGNAL(sourceChanged(const QUrl &)));
423 QSignalSpy progressSpy(obj, SIGNAL(progressChanged(qreal)));
424 QSignalSpy statusSpy(obj, SIGNAL(statusChanged(QQuickImageBase::Status)));
427 ctxt->setContextProperty("srcImage", testFileUrl("stickman.gif"));
428 QTRY_VERIFY(obj->status() == QQuickImage::Ready);
429 QTRY_VERIFY(obj->progress() == 1.0);
430 QTRY_COMPARE(sourceSpy.count(), 0);
431 QTRY_COMPARE(progressSpy.count(), 0);
432 QTRY_COMPARE(statusSpy.count(), 0);
434 // Loading local file
435 ctxt->setContextProperty("srcImage", testFileUrl("colors.gif"));
436 QTRY_VERIFY(obj->status() == QQuickImage::Ready);
437 QTRY_VERIFY(obj->progress() == 1.0);
438 QTRY_COMPARE(sourceSpy.count(), 1);
439 QTRY_COMPARE(progressSpy.count(), 0);
440 QTRY_COMPARE(statusSpy.count(), 1);
442 // Loading remote file
443 ctxt->setContextProperty("srcImage", "http://127.0.0.1:14449/stickman.gif");
444 QTRY_VERIFY(obj->status() == QQuickImage::Loading);
445 QTRY_VERIFY(obj->progress() == 0.0);
446 QTRY_VERIFY(obj->status() == QQuickImage::Ready);
447 QTRY_VERIFY(obj->progress() == 1.0);
448 QTRY_COMPARE(sourceSpy.count(), 2);
449 QTRY_VERIFY(progressSpy.count() > 1);
450 QTRY_COMPARE(statusSpy.count(), 3);
452 ctxt->setContextProperty("srcImage", "");
453 QTRY_VERIFY(obj->status() == QQuickImage::Null);
454 QTRY_VERIFY(obj->progress() == 0.0);
455 QTRY_COMPARE(sourceSpy.count(), 3);
456 QTRY_VERIFY(progressSpy.count() > 2);
457 QTRY_COMPARE(statusSpy.count(), 4);
462 QTEST_MAIN(tst_qquickanimatedimage)
464 #include "tst_qquickanimatedimage.moc"