Files
z-bar-qt/Plugins/ZShell/Wallpaper/wallpapercache.cpp
T
zach b0cb43f75c
C++ / fmt (pull_request) Failing after 6s
C++ / build (pull_request) Failing after 10s
C++ / clang-tidy (pull_request) Failing after 11s
JS/TS / fmt (pull_request) Successful in 10s
JS/TS / lint (pull_request) Successful in 8s
Python / static (pull_request) Failing after 32s
Rust / build (pull_request) Successful in 52s
Python / verify (pull_request) Failing after 1m23s
Rust / fmt (pull_request) Successful in 51s
Rust / clippy (pull_request) Successful in 1m2s
feat: add vaapi path for video wallpapers on generic gpus
2026-10-27 02:15:16 +01:00

171 lines
4.4 KiB
C++

#include "wallpapercache.hpp"
#include <QCryptographicHash>
#include <QDir>
#include <QFileInfo>
#include <QImageReader>
#include <QJsonDocument>
#include <QJsonObject>
#include <QSqlDatabase>
#include <QSqlError>
#include <QSqlQuery>
#include <QThread>
namespace ZShell::wallpaper {
namespace {
QString connectionName() {
return QStringLiteral("wallpaper-cache-%1")
.arg(quintptr(QThread::currentThreadId()));
}
QSqlDatabase openDatabase(const QString& databasePath) {
const QString connection = connectionName();
QSqlDatabase database =
QSqlDatabase::contains(connection)
? QSqlDatabase::database(connection, false)
: QSqlDatabase::addDatabase("QSQLITE", connection);
if (database.databaseName() != databasePath) {
if (database.isOpen()) database.close();
database.setDatabaseName(databasePath);
}
if (!database.isOpen() && !database.open()) return {};
return database;
}
} // namespace
void WallpaperCache::setDbPath(const QString& path) {
std::lock_guard<std::mutex> lock(m_mtx);
m_dbPath = path;
}
QString WallpaperCache::dbPath() const {
std::lock_guard<std::mutex> lock(m_mtx);
return m_dbPath;
}
QByteArray WallpaperCache::cachedBlob(const QString& path) const {
if (path.isEmpty()) return {};
const QString databasePath = dbPath();
if (databasePath.isEmpty()) return {};
const QFileInfo info(path);
QSqlDatabase database = openDatabase(databasePath);
if (!database.isOpen()) return {};
QSqlQuery query(database);
query.prepare("SELECT cache, size, mtime FROM wallpapers WHERE path = ?");
query.addBindValue(info.absoluteFilePath());
if (!query.exec() || !query.next()) return {};
const QByteArray blob = query.value(0).toByteArray();
if (blob.isEmpty()) return {};
const qint64 mtime = info.lastModified().toMSecsSinceEpoch() / 1000;
if (query.value(1).toLongLong() != info.size() ||
query.value(2).toLongLong() != mtime) {
return {};
}
return blob;
}
QImage WallpaperCache::decodeImage(
const QString& path, const QSize& decodeSize) const {
if (path.isEmpty()) return {};
QImageReader probe(path);
const QSize source = probe.size();
QSize required = source.isEmpty() ? decodeSize : source;
if (!source.isEmpty() && !decodeSize.isEmpty()) {
const QSize cover =
source.scaled(decodeSize, Qt::KeepAspectRatioByExpanding);
if (cover.width() <= source.width() &&
cover.height() <= source.height())
required = cover;
}
const QByteArray blob = cachedBlob(path);
if (!blob.isEmpty()) {
QImage image = QImage::fromData(blob, "JPEG");
if (!image.isNull() && image.width() >= required.width() &&
image.height() >= required.height()) {
return image.convertToFormat(QImage::Format_RGBA8888);
}
}
QImageReader reader(path);
reader.setAutoTransform(true);
if (!decodeSize.isEmpty() && !source.isEmpty())
reader.setScaledSize(
source.scaled(decodeSize, Qt::KeepAspectRatioByExpanding));
QImage image = reader.read();
if (image.isNull()) return {};
return image.convertToFormat(QImage::Format_RGBA8888);
}
QByteArray WallpaperCache::posterBlob(const QString& path) const {
if (path.isEmpty()) return {};
const QString databasePath = dbPath();
if (databasePath.isEmpty()) return {};
const QFileInfo info(path);
QSqlDatabase database = openDatabase(databasePath);
if (!database.isOpen()) return {};
QSqlQuery query(database);
query.prepare("SELECT poster, size, mtime FROM wallpapers WHERE path = ?");
query.addBindValue(info.absoluteFilePath());
if (!query.exec() || !query.next()) return {};
const QByteArray blob = query.value(0).toByteArray();
if (blob.isEmpty()) return {};
const qint64 mtime = info.lastModified().toMSecsSinceEpoch() / 1000;
if (query.value(1).toLongLong() != info.size() ||
query.value(2).toLongLong() != mtime) {
return {};
}
return blob;
}
QVariantMap WallpaperCache::cropsForPath(const QString& path) const {
if (path.isEmpty()) return {};
const QString databasePath = dbPath();
if (databasePath.isEmpty()) return {};
const QFileInfo info(path);
QSqlDatabase database = openDatabase(databasePath);
if (!database.isOpen()) return {};
QSqlQuery query(database);
query.prepare("SELECT crop FROM wallpapers WHERE path = ?");
query.addBindValue(info.absoluteFilePath());
if (!query.exec() || !query.next()) return {};
const QByteArray json = query.value(0).toByteArray();
if (json.isEmpty()) return {};
const auto doc = QJsonDocument::fromJson(json);
if (!doc.isObject()) return {};
return doc.object().toVariantMap();
}
} // namespace ZShell::wallpaper