Pytop/src/Pytop/widgets/Grid.py

220 lines
7.5 KiB
Python

# Python imports
import os, threading, time
from os.path import isdir, isfile, join
from os import listdir
# Gtk imports
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('Gdk', '3.0')
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
# Application imports
from .Icon import Icon
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.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.selectedFiles = []
self.currentPath = ""
self.grid.set_model(self.store)
self.grid.set_pixbuf_column(0)
self.grid.set_text_column(1)
self.grid.connect("item-activated", self.iconDblLeftClick)
self.grid.connect("button_release_event", self.iconSingleClick, (self.grid,))
def setNewDirectory(self, path):
self.store.clear()
self.currentPath = path
dirPaths = ['.', '..']
vids = []
images = []
desktop = []
files = []
for f in listdir(path):
file = join(path, f)
if self.hideHiddenFiles:
if f.startswith('.'):
continue
if isfile(file):
lowerName = file.lower()
if lowerName.endswith(self.vidsFilter):
vids.append(f)
elif lowerName.endswith(self.imagesFilter):
images.append(f)
elif lowerName.endswith((".desktop",)):
desktop.append(f)
else:
files.append(f)
else:
dirPaths.append(f)
dirPaths.sort()
vids.sort()
images.sort()
desktop.sort()
files.sort()
files = dirPaths + vids + images + desktop + files
self.generateGridIcons(path, files)
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 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)
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)
self.store.set_value(itr, 0, icon)
def get_system_thumbnail(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 GdkPixbuf.Pixbuf.new_from_file(iconPath)
else:
return None
else:
return None
except Exception as e:
print("System icon generation issue:")
print( repr(e) )
return None
def iconDblLeftClick(self, widget, item):
try:
model = widget.get_model()
fileName = model[item][1]
dir = self.currentPath
file = dir + "/" + fileName
if fileName == ".":
self.setNewDirectory(dir)
elif fileName == "..":
parentDir = os.path.abspath(os.path.join(dir, os.pardir))
self.currentPath = parentDir
self.setNewDirectory(parentDir)
self.settings.saveSettings(parentDir)
elif isdir(file):
self.currentPath = file
self.setNewDirectory(self.currentPath)
self.settings.saveSettings(self.currentPath)
elif isfile(file):
self.fileHandler.openFile(file)
except Exception as e:
print(e)
def iconSingleClick(self, widget, eve, rclicked_icon):
try:
if eve.type == gdk.EventType.BUTTON_RELEASE and eve.button == 1:
self.selectedFiles.clear()
items = widget.get_selected_items()
model = widget.get_model()
dir = self.currentPath
for item in items:
fileName = model[item][1]
if fileName != "." and fileName != "..":
file = dir + "/" + fileName
self.selectedFiles.append(file) # Used for return to caller
elif eve.type == gdk.EventType.BUTTON_RELEASE and eve.button == 3:
input = self.builder.get_object("filenameInput")
controls = self.builder.get_object("iconControlsWindow")
iconsButtonBox = self.builder.get_object("iconsButtonBox")
menuButtonBox = self.builder.get_object("menuButtonBox")
if len(self.selectedFiles) == 1:
parts = self.selectedFiles[0].split("/")
input.set_text(parts[len(parts) - 1])
input.show()
iconsButtonBox.show()
menuButtonBox.hide()
controls.show()
elif len(self.selectedFiles) > 1:
input.set_text("")
input.hide()
menuButtonBox.hide()
iconsButtonBox.show()
controls.show()
else:
input.set_text("")
input.show()
menuButtonBox.show()
iconsButtonBox.hide()
controls.show()
except Exception as e:
print(e)
def returnSelectedFiles(self):
# NOTE: Just returning selectedFiles looks like it returns a "pointer"
# to the children. This means we lose the list if any left click occures
# in this class.
files = []
for file in self.selectedFiles:
files.append(file)
return files
def returnCurrentPath(self):
currentPath = self.currentPath
return currentPath