Created directory watch events, finished cut, copy, delete actions
This commit is contained in:
		@@ -22,6 +22,8 @@ class View(Settings, FileHandler, Launcher, Icon, Path):
 | 
			
		||||
        self.id_length   = 10
 | 
			
		||||
 | 
			
		||||
        self.id          = ""
 | 
			
		||||
        self.wid         = None
 | 
			
		||||
        self.dir_watcher = None
 | 
			
		||||
        self.hide_hidden = self.HIDE_HIDDEN_FILES
 | 
			
		||||
        self.files       = []
 | 
			
		||||
        self.dirs        = []
 | 
			
		||||
@@ -45,6 +47,18 @@ class View(Settings, FileHandler, 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      = []
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,6 @@ from .mixins import *
 | 
			
		||||
from shellfm import WindowController
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def threaded(fn):
 | 
			
		||||
    def wrapper(*args, **kwargs):
 | 
			
		||||
        threading.Thread(target=fn, args=args, kwargs=kwargs).start()
 | 
			
		||||
@@ -98,14 +97,12 @@ class Signals(PaneMixin, WindowMixin):
 | 
			
		||||
            if "alt" in keyname:
 | 
			
		||||
                self.altDown = True
 | 
			
		||||
 | 
			
		||||
    # NOTE: Yes, this should actually be mapped to some key
 | 
			
		||||
    #       controller setting file or something. Sue me.
 | 
			
		||||
    # NOTE: Yes, this should actually be mapped to some key controller setting
 | 
			
		||||
    #       file or something. Sue me.
 | 
			
		||||
    def global_key_release_controller(self, eve, user_data):
 | 
			
		||||
        keyname = Gdk.keyval_name(user_data.keyval).lower()
 | 
			
		||||
        if debug:
 | 
			
		||||
            print(f"global_key_release_controller > key > {keyname}")
 | 
			
		||||
        print(f"global_key_release_controller > key > {keyname}")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        if "control" in keyname or "alt" in keyname or "shift" in keyname:
 | 
			
		||||
            if "control" in keyname:
 | 
			
		||||
@@ -145,6 +142,9 @@ class Signals(PaneMixin, WindowMixin):
 | 
			
		||||
            dir      = view.get_current_directory()
 | 
			
		||||
            self.execute("terminator", dir)
 | 
			
		||||
 | 
			
		||||
        if keyname == "delete":
 | 
			
		||||
            self.trash_files()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def execute(self, option, start_dir=os.getenv("HOME")):
 | 
			
		||||
        DEVNULL = open(os.devnull, 'w')
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,8 @@
 | 
			
		||||
# Python imports
 | 
			
		||||
 | 
			
		||||
# Lib imports
 | 
			
		||||
from gi.repository import GObject, Gio
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Application imports
 | 
			
		||||
from . import WidgetMixin
 | 
			
		||||
@@ -15,6 +17,7 @@ class TabMixin(WidgetMixin):
 | 
			
		||||
        view        = self.window_controller.add_view_for_window_by_nickname(f"window_{wid}")
 | 
			
		||||
        view.logger = self.logger
 | 
			
		||||
 | 
			
		||||
        view.set_wid(wid)
 | 
			
		||||
        if path: view.set_path(path)
 | 
			
		||||
 | 
			
		||||
        tab           = self.create_tab_widget(view)
 | 
			
		||||
@@ -30,6 +33,42 @@ class TabMixin(WidgetMixin):
 | 
			
		||||
        notebook.set_tab_reorderable(scroll, True)
 | 
			
		||||
        self.load_store(view, store)
 | 
			
		||||
        self.set_window_title()
 | 
			
		||||
        self.set_file_watcher(view)
 | 
			
		||||
 | 
			
		||||
    def set_file_watcher(self, view):
 | 
			
		||||
        if view.get_dir_watcher():
 | 
			
		||||
            watcher = view.get_dir_watcher()
 | 
			
		||||
            watcher.cancel()
 | 
			
		||||
            if debug:
 | 
			
		||||
                print(f"Watcher Is Cancelled:  {watcher.is_cancelled()}")
 | 
			
		||||
 | 
			
		||||
        dir_watcher  = Gio.File.new_for_path(view.get_current_directory()) \
 | 
			
		||||
                                .monitor_directory(Gio.FileMonitorFlags.WATCH_MOVES,
 | 
			
		||||
                                                    Gio.Cancellable()
 | 
			
		||||
                                                    )
 | 
			
		||||
 | 
			
		||||
        wid = view.get_wid()
 | 
			
		||||
        tid = view.get_tab_id()
 | 
			
		||||
        dir_watcher.connect("changed", self.dir_watch_updates, (f"{wid}|{tid}",))
 | 
			
		||||
        view.set_dir_watcher(dir_watcher)
 | 
			
		||||
 | 
			
		||||
    def dir_watch_updates(self, file_monitor, file, other_file=None, eve_type=None, data=None):
 | 
			
		||||
        if eve_type ==  Gio.FileMonitorEvent.CREATED or \
 | 
			
		||||
            eve_type ==  Gio.FileMonitorEvent.DELETED or \
 | 
			
		||||
            eve_type == Gio.FileMonitorEvent.RENAMED or \
 | 
			
		||||
            eve_type == Gio.FileMonitorEvent.MOVED_IN or \
 | 
			
		||||
            eve_type == Gio.FileMonitorEvent.MOVED_OUT:
 | 
			
		||||
                wid, tid  = data[0].split("|")
 | 
			
		||||
                notebook  = self.builder.get_object(f"window_{wid}")
 | 
			
		||||
                view      = self.get_fm_window(wid).get_view_by_id(tid)
 | 
			
		||||
                iconview  = self.builder.get_object(f"{wid}|{tid}|iconview")
 | 
			
		||||
                store     = iconview.get_model()
 | 
			
		||||
                _store, tab_label = self.get_store_and_label_from_notebook(notebook, f"{wid}|{tid}")
 | 
			
		||||
 | 
			
		||||
                view.load_directory()
 | 
			
		||||
                self.load_store(view, store)
 | 
			
		||||
                tab_label.set_label(view.get_end_of_path())
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def close_tab(self, button, eve=None):
 | 
			
		||||
        notebook = button.get_parent().get_parent()
 | 
			
		||||
@@ -37,6 +76,9 @@ class TabMixin(WidgetMixin):
 | 
			
		||||
        wid      = int(notebook.get_name()[-1])
 | 
			
		||||
        scroll   = self.builder.get_object(f"{wid}|{tid}")
 | 
			
		||||
        page     = notebook.page_num(scroll)
 | 
			
		||||
        view     = self.get_fm_window(wid).get_view_by_id(tid)
 | 
			
		||||
        watcher  = view.get_dir_watcher()
 | 
			
		||||
        watcher.cancel()
 | 
			
		||||
 | 
			
		||||
        self.get_fm_window(wid).delete_view_by_id(tid)
 | 
			
		||||
        notebook.remove_page(page)
 | 
			
		||||
@@ -95,6 +137,8 @@ class TabMixin(WidgetMixin):
 | 
			
		||||
        self.set_path_text(wid, tid)
 | 
			
		||||
        tab_label.set_label(view.get_end_of_path())
 | 
			
		||||
        self.set_window_title()
 | 
			
		||||
        self.set_file_watcher(view)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def keyboard_close_tab(self):
 | 
			
		||||
        wid, tid  = self.window_controller.get_active_data()
 | 
			
		||||
@@ -122,13 +166,6 @@ class TabMixin(WidgetMixin):
 | 
			
		||||
        elif data == None:                   # Save button 'event'
 | 
			
		||||
            view.update_file(nFile)
 | 
			
		||||
 | 
			
		||||
    def delete_file(self):
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def move_file(self, view, fFile, tFile):
 | 
			
		||||
        view.move_file(fFile.replace("file://", ""), tFile)
 | 
			
		||||
 | 
			
		||||
    def menu_bar_copy(self, widget, eve):
 | 
			
		||||
        self.copy_file()
 | 
			
		||||
 | 
			
		||||
@@ -147,7 +184,58 @@ class TabMixin(WidgetMixin):
 | 
			
		||||
        self.to_cut_files = uris
 | 
			
		||||
 | 
			
		||||
    def paste_files(self):
 | 
			
		||||
        if len(self.to_copy_files):
 | 
			
		||||
            pass
 | 
			
		||||
        wid, tid  = self.window_controller.get_active_data()
 | 
			
		||||
        view      = self.get_fm_window(wid).get_view_by_id(tid)
 | 
			
		||||
        to_path   = f"{view.get_current_directory()}"
 | 
			
		||||
 | 
			
		||||
        if len(self.to_copy_files) > 0:
 | 
			
		||||
            self.handle_file(self.to_copy_files, "copy", to_path)
 | 
			
		||||
        else:
 | 
			
		||||
            pass
 | 
			
		||||
            self.handle_file(self.to_cut_files, "move", to_path)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def move_file(self, view, fFile, tFile):
 | 
			
		||||
        self.handle_file([fFile], "move", tFile)
 | 
			
		||||
 | 
			
		||||
    def delete_files(self):
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    def trash_files(self):
 | 
			
		||||
        wid, tid  = self.window_controller.get_active_data()
 | 
			
		||||
        view      = self.get_fm_window(wid).get_view_by_id(tid)
 | 
			
		||||
        iconview  = self.builder.get_object(f"{wid}|{tid}|iconview")
 | 
			
		||||
        store     = iconview.get_model()
 | 
			
		||||
        uris      = self.format_to_uris(store, wid, tid, self.selected_files)
 | 
			
		||||
        self.handle_file(uris, "trash")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    # NOTE: Gio moves files by generating the target file path with name in it
 | 
			
		||||
    #       We can't just give a base target directory and run with it.
 | 
			
		||||
    #       Also, the display name is UTF-8 safe and meant for displaying in GUIs
 | 
			
		||||
    def handle_file(self, paths, action, base_dir=None):
 | 
			
		||||
        paths  = self.preprocess_paths(paths)
 | 
			
		||||
        target = None
 | 
			
		||||
 | 
			
		||||
        for path in paths:
 | 
			
		||||
            try:
 | 
			
		||||
                f = Gio.File.new_for_uri(path)
 | 
			
		||||
                if base_dir:
 | 
			
		||||
                    info    = f.query_info("standard::display-name", 0, cancellable=None)
 | 
			
		||||
                    _target = f"file://{base_dir}/{info.get_display_name()}"
 | 
			
		||||
                    target  = Gio.File.new_for_uri(_target)
 | 
			
		||||
 | 
			
		||||
                if action == "trash":
 | 
			
		||||
                    f.trash(cancellable=None)
 | 
			
		||||
                if action == "copy":
 | 
			
		||||
                    f.copy(target, flags=Gio.FileCopyFlags.OVERWRITE, cancellable=None)
 | 
			
		||||
                if action == "move":
 | 
			
		||||
                    f.move(target, flags=Gio.FileCopyFlags.OVERWRITE, cancellable=None)
 | 
			
		||||
            except GObject.GError as e:
 | 
			
		||||
                raise OSError(e.message)
 | 
			
		||||
 | 
			
		||||
    def preprocess_paths(self, paths):
 | 
			
		||||
        if not isinstance(paths, list):
 | 
			
		||||
            paths = [paths]
 | 
			
		||||
        # Convert items such as pathlib paths to strings
 | 
			
		||||
        paths = [path.__fspath__() if hasattr(path, "__fspath__") else path for path in paths]
 | 
			
		||||
        return paths
 | 
			
		||||
 
 | 
			
		||||
@@ -114,6 +114,7 @@ class WindowMixin(TabMixin):
 | 
			
		||||
                self.load_store(view, model)
 | 
			
		||||
                tab_label.set_label(view.get_end_of_path())
 | 
			
		||||
                path_entry.set_text(view.get_current_directory())
 | 
			
		||||
                self.set_file_watcher(view)
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            print(repr(e))
 | 
			
		||||
 | 
			
		||||
@@ -152,9 +153,5 @@ class WindowMixin(TabMixin):
 | 
			
		||||
                        print(f"URI:  {uri}")
 | 
			
		||||
                    self.move_file(view, uri, dest)
 | 
			
		||||
 | 
			
		||||
                # Reloads new directory
 | 
			
		||||
                view.load_directory()
 | 
			
		||||
                self.load_store(view, store)
 | 
			
		||||
 | 
			
		||||
    def create_new_view_notebook(self, widget=None, wid=None, path=None):
 | 
			
		||||
        self.create_tab(wid, path)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user