Changed grid making process. Cleaned up Icon logic.

This commit is contained in:
Maxim Stewart 2019-06-20 21:58:19 -05:00
parent f147922ca8
commit d23a8606f0
13 changed files with 463 additions and 247 deletions

View File

@ -2,7 +2,7 @@
Pytop is a Gtk + Python gui to have a custom desktop interface. Pytop is a Gtk + Python gui to have a custom desktop interface.
# Notes # Notes
```sudo apt-get install python3 steamcmd ```sudo apt-get install python3 wget steamcmd```
# TODO # TODO
<ul> <ul>

View File

@ -29,5 +29,8 @@ class Main:
if __name__ == "__main__": if __name__ == "__main__":
main = Main() try:
gtk.main() main = Main()
gtk.main()
except Exception as e:
print(e)

View File

@ -17,7 +17,6 @@
</object> </object>
<object class="GtkWindow" id="Window"> <object class="GtkWindow" id="Window">
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="window_position">center</property>
<property name="default_width">800</property> <property name="default_width">800</property>
<property name="default_height">600</property> <property name="default_height">600</property>
<property name="type_hint">desktop</property> <property name="type_hint">desktop</property>
@ -101,6 +100,8 @@
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="margin">6</property> <property name="margin">6</property>
<property name="selection_mode">multiple</property>
<property name="columns">6</property>
</object> </object>
</child> </child>
</object> </object>
@ -115,10 +116,10 @@
</object> </object>
</child> </child>
</object> </object>
<object class="GtkPopoverMenu" id="iconControlsWindow"> <object class="GtkPopover" id="iconControlsWindow">
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="relative_to">Desktop</property> <property name="relative_to">popOutBttn</property>
<property name="position">right</property> <property name="position">bottom</property>
<child> <child>
<object class="GtkBox"> <object class="GtkBox">
<property name="visible">True</property> <property name="visible">True</property>
@ -212,9 +213,6 @@
</packing> </packing>
</child> </child>
</object> </object>
<packing>
<property name="submenu">main</property>
</packing>
</child> </child>
</object> </object>
<object class="GtkPopover" id="webViewer"> <object class="GtkPopover" id="webViewer">

View File

@ -34,3 +34,55 @@ cell:focus {
outline-style: solid; outline-style: solid;
outline-color: rgba(0, 232, 255, 0.64); outline-color: rgba(0, 232, 255, 0.64);
} }
/* Ivonview and children default color */
.view {
background-color: rgba(0, 0, 0, 0.22);
color: #ebebeb;
}
/* Hover over color when not selected */
.view:hover {
box-shadow: inset 0 0 0 9999px alpha(rgba(0, 232, 255, 0.64), 0.54);
}
/* Handles the icon selection hover and selected hover color. */
.view:selected,
.view:selected:hover {
box-shadow: inset 0 0 0 9999px rgba(15, 134, 13, 0.49);
}
/* Rubberband coloring */
.rubberband,
rubberband,
flowbox rubberband,
treeview.view rubberband,
.content-view rubberband,
.content-view .rubberband,
XfdesktopIconView.view .rubberband {
border: 1px solid #6c6c6c;
background-color: rgba(21, 158, 167, 0.57);
}
XfdesktopIconView.view:active {
background-color: rgba(172, 102, 21, 1);
}
XfdesktopIconView.view {
border-radius: 4px;
background-color: transparent;
color: white;
text-shadow: 0 1px 1px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);
}
XfdesktopIconView.view:active {
box-shadow: none;
text-shadow: none;
}
XfdesktopIconView.view .rubberband {
border-radius: 0;
}

View File

@ -41,9 +41,16 @@ class Grid:
self.desktop.set_text_column(1) self.desktop.set_text_column(1)
self.desktop.connect("item-activated", self.iconLeftClickEventManager) self.desktop.connect("item-activated", self.iconLeftClickEventManager)
self.desktop.connect("button_press_event", self.iconRightClickEventManager, (self.desktop,)) self.desktop.connect("button_press_event", self.iconRightClickEventManager, (self.desktop,))
self.desktop.connect("selection-changed", self.setIconSelectionArray, (self.desktop,))
self.vidsList = ('.mkv', '.avi', '.flv', '.mov', '.m4v', '.mpg', '.wmv', '.mpeg', '.mp4', '.webm') self.vidsList = ('.mkv', '.avi', '.flv', '.mov', '.m4v', '.mpg', '.wmv', '.mpeg', '.mp4', '.webm')
self.imagesList = ('.png', '.jpg', '.jpeg', '.gif', '.ico', '.tga') self.imagesList = ('.png', '.jpg', '.jpeg', '.gif', '.ico', '.tga')
self.copyCutArry = []
self.gtkLock = False # Thread checks for gtkLock
self.threadLock = False # Gtk checks for thread lock
self.toWorkPool = [] # Thread fills pool and gtk empties it
self.setIconViewDir(newPath) self.setIconViewDir(newPath)
@ -81,18 +88,56 @@ class Grid:
files.sort() files.sort()
files = dirPaths + vids + images + desktop + files files = dirPaths + vids + images + desktop + files
self.generateDirectoryGrid(path, files) self.generateDirectoryGrid(path, files) # Run helper thread...
glib.idle_add(self.addToGrid, (file,)) # 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.
@threaded @threaded
def generateDirectoryGrid(self, dirPath, files): def generateDirectoryGrid(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
storageQue = []
for file in files: for file in files:
image = Icon(self.settings).createIcon(dirPath, file) image = Icon(self.settings).createIcon(dirPath, file)
# NOTE: Passing pixbuf after retreval to keep Icon.py file more universaly usable.
# We can just remove get_pixbuf to get a gtk image if len(storageQue) > 0:
glib.idle_add(self.addToGrid, (image.get_pixbuf(), file,)) for dataSet in storageQue:
self.toWorkPool.append(dataSet)
self.toWorkPool.append([image.get_pixbuf(), file])
self.threadLock = False
self.gtkLock = True
storageQue.clear()
def addToGrid(self, args): def addToGrid(self, args):
self.store.append([args[0], args[1]]) # 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)
if len(self.store) == len(files): # Vonfirm processed all files and cleanup
self.gtkLock = False
self.threadLock = False
self.toWorkPool.clear()
return False
# Check again when idle. If nothing else is updating
# this function gets called immediatly so we play hot potato
else:
self.toWorkPool.clear()
self.gtkLock = False
self.threadLock = True
return True
def setIconSelectionArray(self, widget, data=None):
os.system('cls||clear')
print(data)
def iconLeftClickEventManager(self, widget, item): def iconLeftClickEventManager(self, widget, item):
try: try:
@ -121,8 +166,6 @@ class Grid:
popover = self.builder.get_object("iconControlsWindow") popover = self.builder.get_object("iconControlsWindow")
popover.show_all() popover.show_all()
popover.popup() popover.popup()
print(popover)
# # NOTE: Need to change name of listview box... # # NOTE: Need to change name of listview box...
# children = widget.get_children()[0].get_children() # children = widget.get_children()[0].get_children()
# fileName = children[1].get_text() # fileName = children[1].get_text()

View File

@ -23,127 +23,146 @@ def threaded(fn):
class Icon: class Icon:
def __init__(self, settings): def __init__(self, settings):
self.settings = settings self.settings = settings
self.thubnailGen = self.settings.getThumbnailGenerator() self.thubnailGen = self.settings.getThumbnailGenerator()
self.GTK_ORIENTATION = settings.returnIconImagePos() self.GTK_ORIENTATION = settings.returnIconImagePos()
self.usrHome = settings.returnUserHome() self.usrHome = settings.returnUserHome()
self.iconContainerWxH = settings.returnContainerWH() self.iconContainerWH = settings.returnContainerWH()
self.systemIconImageWxH = settings.returnSystemIconImageWH() self.systemIconImageWH = settings.returnSystemIconImageWH()
self.viIconWxH = settings.returnVIIconWH() self.viIconWH = settings.returnVIIconWH()
def createIcon(self, dir, file): def createIcon(self, dir, file):
fullPath = dir + "/" + file fullPath = dir + "/" + file
thumbnl = self.getIconImage(file, fullPath) return self.getIconImage(file, fullPath)
return thumbnl
def getIconImage(self, file, fullPath): def getIconImage(self, file, fullPath):
thumbnl = gtk.Image()
vidsList = ('.mkv', '.avi', '.flv', '.mov', '.m4v', '.mpg', '.wmv', '.mpeg', '.mp4', '.webm')
imagesList = ('.png', '.jpg', '.jpeg', '.gif', '.ico', '.tga')
try: try:
if file.lower().endswith(vidsList): # Video thumbnail thumbnl = None
vidsList = ('.mkv', '.avi', '.flv', '.mov', '.m4v', '.mpg', '.wmv', '.mpeg', '.mp4', '.webm')
imagesList = ('.png', '.jpg', '.jpeg', '.gif', '.ico', '.tga')
# Video thumbnail
if file.lower().endswith(vidsList):
fileHash = hashlib.sha256(str.encode(fullPath)).hexdigest() fileHash = hashlib.sha256(str.encode(fullPath)).hexdigest()
hashImgpth = self.usrHome + "/.thumbnails/normal/" + fileHash + ".png" hashImgPth = self.usrHome + "/.thumbnails/normal/" + fileHash + ".png"
if isfile(hashImgpth) == False: if isfile(hashImgPth) == False:
self.generateVideoThumbnail(fullPath, hashImgpth) self.generateVideoThumbnail(fullPath, hashImgPth)
thumbnl = self.createIconImageBuffer(hashImgpth, self.viIconWxH) thumbnl = self.createIconImageBuffer(hashImgPth, self.viIconWH)
elif file.lower().endswith(imagesList): # Image Icon # Image Icon
thumbnl = self.createIconImageBuffer(fullPath, self.viIconWxH) elif file.lower().endswith(imagesList):
else: # System icons thumbnl = self.createIconImageBuffer(fullPath, self.viIconWH)
thumbnl = self.nonImageOrVideoIcon(fullPath) # .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, try stock file icon...
thumbnl = gtk.Image.new_from_icon_name("gtk-file", gtk.IconSize.LARGE_TOOLBAR)
if thumbnl == None: # If no icon whatsoever, return internal default
thumbnl = gtk.Image.new_from_file("resources/icons/bin.png")
return thumbnl
except Exception as e: except Exception as e:
print(e) print(e)
return gtk.Image.new_from_file("resources/icons/bin.png") return gtk.Image.new_from_file("resources/icons/bin.png")
if thumbnl == None: # If no system icon, try stock file icon...
thumbnl = gtk.Image.new_from_icon_name("gtk-file", gtk.IconSize.LARGE_TOOLBAR)
if thumbnl == None:
thumbnl = gtk.Image.new_from_file("resources/icons/bin.png")
return thumbnl def parseDesktopFiles(self, fullPath):
try:
xdgObj = DesktopEntry(fullPath)
icon = xdgObj.getIcon()
iconsDirs = "/usr/share/icons"
altIconPath = ""
if "steam" in icon:
steamIconsDir = self.usrHome + "/.thumbnails/steam_icons/"
name = xdgObj.getName()
fileHash = hashlib.sha256(str.encode(name)).hexdigest()
if isdir(steamIconsDir) == False:
os.mkdir(steamIconsDir)
hashImgPth = steamIconsDir + fileHash + ".jpg"
if isfile(hashImgPth) == True:
# Use video sizes since headers are bigger
return self.createIconImageBuffer(hashImgPth, self.viIconWH)
execStr = xdgObj.getExec()
parts = execStr.split("steam://rungameid/")
id = parts[len(parts) - 1]
# NOTE: Can try this logic instead...
# if command exists use it instead of header image
# if "steamcmd app_info_print id":
# proc = subprocess.Popen(["steamcmd", "app_info_print", id])
# proc.wait()
# else:
# use the bottom logic
imageLink = "https://steamcdn-a.akamaihd.net/steam/apps/" + id + "/header.jpg"
proc = subprocess.Popen(["wget", "-O", hashImgPth, imageLink])
proc.wait()
# Use video sizes since headers are bigger
return self.createIconImageBuffer(hashImgPth, self.viIconWH)
elif os.path.exists(icon):
return self.createIconImageBuffer(icon, self.systemIconImageWH)
else:
for (dirpath, dirnames, filenames) in os.walk(iconsDirs):
for file in filenames:
appNM = "application-x-" + icon
if appNM in file:
altIconPath = dirpath + "/" + file
break
return self.createIconImageBuffer(altIconPath, self.systemIconImageWH)
except Exception as e:
print(e)
return None
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())
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)
else:
return None
else:
return None
except Exception as e:
print(e)
return None
def nonImageOrVideoIcon(self, fullPath):
if fullPath.lower().endswith( ('.desktop',) ):
return self.parseDesktopFiles(fullPath)
else:
thumbPth = self.getSystemThumbnail(fullPath, self.systemIconImageWxH[0])
return self.createIconImageBuffer(thumbPth, self.systemIconImageWxH)
def createIconImageBuffer(self, path, wxh): def createIconImageBuffer(self, path, wxh):
try: try:
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(path, wxh[0], wxh[1], False) pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(path, wxh[0], wxh[1], False)
return gtk.Image.new_from_pixbuf(pixbuf)
except Exception as e: except Exception as e:
return gtk.Image.new_from_file("resources/icons/bin.png") return None
def parseDesktopFiles(self, fullPath): return gtk.Image.new_from_pixbuf(pixbuf)
xdgObj = DesktopEntry(fullPath)
icon = xdgObj.getIcon()
iconsDirs = "/usr/share/icons"
altIconPath = ""
if "steam" in icon: # This whole thing is iffy at best but I want my damn icons!!
steamIconsDir = self.usrHome + "/.thumbnails/steam_icons/"
name = xdgObj.getName()
fileHash = hashlib.sha256(str.encode(name)).hexdigest()
if isdir(steamIconsDir) == False: def generateVideoThumbnail(self, fullPath, hashImgPth):
os.mkdir(steamIconsDir) try:
proc = subprocess.Popen([self.thubnailGen, "-t", "65%", "-s", "300", "-c", "jpg", "-i", fullPath, "-o", hashImgPth])
hashImgpth = steamIconsDir + fileHash + ".jpg"
if isfile(hashImgpth) == True:
# Use video sizes since headers are bigger
return self.createIconImageBuffer(hashImgpth, self.viIconWxH)
execStr = xdgObj.getExec()
parts = execStr.split("steam://rungameid/")
id = parts[len(parts) - 1]
# NOTE: Can try this logic instead...
# if command exists use it instead of header image
# if "steamcmd app_info_print id":
# proc = subprocess.Popen(["steamcmd", "app_info_print", id])
# proc.wait()
# else:
# use the bottom logic
imageLink = "https://steamcdn-a.akamaihd.net/steam/apps/" + id + "/header.jpg"
proc = subprocess.Popen(["wget", "-O", hashImgpth, imageLink])
proc.wait() proc.wait()
except Exception as e:
# Use video sizes since headers are bigger print(e)
return self.createIconImageBuffer(hashImgpth, self.viIconWxH)
elif os.path.exists(icon):
return self.createIconImageBuffer(icon, self.systemIconImageWxH)
else:
for (dirpath, dirnames, filenames) in os.walk(iconsDirs):
for file in filenames:
appNM = "application-x-" + icon
if appNM in file:
altIconPath = dirpath + "/" + file
break
return self.createIconImageBuffer(altIconPath, self.systemIconImageWxH)
def getSystemThumbnail(self, filename, size):
final_filename = ""
if os.path.exists(filename):
file = gio.File.new_for_path(filename)
info = file.query_info('standard::icon' , 0 , gio.Cancellable())
icon = info.get_icon().get_names()[0]
icon_theme = gtk.IconTheme.get_default()
icon_file = icon_theme.lookup_icon(icon , size , 0)
if icon_file != None:
final_filename = icon_file.get_filename()
return final_filename
def generateVideoThumbnail(self, fullPath, hashImgpth):
proc = subprocess.Popen([self.thubnailGen, "-t", "65%", "-s", "300", "-c", "jpg", "-i", fullPath, "-o", hashImgpth])
proc.wait()

View File

@ -52,16 +52,9 @@ class Settings:
styleContext.add_provider_for_screen(screen, cssProvider, gtk.STYLE_PROVIDER_PRIORITY_USER) styleContext.add_provider_for_screen(screen, cssProvider, gtk.STYLE_PROVIDER_PRIORITY_USER)
window.set_app_paintable(True) window.set_app_paintable(True)
window.connect("draw", self.area_draw)
monitors = self.getMonitorData(screen) monitors = self.getMonitorData(screen)
window.resize(monitors[0].width, monitors[0].height) window.resize(monitors[0].width, monitors[0].height)
def area_draw(self, widget, cr):
cr.set_source_rgba(0.0, 0.0, 0.0, 0.64)
cr.set_operator(cairo.OPERATOR_SOURCE)
cr.paint()
cr.set_operator(cairo.OPERATOR_OVER)
def getMonitorData(self, screen): def getMonitorData(self, screen):
monitors = [] monitors = []
for m in range(screen.get_n_monitors()): for m in range(screen.get_n_monitors()):

View File

@ -29,5 +29,8 @@ class Main:
if __name__ == "__main__": if __name__ == "__main__":
main = Main() try:
gtk.main() main = Main()
gtk.main()
except Exception as e:
print(e)

View File

@ -17,7 +17,6 @@
</object> </object>
<object class="GtkWindow" id="Window"> <object class="GtkWindow" id="Window">
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="window_position">center</property>
<property name="default_width">800</property> <property name="default_width">800</property>
<property name="default_height">600</property> <property name="default_height">600</property>
<property name="type_hint">desktop</property> <property name="type_hint">desktop</property>
@ -101,6 +100,8 @@
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="margin">6</property> <property name="margin">6</property>
<property name="selection_mode">multiple</property>
<property name="columns">6</property>
</object> </object>
</child> </child>
</object> </object>
@ -115,10 +116,10 @@
</object> </object>
</child> </child>
</object> </object>
<object class="GtkPopoverMenu" id="iconControlsWindow"> <object class="GtkPopover" id="iconControlsWindow">
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="relative_to">Desktop</property> <property name="relative_to">popOutBttn</property>
<property name="position">right</property> <property name="position">bottom</property>
<child> <child>
<object class="GtkBox"> <object class="GtkBox">
<property name="visible">True</property> <property name="visible">True</property>
@ -212,9 +213,6 @@
</packing> </packing>
</child> </child>
</object> </object>
<packing>
<property name="submenu">main</property>
</packing>
</child> </child>
</object> </object>
<object class="GtkPopover" id="webViewer"> <object class="GtkPopover" id="webViewer">

View File

@ -34,3 +34,55 @@ cell:focus {
outline-style: solid; outline-style: solid;
outline-color: rgba(0, 232, 255, 0.64); outline-color: rgba(0, 232, 255, 0.64);
} }
/* Ivonview and children default color */
.view {
background-color: rgba(0, 0, 0, 0.22);
color: #ebebeb;
}
/* Hover over color when not selected */
.view:hover {
box-shadow: inset 0 0 0 9999px alpha(rgba(0, 232, 255, 0.64), 0.54);
}
/* Handles the icon selection hover and selected hover color. */
.view:selected,
.view:selected:hover {
box-shadow: inset 0 0 0 9999px rgba(15, 134, 13, 0.49);
}
/* Rubberband coloring */
.rubberband,
rubberband,
flowbox rubberband,
treeview.view rubberband,
.content-view rubberband,
.content-view .rubberband,
XfdesktopIconView.view .rubberband {
border: 1px solid #6c6c6c;
background-color: rgba(21, 158, 167, 0.57);
}
XfdesktopIconView.view:active {
background-color: rgba(172, 102, 21, 1);
}
XfdesktopIconView.view {
border-radius: 4px;
background-color: transparent;
color: white;
text-shadow: 0 1px 1px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);
}
XfdesktopIconView.view:active {
box-shadow: none;
text-shadow: none;
}
XfdesktopIconView.view .rubberband {
border-radius: 0;
}

View File

@ -41,9 +41,16 @@ class Grid:
self.desktop.set_text_column(1) self.desktop.set_text_column(1)
self.desktop.connect("item-activated", self.iconLeftClickEventManager) self.desktop.connect("item-activated", self.iconLeftClickEventManager)
self.desktop.connect("button_press_event", self.iconRightClickEventManager, (self.desktop,)) self.desktop.connect("button_press_event", self.iconRightClickEventManager, (self.desktop,))
self.desktop.connect("selection-changed", self.setIconSelectionArray, (self.desktop,))
self.vidsList = ('.mkv', '.avi', '.flv', '.mov', '.m4v', '.mpg', '.wmv', '.mpeg', '.mp4', '.webm') self.vidsList = ('.mkv', '.avi', '.flv', '.mov', '.m4v', '.mpg', '.wmv', '.mpeg', '.mp4', '.webm')
self.imagesList = ('.png', '.jpg', '.jpeg', '.gif', '.ico', '.tga') self.imagesList = ('.png', '.jpg', '.jpeg', '.gif', '.ico', '.tga')
self.copyCutArry = []
self.gtkLock = False # Thread checks for gtkLock
self.threadLock = False # Gtk checks for thread lock
self.toWorkPool = [] # Thread fills pool and gtk empties it
self.setIconViewDir(newPath) self.setIconViewDir(newPath)
@ -81,18 +88,56 @@ class Grid:
files.sort() files.sort()
files = dirPaths + vids + images + desktop + files files = dirPaths + vids + images + desktop + files
self.generateDirectoryGrid(path, files) self.generateDirectoryGrid(path, files) # Run helper thread...
glib.idle_add(self.addToGrid, (file,)) # 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.
@threaded @threaded
def generateDirectoryGrid(self, dirPath, files): def generateDirectoryGrid(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
storageQue = []
for file in files: for file in files:
image = Icon(self.settings).createIcon(dirPath, file) image = Icon(self.settings).createIcon(dirPath, file)
# NOTE: Passing pixbuf after retreval to keep Icon.py file more universaly usable.
# We can just remove get_pixbuf to get a gtk image if len(storageQue) > 0:
glib.idle_add(self.addToGrid, (image.get_pixbuf(), file,)) for dataSet in storageQue:
self.toWorkPool.append(dataSet)
self.toWorkPool.append([image.get_pixbuf(), file])
self.threadLock = False
self.gtkLock = True
storageQue.clear()
def addToGrid(self, args): def addToGrid(self, args):
self.store.append([args[0], args[1]]) # 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)
if len(self.store) == len(files): # Vonfirm processed all files and cleanup
self.gtkLock = False
self.threadLock = False
self.toWorkPool.clear()
return False
# Check again when idle. If nothing else is updating
# this function gets called immediatly so we play hot potato
else:
self.toWorkPool.clear()
self.gtkLock = False
self.threadLock = True
return True
def setIconSelectionArray(self, widget, data=None):
os.system('cls||clear')
print(data)
def iconLeftClickEventManager(self, widget, item): def iconLeftClickEventManager(self, widget, item):
try: try:
@ -121,8 +166,6 @@ class Grid:
popover = self.builder.get_object("iconControlsWindow") popover = self.builder.get_object("iconControlsWindow")
popover.show_all() popover.show_all()
popover.popup() popover.popup()
print(popover)
# # NOTE: Need to change name of listview box... # # NOTE: Need to change name of listview box...
# children = widget.get_children()[0].get_children() # children = widget.get_children()[0].get_children()
# fileName = children[1].get_text() # fileName = children[1].get_text()

View File

@ -23,127 +23,146 @@ def threaded(fn):
class Icon: class Icon:
def __init__(self, settings): def __init__(self, settings):
self.settings = settings self.settings = settings
self.thubnailGen = self.settings.getThumbnailGenerator() self.thubnailGen = self.settings.getThumbnailGenerator()
self.GTK_ORIENTATION = settings.returnIconImagePos() self.GTK_ORIENTATION = settings.returnIconImagePos()
self.usrHome = settings.returnUserHome() self.usrHome = settings.returnUserHome()
self.iconContainerWxH = settings.returnContainerWH() self.iconContainerWH = settings.returnContainerWH()
self.systemIconImageWxH = settings.returnSystemIconImageWH() self.systemIconImageWH = settings.returnSystemIconImageWH()
self.viIconWxH = settings.returnVIIconWH() self.viIconWH = settings.returnVIIconWH()
def createIcon(self, dir, file): def createIcon(self, dir, file):
fullPath = dir + "/" + file fullPath = dir + "/" + file
thumbnl = self.getIconImage(file, fullPath) return self.getIconImage(file, fullPath)
return thumbnl
def getIconImage(self, file, fullPath): def getIconImage(self, file, fullPath):
thumbnl = gtk.Image()
vidsList = ('.mkv', '.avi', '.flv', '.mov', '.m4v', '.mpg', '.wmv', '.mpeg', '.mp4', '.webm')
imagesList = ('.png', '.jpg', '.jpeg', '.gif', '.ico', '.tga')
try: try:
if file.lower().endswith(vidsList): # Video thumbnail thumbnl = None
vidsList = ('.mkv', '.avi', '.flv', '.mov', '.m4v', '.mpg', '.wmv', '.mpeg', '.mp4', '.webm')
imagesList = ('.png', '.jpg', '.jpeg', '.gif', '.ico', '.tga')
# Video thumbnail
if file.lower().endswith(vidsList):
fileHash = hashlib.sha256(str.encode(fullPath)).hexdigest() fileHash = hashlib.sha256(str.encode(fullPath)).hexdigest()
hashImgpth = self.usrHome + "/.thumbnails/normal/" + fileHash + ".png" hashImgPth = self.usrHome + "/.thumbnails/normal/" + fileHash + ".png"
if isfile(hashImgpth) == False: if isfile(hashImgPth) == False:
self.generateVideoThumbnail(fullPath, hashImgpth) self.generateVideoThumbnail(fullPath, hashImgPth)
thumbnl = self.createIconImageBuffer(hashImgpth, self.viIconWxH) thumbnl = self.createIconImageBuffer(hashImgPth, self.viIconWH)
elif file.lower().endswith(imagesList): # Image Icon # Image Icon
thumbnl = self.createIconImageBuffer(fullPath, self.viIconWxH) elif file.lower().endswith(imagesList):
else: # System icons thumbnl = self.createIconImageBuffer(fullPath, self.viIconWH)
thumbnl = self.nonImageOrVideoIcon(fullPath) # .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, try stock file icon...
thumbnl = gtk.Image.new_from_icon_name("gtk-file", gtk.IconSize.LARGE_TOOLBAR)
if thumbnl == None: # If no icon whatsoever, return internal default
thumbnl = gtk.Image.new_from_file("resources/icons/bin.png")
return thumbnl
except Exception as e: except Exception as e:
print(e) print(e)
return gtk.Image.new_from_file("resources/icons/bin.png") return gtk.Image.new_from_file("resources/icons/bin.png")
if thumbnl == None: # If no system icon, try stock file icon...
thumbnl = gtk.Image.new_from_icon_name("gtk-file", gtk.IconSize.LARGE_TOOLBAR)
if thumbnl == None:
thumbnl = gtk.Image.new_from_file("resources/icons/bin.png")
return thumbnl def parseDesktopFiles(self, fullPath):
try:
xdgObj = DesktopEntry(fullPath)
icon = xdgObj.getIcon()
iconsDirs = "/usr/share/icons"
altIconPath = ""
if "steam" in icon:
steamIconsDir = self.usrHome + "/.thumbnails/steam_icons/"
name = xdgObj.getName()
fileHash = hashlib.sha256(str.encode(name)).hexdigest()
if isdir(steamIconsDir) == False:
os.mkdir(steamIconsDir)
hashImgPth = steamIconsDir + fileHash + ".jpg"
if isfile(hashImgPth) == True:
# Use video sizes since headers are bigger
return self.createIconImageBuffer(hashImgPth, self.viIconWH)
execStr = xdgObj.getExec()
parts = execStr.split("steam://rungameid/")
id = parts[len(parts) - 1]
# NOTE: Can try this logic instead...
# if command exists use it instead of header image
# if "steamcmd app_info_print id":
# proc = subprocess.Popen(["steamcmd", "app_info_print", id])
# proc.wait()
# else:
# use the bottom logic
imageLink = "https://steamcdn-a.akamaihd.net/steam/apps/" + id + "/header.jpg"
proc = subprocess.Popen(["wget", "-O", hashImgPth, imageLink])
proc.wait()
# Use video sizes since headers are bigger
return self.createIconImageBuffer(hashImgPth, self.viIconWH)
elif os.path.exists(icon):
return self.createIconImageBuffer(icon, self.systemIconImageWH)
else:
for (dirpath, dirnames, filenames) in os.walk(iconsDirs):
for file in filenames:
appNM = "application-x-" + icon
if appNM in file:
altIconPath = dirpath + "/" + file
break
return self.createIconImageBuffer(altIconPath, self.systemIconImageWH)
except Exception as e:
print(e)
return None
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())
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)
else:
return None
else:
return None
except Exception as e:
print(e)
return None
def nonImageOrVideoIcon(self, fullPath):
if fullPath.lower().endswith( ('.desktop',) ):
return self.parseDesktopFiles(fullPath)
else:
thumbPth = self.getSystemThumbnail(fullPath, self.systemIconImageWxH[0])
return self.createIconImageBuffer(thumbPth, self.systemIconImageWxH)
def createIconImageBuffer(self, path, wxh): def createIconImageBuffer(self, path, wxh):
try: try:
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(path, wxh[0], wxh[1], False) pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(path, wxh[0], wxh[1], False)
return gtk.Image.new_from_pixbuf(pixbuf)
except Exception as e: except Exception as e:
return gtk.Image.new_from_file("resources/icons/bin.png") return None
def parseDesktopFiles(self, fullPath): return gtk.Image.new_from_pixbuf(pixbuf)
xdgObj = DesktopEntry(fullPath)
icon = xdgObj.getIcon()
iconsDirs = "/usr/share/icons"
altIconPath = ""
if "steam" in icon: # This whole thing is iffy at best but I want my damn icons!!
steamIconsDir = self.usrHome + "/.thumbnails/steam_icons/"
name = xdgObj.getName()
fileHash = hashlib.sha256(str.encode(name)).hexdigest()
if isdir(steamIconsDir) == False: def generateVideoThumbnail(self, fullPath, hashImgPth):
os.mkdir(steamIconsDir) try:
proc = subprocess.Popen([self.thubnailGen, "-t", "65%", "-s", "300", "-c", "jpg", "-i", fullPath, "-o", hashImgPth])
hashImgpth = steamIconsDir + fileHash + ".jpg"
if isfile(hashImgpth) == True:
# Use video sizes since headers are bigger
return self.createIconImageBuffer(hashImgpth, self.viIconWxH)
execStr = xdgObj.getExec()
parts = execStr.split("steam://rungameid/")
id = parts[len(parts) - 1]
# NOTE: Can try this logic instead...
# if command exists use it instead of header image
# if "steamcmd app_info_print id":
# proc = subprocess.Popen(["steamcmd", "app_info_print", id])
# proc.wait()
# else:
# use the bottom logic
imageLink = "https://steamcdn-a.akamaihd.net/steam/apps/" + id + "/header.jpg"
proc = subprocess.Popen(["wget", "-O", hashImgpth, imageLink])
proc.wait() proc.wait()
except Exception as e:
# Use video sizes since headers are bigger print(e)
return self.createIconImageBuffer(hashImgpth, self.viIconWxH)
elif os.path.exists(icon):
return self.createIconImageBuffer(icon, self.systemIconImageWxH)
else:
for (dirpath, dirnames, filenames) in os.walk(iconsDirs):
for file in filenames:
appNM = "application-x-" + icon
if appNM in file:
altIconPath = dirpath + "/" + file
break
return self.createIconImageBuffer(altIconPath, self.systemIconImageWxH)
def getSystemThumbnail(self, filename, size):
final_filename = ""
if os.path.exists(filename):
file = gio.File.new_for_path(filename)
info = file.query_info('standard::icon' , 0 , gio.Cancellable())
icon = info.get_icon().get_names()[0]
icon_theme = gtk.IconTheme.get_default()
icon_file = icon_theme.lookup_icon(icon , size , 0)
if icon_file != None:
final_filename = icon_file.get_filename()
return final_filename
def generateVideoThumbnail(self, fullPath, hashImgpth):
proc = subprocess.Popen([self.thubnailGen, "-t", "65%", "-s", "300", "-c", "jpg", "-i", fullPath, "-o", hashImgpth])
proc.wait()

View File

@ -52,16 +52,9 @@ class Settings:
styleContext.add_provider_for_screen(screen, cssProvider, gtk.STYLE_PROVIDER_PRIORITY_USER) styleContext.add_provider_for_screen(screen, cssProvider, gtk.STYLE_PROVIDER_PRIORITY_USER)
window.set_app_paintable(True) window.set_app_paintable(True)
window.connect("draw", self.area_draw)
monitors = self.getMonitorData(screen) monitors = self.getMonitorData(screen)
window.resize(monitors[0].width, monitors[0].height) window.resize(monitors[0].width, monitors[0].height)
def area_draw(self, widget, cr):
cr.set_source_rgba(0.0, 0.0, 0.0, 0.64)
cr.set_operator(cairo.OPERATOR_SOURCE)
cr.paint()
cr.set_operator(cairo.OPERATOR_OVER)
def getMonitorData(self, screen): def getMonitorData(self, screen):
monitors = [] monitors = []
for m in range(screen.get_n_monitors()): for m in range(screen.get_n_monitors()):