如何在 KDE/Dolphin 上提前生成缩略图?

如何在 KDE/Dolphin 上提前生成缩略图?

回顾此问答关于在 Nautilus/GNOME 上预生成缩略图我最近发现,那里发布的所有脚本都无法在 KDE Plasma 5/Dolphin 文件管理器上运行。

有没有什么方法可以在 KDE 上提前生成缩略图,而不必手动浏览每个文件夹?

答案1

介绍

因此,事实证明 KDE 和 GNOME 现在遵循略有不同的缩略图命名和元数据约定。这非常不幸,因为这些问题本应随着自由标准组织

我已经提交了KDE 的错误报告希望最终能解决这个问题,但目前 KDE 和 GNOME 生成的缩略图彼此不兼容。

缩略图脚本用于弥合 KDE/GNOME 差距

为了解决这种不兼容性,我最终修改 James Henstridge 在上面链接的问答中发布的 Python 脚本。我实现的主要更改是更新生成的缩略图以便被 KDE 识别的功能(通过重命名它们并更新 PNG 元数据块)。

以下是上述脚本的当前修订版本:

#!/usr/bin/python3

"""
Thumbnail generator for KDE/GNOME

Largely based on a script by James Henstridge
(https://askubuntu.com/a/201997)

Unfortunately there seems to be some disagreement between GNOME and KDE
towards how to follow the XDG specs for saving thumbnails. This script
is meant as a workaround to that issue, generating thumbnails that follow
both specifications.

Dependencies: python3 gir1.2-gnomedesktop-3.0 python-pillow

pillow can be installed with `pip install pillow`

You will also need to have the corresponding thumbnailers installed (e.g.
evince-thumbnailer). KDE thumbnailers are not supported. All previews are
generated through GNOME's thumbnail factory and then made compatible with KDE.

Further references:

Thumbnail specifications in KDE/GNOME:

- https://bugs.kde.org/show_bug.cgi?id=393015
- https://api.kde.org/frameworks/kio/html/previewjob_8cpp_source.html
- https://lazka.github.io/pgi-docs/GnomeDesktop-3.0/classes/DesktopThumbnailFactory.html

Setting PNG metadata:

- http://pillow.readthedocs.io/en/5.1.x/PIL.html#PIL.PngImagePlugin.PngInfo
- https://stackoverflow.com/a/10552742/1708932

Copyright: (c) 2012 James Henstridge <https://launchpad.net/~jamesh>
           (c) 2018 Glutanimate <https://glutanimate.com/>
License: MIT license
"""

import os
import sys
from hashlib import md5

from PIL import Image
from PIL import PngImagePlugin

import gi
gi.require_version('GnomeDesktop', '3.0')
from gi.repository import Gio, GnomeDesktop

# FIXME: Hardcoding the Thumbnailer to a generic name
#        regardless of MIME type might not always work
KDE_THUMBNAILER = "KDE Thumbnail Generator"


def update_name_and_meta(thumb_path, filename, mtime, mime_type, size):
    print("Making thumb compatible with KDE...")
    abs_path = os.path.abspath(filename)
    # The spaces in our URI are not escaped. This is not in accordance
    # with the URI RFC2396 which is listed in the freedesktop specs,
    # but it's what KDE currently uses 
    # (cf.: https://bugs.kde.org/show_bug.cgi?id=393015)
    kde_uri = "file://" + abs_path  
    kde_md5 = md5(kde_uri.encode("utf-8")).hexdigest()
    thumb_dir = os.path.dirname(thumb_path)
    kde_thumb_path = os.path.join(thumb_dir, kde_md5 + ".png")

    if os.path.exists(kde_thumb_path):
        print("KDE thumb already exists. Skipping")
        return

    im = Image.open(thumb_path)

    # Set PNG metadata chunk
    meta = PngImagePlugin.PngInfo()
    meta.add_itxt("Software", KDE_THUMBNAILER)
    meta.add_text("Thumb::MTime", str(int(mtime)))
    meta.add_text("Thumb::Mimetype", mime_type)
    meta.add_text("Thumb::Size", str(size))
    meta.add_itxt("Thumb::URI", kde_uri)

    im.save(kde_thumb_path, "png", pnginfo=meta)

    # uncomment this to remove GNOME thumbnails:
    # os.remove(thumb_path)


def make_thumbnail(factory, filename):
    mtime = os.path.getmtime(filename)
    # Use Gio to determine the URI and mime type
    f = Gio.file_new_for_path(filename)
    uri = f.get_uri()
    info = f.query_info(
        'standard::content-type', Gio.FileQueryInfoFlags.NONE, None)
    mime_type = info.get_content_type()
    size = info.get_size()

    if factory.lookup(uri, mtime) is not None:
        print("FRESH       %s" % uri)
        return False

    if not factory.can_thumbnail(uri, mime_type, mtime):
        print("UNSUPPORTED %s" % uri)
        return False

    thumbnail = factory.generate_thumbnail(uri, mime_type)
    if thumbnail is None:
        print("ERROR       %s" % uri)
        return False

    factory.save_thumbnail(thumbnail, uri, mtime)

    thumb_path = factory.lookup(uri, mtime)
    update_name_and_meta(thumb_path, filename, mtime, mime_type, size)

    print("OK          %s" % uri)

    return True


def thumbnail_folder(factory, folder):
    for dirpath, dirnames, filenames in os.walk(folder):
        for filename in filenames:
            make_thumbnail(factory, os.path.join(dirpath, filename))


def main(argv):
    factory = GnomeDesktop.DesktopThumbnailFactory()
    for filename in argv[1:]:
        if os.path.isdir(filename):
            thumbnail_folder(factory, filename)
        else:
            make_thumbnail(factory, filename)


if __name__ == '__main__':
    sys.exit(main(sys.argv))

安装

将上面的代码部分复制并粘贴到新文件中,为其选择一个合适的名称(例如thumbnailer),并将其标记为可执行文件。

依赖项

要使脚本正常工作,您需要安装 GNOME 的 Python 绑定。脚本还依赖于pillow可通过 进行安装的 Python 库pip

以下命令应处理所有依赖关系:

sudo apt install gir1.2-gnomedesktop-3.0 python3-pip
pip3 install pillow

缩略图首先通过 GNOME 的缩略图工厂生成,然后与 KDE 兼容。因此,您仍需要安装所有相应的 GNOME 缩略图模块。不支持 KDE 自己的缩略图模块。例如:要使脚本支持生成 PDF 缩略图,您必须安装evince

(我本来很想直接使用 KDE 的 python 绑定,但看起来 pykde4 和 pykde5 都已被废弃多年了)。

用法

一般用法与任何其他缩略图脚本相同。只需使用要生成缩略图的文件或文件夹作为参数来调用它,例如:

thumbnailer /home/Documents

参考

KDE/GNOME 中的缩略图规格:

设置 PNG 元数据:

相关内容