From 5595122a6d59e981cb8955842b98b2d547f1f477 Mon Sep 17 00:00:00 2001 From: itdominator <1itdominator@gmail.com> Date: Sat, 27 Nov 2021 01:54:08 -0600 Subject: [PATCH] Added file handler logic; switched to using GdkPixBuff --- src/shellfm/windows/WindowController.py | 15 ++-- src/shellfm/windows/view/Path.py | 25 ++++-- src/shellfm/windows/view/View.py | 39 ++++++--- src/shellfm/windows/view/icons/Icon.py | 27 ++----- .../view/icons/mixins/DesktopIconMixin.py | 3 + src/shellfm/windows/view/utils/FileHandler.py | 80 +++++++++++++++++++ src/shellfm/windows/view/utils/Settings.py | 3 +- 7 files changed, 146 insertions(+), 46 deletions(-) create mode 100644 src/shellfm/windows/view/utils/FileHandler.py diff --git a/src/shellfm/windows/WindowController.py b/src/shellfm/windows/WindowController.py index 470d725..bcfd90a 100644 --- a/src/shellfm/windows/WindowController.py +++ b/src/shellfm/windows/WindowController.py @@ -1,23 +1,22 @@ # Python imports -import json +import threading, subprocess, time, json from os import path # Lib imports - # Application imports from . import Window class WindowController: def __init__(self): - USER_HOME = path.expanduser('~') - CONFIG_PATH = USER_HOME + "/.config/pyfm" - self.session_file = CONFIG_PATH + "/session.json" + USER_HOME = path.expanduser('~') + CONFIG_PATH = USER_HOME + "/.config/pyfm" + self.session_file = CONFIG_PATH + "/session.json" - self.active_window_id = "" - self.active_tab_id = "" - self.windows = [] + self.active_window_id = "" + self.active_tab_id = "" + self.windows = [] def set_active_data(self, wid, tid): diff --git a/src/shellfm/windows/view/Path.py b/src/shellfm/windows/view/Path.py index 986dda8..91787b0 100644 --- a/src/shellfm/windows/view/Path.py +++ b/src/shellfm/windows/view/Path.py @@ -29,15 +29,28 @@ class Path: self.load_directory() - def set_path(self, path): - self.path = list( filter(None, path.replace("\\", "/").split('/')) ) - self.load_directory() + if path == self.get_path(): + return + + if os.path.isdir(path): + self.path = list( filter(None, path.replace("\\", "/").split('/')) ) + self.load_directory() + return True + + return False def set_path_with_sub_path(self, sub_path): - path = os.path.join(self.get_home(), sub_path) - self.path = list( filter(None, path.replace("\\", "/").split('/')) ) - self.load_directory() + path = os.path.join(self.get_home(), sub_path) + if path == self.get_path(): + return False + + if os.path.isdir(path): + self.path = list( filter(None, path.replace("\\", "/").split('/')) ) + self.load_directory() + return True + + return False def set_to_home(self): home = os.path.expanduser("~") + self.subpath diff --git a/src/shellfm/windows/view/View.py b/src/shellfm/windows/view/View.py index 3d5eed1..ae0bbb8 100644 --- a/src/shellfm/windows/view/View.py +++ b/src/shellfm/windows/view/View.py @@ -11,23 +11,26 @@ from random import randint # Application imports -from .utils import Settings, Launcher +from .utils import Settings, Launcher, FileHandler from .icons import Icon from . import Path -class View(Settings, Launcher, Icon, Path): +class View(Settings, FileHandler, Launcher, Icon, Path): def __init__(self): - self. logger = None - self.id_length = 10 + self. logger = None + self.id_length = 10 - self.id = "" - self.files = [] - self.dirs = [] - self.vids = [] - self.images = [] - self.desktop = [] - self.ungrouped = [] + self.id = "" + self.wid = None + self.dir_watcher = None + self.hide_hidden = self.HIDE_HIDDEN_FILES + self.files = [] + self.dirs = [] + self.vids = [] + self.images = [] + self.desktop = [] + self.ungrouped = [] self.generate_id() self.set_to_home() @@ -44,6 +47,18 @@ class View(Settings, Launcher, Icon, Path): def get_tab_id(self): return self.id + def set_wid(self, _wid): + self.wid = _wid + + def get_wid(self): + return self.wid + + def set_dir_watcher(self, watcher): + self.dir_watcher = watcher + + def get_dir_watcher(self): + return self.dir_watcher + def load_directory(self): path = self.get_path() self.dirs = [".", ".."] @@ -59,7 +74,7 @@ class View(Settings, Launcher, Icon, Path): for f in listdir(path): file = join(path, f) - if self.HIDE_HIDDEN_FILES: + if self.hide_hidden: if f.startswith('.'): continue diff --git a/src/shellfm/windows/view/icons/Icon.py b/src/shellfm/windows/view/icons/Icon.py index 474127c..f551ee6 100644 --- a/src/shellfm/windows/view/icons/Icon.py +++ b/src/shellfm/windows/view/icons/Icon.py @@ -3,16 +3,12 @@ import os, subprocess, threading, hashlib from os.path import isfile # Gtk imports -import gi -gi.require_version('Gtk', '3.0') - -from gi.repository import Gtk +from gi.repository import GdkPixbuf # Application imports from .mixins import * - def threaded(fn): def wrapper(*args, **kwargs): threading.Thread(target=fn, args=args, kwargs=kwargs).start() @@ -34,17 +30,10 @@ class Icon(DesktopIconMixin, VideoIconMixin): thumbnl = self.create_scaled_image(full_path, self.VIDEO_ICON_WH) elif full_path.lower().endswith( ('.desktop',) ): # .desktop file parsing thumbnl = self.parse_desktop_files(full_path) - else: # System icons - thumbnl = self.get_system_thumbnail(full_path, self.SYS_ICON_WH[0]) - - if thumbnl == None: # If no icon whatsoever, return internal default - thumbnl = Gtk.Image.new_from_file(self.DEFAULT_ICON) return thumbnl except Exception as e: - print("Icon generation issue:") - print( repr(e) ) - return Gtk.Image.new_from_file(self.DEFAULT_ICON) + return None def create_thumbnail(self, dir, file): full_path = dir + "/" + file @@ -56,20 +45,20 @@ class Icon(DesktopIconMixin, VideoIconMixin): thumbnl = self.create_scaled_image(hash_img_pth, self.VIDEO_ICON_WH) if thumbnl == None: # If no icon whatsoever, return internal default - thumbnl = Gtk.Image.new_from_file(self.DEFAULT_ICONS + "/video.png") + thumbnl = GdkPixbuf.Pixbuf.new_from_file(self.DEFAULT_ICONS + "/video.png") return thumbnl except Exception as e: print("Thumbnail generation issue:") print( repr(e) ) - return Gtk.Image.new_from_file(self.DEFAULT_ICONS + "/video.png") + return GdkPixbuf.Pixbuf.new_from_file(self.DEFAULT_ICONS + "/video.png") def create_scaled_image(self, path, wxh): try: - pixbuf = Gtk.Image.new_from_file(path).get_pixbuf() + pixbuf = GdkPixbuf.Pixbuf.new_from_file(path) scaled_pixbuf = pixbuf.scale_simple(wxh[0], wxh[1], 2) # 2 = BILINEAR and is best by default - return Gtk.Image.new_from_pixbuf(scaled_pixbuf) + return scaled_pixbuf except Exception as e: print("Image Scaling Issue:") print( repr(e) ) @@ -77,11 +66,11 @@ class Icon(DesktopIconMixin, VideoIconMixin): def create_from_file(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 return_generic_icon(self): - return Gtk.Image.new_from_file(self.DEFAULT_ICON) + return GdkPixbuf.Pixbuf.new_from_file(self.DEFAULT_ICON) diff --git a/src/shellfm/windows/view/icons/mixins/DesktopIconMixin.py b/src/shellfm/windows/view/icons/mixins/DesktopIconMixin.py index 720330f..34573cb 100644 --- a/src/shellfm/windows/view/icons/mixins/DesktopIconMixin.py +++ b/src/shellfm/windows/view/icons/mixins/DesktopIconMixin.py @@ -14,6 +14,9 @@ from .xdg.DesktopEntry import DesktopEntry class DesktopIconMixin: + # NOTE: !!!IMPORTANT!!! This method is NOT thread safe and causes seg faults + # when ran from another thread! It took me a while to hunt this info down. + # Gio is the culprit. Pull this into a main Gtk thread if actually needed. def get_system_thumbnail(self, filename, size): try: if os.path.exists(filename): diff --git a/src/shellfm/windows/view/utils/FileHandler.py b/src/shellfm/windows/view/utils/FileHandler.py new file mode 100644 index 0000000..57c69e3 --- /dev/null +++ b/src/shellfm/windows/view/utils/FileHandler.py @@ -0,0 +1,80 @@ + +import os, shutil, subprocess, threading + + +class FileHandler: + def create_file(self, nFile, type): + try: + if TYPE == "dir": + os.mkdir(nFile) + elif TYPE == "file": + open(nFile, 'a').close() + except Exception as e: + print("An error occured creating the file/dir:") + print(repr(e)) + return False + + return True + + def update_file(self, oFile, nFile): + try: + print(f"Renaming: {oFile} --> {nFile}") + os.rename(oFile, nFile) + except Exception as e: + print("An error occured renaming the file:") + print(repr(e)) + return False + + return True + + def delete_file(self, toDeleteFile): + try: + print(f"Deleting: {toDeleteFile}") + if os.path.exists(toDeleteFile): + if os.path.isfile(toDeleteFile): + os.remove(toDeleteFile) + elif os.path.isdir(toDeleteFile): + shutil.rmtree(toDeleteFile) + else: + print("An error occured deleting the file:") + return False + else: + print("The folder/file does not exist") + return False + except Exception as e: + print("An error occured deleting the file:") + print(repr(e)) + return False + + return True + + def move_file(self, fFile, tFile): + try: + print(f"Moving: {fFile} --> {tFile}") + if os.path.exists(fFile) and os.path.exists(tFile): + if not tFile.endswith("/"): + tFile += "/" + + shutil.move(fFile, tFile) + else: + print("The folder/file does not exist") + return False + except Exception as e: + print("An error occured moving the file:") + print(repr(e)) + return False + + return True + + def copy_file(self,fFile, tFile, symlinks=False, ignore=None): + try: + if os.path.isdir(fFile): + shutil.copytree(fFile, tFile, symlinks, ignore) + else: + shutil.copy2(fFile, tFile) + except Exception as e: + print("An error occured copying the file:") + print(repr(e)) + return False + + return True diff --git a/src/shellfm/windows/view/utils/Settings.py b/src/shellfm/windows/view/utils/Settings.py index 7189497..35e51ae 100644 --- a/src/shellfm/windows/view/utils/Settings.py +++ b/src/shellfm/windows/view/utils/Settings.py @@ -57,6 +57,7 @@ class Settings: subpath = settings["base_of_home"] HIDE_HIDDEN_FILES = True if settings["hide_hidden_files"] == "true" else False + FFMPG_THUMBNLR = FFMPG_THUMBNLR if settings["thumbnailer_path"] == "" else settings["thumbnailer_path"] go_past_home = True if settings["go_past_home"] == "true" else False lock_folder = True if settings["lock_folder"] == "true" else False locked_folders = settings["locked_folders"].split("::::") @@ -79,7 +80,7 @@ class Settings: fpdf = ('.pdf') - # Dire structure check + # Dir structure check if path.isdir(REMUX_FOLDER) == False: os.mkdir(REMUX_FOLDER)