Tried improved threading logic

This commit is contained in:
Maxim Stewart 2019-07-07 18:18:51 -05:00
parent d0d316bb87
commit 3dbba19f28
28 changed files with 58 additions and 74 deletions

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

Before

Width:  |  Height:  |  Size: 858 B

After

Width:  |  Height:  |  Size: 858 B

View File

Before

Width:  |  Height:  |  Size: 850 B

After

Width:  |  Height:  |  Size: 850 B

View File

Before

Width:  |  Height:  |  Size: 702 B

After

Width:  |  Height:  |  Size: 702 B

View File

Before

Width:  |  Height:  |  Size: 925 B

After

Width:  |  Height:  |  Size: 925 B

View File

Before

Width:  |  Height:  |  Size: 882 B

After

Width:  |  Height:  |  Size: 882 B

View File

Before

Width:  |  Height:  |  Size: 707 B

After

Width:  |  Height:  |  Size: 707 B

View File

Before

Width:  |  Height:  |  Size: 798 B

After

Width:  |  Height:  |  Size: 798 B

View File

Before

Width:  |  Height:  |  Size: 989 B

After

Width:  |  Height:  |  Size: 989 B

View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -31,7 +31,7 @@ class Settings:
self.usrHome = os.path.expanduser('~')
self.desktopPath = self.usrHome + "/Desktop"
self.iconContainerWxH = [128, 128]
self.systemIconImageWxH = [72, 72]
self.systemIconImageWxH = [56, 56]
self.viIconWxH = [256, 128]
self.DEFAULTCOLOR = gdk.RGBA(0.0, 0.0, 0.0, 0.0) # ~#00000000

View File

@ -21,27 +21,28 @@ from utils.FileHandler import FileHandler
def threaded(fn):
def wrapper(*args, **kwargs):
threading.Thread(target=fn, args=args, kwargs=kwargs).start()
return wrapper
class Grid:
def __init__(self, grid, settings):
self.grid = grid
self.settings = settings
self.fileHandler = FileHandler(self.settings)
self.grid = grid
self.settings = settings
self.fileHandler = FileHandler(self.settings)
self.store = gtk.ListStore(GdkPixbuf.Pixbuf, str)
self.usrHome = settings.returnUserHome()
self.builder = settings.returnBuilder()
self.ColumnSize = settings.returnColumnSize()
self.vidsFilter = settings.returnVidsFilter()
self.imagesFilter = settings.returnImagesFilter()
self.iconFactory = Icon(settings)
self.gtkLock = False # Thread checks for gtkLock
self.threadLock = False # Gtk checks for thread lock
self.helperThread = None # Helper thread object
self.toWorkPool = [] # Thread fills pool and gtk empties it
self.selectedFiles = []
self.currentPath = ""
self.store = gtk.ListStore(GdkPixbuf.Pixbuf, str)
self.usrHome = settings.returnUserHome()
self.hideHiddenFiles = settings.isHideHiddenFiles()
self.builder = settings.returnBuilder()
self.ColumnSize = settings.returnColumnSize()
self.vidsFilter = settings.returnVidsFilter()
self.imagesFilter = settings.returnImagesFilter()
self.iconFactory = Icon(settings)
self.helperThread = None # Helper thread object
self.toWorkPool = [] # Thread fills pool and gtk empties it
self.selectedFiles = []
self.currentPath = ""
self.grid.set_model(self.store)
self.grid.set_pixbuf_column(0)
@ -51,8 +52,6 @@ class Grid:
def setNewDirectory(self, path):
self.store.clear()
self.currentPath = path
dirPaths = ['.', '..']
vids = []
@ -62,15 +61,18 @@ class Grid:
for f in listdir(path):
file = join(path, f)
if self.settings.isHideHiddenFiles():
if self.hideHiddenFiles:
if f.startswith('.'):
continue
if isfile(file):
if file.lower().endswith(self.vidsFilter):
lowerName = file.lower()
if lowerName.endswith(self.vidsFilter):
vids.append(f)
elif file.lower().endswith(self.imagesFilter):
elif lowerName.endswith(self.imagesFilter):
images.append(f)
elif file.lower().endswith((".desktop",)):
elif lowerName.endswith((".desktop",)):
desktop.append(f)
else:
files.append(f)
@ -82,53 +84,38 @@ class Grid:
images.sort()
desktop.sort()
files.sort()
files = dirPaths + vids + images + desktop + files
if self.helperThread:
self.helperThread.terminate()
self.helperThread = None
files = dirPaths + vids + images + desktop + files
self.store.clear()
# Run helper thread...
self.threadLock = True
self.helperThread = threading.Thread(target=self.generateGridIcon, args=(path, files)).start()
glib.idle_add(self.addToGrid, (file,)) # NOTE: This must stay in the main thread b/c
# gtk isn't thread safe/aware So, we
# make a sad lil thread hot potato 'game'
# out of this process.
self.helperThread = threading.Thread(target=self.generateGridIcons, args=(path, files))
self.helperThread.daemon = True # Set this thread as a Daemon Thread
self.helperThread.start()
# self.generateGridIcons(path, files)
glib.idle_add(self.addToGrid, (files,)) # NOTE: This must stay in the main thread b/c
# gtk isn't thread safe/aware.
# @threaded
def generateGridIcon(self, dirPath, files):
# NOTE: We'll be passing pixbuf after retreval to keep Icon.py file more
# universaly usable. We can just remove get_pixbuf to get a gtk.Image type
def generateGridIcons(self, dirPath, files):
for file in files:
image = self.iconFactory.createIcon(dirPath, file)
self.toWorkPool.append([image.get_pixbuf(), file])
self.threadLock = False
self.gtkLock = True
self.toWorkPool.append([image, file])
# NOTE: If nothing else is updating, this function gets called immediatly when return is True.
# Returning False ends checks and "continues normal flow"
def addToGrid(self, args):
# NOTE: Returning true tells gtk to check again in the future when idle.
# False ends checks and "continues normal flow"
files = args[0]
if len(self.toWorkPool) > 0:
for dataSet in self.toWorkPool:
self.store.append(dataSet)
self.store.append([dataSet[0].get_pixbuf(), dataSet[1]])
if len(self.store) == len(files): # Confirm processed all files and cleanup
self.gtkLock = False
self.threadLock = False
self.toWorkPool.clear()
self.toWorkPool.clear()
if len(self.store) == len(files): # Processed all files
return False
# Check again when idle; If nothing else is updating, this function
# gets called immediatly. So, we play hot potato by setting lock to Thread
else:
self.toWorkPool.clear()
self.gtkLock = False
self.threadLock = True
time.sleep(.005) # Fixes refresh and up icon not being added.
else: # Check again when idle
return True
def iconDblLeftClick(self, widget, item):

View File

@ -5,7 +5,6 @@ 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
# Python Imports
@ -50,10 +49,10 @@ class Icon:
if isfile(hashImgPth) == False:
self.generateVideoThumbnail(fullPath, hashImgPth)
thumbnl = self.createIconImageBuffer(hashImgPth, self.viIconWH)
thumbnl = self.createScaledImage(hashImgPth, self.viIconWH)
# Image Icon
elif file.lower().endswith(self.imagesList):
thumbnl = self.createIconImageBuffer(fullPath, self.viIconWH)
thumbnl = self.createScaledImage(fullPath, self.viIconWH)
# .desktop file parsing
elif fullPath.lower().endswith( ('.desktop',) ):
thumbnl = self.parseDesktopFiles(fullPath)
@ -91,7 +90,7 @@ class Icon:
hashImgPth = steamIconsDir + fileHash + ".jpg"
if isfile(hashImgPth) == True:
# Use video sizes since headers are bigger
return self.createIconImageBuffer(hashImgPth, self.viIconWH)
return self.createScaledImage(hashImgPth, self.viIconWH)
execStr = xdgObj.getExec()
parts = execStr.split("steam://rungameid/")
@ -110,9 +109,9 @@ class Icon:
proc.wait()
# Use video sizes since headers are bigger
return self.createIconImageBuffer(hashImgPth, self.viIconWH)
return self.createScaledImage(hashImgPth, self.viIconWH)
elif os.path.exists(icon):
return self.createIconImageBuffer(icon, self.systemIconImageWH)
return self.createScaledImage(icon, self.systemIconImageWH)
else:
for (dirpath, dirnames, filenames) in os.walk(iconsDirs):
for file in filenames:
@ -121,7 +120,7 @@ class Icon:
altIconPath = dirpath + "/" + file
break
return self.createIconImageBuffer(altIconPath, self.systemIconImageWH)
return self.createScaledImage(altIconPath, self.systemIconImageWH)
except Exception as e:
print(e)
return None
@ -129,17 +128,15 @@ class Icon:
def getSystemThumbnail(self, filename, size):
try:
iconPath = None
if os.path.exists(filename):
file = gio.File.new_for_path(filename)
info = file.query_info('standard::icon' , 0 , gio.Cancellable())
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()
iconFile = iconTheme.lookup_icon(icon , size , 0)
if iconFile != None:
iconPath = iconFile.get_filename()
return self.createIconImageBuffer(iconPath, self.systemIconImageWH)
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:
@ -149,15 +146,15 @@ class Icon:
return None
def createIconImageBuffer(self, path, wxh):
def createScaledImage(self, path, wxh):
try:
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(path, wxh[0], wxh[1], False)
pixbuf = gtk.Image.new_from_file(path).get_pixbuf()
scaledPixBuf = pixbuf.scale_simple(wxh[0], wxh[1], 2) # 2 = BILINEAR and is best by default
return gtk.Image.new_from_pixbuf(scaledPixBuf)
except Exception as e:
print(e)
return None
return gtk.Image.new_from_pixbuf(pixbuf)
def generateVideoThumbnail(self, fullPath, hashImgPth):
try:
proc = subprocess.Popen([self.thubnailGen, "-t", "65%", "-s", "300", "-c", "jpg", "-i", fullPath, "-o", hashImgPth])