diff options
Diffstat (limited to 'tests/auto/qquickiconimage/tst_qquickiconimage.cpp')
-rw-r--r-- | tests/auto/qquickiconimage/tst_qquickiconimage.cpp | 465 |
1 files changed, 465 insertions, 0 deletions
diff --git a/tests/auto/qquickiconimage/tst_qquickiconimage.cpp b/tests/auto/qquickiconimage/tst_qquickiconimage.cpp new file mode 100644 index 00000000..86bd2f2c --- /dev/null +++ b/tests/auto/qquickiconimage/tst_qquickiconimage.cpp @@ -0,0 +1,465 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qtest.h> +#include <QtTest/qsignalspy.h> + +#include <QtCore/qmath.h> +#include <QtQml/qqmlengine.h> +#include <QtQml/qqmlcomponent.h> +#include <QtQuick/qquickitem.h> +#include <QtQuick/qquickview.h> +#include <QtQuick/qquickitemgrabresult.h> +#include <QtQuick/private/qquickimage_p.h> +#include <QtQuickControls2/private/qquickiconimage_p.h> + +#include "../shared/util.h" +#include "../shared/visualtestutil.h" + +using namespace QQuickVisualTestUtil; + +class tst_qquickiconimage : public QQmlDataTest +{ + Q_OBJECT +public: + tst_qquickiconimage(); + +private slots: + void initTestCase(); + void defaults(); + void nameBindingSourceSize(); + void nameBindingSourceSizeWidthHeight(); + void nameBindingNoSizes(); + void sourceBindingNoSizes(); + void sourceBindingSourceSize(); + void sourceBindingSourceSizeWidthHeight(); + void sourceBindingSourceTooLarge(); + void changeSourceSize(); + void alignment_data(); + void alignment(); + void svgNoSizes(); + void svgSourceBindingSourceSize(); + void color(); + +private: + void setTheme(); + + qreal dpr; + int integerDpr; +}; + +static QImage grabItemToImage(QQuickItem *item) +{ + QSharedPointer<QQuickItemGrabResult> result = item->grabToImage(); + QSignalSpy spy(result.data(), SIGNAL(ready())); + spy.wait(); + return result->image(); +} + +#define SKIP_IF_DPR_TOO_HIGH() \ + if (dpr > 2) \ + QSKIP("Test does not support device pixel ratio greater than 2") + +tst_qquickiconimage::tst_qquickiconimage() : + dpr(qGuiApp->devicePixelRatio()), + integerDpr(qCeil(dpr)) +{ +} + +void tst_qquickiconimage::initTestCase() +{ + QQmlDataTest::initTestCase(); + QIcon::setThemeName(QStringLiteral("testtheme")); +} + +void tst_qquickiconimage::defaults() +{ + QQuickIconImage iconImage; + QCOMPARE(iconImage.fillMode(), QQuickImage::Pad); + QCOMPARE(iconImage.name(), QString()); + QCOMPARE(iconImage.source(), QUrl()); + QCOMPARE(iconImage.color(), QColor(Qt::transparent)); +} + +void tst_qquickiconimage::nameBindingSourceSize() +{ + // We can't have images for every DPR. + SKIP_IF_DPR_TOO_HIGH(); + + QQuickView view(testFileUrl("nameBindingSourceSize.qml")); + QCOMPARE(view.status(), QQuickView::Ready); + view.show(); + view.requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(&view)); + + QQuickIconImage *iconImage = qobject_cast<QQuickIconImage*>(view.rootObject()->childItems().at(0)); + QVERIFY(iconImage); + + QQuickItem *image = view.rootObject()->childItems().at(1); + QVERIFY(image); + + QCOMPARE(grabItemToImage(iconImage), grabItemToImage(image)); + QCOMPARE(iconImage->sourceSize().width(), 22); + QCOMPARE(iconImage->sourceSize().height(), 22); + QCOMPARE(iconImage->implicitWidth(), 22.0); + QCOMPARE(iconImage->implicitHeight(), 22.0); + QCOMPARE(iconImage->width(), 22.0); + QCOMPARE(iconImage->height(), 22.0); + + // The requested width of 16 is less than the pixmap's size on disk which + // is 22x22. Our default fillMode, Pad, would result in the image being clipped, + // so instead we change the fillMode to PreserveAspectFit. Doing so causes + // QQuickImage::updatePaintedGeometry() to set our implicit size to 22x16 to + // ensure that the aspect ratio is respected. Since we have no explicit height, + // the height (previously 22) becomes the implicit height (16). + iconImage->setWidth(16.0); + QCOMPARE(iconImage->fillMode(), QQuickImage::PreserveAspectFit); + QCOMPARE(iconImage->sourceSize().width(), 22); + QCOMPARE(iconImage->sourceSize().height(), 22); + QCOMPARE(iconImage->implicitWidth(), 22.0); + QCOMPARE(iconImage->implicitHeight(), 16.0); + QCOMPARE(iconImage->width(), 16.0); + QCOMPARE(iconImage->height(), 16.0); +} + +void tst_qquickiconimage::nameBindingSourceSizeWidthHeight() +{ + SKIP_IF_DPR_TOO_HIGH(); + + QQuickView view(testFileUrl("nameBindingSourceSizeWidthHeight.qml")); + QCOMPARE(view.status(), QQuickView::Ready); + view.show(); + + QQuickIconImage *iconImage = qobject_cast<QQuickIconImage*>(view.rootObject()); + QVERIFY(iconImage); + QCOMPARE(iconImage->sourceSize().width(), 22); + QCOMPARE(iconImage->sourceSize().height(), 22); + QCOMPARE(iconImage->implicitWidth(), 22.0); + QCOMPARE(iconImage->implicitHeight(), 22.0); + QCOMPARE(iconImage->width(), 16.0); + QCOMPARE(iconImage->height(), 16.0); +} + +void tst_qquickiconimage::nameBindingNoSizes() +{ + SKIP_IF_DPR_TOO_HIGH(); + + QQuickView view(testFileUrl("nameBindingNoSizes.qml")); + QCOMPARE(view.status(), QQuickView::Ready); + view.show(); + + QQuickIconImage *iconImage = qobject_cast<QQuickIconImage*>(view.rootObject()); + QVERIFY(iconImage); + // The smallest available size will be chosen. + QCOMPARE(iconImage->sourceSize().width(), 16); + QCOMPARE(iconImage->sourceSize().height(), 16); + QCOMPARE(iconImage->implicitWidth(), 16.0); + QCOMPARE(iconImage->implicitHeight(), 16.0); + QCOMPARE(iconImage->width(), 16.0); + QCOMPARE(iconImage->height(), 16.0); +} + +void tst_qquickiconimage::sourceBindingNoSizes() +{ + SKIP_IF_DPR_TOO_HIGH(); + + QQuickView view(testFileUrl("sourceBindingNoSizes.qml")); + QCOMPARE(view.status(), QQuickView::Ready); + view.show(); + view.requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(&view)); + + QQuickIconImage *iconImage = qobject_cast<QQuickIconImage*>(view.rootObject()->childItems().at(0)); + QVERIFY(iconImage); + + QQuickItem *image = view.rootObject()->childItems().at(1); + QVERIFY(image); + + QCOMPARE(iconImage->sourceSize().width(), 22 * integerDpr); + QCOMPARE(iconImage->sourceSize().height(), 22 * integerDpr); + QCOMPARE(iconImage->implicitWidth(), 22.0); + QCOMPARE(iconImage->implicitHeight(), 22.0); + QCOMPARE(iconImage->width(), 22.0); + QCOMPARE(iconImage->height(), 22.0); + QCOMPARE(grabItemToImage(iconImage), grabItemToImage(image)); +} + +void tst_qquickiconimage::sourceBindingSourceSize() +{ + SKIP_IF_DPR_TOO_HIGH(); + + QQuickView view(testFileUrl("sourceBindingSourceSize.qml")); + QCOMPARE(view.status(), QQuickView::Ready); + view.show(); + view.requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(&view)); + + QQuickIconImage *iconImage = qobject_cast<QQuickIconImage*>(view.rootObject()->childItems().at(0)); + QVERIFY(iconImage); + + QQuickItem *image = view.rootObject()->childItems().at(1); + QVERIFY(image); + + QCOMPARE(iconImage->sourceSize().width(), 22); + QCOMPARE(iconImage->sourceSize().height(), 22); + QCOMPARE(iconImage->implicitWidth(), 22.0); + QCOMPARE(iconImage->implicitHeight(), 22.0); + QCOMPARE(iconImage->width(), 22.0); + QCOMPARE(iconImage->height(), 22.0); + QCOMPARE(grabItemToImage(iconImage), grabItemToImage(image)); + + // Changing width and height should not affect sourceSize. + iconImage->setWidth(50); + QCOMPARE(iconImage->sourceSize().width(), 22); + QCOMPARE(iconImage->sourceSize().height(), 22); + iconImage->setHeight(50); + QCOMPARE(iconImage->sourceSize().width(), 22); + QCOMPARE(iconImage->sourceSize().height(), 22); +} + +void tst_qquickiconimage::sourceBindingSourceSizeWidthHeight() +{ + SKIP_IF_DPR_TOO_HIGH(); + + QQuickView view(testFileUrl("sourceBindingSourceSizeWidthHeight.qml")); + QCOMPARE(view.status(), QQuickView::Ready); + view.show(); + view.requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(&view)); + + QQuickIconImage *iconImage = qobject_cast<QQuickIconImage*>(view.rootObject()); + QVERIFY(iconImage); + QCOMPARE(iconImage->sourceSize().width(), 22); + QCOMPARE(iconImage->sourceSize().height(), 22); + QCOMPARE(iconImage->implicitWidth(), 22.0); + QCOMPARE(iconImage->implicitHeight(), 22.0); + QCOMPARE(iconImage->width(), 16.0); + QCOMPARE(iconImage->height(), 16.0); +} + +void tst_qquickiconimage::sourceBindingSourceTooLarge() +{ + SKIP_IF_DPR_TOO_HIGH(); + + QQuickView view(testFileUrl("sourceBindingSourceTooLarge.qml")); + QCOMPARE(view.status(), QQuickView::Ready); + view.show(); + view.requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(&view)); + + QQuickIconImage *iconImage = qobject_cast<QQuickIconImage*>(view.rootObject()); + QVERIFY(iconImage); + QCOMPARE(iconImage->sourceSize().width(), 32); + QCOMPARE(iconImage->sourceSize().height(), 32); + QCOMPARE(iconImage->implicitWidth(), 22.0); + QCOMPARE(iconImage->implicitHeight(), 22.0); + QCOMPARE(iconImage->width(), 22.0); + QCOMPARE(iconImage->height(), 22.0); +} + +void tst_qquickiconimage::alignment_data() +{ + QTest::addColumn<QQuickImage::HAlignment>("horizontalAlignment"); + QTest::addColumn<QQuickImage::VAlignment>("verticalAlignment"); + + QTest::newRow("AlignLeft,AlignTop") << QQuickImage::AlignLeft << QQuickImage::AlignTop; + QTest::newRow("AlignLeft,AlignVCenter") << QQuickImage::AlignLeft << QQuickImage::AlignVCenter; + QTest::newRow("AlignLeft,AlignBottom") << QQuickImage::AlignLeft << QQuickImage::AlignBottom; + QTest::newRow("AlignHCenter,AlignTop") << QQuickImage::AlignHCenter << QQuickImage::AlignTop; + QTest::newRow("AlignHCenter,AlignVCenter") << QQuickImage::AlignHCenter << QQuickImage::AlignVCenter; + QTest::newRow("AlignHCenter,AlignBottom") << QQuickImage::AlignHCenter << QQuickImage::AlignBottom; + QTest::newRow("AlignRight,AlignTop") << QQuickImage::AlignRight << QQuickImage::AlignTop; + QTest::newRow("AlignRight,AlignVCenter") << QQuickImage::AlignRight << QQuickImage::AlignVCenter; + QTest::newRow("AlignRight,AlignBottom") << QQuickImage::AlignRight << QQuickImage::AlignBottom; +} + +void tst_qquickiconimage::alignment() +{ + SKIP_IF_DPR_TOO_HIGH(); + + QFETCH(QQuickImage::HAlignment, horizontalAlignment); + QFETCH(QQuickImage::VAlignment, verticalAlignment); + + QQuickView view(testFileUrl("alignment.qml")); + QCOMPARE(view.status(), QQuickView::Ready); + view.show(); + view.requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(&view)); + + QQuickIconImage *iconImage = qobject_cast<QQuickIconImage*>(view.rootObject()->childItems().at(0)); + QVERIFY(iconImage); + + QQuickImage *image = qobject_cast<QQuickImage*>(view.rootObject()->childItems().at(1)); + QVERIFY(image); + + // The default fillMode for IconImage is Image::Pad, so these two grabs + // should only be equal when the device pixel ratio is 1 or 2, as there is no + // @3x version of the image, and hence the Image will be upscaled + // and therefore blurry when the ratio is higher than 2. + if (qGuiApp->devicePixelRatio() <= 2) + QCOMPARE(grabItemToImage(iconImage), grabItemToImage(image)); + else + QVERIFY(grabItemToImage(iconImage) != grabItemToImage(image)); + + // Check that the images are what we expect in different alignment configurations. + iconImage->setWidth(200); + iconImage->setHeight(100); + iconImage->setHorizontalAlignment(horizontalAlignment); + iconImage->setVerticalAlignment(verticalAlignment); + iconImage->setFillMode(QQuickImage::Pad); + image->setWidth(200); + image->setHeight(100); + image->setHorizontalAlignment(horizontalAlignment); + image->setVerticalAlignment(verticalAlignment); + image->setFillMode(QQuickImage::Pad); + + if (qGuiApp->devicePixelRatio() <= 2) + QCOMPARE(grabItemToImage(iconImage), grabItemToImage(image)); + else + QVERIFY(grabItemToImage(iconImage) != grabItemToImage(image)); +} + +void tst_qquickiconimage::svgNoSizes() +{ +#ifndef QT_SVG_LIB + QSKIP("This test requires qtsvg"); +#else + QQuickView view(testFileUrl("svgNoSizes.qml")); + QCOMPARE(view.status(), QQuickView::Ready); + view.show(); + view.requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(&view)); + + QQuickIconImage *iconImage = qobject_cast<QQuickIconImage*>(view.rootObject()->childItems().at(0)); + QVERIFY(iconImage); + + QQuickImage *image = qobject_cast<QQuickImage*>(view.rootObject()->childItems().at(1)); + QVERIFY(image); + + QCOMPARE(iconImage->sourceSize().width(), 48); + QCOMPARE(iconImage->sourceSize().height(), 48); + QCOMPARE(iconImage->implicitWidth(), 48.0); + QCOMPARE(iconImage->implicitHeight(), 48.0); + QCOMPARE(iconImage->width(), 48.0); + QCOMPARE(iconImage->height(), 48.0); + QCOMPARE(grabItemToImage(iconImage), grabItemToImage(image)); +#endif +} + +void tst_qquickiconimage::svgSourceBindingSourceSize() +{ +#ifndef QT_SVG_LIB + QSKIP("This test requires qtsvg"); +#else + QQuickView view(testFileUrl("alignment.qml")); + QCOMPARE(view.status(), QQuickView::Ready); + view.show(); + view.requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(&view)); + + QQuickIconImage *iconImage = qobject_cast<QQuickIconImage*>(view.rootObject()->childItems().at(0)); + QVERIFY(iconImage); + + QQuickImage *image = qobject_cast<QQuickImage*>(view.rootObject()->childItems().at(1)); + QVERIFY(image); + + QCOMPARE(iconImage->sourceSize().width(), 22); + QCOMPARE(iconImage->sourceSize().height(), 22); + QCOMPARE(iconImage->implicitWidth(), 22.0); + QCOMPARE(iconImage->implicitHeight(), 22.0); + QCOMPARE(iconImage->width(), 22.0); + QCOMPARE(iconImage->height(), 22.0); + QCOMPARE(grabItemToImage(iconImage), grabItemToImage(image)); +#endif +} + +void tst_qquickiconimage::color() +{ + SKIP_IF_DPR_TOO_HIGH(); + + QQuickView view(testFileUrl("color.qml")); + QCOMPARE(view.status(), QQuickView::Ready); + view.show(); + view.requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(&view)); + + QQuickIconImage *iconImage = qobject_cast<QQuickIconImage*>(view.rootObject()->childItems().at(0)); + QVERIFY(iconImage); + + QQuickImage *image = qobject_cast<QQuickImage*>(view.rootObject()->childItems().at(1)); + QVERIFY(image); + + QImage iconImageWindowGrab = grabItemToImage(iconImage); + QCOMPARE(iconImageWindowGrab, grabItemToImage(image)); + + // Transparent pixels should remain transparent. + QCOMPARE(iconImageWindowGrab.pixelColor(0, 0), QColor(0, 0, 0, 0)); + + // Set a color after component completion. + iconImage->setColor(QColor(Qt::green)); + iconImageWindowGrab = grabItemToImage(iconImage); + const QPoint centerPixelPos(11, 11); + QCOMPARE(iconImageWindowGrab.pixelColor(centerPixelPos), QColor(Qt::green)); + + // Set a semi-transparent color after component completion. + iconImage->setColor(QColor(0, 0, 255, 127)); + iconImageWindowGrab = grabItemToImage(iconImage); + QCOMPARE(iconImageWindowGrab.pixelColor(centerPixelPos).red(), 0); + QCOMPARE(iconImageWindowGrab.pixelColor(centerPixelPos).green(), 0); + QCOMPARE(iconImageWindowGrab.pixelColor(centerPixelPos).blue(), 255); + QCOMPARE(iconImageWindowGrab.pixelColor(centerPixelPos).alpha(), 127); +} + +void tst_qquickiconimage::changeSourceSize() +{ + QQuickView view(testFileUrl("sourceBindingSourceSize.qml")); + QCOMPARE(view.status(), QQuickView::Ready); + view.show(); + view.requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(&view)); + + QQuickIconImage *iconImage = qobject_cast<QQuickIconImage*>(view.rootObject()->childItems().at(0)); + QVERIFY(iconImage); + + // Ensure that there isn't any infinite recursion when trying to change the sourceSize. + QSize sourceSize = iconImage->sourceSize(); + sourceSize.setWidth(sourceSize.width() - 1); + iconImage->setSourceSize(sourceSize); +} + +int main(int argc, char *argv[]) +{ + QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); + QGuiApplication app(argc, argv); + Q_UNUSED(app); + tst_qquickiconimage test; + QTEST_SET_MAIN_SOURCE_PATH + return QTest::qExec(&test, argc, argv); +} + +#include "tst_qquickiconimage.moc" |