From ab9fca8c33200d598fc7d14ab474264f6a99e49c Mon Sep 17 00:00:00 2001 From: itdominator <1itdominator@gmail.com> Date: Sat, 20 Nov 2021 03:26:14 -0600 Subject: [PATCH] Better thumbnailer setup. Garunteed no crashes due to Gio out of thread --- src/Pytop/widgets/Grid.py | 78 ++++++++++++++++++++++----------------- src/Pytop/widgets/Icon.py | 49 +++++------------------- 2 files changed, 54 insertions(+), 73 deletions(-) diff --git a/src/Pytop/widgets/Grid.py b/src/Pytop/widgets/Grid.py index ae67fb7..7f7de0d 100644 --- a/src/Pytop/widgets/Grid.py +++ b/src/Pytop/widgets/Grid.py @@ -9,9 +9,10 @@ import gi gi.require_version('Gtk', '3.0') gi.require_version('Gdk', '3.0') -from gi.repository import Gtk as gtk -from gi.repository import Gdk as gdk -from gi.repository import GLib as glib +from gi.repository import Gtk +from gi.repository import Gdk +from gi.repository import GLib +from gi.repository import Gio from gi.repository import GdkPixbuf @@ -32,7 +33,7 @@ class Grid: self.settings = settings self.fileHandler = FileHandler(self.settings) - self.store = gtk.ListStore(GdkPixbuf.Pixbuf, str) + self.store = Gtk.ListStore(GdkPixbuf.Pixbuf, str) self.usrHome = settings.returnUserHome() self.hideHiddenFiles = settings.isHideHiddenFiles() self.builder = settings.returnBuilder() @@ -86,45 +87,54 @@ class Grid: files = dirPaths + vids + images + desktop + files self.generateGridIcons(path, files) - self.fillVideoIcons(path, vids, len(dirPaths)) + + + def generateGridIcons(self, dir, files): + icon = GdkPixbuf.Pixbuf.new_from_file(self.iconFactory.INTERNAL_ICON_PTH) + for i, file in enumerate(files): + self.store.append([icon, file]) + self.create_icon(i, dir, file) @threaded - def generateGridIcons(self, dirPath, files): - for file in files: - image = self.iconFactory.createIcon(dirPath, file).get_pixbuf() - glib.idle_add(self.addToGrid, (image, file,)) + def create_icon(self, i, dir, file): + icon = self.iconFactory.createIcon(dir, file) + fpath = dir + "/" + file + GLib.idle_add(self.update_store, (i, icon, fpath,)) + def update_store(self, item): + i, icon, fpath = item + itr = self.store.get_iter(i) - @threaded - def fillVideoIcons(self, dirPath, files, start): - model = self.grid.get_model() + if not icon: + icon = self.get_system_thumbnail(fpath, self.iconFactory.systemIconImageWH[0]) + if not icon: + if fpath.endswith(".gif"): + icon = GdkPixbuf.PixbufAnimation.get_static_image(fpath) + else: + icon = GdkPixbuf.Pixbuf.new_from_file(self.iconFactory.INTERNAL_ICON_PTH) - # Wait till we have a proper index... - while len(self.store) < (start + 1): - time.sleep(.650) + self.store.set_value(itr, 0, icon) - i = start - for file in files: - self.updateGrid(model, dirPath, file, i) - i += 1 - - @threaded - def updateGrid(self, model, dirPath, file, i): + def get_system_thumbnail(self, filename, size): try: - image = self.iconFactory.createThumbnail(dirPath, file).get_pixbuf() - iter = model.get_iter_from_string(str(i)) - glib.idle_add(self.replaceInGrid, (iter, image,)) + if os.path.exists(filename): + gioFile = Gio.File.new_for_path(filename) + info = gioFile.query_info('standard::icon' , 0, Gio.Cancellable()) + icon = info.get_icon().get_names()[0] + iconTheme = Gtk.IconTheme.get_default() + iconData = iconTheme.lookup_icon(icon , size , 0) + if iconData: + iconPath = iconData.get_filename() + return GdkPixbuf.Pixbuf.new_from_file(iconPath) + else: + return None + else: + return None except Exception as e: - # Errors seem to happen when fillVideoIcons index wait check is to low - print("widgets/Grid.py sinking errors on updateGrid method...") - - def addToGrid(self, dataSet): - self.store.append([dataSet[0], dataSet[1]]) - - def replaceInGrid(self, dataSet): - # Iter, row column, new pixbuf... - self.store.set_value(dataSet[0], 0 , dataSet[1]) + print("System icon generation issue:") + print( repr(e) ) + return None def iconDblLeftClick(self, widget, item): diff --git a/src/Pytop/widgets/Icon.py b/src/Pytop/widgets/Icon.py index 2562a9b..55ff4b8 100644 --- a/src/Pytop/widgets/Icon.py +++ b/src/Pytop/widgets/Icon.py @@ -5,11 +5,9 @@ from os.path import isdir, isfile, join # Gtk imports import gi -gi.require_version('Gtk', '3.0') gi.require_version('Gdk', '3.0') -from gi.repository import Gtk as gtk -from gi.repository import Gio as gio +from gi.repository import GdkPixbuf from xdg.DesktopEntry import DesktopEntry @@ -55,13 +53,13 @@ class Icon: thumbnl = self.createScaledImage(hashImgPth, self.viIconWH) if thumbnl == None: # If no icon whatsoever, return internal default - thumbnl = gtk.Image.new_from_file(self.SCRIPT_PTH + "../resources/icons/video.png") + thumbnl = GdkPixbuf.Pixbuf.new_from_file(self.SCRIPT_PTH + "../resources/icons/video.png") return thumbnl except Exception as e: print("Thumbnail generation issue:") print( repr(e) ) - return gtk.Image.new_from_file(self.SCRIPT_PTH + "../resources/icons/video.png") + return GdkPixbuf.Pixbuf.new_from_file(self.SCRIPT_PTH + "../resources/icons/video.png") def getIconImage(self, file, fullPath): @@ -70,25 +68,19 @@ class Icon: # Video icon if file.lower().endswith(self.vidsList): - thumbnl = gtk.Image.new_from_file(self.SCRIPT_PTH + "../resources/icons/video.png") + thumbnl = GdkPixbuf.Pixbuf.new_from_file(self.SCRIPT_PTH + "../resources/icons/video.png") # Image Icon elif file.lower().endswith(self.imagesList): thumbnl = self.createScaledImage(fullPath, self.viIconWH) # .desktop file parsing elif fullPath.lower().endswith( ('.desktop',) ): thumbnl = self.parseDesktopFiles(fullPath) - # System icons - else: - thumbnl = self.getSystemThumbnail(fullPath, self.systemIconImageWH[0]) - - if thumbnl == None: # If no icon whatsoever, return internal default - thumbnl = gtk.Image.new_from_file(self.INTERNAL_ICON_PTH) return thumbnl except Exception as e: print("Icon generation issue:") print( repr(e) ) - return gtk.Image.new_from_file(self.INTERNAL_ICON_PTH) + return GdkPixbuf.Pixbuf.new_from_file(self.INTERNAL_ICON_PTH) def parseDesktopFiles(self, fullPath): try: @@ -126,7 +118,7 @@ class Icon: for iconsDir in iconsDirs: altIconPath = self.traverseIconsFolder(iconsDir, icon) - if altIconPath is not "": + if altIconPath != "": break return self.createScaledImage(altIconPath, self.systemIconImageWH) @@ -149,32 +141,11 @@ class Icon: return altIconPath - def getSystemThumbnail(self, filename, size): - try: - if os.path.exists(filename): - gioFile = gio.File.new_for_path(filename) - info = gioFile.query_info('standard::icon' , 0, gio.Cancellable()) - icon = info.get_icon().get_names()[0] - iconTheme = gtk.IconTheme.get_default() - iconData = iconTheme.lookup_icon(icon , size , 0) - if iconData: - iconPath = iconData.get_filename() - return gtk.Image.new_from_file(iconPath) # This seems to cause a lot of core dump issues... - else: - return None - else: - return None - except Exception as e: - print("system icon generation issue:") - print( repr(e) ) - return None - - def createScaledImage(self, path, wxh): try: - pixbuf = gtk.Image.new_from_file(path).get_pixbuf() + pixbuf = GdkPixbuf.Pixbuf.new_from_file(path) scaledPixBuf = pixbuf.scale_simple(wxh[0], wxh[1], 2) # 2 = BILINEAR and is best by default - return gtk.Image.new_from_pixbuf(scaledPixBuf) + return scaledPixBuf except Exception as e: print("Image Scaling Issue:") print( repr(e) ) @@ -182,14 +153,14 @@ class Icon: def createFromFile(self, path): try: - return gtk.Image.new_from_file(path) + return GdkPixbuf.Pixbuf.new_from_file(path) except Exception as e: print("Image from file Issue:") print( repr(e) ) return None def returnGenericIcon(self): - return gtk.Image.new_from_file(self.INTERNAL_ICON_PTH) + return GdkPixbuf.Pixbuf.new_from_file(self.INTERNAL_ICON_PTH) def generateVideoThumbnail(self, fullPath, hashImgPth):