Thumbnail work, added locals setting, cleanup
This commit is contained in:
parent
f440ff3d96
commit
639f14df5e
|
@ -115,9 +115,7 @@ class Plugin(PluginBase):
|
||||||
hash_img_pth = f"{self._fm_state.tab.ABS_THUMBS_PTH}/{file_hash}.jpg"
|
hash_img_pth = f"{self._fm_state.tab.ABS_THUMBS_PTH}/{file_hash}.jpg"
|
||||||
|
|
||||||
try:
|
try:
|
||||||
os.remove(hash_img_pth) if os.path.isfile(hash_img_pth) else ...
|
self._fm_state.tab.create_video_thumbnail(f"{dir}/{file}", f"{scrub_percent}%", True)
|
||||||
|
|
||||||
self._fm_state.tab.create_thumbnail(dir, file, f"{scrub_percent}%")
|
|
||||||
preview_pixbuf = GdkPixbuf.Pixbuf.new_from_file(hash_img_pth)
|
preview_pixbuf = GdkPixbuf.Pixbuf.new_from_file(hash_img_pth)
|
||||||
self._thumbnail_preview_img.set_from_pixbuf(preview_pixbuf)
|
self._thumbnail_preview_img.set_from_pixbuf(preview_pixbuf)
|
||||||
|
|
||||||
|
@ -135,8 +133,7 @@ class Plugin(PluginBase):
|
||||||
uri = self._fm_state.uris[0]
|
uri = self._fm_state.uris[0]
|
||||||
path = self._fm_state.tab.get_current_directory()
|
path = self._fm_state.tab.get_current_directory()
|
||||||
parts = uri.split("/")
|
parts = uri.split("/")
|
||||||
|
file_hash = self._fm_state.tab.fast_hash(uri)
|
||||||
file_hash = hashlib.sha256(str.encode(uri)).hexdigest()
|
|
||||||
hash_img_pth = f"{self._fm_state.tab.ABS_THUMBS_PTH}/{file_hash}.jpg"
|
hash_img_pth = f"{self._fm_state.tab.ABS_THUMBS_PTH}/{file_hash}.jpg"
|
||||||
preview_pixbuf = GdkPixbuf.Pixbuf.new_from_file(hash_img_pth)
|
preview_pixbuf = GdkPixbuf.Pixbuf.new_from_file(hash_img_pth)
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
# Python imports
|
# Python imports
|
||||||
import argparse
|
import argparse
|
||||||
import faulthandler
|
import faulthandler
|
||||||
|
import locale
|
||||||
import traceback
|
import traceback
|
||||||
from setproctitle import setproctitle
|
from setproctitle import setproctitle
|
||||||
|
|
||||||
|
@ -20,6 +21,8 @@ from app import Application
|
||||||
|
|
||||||
def run():
|
def run():
|
||||||
try:
|
try:
|
||||||
|
locale.setlocale(locale.LC_NUMERIC, 'C')
|
||||||
|
|
||||||
setproctitle(f"{app_name}")
|
setproctitle(f"{app_name}")
|
||||||
faulthandler.enable() # For better debug info
|
faulthandler.enable() # For better debug info
|
||||||
|
|
||||||
|
|
|
@ -12,16 +12,18 @@ class PluginBaseException(Exception):
|
||||||
|
|
||||||
|
|
||||||
class PluginBase:
|
class PluginBase:
|
||||||
def __init__(self):
|
def __init__(self, **kwargs):
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
self.name = "Example Plugin" # NOTE: Need to remove after establishing private bidirectional 1-1 message bus
|
self.name = "Example Plugin" # NOTE: Need to remove after establishing private bidirectional 1-1 message bus
|
||||||
# where self.name should not be needed for message comms
|
# where self.name should not be needed for message comms
|
||||||
|
|
||||||
self._builder = None
|
self._builder = None
|
||||||
self._ui_objects = None
|
self._ui_objects = None
|
||||||
self._fm_state = None
|
self._fm_state = None
|
||||||
self._event_system = None
|
self._event_system = None
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def set_fm_event_system(self, fm_event_system):
|
def set_fm_event_system(self, fm_event_system):
|
||||||
"""
|
"""
|
||||||
Requests Key: 'pass_fm_events': "true"
|
Requests Key: 'pass_fm_events': "true"
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# Python imports
|
# Python imports
|
||||||
|
import os
|
||||||
import hashlib
|
import hashlib
|
||||||
from os.path import isfile
|
from os.path import isfile
|
||||||
|
|
||||||
|
@ -34,31 +35,30 @@ class Icon(DesktopIconMixin, VideoIconMixin, MeshsIconMixin):
|
||||||
if file.lower().endswith(self.fmeshs): # 3D Mesh icon
|
if file.lower().endswith(self.fmeshs): # 3D Mesh icon
|
||||||
...
|
...
|
||||||
if file.lower().endswith(self.fvideos): # Video icon
|
if file.lower().endswith(self.fvideos): # Video icon
|
||||||
thumbnl = self.create_thumbnail(dir, file, full_path)
|
thumbnl = self.create_video_thumbnail(full_path)
|
||||||
elif file.lower().endswith(self.fimages): # Image Icon
|
elif file.lower().endswith(self.fimages): # Image Icon
|
||||||
thumbnl = self.create_scaled_image(full_path)
|
thumbnl = self.create_scaled_image(full_path)
|
||||||
elif file.lower().endswith( (".blend",) ): # Blender icon
|
elif file.lower().endswith( (".blend",) ): # Blender icon
|
||||||
thumbnl = self.create_blender_thumbnail(dir, file, full_path)
|
thumbnl = self.create_blender_thumbnail(full_path)
|
||||||
elif full_path.lower().endswith( ('.desktop',) ): # .desktop file parsing
|
elif full_path.lower().endswith( ('.desktop',) ): # .desktop file parsing
|
||||||
thumbnl = self.parse_desktop_files(full_path)
|
thumbnl = self.find_thumbnail_from_desktop_file(full_path)
|
||||||
|
|
||||||
if not thumbnl:
|
if not thumbnl:
|
||||||
thumbnl = self.get_system_thumbnail(full_path, self.sys_icon_wh[0])
|
thumbnl = self.get_system_thumbnail(full_path, self.sys_icon_wh[0])
|
||||||
|
|
||||||
if not thumbnl:
|
if not thumbnl:
|
||||||
thumbnl = self.return_generic_icon()
|
thumbnl = self.get_generic_icon()
|
||||||
|
|
||||||
return thumbnl
|
return thumbnl
|
||||||
except Exception:
|
except Exception:
|
||||||
...
|
...
|
||||||
|
|
||||||
return self.return_generic_icon()
|
return self.get_generic_icon()
|
||||||
|
|
||||||
def create_blender_thumbnail(self, dir, file, full_path=None):
|
def create_blender_thumbnail(self, full_path):
|
||||||
try:
|
try:
|
||||||
file_hash = hashlib.sha256(str.encode(full_path)).hexdigest()
|
path_exists, hash_img_path = self.generate_hash_and_path(full_path)
|
||||||
hash_img_path = f"{self.ABS_THUMBS_PTH}/{file_hash}.png"
|
if not path_exists:
|
||||||
if not isfile(hash_img_path):
|
|
||||||
self.generate_blender_thumbnail(full_path, hash_img_path)
|
self.generate_blender_thumbnail(full_path, hash_img_path)
|
||||||
|
|
||||||
return self.create_scaled_image(hash_img_path, self.video_icon_wh)
|
return self.create_scaled_image(hash_img_path, self.video_icon_wh)
|
||||||
|
@ -68,11 +68,14 @@ class Icon(DesktopIconMixin, VideoIconMixin, MeshsIconMixin):
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def create_thumbnail(self, dir, file, full_path=None, scrub_percent = "65%"):
|
def create_video_thumbnail(self, full_path, scrub_percent = "65%", replace=False):
|
||||||
try:
|
try:
|
||||||
file_hash = hashlib.sha256(str.encode(full_path)).hexdigest()
|
path_exists, hash_img_path = self.generate_hash_and_path(full_path)
|
||||||
hash_img_path = f"{self.ABS_THUMBS_PTH}/{file_hash}.jpg"
|
if path_exists and replace:
|
||||||
if not isfile(hash_img_path):
|
os.remove(hash_img_path)
|
||||||
|
path_exists = False
|
||||||
|
|
||||||
|
if not path_exists:
|
||||||
self.generate_video_thumbnail(full_path, hash_img_path, scrub_percent)
|
self.generate_video_thumbnail(full_path, hash_img_path, scrub_percent)
|
||||||
|
|
||||||
return self.create_scaled_image(hash_img_path, self.video_icon_wh)
|
return self.create_scaled_image(hash_img_path, self.video_icon_wh)
|
||||||
|
@ -103,18 +106,6 @@ class Icon(DesktopIconMixin, VideoIconMixin, MeshsIconMixin):
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def image2pixbuf(self, full_path, wxh):
|
|
||||||
"""Convert Pillow image to GdkPixbuf"""
|
|
||||||
im = PImage.open(full_path)
|
|
||||||
data = im.tobytes()
|
|
||||||
data = GLib.Bytes.new(data)
|
|
||||||
w, h = im.size
|
|
||||||
|
|
||||||
pixbuf = GdkPixbuf.Pixbuf.new_from_bytes(data, GdkPixbuf.Colorspace.RGB,
|
|
||||||
False, 8, w, h, w * 3)
|
|
||||||
|
|
||||||
return pixbuf.scale_simple(wxh[0], wxh[1], 2) # BILINEAR = 2
|
|
||||||
|
|
||||||
def create_from_file(self, full_path):
|
def create_from_file(self, full_path):
|
||||||
try:
|
try:
|
||||||
return GdkPixbuf.Pixbuf.new_from_file(full_path)
|
return GdkPixbuf.Pixbuf.new_from_file(full_path)
|
||||||
|
@ -137,5 +128,41 @@ class Icon(DesktopIconMixin, VideoIconMixin, MeshsIconMixin):
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def return_generic_icon(self):
|
def get_generic_icon(self):
|
||||||
return GdkPixbuf.Pixbuf.new_from_file(self.DEFAULT_ICON)
|
return GdkPixbuf.Pixbuf.new_from_file(self.DEFAULT_ICON)
|
||||||
|
|
||||||
|
def generate_hash_and_path(self, full_path):
|
||||||
|
file_hash = self.fast_hash(full_path)
|
||||||
|
hash_img_path = f"{self.ABS_THUMBS_PTH}/{file_hash}.jpg"
|
||||||
|
path_exists = True if isfile(hash_img_path) else False
|
||||||
|
|
||||||
|
return path_exists, hash_img_path
|
||||||
|
|
||||||
|
|
||||||
|
def fast_hash(self, filename, hash_factory=hashlib.md5, chunk_num_blocks=128, i=1):
|
||||||
|
h = hash_factory()
|
||||||
|
with open(filename,'rb') as f:
|
||||||
|
f.seek(0, 2)
|
||||||
|
mid = int(f.tell() / 2)
|
||||||
|
f.seek(mid, 0)
|
||||||
|
|
||||||
|
while chunk := f.read(chunk_num_blocks*h.block_size):
|
||||||
|
h.update(chunk)
|
||||||
|
if (i == 12):
|
||||||
|
break
|
||||||
|
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
return h.hexdigest()
|
||||||
|
|
||||||
|
def image2pixbuf(self, full_path, wxh):
|
||||||
|
"""Convert Pillow image to GdkPixbuf"""
|
||||||
|
im = PImage.open(full_path)
|
||||||
|
data = im.tobytes()
|
||||||
|
data = GLib.Bytes.new(data)
|
||||||
|
w, h = im.size
|
||||||
|
|
||||||
|
pixbuf = GdkPixbuf.Pixbuf.new_from_bytes(data, GdkPixbuf.Colorspace.RGB,
|
||||||
|
False, 8, w, h, w * 3)
|
||||||
|
|
||||||
|
return pixbuf.scale_simple(wxh[0], wxh[1], 2) # BILINEAR = 2
|
||||||
|
|
|
@ -17,7 +17,7 @@ from .xdg.DesktopEntry import DesktopEntry
|
||||||
|
|
||||||
|
|
||||||
class DesktopIconMixin:
|
class DesktopIconMixin:
|
||||||
def parse_desktop_files(self, full_path):
|
def find_thumbnail_from_desktop_file(self, full_path):
|
||||||
try:
|
try:
|
||||||
xdgObj = DesktopEntry(full_path)
|
xdgObj = DesktopEntry(full_path)
|
||||||
icon = xdgObj.getIcon()
|
icon = xdgObj.getIcon()
|
||||||
|
|
Loading…
Reference in New Issue