diff --git a/wallpapers/image/CMakeLists.txt b/wallpapers/image/CMakeLists.txt --- a/wallpapers/image/CMakeLists.txt +++ b/wallpapers/image/CMakeLists.txt @@ -6,8 +6,8 @@ backgroundlistmodel.cpp ) - add_library(plasma_wallpaper_imageplugin SHARED ${image_SRCS}) + target_link_libraries(plasma_wallpaper_imageplugin Qt5::Core Qt5::Quick @@ -22,6 +22,8 @@ KF5::GuiAddons ) +add_subdirectory(autotests) + install(TARGETS plasma_wallpaper_imageplugin DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/plasma/wallpapers/image) install(FILES qmldir DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/plasma/wallpapers/image) diff --git a/wallpapers/image/autotests/CMakeLists.txt b/wallpapers/image/autotests/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/wallpapers/image/autotests/CMakeLists.txt @@ -0,0 +1,11 @@ +set(testfindpreferredimage_SRCS + testfindpreferredimage.cpp + ../image.cpp + ../backgroundlistmodel.cpp + ) + +add_executable(testfindpreferredimage EXCLUDE_FROM_ALL ${testfindpreferredimage_SRCS}) + +target_link_libraries(testfindpreferredimage + plasma_wallpaper_imageplugin + Qt5::Test) diff --git a/wallpapers/image/autotests/testfindpreferredimage.cpp b/wallpapers/image/autotests/testfindpreferredimage.cpp new file mode 100644 --- /dev/null +++ b/wallpapers/image/autotests/testfindpreferredimage.cpp @@ -0,0 +1,106 @@ +/*************************************************************************** + * Copyright 2016 Antonio Larrosa * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program 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 General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * + ***************************************************************************/ +#include "image.h" +#include +#include + +extern QSize resSize(const QString &str); + +QString formatResolution(const QString &str) +{ + QSize size = resSize(str); + float aspectRatio = (size.height() > 0 ) ? size.width() / (float)size.height() : 0; + return QString("%1 (%2)").arg(str, 9).arg(aspectRatio, 7); +} + +class TestResolutions: public QObject +{ + Q_OBJECT + +private slots: + void testResolutions_data(); + void testResolutions(); + +protected: + Image m_image; + QStringList m_images; +}; + +void TestResolutions::testResolutions_data() +{ + // The list of available wallpaper image sizes + m_images << QStringLiteral("1280x1024") + << QStringLiteral("1350x1080") + << QStringLiteral("1440x1080") + << QStringLiteral("1600x1200") + << QStringLiteral("1920x1080") + << QStringLiteral("1920x1200") + << QStringLiteral("3840x2400"); + qDebug() << "Available images:"; + foreach( auto image, m_images) { + qDebug() << formatResolution(image); + } + + // The list of possible screen resolutions to test and the appropiate images that should be chosen + QTest::addColumn("resolution"); + QTest::addColumn("expected"); + QTest::newRow("1280x1024") << QStringLiteral("1280x1024") << QStringLiteral("1280x1024"); + QTest::newRow("1350x1080") << QStringLiteral("1350x1080") << QStringLiteral("1350x1080"); + QTest::newRow("1440x1080") << QStringLiteral("1440x1080") << QStringLiteral("1440x1080"); + QTest::newRow("1600x1200") << QStringLiteral("1600x1200") << QStringLiteral("1600x1200"); + QTest::newRow("1920x1080") << QStringLiteral("1920x1080") << QStringLiteral("1920x1080"); + QTest::newRow("1920x1200") << QStringLiteral("1920x1200") << QStringLiteral("1920x1200"); + QTest::newRow("3840x2400") << QStringLiteral("3840x2400") << QStringLiteral("3840x2400"); + QTest::newRow("4096x2160") << QStringLiteral("4096x2160") << QStringLiteral("1920x1080"); + QTest::newRow("3840x2160") << QStringLiteral("3840x2160") << QStringLiteral("1920x1080"); + QTest::newRow("3200x1800") << QStringLiteral("3200x1800") << QStringLiteral("1920x1080"); + QTest::newRow("2048x1080") << QStringLiteral("2048x1080") << QStringLiteral("1920x1080"); + QTest::newRow("1680x1050") << QStringLiteral("1680x1050") << QStringLiteral("1920x1200"); + QTest::newRow("1400x1050") << QStringLiteral("1400x1050") << QStringLiteral("1440x1080"); + QTest::newRow("1440x900") << QStringLiteral("1440x900") << QStringLiteral("1920x1200"); + QTest::newRow("1280x960") << QStringLiteral("1280x960") << QStringLiteral("1440x1080"); + QTest::newRow("1280x854") << QStringLiteral("1280x854") << QStringLiteral("1920x1200"); + QTest::newRow("1280x800") << QStringLiteral("1280x800") << QStringLiteral("1920x1200"); + QTest::newRow("1280x720") << QStringLiteral("1280x720") << QStringLiteral("1920x1080"); + QTest::newRow("1152x768") << QStringLiteral("1152x768") << QStringLiteral("1920x1200"); + QTest::newRow("1024x768") << QStringLiteral("1024x768") << QStringLiteral("1440x1080"); + QTest::newRow("800x600") << QStringLiteral("800x600") << QStringLiteral("1440x1080"); + QTest::newRow("848x480") << QStringLiteral("848x480") << QStringLiteral("1920x1080"); + QTest::newRow("720x480") << QStringLiteral("720x480") << QStringLiteral("1920x1200"); + QTest::newRow("640x480") << QStringLiteral("640x480") << QStringLiteral("1440x1080"); + QTest::newRow("1366x768") << QStringLiteral("1366x768") << QStringLiteral("1920x1080"); + QTest::newRow("1600x814") << QStringLiteral("1600x814") << QStringLiteral("1920x1080"); +} + +void TestResolutions::testResolutions() +{ + QFETCH(QString, resolution); + QFETCH(QString, expected); + + m_image.setTargetSize( resSize( resolution ) ); + QString preferred = m_image.findPreferedImage(m_images); + + qDebug() << "For a screen size of " << formatResolution(resolution) + << " the " << formatResolution(preferred) << " wallpaper was preferred"; + + QCOMPARE(preferred, expected); +} + +QTEST_MAIN(TestResolutions) +#include "testfindpreferredimage.moc" diff --git a/wallpapers/image/image.h b/wallpapers/image/image.h --- a/wallpapers/image/image.h +++ b/wallpapers/image/image.h @@ -114,6 +114,7 @@ void setSlidePaths(const QStringList &slidePaths); void findPreferedImageInPackage(KPackage::Package &package); + QString findPreferedImage(const QStringList &images); void classBegin() override; void componentComplete() override; diff --git a/wallpapers/image/image.cpp b/wallpapers/image/image.cpp --- a/wallpapers/image/image.cpp +++ b/wallpapers/image/image.cpp @@ -156,13 +156,14 @@ float distance(const QSize& size, const QSize& desired) { // compute difference of areas - float delta = size.width() * size.height() - - desired.width() * desired.height(); - // scale down to about 1.0 - delta /= ((desired.width() * desired.height())+(size.width() * size.height()))/2; + float desiredAspectRatio = ( desired.height() > 0 ) ? desired.width() / (float)desired.height() : 0; + float candidateAspectRatio = ( size.height() > 0 ) ? size.width() / (float)size.height() : FLT_MAX; + + float delta = size.width() - desired.width(); + delta = (delta >= 0.0 ? delta : -delta*2 ); // Penalize for scaling up + + return qAbs(candidateAspectRatio - desiredAspectRatio)*25000 + delta; - // Difference of areas, slight preference to scale down - return delta >= 0.0 ? delta : -delta + 2.0; } QSize resSize(const QString &str) @@ -176,56 +177,48 @@ return QSize(); } -void Image::findPreferedImageInPackage(KPackage::Package &package) +QString Image::findPreferedImage(const QStringList &images) { - if (!package.isValid() || !package.filePath("preferred").isEmpty()) { - return; - } - - QStringList images = package.entryList("images"); if (images.empty()) { - return; + return QString(); } - //qDebug() << "wanted" << m_targetSize << "options" << images; - - // choose the nearest resolution, always preferring images with the same aspect ratio + //float targetAspectRatio = (m_targetSize.height() > 0 ) ? m_targetSize.width() / (float)m_targetSize.height() : 0; + //qDebug() << "wanted" << m_targetSize << "options" << images << "aspect ratio" << targetAspectRatio; float best = FLT_MAX; - float bestWithSameAspectRatio = FLT_MAX; - float targetAspectRatio = m_targetSize.width()/(float)m_targetSize.height(); QString bestImage; - QString bestImageWithSameAspectRatio; foreach (const QString &entry, images) { QSize candidate = resSize(QFileInfo(entry).baseName()); if (candidate == QSize()) { continue; } - float candidateAspectRatio = candidate.width()/(float)candidate.height(); + //float candidateAspectRatio = (candidate.height() > 0 ) ? candidate.width() / (float)candidate.height() : FLT_MAX; - double dist = distance(candidate, m_targetSize); + float dist = distance(candidate, m_targetSize); //qDebug() << "candidate" << candidate << "distance" << dist << "aspect ratio" << candidateAspectRatio; - if ( candidateAspectRatio == targetAspectRatio && (bestImageWithSameAspectRatio.isEmpty() || dist < bestWithSameAspectRatio) ) { - bestImageWithSameAspectRatio = entry; - bestWithSameAspectRatio = dist; - //qDebug() << "bestWithSameAspectRatio" << bestImageWithSameAspectRatio; - if (dist == 0) { - break; - } - } else if (bestImage.isEmpty() || dist < best) { + if (bestImage.isEmpty() || dist < best) { bestImage = entry; best = dist; //qDebug() << "best" << bestImage; } } - if (!bestImageWithSameAspectRatio.isEmpty()) // Always prefer an image with the same aspect ratio as the target (if available) - bestImage=bestImageWithSameAspectRatio; - //qDebug() << "best image" << bestImage; + return bestImage; +} + +void Image::findPreferedImageInPackage(KPackage::Package &package) +{ + if (!package.isValid() || !package.filePath("preferred").isEmpty()) { + return; + } + + QString preferred = findPreferedImage( package.entryList("images") ); + package.removeDefinition("preferred"); - package.addFileDefinition("preferred", "images/" + bestImage, i18n("Recommended wallpaper file")); + package.addFileDefinition("preferred", "images/" + preferred, i18n("Recommended wallpaper file")); } QSize Image::targetSize() const