thumbnailer: better caching
This commit is contained in:
parent
57f815bdc8
commit
1a650b73bc
3 changed files with 75 additions and 66 deletions
|
|
@ -28,23 +28,25 @@ Item {
|
||||||
id: two
|
id: two
|
||||||
}
|
}
|
||||||
|
|
||||||
component Img: Image {
|
component Img: CachingImage {
|
||||||
id: img
|
id: img
|
||||||
|
|
||||||
function update(): void {
|
function update(): void {
|
||||||
if (source === root.source)
|
const srcPath = `${root.source}`.slice(7);
|
||||||
|
if (thumbnail.originalPath === srcPath) {
|
||||||
root.current = this;
|
root.current = this;
|
||||||
else
|
} else
|
||||||
source = root.source;
|
path = srcPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
asynchronous: true
|
asynchronous: true
|
||||||
|
cache: false
|
||||||
fillMode: Image.PreserveAspectCrop
|
fillMode: Image.PreserveAspectCrop
|
||||||
|
|
||||||
opacity: 0
|
opacity: 0
|
||||||
scale: Wallpapers.showPreview ? 1 : 0.8
|
scale: Wallpapers.showPreview ? 1 : 0.8
|
||||||
sourceSize.width: width
|
|
||||||
sourceSize.height: height
|
|
||||||
|
|
||||||
onStatusChanged: {
|
onStatusChanged: {
|
||||||
if (status === Image.Ready)
|
if (status === Image.Ready)
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
pragma Singleton
|
pragma Singleton
|
||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Io
|
import Quickshell.Io
|
||||||
|
import QtQuick
|
||||||
import Qt.labs.platform
|
import Qt.labs.platform
|
||||||
|
|
||||||
Singleton {
|
Singleton {
|
||||||
|
|
@ -9,36 +11,64 @@ Singleton {
|
||||||
|
|
||||||
readonly property string thumbDir: `${StandardPaths.standardLocations(StandardPaths.GenericCacheLocation)[0]}/caelestia/thumbnails`.slice(7)
|
readonly property string thumbDir: `${StandardPaths.standardLocations(StandardPaths.GenericCacheLocation)[0]}/caelestia/thumbnails`.slice(7)
|
||||||
|
|
||||||
function go(sha: string, path: string, width: int, height: int): string {
|
function go(path: string, width: int, height: int): var {
|
||||||
if (!sha || !path || !width || !height)
|
return thumbComp.createObject(root, {
|
||||||
return "";
|
originalPath: path,
|
||||||
|
width: width,
|
||||||
const thumbPath = `${thumbDir}/${sha}@${width}x${height}-exact.png`;
|
height: height
|
||||||
|
});
|
||||||
thumbProc.path = path;
|
|
||||||
thumbProc.thumbPath = thumbPath;
|
|
||||||
thumbProc.width = width;
|
|
||||||
thumbProc.height = height;
|
|
||||||
thumbProc.startDetached();
|
|
||||||
|
|
||||||
return thumbPath;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Process {
|
component Thumbnail: QtObject {
|
||||||
id: thumbProc
|
id: obj
|
||||||
|
|
||||||
|
required property string originalPath
|
||||||
|
required property int width
|
||||||
|
required property int height
|
||||||
|
|
||||||
property string path
|
property string path
|
||||||
property string thumbPath
|
|
||||||
property int width
|
|
||||||
property int height
|
|
||||||
|
|
||||||
command: ["fish", "-c", `
|
readonly property Process shaProc: Process {
|
||||||
if ! test -f ${thumbPath}
|
running: true
|
||||||
set -l size (identify -ping -format '%w\n%h' ${path})
|
command: ["sha1sum", obj.originalPath]
|
||||||
if test $size[1] -gt ${width} -o $size[2] -gt ${height}
|
stdout: SplitParser {
|
||||||
magick ${path} -thumbnail ${width}x${height}^ -background none -gravity center -extent ${width}x${height} -unsharp 0x.5 ${thumbPath}
|
onRead: data => {
|
||||||
|
const sha = data.split(" ")[0];
|
||||||
|
obj.path = `${root.thumbDir}/${sha}@${obj.width}x${obj.height}-exact.png`;
|
||||||
|
obj.thumbProc.running = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly property Process thumbProc: Process {
|
||||||
|
command: ["fish", "-c", `
|
||||||
|
if test -f ${obj.path}
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
set -l size (identify -ping -format '%w\n%h' ${obj.originalPath})
|
||||||
|
if test $size[1] -gt ${obj.width} -o $size[2] -gt ${obj.height}
|
||||||
|
magick ${obj.originalPath} -${obj.width > 1024 || obj.height > 1024 ? "resize" : "thumbnail"} ${obj.width}x${obj.height}^ -background none -gravity center -extent ${obj.width}x${obj.height} -unsharp 0x.5 ${obj.path}
|
||||||
|
else
|
||||||
|
cp ${obj.originalPath} ${obj.path}
|
||||||
end
|
end
|
||||||
end
|
end`]
|
||||||
`]
|
onExited: code => {
|
||||||
|
if (code === 0) {
|
||||||
|
const path = obj.path;
|
||||||
|
obj.path = "";
|
||||||
|
obj.path = path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function reload(): void {
|
||||||
|
shaProc.running = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: thumbComp
|
||||||
|
|
||||||
|
Thumbnail {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,46 +5,23 @@ import QtQuick
|
||||||
Image {
|
Image {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
required property string path
|
property string path
|
||||||
property string thumbnail
|
readonly property Thumbnailer.Thumbnail thumbnail: Thumbnailer.go(path, width, height)
|
||||||
|
|
||||||
source: {
|
source: thumbnail.path ? `file://${thumbnail.path}` : ""
|
||||||
if (thumbnail)
|
|
||||||
return `file://${thumbnail}`;
|
|
||||||
shaProc.running = true;
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
asynchronous: true
|
asynchronous: true
|
||||||
fillMode: Image.PreserveAspectCrop
|
fillMode: Image.PreserveAspectCrop
|
||||||
|
|
||||||
onPathChanged: shaProc.running = true
|
onPathChanged: {
|
||||||
onWidthChanged: shaProc.running = true
|
thumbnail.originalPath = path;
|
||||||
onHeightChanged: shaProc.running = true
|
thumbnail.reload();
|
||||||
onStatusChanged: {
|
|
||||||
if (status === Image.Error)
|
|
||||||
waitProc.running = true;
|
|
||||||
}
|
}
|
||||||
|
onWidthChanged: {
|
||||||
Process {
|
thumbnail.width = width;
|
||||||
id: shaProc
|
thumbnail.reload();
|
||||||
|
|
||||||
command: ["sha1sum", root.path]
|
|
||||||
stdout: SplitParser {
|
|
||||||
onRead: data => root.thumbnail = Thumbnailer.go(data.split(" ")[0], root.path, root.width, root.height)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
onHeightChanged: {
|
||||||
Process {
|
thumbnail.height = height;
|
||||||
id: waitProc
|
thumbnail.reload();
|
||||||
|
|
||||||
command: ["inotifywait", "-q", "-e", "close_write", "--format", "%w%f", "-m", root.thumbnail.slice(0, root.thumbnail.lastIndexOf("/"))]
|
|
||||||
stdout: SplitParser {
|
|
||||||
onRead: file => {
|
|
||||||
if (file === root.thumbnail) {
|
|
||||||
root.source = file;
|
|
||||||
waitProc.running = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue