on xenial help sign in
Don't be clever about wallpapers

It appears that our wallpaper rendering was a victim of premature optimization. The image cache and cross-fading image caused some significant performance and memory issues. Qt includes its own cache for images. It's implicitly enabled whenever you use an Image component. This cache ensures that only one copy of an image is in RAM if possible. We explicitly disabled this on CrossFadeImage[1]. The ImageCache also caused each image to be loaded from disk every time it was used -- for example, every time the user locked their device and the Greeter was created (twice for the NarrowView greeter!). This was the cause of several noticeable pauses when navigating the shell as well, for example when opening the Drawer. I've removed the ImageCache as it is no longer needed. Setting SourceSize in Wallpaper.qml actually increased memory use and load times in my testing. For that reason I've removed the usage. In my testing, this change saves up to 150MB of RAM (!) when sitting on the narrow Greeter, and up to 50MB when sitting at the Background. The numbers depend on the size of the wallpaper in use, but the reduction is quite significant. However, this change removes the background fading whenever it is changed. I believe the performance benefits outweigh this eye candy. [1] https://github.com/ubports/ubuntu-ui-toolkit/blob/eb36fcaad14e28b9e73fe4f4d5c73fbe81922855/src/imports/Components/1.2/CrossFadeImage10.qml#L94

commit919293d9628561b661da4e06018eaed2c84b7122 authorDalton Durst <dalton@ubports.com> dateWed 12 Feb 2020, 18:34 (7 years ago) parentba2d37f
17 files changed+5−576
debian/unity8-private.install−1 plugins/CMakeLists.txt−1 plugins/ImageCache/CMakeLists.txt−8 plugins/ImageCache/ImageCache.cpp−135 plugins/ImageCache/ImageCache.h−53 plugins/ImageCache/plugin.cpp−39 plugins/ImageCache/plugin.h−31 plugins/ImageCache/qmldir−2 qml/Components/Wallpaper.qml+1−14 qml/Launcher/Drawer.qml+1−2 qml/Shell.qml+3−11 tests/plugins/CMakeLists.txt−1 tests/plugins/ImageCache/CMakeLists.txt−30 tests/plugins/ImageCache/graphics/wide.jpg tests/plugins/ImageCache/test.cpp−216 tests/plugins/ImageCache/test.qml−23 tests/qmltests/tst_Shell.qml−9
debian/unity8-private.install−1
@@ -3,7 +3,6 @@ usr/lib/*/unity8/qml/AccountsService
33usr/lib/*/unity8/qml/Cursor
44usr/lib/*/unity8/qml/GlobalShortcut
55usr/lib/*/unity8/qml/Greeter
6−usr/lib/*/unity8/qml/ImageCache
76usr/lib/*/unity8/qml/LightDM
87usr/lib/*/unity8/qml/Lights
98usr/lib/*/unity8/qml/Powerd
plugins/CMakeLists.txt−1
@@ -15,7 +15,6 @@ add_subdirectory(AccountsService)
1515add_subdirectory(Cursor)
1616add_subdirectory(GlobalShortcut)
1717add_subdirectory(Greeter)
18−add_subdirectory(ImageCache)
1918add_subdirectory(LightDM)
2019add_subdirectory(Lights)
2120add_subdirectory(Powerd)
plugins/ImageCache/CMakeLists.txtdeleted−8
@@ -1,8 +0,0 @@
1−add_library(ImageCache-qml MODULE
2− ImageCache.cpp
3− plugin.cpp
4− )
5−
6−qt5_use_modules(ImageCache-qml Gui Qml Quick)
7−
8−add_unity8_plugin(ImageCache 0.1 ImageCache TARGETS ImageCache-qml)
plugins/ImageCache/ImageCache.cppdeleted−135
@@ -1,135 +0,0 @@
1−/*
2− * Copyright (C) 2016 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#include <QDateTime>
18−#include <QDebug>
19−#include <QDir>
20−#include <QUrl>
21−#include <QUrlQuery>
22−
23−#include "ImageCache.h"
24−
25−ImageCache::ImageCache()
26− : QQuickImageProvider(QQmlImageProviderBase::Image,
27− QQmlImageProviderBase::ForceAsynchronousImageLoading)
28−{
29−}
30−
31−QString ImageCache::imageCacheRoot()
32−{
33− QString xdgCache(qgetenv("XDG_CACHE_HOME"));
34− if (xdgCache.isEmpty()) {
35− xdgCache = QDir::homePath() + QStringLiteral("/.cache");
36− }
37−
38− return QDir::cleanPath(xdgCache) + QStringLiteral("/unity8/imagecache");
39−}
40−
41−QFileInfo ImageCache::imagePath(const QUrl &image)
42−{
43− QUrlQuery query(image);
44−
45− auto name = query.queryItemValue(QStringLiteral("name"));
46− if (name.isEmpty()) {
47− name = QStringLiteral("/paths") + image.toLocalFile();
48− } else {
49− name = QStringLiteral("/names/") + name;
50− }
51−
52− return QFileInfo(imageCacheRoot() + name);
53−}
54−
55−bool ImageCache::needsUpdate(const QUrl &image, const QFileInfo &cachePath, const QSize &imageSize, const QSize &requestedSize, QSize &finalSize)
56−{
57− if (!cachePath.exists())
58− return true;
59−
60− QFileInfo imageInfo(image.toLocalFile());
61− if (imageInfo.lastModified() > cachePath.lastModified())
62− return true;
63−
64− QSize cacheSize(QImageReader(cachePath.filePath()).size());
65− finalSize = calculateSize(imageSize, requestedSize);
66− if (finalSize.isValid() && cacheSize != finalSize)
67− return true;
68−
69− return false;
70−}
71−
72−QSize ImageCache::calculateSize(const QSize &imageSize, const QSize &requestedSize)
73−{
74− QSize finalSize(requestedSize);
75−
76− if (finalSize.width() == 0) {
77− finalSize.setWidth(imageSize.width() * (((double)finalSize.height()) / imageSize.height()));
78− } else if (finalSize.height() == 0) {
79− finalSize.setHeight(imageSize.height() * (((double)finalSize.width()) / imageSize.width()));
80− }
81−
82− return finalSize;
83−}
84−
85−QImage ImageCache::loadAndCacheImage(QImageReader &reader, const QFileInfo &cachePath, const QSize &finalSize)
86−{
87− reader.setQuality(100);
88− reader.setScaledSize(finalSize);
89− auto format = reader.format(); // can't get this after reading
90−
91− QImage loadedImage(reader.read());
92− if (loadedImage.isNull()) {
93− qWarning() << "ImageCache could not read image" << reader.fileName() << ":" << reader.errorString();
94− return QImage();
95− }
96−
97− cachePath.dir().mkpath(QStringLiteral("."));
98− loadedImage.save(cachePath.filePath(), format, 100);
99−
100− return loadedImage;
101−}
102−
103−QImage ImageCache::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
104−{
105− QUrl image(id);
106− QImageReader imageReader(image.toLocalFile());
107− QSize imageSize(imageReader.size());
108− QImage result;
109−
110− // Early exit here, with no sourceSize, scaled-up sourceSize, or bad source image
111− if ((requestedSize.width() <= 0 && requestedSize.height() <= 0) ||
112− imageSize.isEmpty() ||
113− requestedSize.height() >= imageSize.height() ||
114− requestedSize.width() >= imageSize.width()) {
115− // We're only interested in scaling down, not up.
116− result = imageReader.read();
117− *size = result.size();
118− return result;
119− }
120−
121− auto cachePath = imagePath(image);
122− QSize finalSize;
123−
124− if (needsUpdate(image, cachePath, imageSize, requestedSize, finalSize)) {
125− if (finalSize.isEmpty()) {
126− finalSize = calculateSize(imageSize, requestedSize);
127− }
128− result = loadAndCacheImage(imageReader, cachePath, finalSize);
129− } else {
130− result = QImage(cachePath.filePath());
131− }
132−
133− *size = result.size();
134− return result;
135−}
plugins/ImageCache/ImageCache.hdeleted−53
@@ -1,53 +0,0 @@
1−/*
2− * Copyright (C) 2016 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#pragma once
18−
19−#include <QFileInfo>
20−#include <QImageReader>
21−#include <QQuickImageProvider>
22−#include <QSize>
23−
24−/**
25− * This class accepts an id formulated like a URL. So you'd use something like:
26− *
27− * Image {
28− * source: "image://unity8imagecache/file:///usr/share/..."
29− * }
30− *
31− * Right now, we only support file:/// URLs. We do accept some flags though:
32− *
33− * ?name=NAME
34− * - This will use NAME as the cache lookup key instead of the provided URL.
35− *
36− * We don't do any cleaning of old cached files yet. So you may want to always
37− * provide a name to avoid leaving lots of files around.
38− */
39−
40−class ImageCache: public QQuickImageProvider
41−{
42−public:
43− ImageCache();
44−
45− QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize) override;
46−
47−private:
48− static QString imageCacheRoot();
49− static QFileInfo imagePath(const QUrl &image);
50− static bool needsUpdate(const QUrl &image, const QFileInfo &cachePath, const QSize &imageSize, const QSize &requestedSize, QSize &finalSize);
51− static QSize calculateSize(const QSize &imageSize, const QSize &requestedSize);
52− static QImage loadAndCacheImage(QImageReader &reader, const QFileInfo &cachePath, const QSize &finalSize);
53−};
plugins/ImageCache/plugin.cppdeleted−39
@@ -1,39 +0,0 @@
1−/*
2− * Copyright (C) 2016 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#include <QQmlEngine>
18−
19−#include "ImageCache.h"
20−#include "plugin.h"
21−
22−#include <QtQml>
23−
24−void ImageCachePlugin::registerTypes(const char *uri)
25−{
26− Q_ASSERT(uri == QLatin1String("ImageCache"));
27−
28− qmlRegisterTypeNotAvailable(uri, 0, 1, "__ImageCacheIgnoreMe",
29− QStringLiteral("Ignore this: QML plugins must contain at least one type"));
30−}
31−
32−void ImageCachePlugin::initializeEngine(QQmlEngine* engine, const char* uri)
33−{
34− Q_ASSERT(uri == QLatin1String("ImageCache"));
35−
36− QQmlExtensionPlugin::initializeEngine(engine, uri);
37−
38− engine->addImageProvider("unity8imagecache", new ImageCache);
39−}
plugins/ImageCache/plugin.hdeleted−31
@@ -1,31 +0,0 @@
1−/*
2− * Copyright (C) 2016 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#pragma once
18−
19−#include <QQmlExtensionPlugin>
20−
21−class QQmlEngine;
22−
23−class ImageCachePlugin : public QQmlExtensionPlugin
24−{
25− Q_OBJECT
26− Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
27−
28−public:
29− void registerTypes(const char* uri) override;
30− void initializeEngine(QQmlEngine* engine, const char* uri) override;
31−};
plugins/ImageCache/qmldirdeleted−2
@@ -1,2 +0,0 @@
1−module ImageCache
2−plugin ImageCache-qml
qml/Components/Wallpaper.qml+1−14
@@ -22,23 +22,10 @@ Item {
2222 id: root
2323 property url source
2424
25− CrossFadeImage {
25+ Image {
2626 anchors.fill: parent
2727 fillMode: Image.PreserveAspectCrop
2828
29− // Limit how much memory we reserve and avoid reloading when item size
30− // changes or is rotated by specifying sourceSize.
31− //
32− // FIXME: If the source image has a portrait aspect ratio, we should swap
33− // sourceSize.width and sourceSize.height to prevent blurriness from double
34− // scaling. We could easily do that with a tiny image loader to check
35− // the aspect ratio first, but when we change sourceSize, we lose all
36− // the benefits of CrossFadeImage. So we need to fix that component
37− // first to gracefully handle sourceSize changes (LP: #1599203).
38− readonly property int maxSize: Math.max(Screen.width, Screen.height)
39− sourceSize.width: 0
40− sourceSize.height: maxSize
41−
4229 source: root.source
4330 }
4431}
qml/Launcher/Drawer.qml+1−2
@@ -151,11 +151,10 @@ FocusScope {
151151 color: "#111111"
152152 opacity: 0.99
153153
154− Image {
154+ Wallpaper {
155155 id: background
156156 anchors.fill: parent
157157 source: root.background
158− fillMode: Image.PreserveAspectCrop
159158 }
160159
161160 FastBlur {
qml/Shell.qml+3−11
@@ -27,7 +27,6 @@ import Unity.Connectivity 0.1
2727import Unity.Launcher 0.1
2828import GlobalShortcut 1.0 // has to be before Utils, because of WindowInputFilter
2929import GSettings 1.0
30−import ImageCache 0.1
3130import Utils 0.1
3231import Powerd 0.1
3332import SessionBroadcast 0.1
@@ -159,13 +158,6 @@ StyledItem {
159158 readonly property url defaultBackground: "file://" + Constants.defaultWallpaper
160159 readonly property bool hasCustomBackground: background != defaultBackground
161160
162− // Use a cached version of the scaled-down wallpaper (as sometimes the
163− // image can be quite big compared to the device size, including for
164− // our default wallpaper). We use a name=wallpaper argument here to
165− // make sure we don't litter our cache with lots of scaled images. We
166− // only need to bother caching one at a time.
167− readonly property url cachedBackground: background.toString().indexOf("file:///") === 0 ? "image://unity8imagecache/" + background + "?name=wallpaper" : background
168−
169161 GSettings {
170162 id: backgroundSettings
171163 schema.id: "org.gnome.desktop.background"
@@ -423,7 +415,7 @@ StyledItem {
423415 hides: [launcher, panel.indicators, panel.applicationMenus]
424416 tabletMode: shell.usageScenario != "phone"
425417 forcedUnlock: wizard.active || shell.mode === "full-shell"
426− background: wallpaperResolver.cachedBackground
418+ background: wallpaperResolver.background
427419 hasCustomBackground: wallpaperResolver.hasCustomBackground
428420 allowFingerprint: !dialogs.hasActiveDialog &&
429421 !notifications.topmostIsFullscreen &&
@@ -585,7 +577,7 @@ StyledItem {
585577 topPanelHeight: panel.panelHeight
586578 drawerEnabled: !greeter.active
587579 privateMode: greeter.active
588− background: wallpaperResolver.cachedBackground
580+ background: wallpaperResolver.background
589581
590582 onShowDashHome: showHome()
591583 onLauncherApplicationSelected: {
@@ -704,7 +696,7 @@ StyledItem {
704696 model: NotificationBackend.Model
705697 margin: units.gu(1)
706698 hasMouse: shell.hasMouse
707− background: wallpaperResolver.cachedBackground
699+ background: wallpaperResolver.background
708700
709701 y: topmostIsFullscreen ? 0 : panel.panelHeight
710702 height: parent.height - (topmostIsFullscreen ? 0 : panel.panelHeight)
tests/plugins/CMakeLists.txt−1
@@ -2,7 +2,6 @@ add_subdirectory(AccountsService)
22add_subdirectory(Cursor)
33add_subdirectory(GlobalShortcut)
44add_subdirectory(Greeter)
5−add_subdirectory(ImageCache)
65add_subdirectory(LightDM)
76add_subdirectory(SessionBroadcast)
87add_subdirectory(Ubuntu)
tests/plugins/ImageCache/CMakeLists.txtdeleted−30
@@ -1,30 +0,0 @@
1−include_directories(
2− ${CMAKE_CURRENT_BINARY_DIR}
3− )
4−
5−include_directories(
6− SYSTEM
7− ${Qt5Quick_PRIVATE_INCLUDE_DIRS}
8− )
9−
10−add_definitions(-DCURRENT_SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
11−add_definitions(-DTEST_DIR="plugins/ImageCache")
12−remove_definitions(-DQT_NO_KEYWORDS)
13−
14−add_executable(ImageCacheTestExec
15− test.cpp
16− )
17−qt5_use_modules(ImageCacheTestExec Core Quick Test)
18−add_unity8_uitest(ImageCache ImageCacheTestExec
19− DEPENDS ImageCache-qml
20− IMPORT_PATHS ${UNITY_PLUGINPATH}
21− )
22−install(TARGETS ImageCacheTestExec
23− DESTINATION "${SHELL_PRIVATE_LIBDIR}/tests/plugins/ImageCache"
24−)
25−install(FILES test.qml
26− DESTINATION "${SHELL_APP_DIR}/tests/plugins/ImageCache"
27−)
28−install(DIRECTORY graphics
29− DESTINATION "${SHELL_APP_DIR}/tests/plugins/ImageCache"
30−)
tests/plugins/ImageCache/graphics/wide.jpgdeleted

Binary file not shown.

tests/plugins/ImageCache/test.cppdeleted−216
@@ -1,216 +0,0 @@
1−/*
2− * Copyright (C) 2016 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−#include <QCoreApplication>
18−#include <QFileInfo>
19−#include <QImageReader>
20−#include <QQuickView>
21−#include <QTemporaryDir>
22−#include <QtTestGui>
23−#include <private/qquickimage_p.h>
24−#include <time.h>
25−#include <utime.h>
26−
27−#include <paths.h>
28−
29−Q_DECLARE_METATYPE(QQuickImage::Status)
30−
31−class ImageCacheTest : public QObject
32−{
33− Q_OBJECT
34−
35−private:
36−
37− void setUpImage(const QString &name, const QSize &sourceSize = QSize())
38− {
39− QString url = "image://unity8imagecache/file://" + sourceFile(name);
40− image->setProperty("sourceSize", sourceSize);
41− image->setProperty("source", url);
42− }
43−
44− void waitForImage(QQuickImage::Status status = QQuickImage::Ready)
45− {
46− QTRY_COMPARE(image->property("status"), QVariant((int)status));
47− }
48−
49− QSize cachedImageSize(const QString &filename)
50− {
51− QImageReader reader(filename);
52− return reader.size();
53− }
54−
55− QString sourceFile(const QString &name)
56− {
57− return testDataDir() + "/" TEST_DIR "/graphics/" + name;
58− }
59−
60− QString cachedFile(bool isPath, const QString &name)
61− {
62− if (isPath)
63− return home->path() + "/.cache/unity8/imagecache/paths" + sourceFile(name);
64− else
65− return home->path() + "/.cache/unity8/imagecache/names/" + name;
66− }
67−
68− void createCachedImage(const QString &name, const QString &cachePath, const QSize &cacheSize, time_t mtime_in = 0)
69− {
70− QString origPath = sourceFile(name);
71− QImageReader origImage(origPath);
72− origImage.setScaledSize(cacheSize);
73− auto format = origImage.format(); // can't get this after reading
74−
75− QImage cacheImage(origImage.read());
76− QVERIFY(!cacheImage.isNull());
77−
78− QFileInfo(cachePath).dir().mkpath(QStringLiteral("."));
79− QVERIFY(cacheImage.save(cachePath, format, 100));
80−
81− // Make file a few seconds old, so we can more easily tell if it gets updated
82− auto mtime = mtime_in == 0 ? QFileInfo(cachePath).lastModified().toTime_t() - 5 : mtime_in;
83− struct utimbuf timebuffer;
84− timebuffer.modtime = mtime;
85− timebuffer.actime = timebuffer.modtime;
86− QCOMPARE(utime(cachePath.toUtf8().data(), &timebuffer), 0);
87− }
88−
89−private Q_SLOTS:
90−
91− void init()
92− {
93− home = new QTemporaryDir();
94− QVERIFY(home->isValid());
95− qputenv("HOME", home->path().toUtf8());
96−
97− view = new QQuickView();
98− view->setSource(QUrl::fromLocalFile(testDataDir() + "/" TEST_DIR "/test.qml"));
99− image = view->rootObject();
100−
101− view->show();
102− QTest::qWaitForWindowExposed(view);
103−
104− waitForImage(QQuickImage::Null);
105− }
106−
107− void cleanup()
108− {
109− delete view;
110− delete home;
111− }
112−
113− void testFileNotFound()
114− {
115− setUpImage("NOTHERE");
116− waitForImage(QQuickImage::Error);
117− QVERIFY(!QFile::exists(cachedFile(true, "NOTHERE")));
118− }
119−
120− void testNoSourceSize()
121− {
122− setUpImage("wide.jpg");
123− waitForImage();
124− QVERIFY(!QFile::exists(cachedFile(true, "wide.jpg")));
125− }
126−
127− void testNoScalingUp()
128− {
129− setUpImage("wide.jpg", QSize(1000, 1000));
130− waitForImage();
131− QVERIFY(!QFile::exists(cachedFile(true, "wide.jpg")));
132− }
133−
134− void testFullSourceSize()
135− {
136− setUpImage("wide.jpg", QSize(100, 100));
137− waitForImage();
138− QCOMPARE(cachedImageSize(cachedFile(true, "wide.jpg")), QSize(100, 100));
139− }
140−
141− void testWidthSourceSize()
142− {
143− setUpImage("wide.jpg", QSize(100, 0));
144− waitForImage();
145− // wide.jpg is 500x200
146− QCOMPARE(cachedImageSize(cachedFile(true, "wide.jpg")), QSize(100, 40));
147− }
148−
149− void testHeightSourceSize()
150− {
151− setUpImage("wide.jpg", QSize(0, 100));
152− waitForImage();
153− // wide.jpg is 500x200
154− QCOMPARE(cachedImageSize(cachedFile(true, "wide.jpg")), QSize(250, 100));
155− }
156−
157− void testNameArg()
158− {
159− setUpImage("wide.jpg?name=foo", QSize(0, 100));
160− waitForImage();
161− QVERIFY(!QFile::exists(cachedFile(true, ""))); // check for dir itself
162− QVERIFY(QFile::exists(cachedFile(false, "foo")));
163− }
164−
165− void testLoadCache()
166− {
167− auto cacheName = cachedFile(false, "foo");
168− createCachedImage("wide.jpg", cacheName, QSize(250, 100));
169− auto mtime = QFileInfo(cacheName).lastModified();
170−
171− auto now = time(NULL);
172− QVERIFY(QFileInfo(cacheName).lastModified().toTime_t() < now); // sanity check
173−
174− setUpImage("wide.jpg?name=foo", QSize(0, 100));
175− waitForImage();
176− QCOMPARE(QFileInfo(cacheName).lastModified(), mtime); // wasn't recreated
177− }
178−
179− void testDifferentSize()
180− {
181− auto cacheName = cachedFile(false, "foo");
182− createCachedImage("wide.jpg", cacheName, QSize(250, 100));
183−
184− auto now = time(NULL);
185− QVERIFY(QFileInfo(cacheName).lastModified().toTime_t() < now); // sanity check
186−
187− setUpImage("wide.jpg?name=foo", QSize(100, 0));
188− waitForImage();
189− QVERIFY(QFileInfo(cacheName).lastModified().toTime_t() >= now); // was recreated
190− }
191−
192− void testStaleCache()
193− {
194− auto sourceName = sourceFile("wide.jpg");
195− auto mtime = QFileInfo(sourceName).lastModified().toTime_t() - 5;
196−
197− auto cacheName = cachedFile(false, "foo");
198− createCachedImage("wide.jpg", cacheName, QSize(250, 100), mtime);
199−
200− auto now = time(NULL);
201− QVERIFY(QFileInfo(cacheName).lastModified().toTime_t() < now); // sanity check
202−
203− setUpImage("wide.jpg?name=foo", QSize(0, 100));
204− waitForImage();
205− QVERIFY(QFileInfo(cacheName).lastModified().toTime_t() >= now); // was recreated
206− }
207−
208−private:
209− QQuickView *view;
210− QObject *image;
211− QTemporaryDir *home;
212−};
213−
214−QTEST_MAIN(ImageCacheTest)
215−
216−#include "test.moc"
tests/plugins/ImageCache/test.qmldeleted−23
@@ -1,23 +0,0 @@
1−/*
2− * Copyright 2016 Canonical Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.4
18−import ImageCache 0.1
19−
20−Image {
21− width: 400
22− height: 400
23−}
tests/qmltests/tst_Shell.qml−9
@@ -1306,15 +1306,6 @@ Rectangle {
13061306 compare(wallpaperResolver.background, AccountsService.backgroundFile);
13071307 }
13081308
1309− function test_cachedBackground() {
1310− loadShell("desktop", 0);
1311−
1312− var greeter = findChild(shell, "greeter");
1313− verify(!greeter.hasCustomBackground);
1314− compare(greeter.background.toString().indexOf("image://unity8imagecache/file:///"), 0);
1315− verify(greeter.background.toString().indexOf("?name=wallpaper") > 0);
1316− }
1317−
13181309 function test_tapOnRightEdgeReachesApplicationSurface() {
13191310 loadShell("phone");
13201311 swipeAwayGreeter();