/****************************************************************************** * Copyright 2016 David Rosca * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Library General Public * * License as published by the Free Software Foundation; either * * version 2 of the License, or (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public License * * along with this library; see the file COPYING.LIB. If not, write to * * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301, USA. * *******************************************************************************/ #include "iconitemtest.h" #include #include #include #include #include #include #include #include #include #include "plasma/theme.h" #include "plasma/svg.h" static bool imageIsEmpty(const QImage &img) { for (int i = 0; i < img.width(); ++i) { for (int j = 0; j < img.height(); ++j) { if (img.pixel(i, j) != 0) { return false; } } } return true; } void IconItemTest::initTestCase() { if (qgetenv("XDG_DATA_DIRS").isEmpty()) { QWARN("\n" " !!!\n" " Switching QStandardPaths into testing mode.\n" " Make sure xdg data can be found or set XDG_DATA_DIRS.\n" " !!!\n"); } // make our theme in search path qputenv("XDG_DATA_DIRS", qgetenv("XDG_DATA_DIRS") + ":" + QFINDTESTDATA("data").toLocal8Bit()); // set default icon theme to test-theme QStandardPaths::setTestModeEnabled(true); QString configPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation); if(!QDir(configPath).mkpath(QStringLiteral("."))) { qFatal("Failed to create test configuration directory."); } QFile::remove(configPath); QIcon::setThemeSearchPaths({QFINDTESTDATA("data/icons")}); QIcon::setThemeName("test-theme"); KIconTheme::forceThemeForTests("test-theme"); KIconTheme::reconfigure(); KIconLoader::global()->reconfigure(QString()); m_view = new QQuickView(); m_view->setSource(QUrl::fromLocalFile(QFINDTESTDATA("data/view.qml"))); m_view->show(); QTest::qWaitForWindowExposed(m_view); if (!m_view->rootObject() || !m_view->rootObject()->grabToImage()) { QSKIP("Cannot grab item to image."); } } void IconItemTest::cleanupTestCase() { delete m_view; } void IconItemTest::cleanup() { qDeleteAll(m_view->rootObject()->childItems()); } QQuickItem *IconItemTest::createIconItem() { QByteArray iconQml = "import QtQuick 2.0;" "import org.kde.plasma.core 2.0 as PlasmaCore;" "PlasmaCore.IconItem {" " id: root;" "}"; QQmlComponent component(m_view->engine()); QSignalSpy spy(&component, SIGNAL(statusChanged(QQmlComponent::Status))); component.setData(iconQml, QUrl("test://iconTest")); if (component.status() != QQmlComponent::Ready) { spy.wait(); } QQuickItem *item = qobject_cast(component.create(m_view->engine()->rootContext())); Q_ASSERT(item && qstrcmp(item->metaObject()->className(), "IconItem") == 0); item->setParentItem(m_view->rootObject()); return item; } QImage IconItemTest::grabImage(QQuickItem *item) { QSharedPointer grab = item->grabToImage(); QSignalSpy spy(grab.data(), SIGNAL(ready())); spy.wait(); return grab->image(); } Plasma::Svg *IconItemTest::findPlasmaSvg(QQuickItem *item) { return item->findChild(); } void IconItemTest::changeTheme(Plasma::Theme *theme, const QString &themeName) { if (theme->themeName() != themeName) { QSignalSpy spy(theme, SIGNAL(themeChanged())); theme->setThemeName(themeName); spy.wait(); } } // ------ Tests void IconItemTest::loadPixmap() { QScopedPointer item(createIconItem()); QPixmap sourcePixmap(QFINDTESTDATA("data/test_image.png")); item->setProperty("source", sourcePixmap); QVERIFY(item->property("valid").toBool()); QImage capture = grabImage(item.data()); QCOMPARE(capture, sourcePixmap.toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied)); QCOMPARE(sourcePixmap, item->property("source").value()); } //tests setting icon from a QImage void IconItemTest::loadImage() { QScopedPointer item(createIconItem()); QImage sourceImage(QFINDTESTDATA("data/test_image.png")); item->setProperty("source", sourceImage); QVERIFY(item->property("valid").toBool()); QImage capture = grabImage(item.data()); QCOMPARE(capture, sourceImage.convertToFormat(QImage::Format_ARGB32_Premultiplied)); QCOMPARE(sourceImage, item->property("source").value()); } void IconItemTest::invalidIcon() { QString name("tst-plasma-framework-invalid-icon-name"); KIconLoader iconLoader("tst_plasma-framework"); if (iconLoader.hasIcon(name)) { QSKIP("Current icon theme has 'tst-plasma-framework-invalid-icon-name' icon."); } QQuickItem *item = createIconItem(); item->setProperty("source", name); QVERIFY(!item->property("valid").toBool()); QVERIFY(imageIsEmpty(grabImage(item))); } void IconItemTest::usesPlasmaTheme() { Plasma::Theme theme; if (!theme.themeName().startsWith("default")) { QSKIP("Current Plasma theme is not Breeze."); } // usesPlasmaTheme = true (default) QQuickItem *item1 = createIconItem(); item1->setProperty("source", "konversation"); QVERIFY(item1->property("valid").toBool()); QCOMPARE(QStringLiteral("konversation"), item1->property("source").toString()); Plasma::Svg svg; svg.setContainsMultipleImages(true); svg.setImagePath("icons/konversation"); QImage img1 = grabImage(item1); QImage img2 = svg.image(QSize(item1->width(), item1->height()), "konversation"); QVERIFY(!imageIsEmpty(img1)); QVERIFY(!imageIsEmpty(img2)); QCOMPARE(img1, img2); // usesPlasmaTheme = false QQuickItem *item2 = createIconItem(); item2->setProperty("usesPlasmaTheme", false); item2->setProperty("source", "konversation"); img1 = grabImage(item2); // This depends on konversation icon being different in Plasma Breeze theme // and our test icon theme QVERIFY(img1 != img2); } void IconItemTest::animation() { if (!Plasma::Theme().themeName().startsWith("default")) { // This this depends on the production default theme. QSKIP("Current Plasma theme is not Breeze."); } // animated = true (default) QQuickItem *item1 = createIconItem(); item1->setProperty("source", "user-away"); // first icon is not animated QImage userAwayImg = grabImage(item1); item1->setProperty("source", "user-busy"); grabImage(item1); item1->setProperty("source", "user-away"); // animation from user-busy -> user-away QVERIFY(userAwayImg != grabImage(item1)); // animated = false QQuickItem *item2 = createIconItem(); item2->setProperty("animated", false); item2->setProperty("source", "user-busy"); QImage userBusyImg = grabImage(item2); item2->setProperty("source", "user-away"); QCOMPARE(userAwayImg, grabImage(item2)); item2->setProperty("source", "user-busy"); QCOMPARE(userBusyImg, grabImage(item2)); } void IconItemTest::animationAfterHide() { if (!Plasma::Theme().themeName().startsWith("default")) { // This this depends on the production default theme. QSKIP("Current Plasma theme is not Breeze."); } QQuickItem *item1 = createIconItem(); QQuickItem *item2 = createIconItem(); item1->setProperty("source", "user-away"); item2->setProperty("source", "user-busy"); // first icon is not animated QImage userAwayImg = grabImage(item1); QImage userBusyImg = grabImage(item2); item1->setProperty("source", "user-busy"); grabImage(item1); item1->setProperty("visible", "false"); item1->setProperty("visible", "true"); item1->setProperty("source", "user-away"); // icon was hidden, no animation QCOMPARE(userAwayImg, grabImage(item1)); item1->setProperty("source", "user-busy"); QVERIFY(userBusyImg != grabImage(item1)); } void IconItemTest::bug_359388() { if (!KIconTheme::list().contains("hicolor")) { // This test depends on hicolor icon theme to resolve the icon. QSKIP("hicolor icon theme not available"); } QString name("bug359388"); KIconLoader iconLoader("tst_plasma-framework"); QIcon customThemeIcon(new KIconEngine(name, &iconLoader)); if (iconLoader.hasIcon(name)) { QSKIP("Current icon theme has 'bug359388' icon."); } iconLoader.addAppDir("tst_plasma-framework", QFINDTESTDATA("data/bug359388")); QQuickItem *item1 = createIconItem(); item1->setProperty("source", customThemeIcon); QVERIFY(item1->property("valid").toBool()); QCOMPARE(customThemeIcon, item1->property("source").value()); QQuickItem *item2 = createIconItem(); item2->setProperty("source", QIcon(QFINDTESTDATA("data/bug359388/hicolor/22x22/apps/" + name + ".svg"))); QVERIFY(item2->property("valid").toBool()); QCOMPARE(grabImage(item1), grabImage(item2)); } void IconItemTest::loadSvg() { QString name("tst-plasma-framework-test-icon"); QQuickItem *item = createIconItem(); item->setProperty("animated", false); item->setSize(QSize(22, 22)); item->setProperty("source", name); QVERIFY(item->property("valid").toBool()); Plasma::Svg *svg; svg = findPlasmaSvg(item); Q_ASSERT(svg); QCOMPARE(svg->imagePath(), QFINDTESTDATA("data/icons/test-theme/apps/22/" + name + ".svg")); // we only have 32x32 and 22x22 version in the theme, thus 32x32 is a better match. item->setSize(QSize(64, 64)); // just to update the icon grabImage(item); svg = findPlasmaSvg(item); Q_ASSERT(svg); QCOMPARE(svg->imagePath(), QFINDTESTDATA("data/icons/test-theme/apps/32/" + name + ".svg")); } void IconItemTest::themeChange() { if (!Plasma::Theme().themeName().startsWith("default")) { // This this depends on the production themes (infer their presence from default). QSKIP("Current Plasma theme is not Breeze."); } // Icon from Plasma theme QQuickItem *item1 = createIconItem(); item1->setProperty("animated", false); item1->setProperty("source", "zoom-fit-height"); Plasma::Svg *svg1 = item1->findChild(); changeTheme(svg1->theme(), "breeze-light"); QImage img1 = grabImage(item1); changeTheme(svg1->theme(), "breeze-dark"); QImage img2 = grabImage(item1); QVERIFY(img1 != img2); // Icon from icon theme QQuickItem *item2 = createIconItem(); item2->setProperty("animated", false); item2->setProperty("width", 22); item2->setProperty("height", 22); item2->setProperty("source", "tst-plasma-framework-test-icon"); Plasma::Svg *svg2 = item2->findChild(); changeTheme(svg2->theme(), "breeze-light"); img1 = grabImage(item2); changeTheme(svg2->theme(), "breeze-dark"); img2 = grabImage(item2); QVERIFY(img1 != img2); } void IconItemTest::qiconFromTheme() { // Icon from Plasma theme QQuickItem *item1 = createIconItem(); QIcon icon1 = QIcon::fromTheme("konversation"); item1->setProperty("source", icon1); QVERIFY(item1->findChild()); QVERIFY(!imageIsEmpty(grabImage(item1))); QCOMPARE(icon1, item1->property("source").value()); // Icon from icon theme QQuickItem *item2 = createIconItem(); QIcon icon2 = QIcon::fromTheme("tst-plasma-framework-test-icon"); item2->setProperty("source", icon2); QVERIFY(item2->findChild()); QVERIFY(!imageIsEmpty(grabImage(item2))); QCOMPARE(icon2, item2->property("source").value()); } void IconItemTest::changeColorGroup() { if (!Plasma::Theme().themeName().startsWith("default")) { // This this depends on the production default theme. QSKIP("Current Plasma theme is not Breeze."); } // Icon from Plasma theme QQuickItem *item = createIconItem(); item->setProperty("animated", false); item->setProperty("source", "zoom-fit-height"); Plasma::Svg *svg = item->findChild(); // not using "breeze" theme as that one follows system color scheme // and that one might not have a complementary group or a broken one changeTheme(svg->theme(), "breeze-light"); QSignalSpy spy(svg, SIGNAL(repaintNeeded())); QVERIFY(spy.isValid()); QImage img1 = grabImage(item); item->setProperty("colorGroup", Plasma::Theme::ComplementaryColorGroup); QTRY_VERIFY(spy.count() == 1); QImage img2 = grabImage(item); QVERIFY(img1 != img2); } void IconItemTest::animatingActiveChange() { QQuickItem *item1 = createIconItem(); item1->setProperty("animated", false); item1->setProperty("source", "tst-plasma-framework-test-icon"); QImage img1 = grabImage(item1); QQuickItem *item2 = createIconItem(); item2->setProperty("animated", false); item2->setProperty("active", true); item2->setProperty("source", "tst-plasma-framework-test-icon"); QImage img2 = grabImage(item2); QVERIFY(img1 != img2); item1->setProperty("active", true); img1 = grabImage(item1); QVERIFY(img1 != img2); // animation is running } void IconItemTest::animatingEnabledChange() { QQuickItem *item1 = createIconItem(); item1->setProperty("animated", false); item1->setProperty("source", "tst-plasma-framework-test-icon"); QImage img1 = grabImage(item1); QQuickItem *item2 = createIconItem(); item2->setProperty("animated", false); item2->setProperty("enabled", false); item2->setProperty("source", "tst-plasma-framework-test-icon"); QImage img2 = grabImage(item2); QVERIFY(img1 != img2); item1->setProperty("enabled", false); img1 = grabImage(item1); QVERIFY(img1 != img2); // animation is running } void IconItemTest::windowChanged() { QQuickItem *item = createIconItem(); item->setProperty("animated", false); item->setProperty("source", "tst-plasma-framework-test-icon"); QImage img = grabImage(item); QQuickView newView; newView.setSource(QUrl::fromLocalFile(QFINDTESTDATA("data/view.qml"))); newView.show(); QTest::qWaitForWindowExposed(&newView); item->setProperty("visible", false); item->setParentItem(newView.rootObject()); item->setProperty("visible", true); QCOMPARE(grabImage(item), img); } QTEST_MAIN(IconItemTest)