diff --git a/src/versions/solarfm-0.0.1/SolarFM/solarfm/core/mixins/ui/grid_mixin.py b/src/versions/solarfm-0.0.1/SolarFM/solarfm/core/mixins/ui/grid_mixin.py index d75fb51..9e7fc42 100644 --- a/src/versions/solarfm-0.0.1/SolarFM/solarfm/core/mixins/ui/grid_mixin.py +++ b/src/versions/solarfm-0.0.1/SolarFM/solarfm/core/mixins/ui/grid_mixin.py @@ -26,18 +26,16 @@ class GridMixin: for file in files: 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 if save_state and not trace_debug: self.fm_controller.save_state() - @threaded - def load_icons(self, tab, store, dir, files): - for i, file in enumerate(files): - self.create_icon(i, tab, store, dir, file[0]) - + @daemon_threaded def create_icon(self, i, tab, store, dir, file): icon = tab.create_icon(dir, file) GLib.idle_add(self.update_store, *(i, store, icon,)) @@ -46,7 +44,6 @@ class GridMixin: itr = store.get_iter(i) store.set_value(itr, 0, icon) - def create_tab_widget(self, tab): return TabHeaderWidget(tab, self.close_tab) diff --git a/src/versions/solarfm-0.0.1/SolarFM/solarfm/shellfm/windows/tabs/icons/icon.py b/src/versions/solarfm-0.0.1/SolarFM/solarfm/shellfm/windows/tabs/icons/icon.py index f9a43f8..fe9d677 100644 --- a/src/versions/solarfm-0.0.1/SolarFM/solarfm/shellfm/windows/tabs/icons/icon.py +++ b/src/versions/solarfm-0.0.1/SolarFM/solarfm/shellfm/windows/tabs/icons/icon.py @@ -1,7 +1,8 @@ # Python imports import os -import hashlib from os.path import isfile +import hashlib +import threading # Lib imports import gi @@ -12,7 +13,7 @@ from gi.repository import GdkPixbuf try: from PIL import Image as PImage -except Exception as e: +except ModuleNotFoundError as e: PImage = None # Application imports @@ -22,6 +23,10 @@ from .mixins.desktopiconmixin import DesktopIconMixin +class IconException(Exception): + ... + + class Icon(DesktopIconMixin, VideoIconMixin, MeshsIconMixin): def create_icon(self, dir, file): @@ -30,7 +35,7 @@ class Icon(DesktopIconMixin, VideoIconMixin, MeshsIconMixin): def get_icon_image(self, dir, file, full_path): 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 ... @@ -44,13 +49,10 @@ class Icon(DesktopIconMixin, VideoIconMixin, MeshsIconMixin): thumbnl = self.find_thumbnail_from_desktop_file(full_path) if not thumbnl: - thumbnl = self.get_system_thumbnail(full_path, self.sys_icon_wh[0]) - - if not thumbnl: - thumbnl = self.get_generic_icon() + raise IconException("No known icons found.") return thumbnl - except Exception: + except IconException: ... return self.get_generic_icon() @@ -62,7 +64,7 @@ class Icon(DesktopIconMixin, VideoIconMixin, MeshsIconMixin): self.generate_blender_thumbnail(full_path, hash_img_path) 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( repr(e) ) @@ -79,7 +81,7 @@ class Icon(DesktopIconMixin, VideoIconMixin, MeshsIconMixin): self.generate_video_thumbnail(full_path, hash_img_path, scrub_percent) 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( repr(e) ) @@ -100,7 +102,7 @@ class Icon(DesktopIconMixin, VideoIconMixin, MeshsIconMixin): return self.image2pixbuf(full_path, wxh) 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( repr(e) ) @@ -109,21 +111,37 @@ class Icon(DesktopIconMixin, VideoIconMixin, MeshsIconMixin): def create_from_file(self, full_path): try: return GdkPixbuf.Pixbuf.new_from_file(full_path) - except Exception as e: + except IconException as e: print("Image from file Issue:") print( repr(e) ) 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: - 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) 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) - except Exception: + if data: + icon_path = data.get_filename() + return GdkPixbuf.Pixbuf.new_from_file(icon_path) + + raise IconException("No system icon found...") + except IconException: ... return None diff --git a/src/versions/solarfm-0.0.1/SolarFM/solarfm/shellfm/windows/tabs/icons/mixins/desktopiconmixin.py b/src/versions/solarfm-0.0.1/SolarFM/solarfm/shellfm/windows/tabs/icons/mixins/desktopiconmixin.py index 09da06b..c1f6be0 100644 --- a/src/versions/solarfm-0.0.1/SolarFM/solarfm/shellfm/windows/tabs/icons/mixins/desktopiconmixin.py +++ b/src/versions/solarfm-0.0.1/SolarFM/solarfm/shellfm/windows/tabs/icons/mixins/desktopiconmixin.py @@ -24,43 +24,49 @@ class DesktopIconMixin: alt_icon_path = "" if "steam" in icon: - name = xdgObj.getName() - 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) + return self.get_steam_img(xdgObj) elif os.path.exists(icon): return self.create_scaled_image(icon, self.sys_icon_wh) else: - gio_icon = Gio.Icon.new_for_string(icon) - gicon = Gtk.Image.new_from_gicon(gio_icon, 32) - pixbuf = gicon.get_pixbuf() + pixbuf, alt_icon_path = self.get_icon_from_traversal(icon) if 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) except Exception as e: print(".desktop icon generation issue:") 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): for (dirpath, dirnames, filenames) in os.walk(path): diff --git a/src/versions/solarfm-0.0.1/SolarFM/solarfm/shellfm/windows/tabs/tab.py b/src/versions/solarfm-0.0.1/SolarFM/solarfm/shellfm/windows/tabs/tab.py index fc592a5..1f78dec 100644 --- a/src/versions/solarfm-0.0.1/SolarFM/solarfm/shellfm/windows/tabs/tab.py +++ b/src/versions/solarfm-0.0.1/SolarFM/solarfm/shellfm/windows/tabs/tab.py @@ -224,10 +224,13 @@ class Tab(Settings, FileHandler, Launcher, Icon, Path): return self._dir_watcher 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): - 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: return hashlib.sha256(str.encode(text)).hexdigest()[:18] diff --git a/src/versions/solarfm-0.0.1/SolarFM/solarfm/utils/ipc_server.py b/src/versions/solarfm-0.0.1/SolarFM/solarfm/utils/ipc_server.py index 7d9b44d..23914b5 100644 --- a/src/versions/solarfm-0.0.1/SolarFM/solarfm/utils/ipc_server.py +++ b/src/versions/solarfm-0.0.1/SolarFM/solarfm/utils/ipc_server.py @@ -56,9 +56,12 @@ class IPCServer: @daemon_threaded def _run_ipc_loop(self, listener) -> None: while True: - conn = listener.accept() - start_time = time.perf_counter() - GLib.idle_add(self._handle_ipc_message, *(conn, start_time,)) + try: + conn = listener.accept() + start_time = time.perf_counter() + GLib.idle_add(self._handle_ipc_message, *(conn, start_time,)) + except Exception as e: + ... listener.close()