treeland/waylib/examples/tinywl/wallpaperprovider.cpp

146 lines
4.1 KiB
C++

// Copyright (C) 2024 WenHao Peng <pengwenhao@uniontech.com>.
// SPDX-License-Identifier: Apache-2.0 OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "wallpaperprovider.h"
#include <QDir>
#include <QFileInfo>
#include <QQuickWindow>
#include <QImageReader>
#include <QSGTexture>
#include <QStandardPaths>
WallpaperTextureFactory::WallpaperTextureFactory(WallpaperImageProvider* provider, const QImage &image)
: m_wallpaperProvider(provider)
{
if (image.format() == QImage::Format_ARGB32_Premultiplied
|| image.format() == QImage::Format_RGB32) {
im = image;
} else {
im = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
}
size = im.size();
}
WallpaperTextureFactory::WallpaperTextureFactory(WallpaperImageProvider *provider, const QString &id)
: m_wallpaperProvider(provider)
, m_wallpaperId(id)
{
m_textureExist = true;
}
QSGTexture *WallpaperTextureFactory::createTexture(QQuickWindow *window) const
{
if (m_textureExist)
m_texture = m_wallpaperProvider->getExistTexture(m_wallpaperId);
if (!m_texture) {
m_texture = window->createTextureFromImage(im, QQuickWindow::TextureCanUseAtlas);
const_cast<WallpaperTextureFactory *>(this)->im = QImage();
}
return m_texture;
}
WallpaperImageProvider::WallpaperImageProvider()
: QQuickImageProvider(QQuickImageProvider::Texture)
{
}
WallpaperImageProvider::~WallpaperImageProvider()
{
textureCache.clear();
}
QImage WallpaperImageProvider::loadFile(const QString &path, const QSize &requestedSize)
{
QImageReader imgio(path);
QSize realSize = imgio.size();
if (requestedSize.isValid() &&
requestedSize.width() < realSize.width() &&
requestedSize.height() < realSize.height())
imgio.setScaledSize(requestedSize);
QImage image;
imgio.read(&image);
return image;
}
QSGTexture *WallpaperImageProvider::getExistTexture(const QString& id) const
{
if (textureCache.contains(id)) {
return dynamic_cast<WallpaperTextureFactory*>(textureCache[id].data())->texture();
}
return nullptr;
}
QString WallpaperImageProvider::parseFilePath(const QString &id)
{
QStringList components = id.split("/");
QString home = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
QString local_path = QString("%1/.cache/treeland/wallpaper/%2/%3/%4/")
.arg(home)
.arg(components[0])
.arg(components[1])
.arg(components[2]);
QDir dir(local_path);
QFileInfo fi;
QString img_path;
if (dir.exists()) {
dir.setFilter(QDir::Files | QDir::NoDotAndDotDot);
QFileInfoList filelist = dir.entryInfoList();
fi = filelist.first();
img_path = fi.absoluteFilePath();
}
if (!(fi.exists() && fi.isFile())) {
img_path = ":/qt/qml/Tinywl/res/xx.jpg";
}
return img_path;
}
QQuickTextureFactory *WallpaperImageProvider::requestTexture(const QString &id, QSize *size, const QSize &requestedSize)
{
QQuickTextureFactory *factory = nullptr;
QSize readSize;
QString img_path = parseFilePath(id);
if (textureCache.contains(img_path)) {
auto cache_factory = textureCache[img_path];
if (!cache_factory.isNull()) {
readSize = cache_factory->textureSize();
if (requestedSize.width() < readSize.width() && requestedSize.height() < readSize.height()) {
*size = readSize;
return new WallpaperTextureFactory(this, img_path);
}
}
}
QFileInfo fi(QDir::root(), img_path);
QString path = fi.canonicalFilePath();
if (!path.isEmpty()) {
QImage img = loadFile(path, requestedSize);
readSize = img.size();
if (!img.isNull()) {
factory = new WallpaperTextureFactory(this, img);
}
}
if (size) {
*size = readSize;
}
if (factory) {
textureCache.insert(img_path, factory);
Q_EMIT wallpaperTextureUpdate(img_path, readSize.width() * readSize.height());
}
return factory;
}