From 2bd89e577145ed72983445bfff1a9fe07fbd5de4 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 6 Oct 2023 20:06:36 +0200 Subject: [PATCH] Start: fixes #10221: /tmp/FreeCADStartThumbnails* directories are not removed when FreeCAD terminates The commit adds some new functions: * getThumbnailDir() Returns the path to the thumbnail directory which is a sub-directory of the Cache directory. There is no need to always create a unique directory after each restart because it doesn't harm if the thumbnail directoy contains deprecated files. * createThumbnailDir() Creates the thumbnail directoy if it doesn't exist yet. * getSha1Hash Helper function to compute a SHA-1 hash of a given path. If the same path is passed then the hash value will be the same. This way it can be avoided to create a different image file from a project file after each restart. * getUniquePNG Computes the path of a PNG image file for a given project file. It's also possible to pass an arbitrary string as argument. * useCachedPNG If the PNG image exists and if it's newer than the project file True is returned and False otherwise. The changes in detail are: 1. For a given project file it is checked if the thumbnail directory already contains a cached image. If it's newer than the project file it will used, otherwise it will be re-created. 2. For the system icon to a given file format it is only checked if the icon already exists. If yes, it will be used. --- src/Mod/Start/StartPage/StartPage.py | 57 +++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 6 deletions(-) diff --git a/src/Mod/Start/StartPage/StartPage.py b/src/Mod/Start/StartPage/StartPage.py index 09e0506269..a30a087f8d 100644 --- a/src/Mod/Start/StartPage/StartPage.py +++ b/src/Mod/Start/StartPage/StartPage.py @@ -33,6 +33,7 @@ import re import FreeCAD import FreeCADGui import codecs +import hashlib import urllib.parse from . import TranslationTexts from PySide import QtCore, QtGui @@ -54,6 +55,42 @@ tempfolder = None # store icons inside a subfolder in temp dir defaulticon = None # store a default icon for problematic file types +def getThumbnailDir(): + parent_dir = FreeCAD.getUserCachePath() + return os.path.join(parent_dir, "FreeCADStartThumbnails") + + +def createThumbnailDir(): + path = getThumbnailDir() + if not os.path.exists(path): + os.mkdir(path) + return path + + +def getSha1Hash(path, encode="utf-8"): + sha_hash = hashlib.sha1() + hashed = hashlib.sha1(path.encode(encode)) + hex_digest = hashed.hexdigest().encode(encode) + sha_hash.update(hex_digest) + return sha_hash.hexdigest() + + +def getUniquePNG(filename): + parent_dir = getThumbnailDir() + sha1 = getSha1Hash(filename) + ".png" + return os.path.join(parent_dir, sha1) + + +def useCachedPNG(image, project): + if not os.path.exists(image): + return False + if not os.path.exists(project): + return False + + stamp = os.path.getmtime + return stamp(image) > stamp(project) + + def gethexcolor(color): "returns a color hex value #000000" @@ -180,11 +217,15 @@ def getInfo(filename): if r: descr = r[0] if "thumbnails/Thumbnail.png" in files: + image_png = getUniquePNG(filename) if filename in iconbank: image = iconbank[filename] + elif useCachedPNG(image_png, filename): + image = image_png + iconbank[filename] = image else: imagedata = zfile.read("thumbnails/Thumbnail.png") - image = tempfile.mkstemp(dir=tempfolder, suffix=".png")[1] + image = image_png thumb = open(image, "wb") thumb.write(imagedata) thumb.close() @@ -220,16 +261,20 @@ def getInfo(filename): if not image: i = QtCore.QFileInfo(filename) t = iconprovider.type(i) + filename_png = getUniquePNG(filename) if not t: t = "Unknown" if t in iconbank: image = iconbank[t] + elif os.path.exists(filename_png): + image = filename_png + iconbank[t] = image else: icon = iconprovider.icon(i) if icon.availableSizes(): preferred = icon.actualSize(QtCore.QSize(128, 128)) px = icon.pixmap(preferred) - image = tempfile.mkstemp(dir=tempfolder, suffix=".png")[1] + image = filename_png px.save(image) else: image = getDefaultIcon() @@ -250,7 +295,7 @@ def getDefaultIcon(): icon = iconprovider.icon(i) preferred = icon.actualSize(QtCore.QSize(128, 128)) px = icon.pixmap(preferred) - image = tempfile.mkstemp(dir=tempfolder, suffix=".png")[1] + image = getUniquePNG("default_icon") px.save(image) defaulticon = image @@ -359,7 +404,7 @@ def handle(): if hasattr(Start, "tempfolder"): tempfolder = Start.tempfolder else: - tempfolder = tempfile.mkdtemp(prefix="FreeCADStartThumbnails") + tempfolder = createThumbnailDir() # build the html page skeleton @@ -494,7 +539,7 @@ def handle(): pa = QtGui.QPainter(i) pa.fillRect(i.rect(), gradient) pa.end() - createimg = tempfile.mkstemp(dir=tempfolder, suffix=".png")[1] + createimg = getUniquePNG("createimg") i.save(createimg) iconbank["createimg"] = createimg @@ -676,7 +721,7 @@ def handle(): ] p = QtGui.QPixmap(r) p = p.scaled(24, 24) - img = tempfile.mkstemp(dir=tempfolder, suffix=".png")[1] + img = getUniquePNG(wb) p.save(img) else: img = xpm