Icon generation improvements

This commit is contained in:
itdominator 2023-02-08 17:52:33 -06:00
parent 6e3bf63465
commit d9b471cbaa
5 changed files with 83 additions and 56 deletions

View File

@ -26,18 +26,16 @@ class GridMixin:
for file in files: for file in files:
store.append([None, file[0]]) store.append([None, file[0]])
self.load_icons(tab, store, dir, files) Gtk.main_iteration()
for i, file in enumerate(files):
self.create_icon(i, tab, store, dir, file[0])
# NOTE: Not likely called often from here but it could be useful # NOTE: Not likely called often from here but it could be useful
if save_state and not trace_debug: if save_state and not trace_debug:
self.fm_controller.save_state() self.fm_controller.save_state()
@threaded @daemon_threaded
def load_icons(self, tab, store, dir, files):
for i, file in enumerate(files):
self.create_icon(i, tab, store, dir, file[0])
def create_icon(self, i, tab, store, dir, file): def create_icon(self, i, tab, store, dir, file):
icon = tab.create_icon(dir, file) icon = tab.create_icon(dir, file)
GLib.idle_add(self.update_store, *(i, store, icon,)) GLib.idle_add(self.update_store, *(i, store, icon,))
@ -46,7 +44,6 @@ class GridMixin:
itr = store.get_iter(i) itr = store.get_iter(i)
store.set_value(itr, 0, icon) store.set_value(itr, 0, icon)
def create_tab_widget(self, tab): def create_tab_widget(self, tab):
return TabHeaderWidget(tab, self.close_tab) return TabHeaderWidget(tab, self.close_tab)

View File

@ -1,7 +1,8 @@
# Python imports # Python imports
import os import os
import hashlib
from os.path import isfile from os.path import isfile
import hashlib
import threading
# Lib imports # Lib imports
import gi import gi
@ -12,7 +13,7 @@ from gi.repository import GdkPixbuf
try: try:
from PIL import Image as PImage from PIL import Image as PImage
except Exception as e: except ModuleNotFoundError as e:
PImage = None PImage = None
# Application imports # Application imports
@ -22,6 +23,10 @@ from .mixins.desktopiconmixin import DesktopIconMixin
class IconException(Exception):
...
class Icon(DesktopIconMixin, VideoIconMixin, MeshsIconMixin): class Icon(DesktopIconMixin, VideoIconMixin, MeshsIconMixin):
def create_icon(self, dir, file): def create_icon(self, dir, file):
@ -30,7 +35,7 @@ class Icon(DesktopIconMixin, VideoIconMixin, MeshsIconMixin):
def get_icon_image(self, dir, file, full_path): def get_icon_image(self, dir, file, full_path):
try: try:
thumbnl = None thumbnl = self._get_system_thumbnail_gtk_thread(full_path, self.sys_icon_wh[0])
if file.lower().endswith(self.fmeshs): # 3D Mesh icon if file.lower().endswith(self.fmeshs): # 3D Mesh icon
... ...
@ -44,13 +49,10 @@ class Icon(DesktopIconMixin, VideoIconMixin, MeshsIconMixin):
thumbnl = self.find_thumbnail_from_desktop_file(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]) raise IconException("No known icons found.")
if not thumbnl:
thumbnl = self.get_generic_icon()
return thumbnl return thumbnl
except Exception: except IconException:
... ...
return self.get_generic_icon() return self.get_generic_icon()
@ -62,7 +64,7 @@ class Icon(DesktopIconMixin, VideoIconMixin, MeshsIconMixin):
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)
except Exception as e: except IconException as e:
print("Blender thumbnail generation issue:") print("Blender thumbnail generation issue:")
print( repr(e) ) print( repr(e) )
@ -79,7 +81,7 @@ class Icon(DesktopIconMixin, VideoIconMixin, MeshsIconMixin):
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)
except Exception as e: except IconException as e:
print("Image/Video thumbnail generation issue:") print("Image/Video thumbnail generation issue:")
print( repr(e) ) print( repr(e) )
@ -100,7 +102,7 @@ class Icon(DesktopIconMixin, VideoIconMixin, MeshsIconMixin):
return self.image2pixbuf(full_path, wxh) return self.image2pixbuf(full_path, wxh)
return GdkPixbuf.Pixbuf.new_from_file_at_scale(full_path, wxh[0], wxh[1], True) return GdkPixbuf.Pixbuf.new_from_file_at_scale(full_path, wxh[0], wxh[1], True)
except Exception as e: except IconException as e:
print("Image Scaling Issue:") print("Image Scaling Issue:")
print( repr(e) ) print( repr(e) )
@ -109,21 +111,37 @@ class Icon(DesktopIconMixin, VideoIconMixin, MeshsIconMixin):
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)
except Exception as e: except IconException as e:
print("Image from file Issue:") print("Image from file Issue:")
print( repr(e) ) print( repr(e) )
return None return None
def get_system_thumbnail(self, filename, size): def _get_system_thumbnail_gtk_thread(self, full_path, size):
def _call_gtk_thread(event, result):
result.append( self.get_system_thumbnail(full_path, size) )
event.set()
result = []
event = threading.Event()
GLib.idle_add(_call_gtk_thread, event, result)
event.wait()
return result[0]
def get_system_thumbnail(self, full_path, size):
try: try:
gio_file = Gio.File.new_for_path(filename) gio_file = Gio.File.new_for_path(full_path)
info = gio_file.query_info('standard::icon' , 0, None) info = gio_file.query_info('standard::icon' , 0, None)
icon = info.get_icon().get_names()[0] icon = info.get_icon().get_names()[0]
icon_path = settings.get_icon_theme().lookup_icon(icon , size , 0).get_filename() data = settings.get_icon_theme().lookup_icon(icon , size , 0)
return GdkPixbuf.Pixbuf.new_from_file(icon_path) if data:
except Exception: icon_path = data.get_filename()
return GdkPixbuf.Pixbuf.new_from_file(icon_path)
raise IconException("No system icon found...")
except IconException:
... ...
return None return None

View File

@ -24,43 +24,49 @@ class DesktopIconMixin:
alt_icon_path = "" alt_icon_path = ""
if "steam" in icon: if "steam" in icon:
name = xdgObj.getName() return self.get_steam_img(xdgObj)
file_hash = hashlib.sha256(str.encode(name)).hexdigest()
hash_img_pth = f"{self.STEAM_ICONS_PTH}/{file_hash}.jpg"
if isfile(hash_img_pth) == True:
# Use video sizes since headers are bigger
return self.create_scaled_image(hash_img_pth, self.video_icon_wh)
exec_str = xdgObj.getExec()
parts = exec_str.split("steam://rungameid/")
id = parts[len(parts) - 1]
imageLink = f"{self.STEAM_CDN_URL}{id}/header.jpg"
proc = subprocess.Popen(["wget", "-O", hash_img_pth, imageLink])
proc.wait()
# Use video thumbnail sizes since headers are bigger
return self.create_scaled_image(hash_img_pth, self.video_icon_wh)
elif os.path.exists(icon): elif os.path.exists(icon):
return self.create_scaled_image(icon, self.sys_icon_wh) return self.create_scaled_image(icon, self.sys_icon_wh)
else: else:
gio_icon = Gio.Icon.new_for_string(icon) pixbuf, alt_icon_path = self.get_icon_from_traversal(icon)
gicon = Gtk.Image.new_from_gicon(gio_icon, 32)
pixbuf = gicon.get_pixbuf()
if pixbuf: if pixbuf:
return pixbuf return pixbuf
alt_icon_path = ""
for dir in self.ICON_DIRS:
alt_icon_path = self.traverse_icons_folder(dir, icon)
if alt_icon_path != "":
break
return self.create_scaled_image(alt_icon_path, self.sys_icon_wh) return self.create_scaled_image(alt_icon_path, self.sys_icon_wh)
except Exception as e: except Exception as e:
print(".desktop icon generation issue:") print(".desktop icon generation issue:")
print( repr(e) ) print( repr(e) )
return None
return None
def get_steam_img(self, xdgObj):
name = xdgObj.getName()
file_hash = hashlib.sha256(str.encode(name)).hexdigest()
hash_img_pth = f"{self.STEAM_ICONS_PTH}/{file_hash}.jpg"
if not isfile(hash_img_pth):
exec_str = xdgObj.getExec()
parts = exec_str.split("steam://rungameid/")
id = parts[len(parts) - 1]
imageLink = f"{self.STEAM_CDN_URL}{id}/header.jpg"
proc = subprocess.Popen(["wget", "-O", hash_img_pth, imageLink])
proc.wait()
return self.create_scaled_image(hash_img_pth, self.video_icon_wh)
def get_icon_from_traversal(self, icon):
gio_icon = Gio.Icon.new_for_string(icon)
gicon = Gtk.Image.new_from_gicon(gio_icon, 32)
pixbuf = gicon.get_pixbuf()
alt_icon_path = ""
for dir in self.ICON_DIRS:
alt_icon_path = self.traverse_icons_folder(dir, icon)
if alt_icon_path != "":
break
return pixbuf, alt_icon_path
def traverse_icons_folder(self, path, icon): def traverse_icons_folder(self, path, icon):
for (dirpath, dirnames, filenames) in os.walk(path): for (dirpath, dirnames, filenames) in os.walk(path):

View File

@ -224,10 +224,13 @@ class Tab(Settings, FileHandler, Launcher, Icon, Path):
return self._dir_watcher return self._dir_watcher
def _atoi(self, text): def _atoi(self, text):
return int(text) if text.isdigit() else text return int(text) if text.isnumeric() else text
def _atof(self, text):
return float(text) if text.isnumeric() else text
def _natural_keys(self, text): def _natural_keys(self, text):
return [ self._atoi(c) for c in re.split('(\d+)',text) ] return [ self._atof(c) for c in re.split('(\d+)', text) ]
def _hash_text(self, text) -> str: def _hash_text(self, text) -> str:
return hashlib.sha256(str.encode(text)).hexdigest()[:18] return hashlib.sha256(str.encode(text)).hexdigest()[:18]

View File

@ -56,9 +56,12 @@ class IPCServer:
@daemon_threaded @daemon_threaded
def _run_ipc_loop(self, listener) -> None: def _run_ipc_loop(self, listener) -> None:
while True: while True:
conn = listener.accept() try:
start_time = time.perf_counter() conn = listener.accept()
GLib.idle_add(self._handle_ipc_message, *(conn, start_time,)) start_time = time.perf_counter()
GLib.idle_add(self._handle_ipc_message, *(conn, start_time,))
except Exception as e:
...
listener.close() listener.close()