~mterry/unity8/greeter-arrangement

« back to all changes in this revision

Viewing changes to plugins/ImageCache/ImageCache.cpp

  • Committer: Michael Terry
  • Date: 2016-08-30 14:06:47 UTC
  • Revision ID: michael.terry@canonical.com-20160830140647-0gmw15jq769d2g1q
Use the default system wallpaper instead of our custom one.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 <QImageReader>
 
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 &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
    QSize imageSize(QImageReader(imageInfo.filePath()).size());
 
66
    finalSize = calculateSize(imageSize, requestedSize);
 
67
    if (finalSize.isValid() && cacheSize != finalSize)
 
68
        return true;
 
69
 
 
70
    return false;
 
71
}
 
72
 
 
73
QSize ImageCache::calculateSize(const QSize &imageSize, const QSize &requestedSize)
 
74
{
 
75
    QSize finalSize(requestedSize);
 
76
 
 
77
    if (finalSize.width() == 0) {
 
78
        finalSize.setWidth(imageSize.width() * (((double)finalSize.height()) / imageSize.height()));
 
79
    } else if (finalSize.height() == 0) {
 
80
        finalSize.setHeight(imageSize.height() * (((double)finalSize.width()) / imageSize.width()));
 
81
    }
 
82
 
 
83
    return finalSize;
 
84
}
 
85
 
 
86
QImage ImageCache::loadAndCacheImage(const QUrl &image, const QFileInfo &cachePath, const QSize &finalSize)
 
87
{
 
88
    QImageReader reader(image.toLocalFile());
 
89
    reader.setQuality(100);
 
90
    reader.setScaledSize(finalSize);
 
91
    auto format = reader.format(); // can't get this after reading
 
92
 
 
93
    QImage loadedImage(reader.read());
 
94
    if (loadedImage.isNull()) {
 
95
        qWarning() << "ImageCache could not read image" << image.path();
 
96
        return QImage();
 
97
    }
 
98
 
 
99
    cachePath.dir().mkpath(QStringLiteral("."));
 
100
    loadedImage.save(cachePath.filePath(), format, 100);
 
101
 
 
102
    return loadedImage;
 
103
}
 
104
 
 
105
QImage ImageCache::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
 
106
{
 
107
    QUrl image(id);
 
108
    QSize imageSize(QImageReader(image.toLocalFile()).size());
 
109
    QImage result;
 
110
 
 
111
    // Early exit here, with no sourceSize, scaled-up sourceSize, or bad source image
 
112
    if ((requestedSize.width() <= 0 && requestedSize.height() <= 0) ||
 
113
        imageSize.isEmpty() ||
 
114
        requestedSize.height() >= imageSize.height() ||
 
115
        requestedSize.width() >= imageSize.width()) {
 
116
        // We're only interested in scaling down, not up.
 
117
        result = QImage(image.toLocalFile());
 
118
        *size = result.size();
 
119
        return result;
 
120
    }
 
121
 
 
122
    auto cachePath = imagePath(image);
 
123
    QSize finalSize;
 
124
 
 
125
    if (needsUpdate(image, cachePath, requestedSize, finalSize)) {
 
126
        if (finalSize.isEmpty()) {
 
127
            finalSize = calculateSize(imageSize, requestedSize);
 
128
        }
 
129
        result = loadAndCacheImage(image, cachePath, finalSize);
 
130
    } else {
 
131
        result = QImage(cachePath.filePath());
 
132
    }
 
133
 
 
134
    *size = result.size();
 
135
    return result;
 
136
}