Moved file exists functionality to class and new glade file
This commit is contained in:
@@ -22,6 +22,13 @@ def daemon_threaded_wrapper(fn):
|
||||
threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=True).start()
|
||||
return wrapper
|
||||
|
||||
def sizeof_fmt_def(num, suffix="B"):
|
||||
for unit in ["", "K", "M", "G", "T", "Pi", "Ei", "Zi"]:
|
||||
if abs(num) < 1024.0:
|
||||
return f"{num:3.1f} {unit}{suffix}"
|
||||
num /= 1024.0
|
||||
return f"{num:.1f} Yi{suffix}"
|
||||
|
||||
|
||||
|
||||
# NOTE: Just reminding myself we can add to builtins two different ways...
|
||||
@@ -34,4 +41,5 @@ builtins.endpoint_registry = EndpointRegistry()
|
||||
|
||||
builtins.threaded = threaded_wrapper
|
||||
builtins.daemon_threaded = daemon_threaded_wrapper
|
||||
builtins.sizeof_fmt = sizeof_fmt_def
|
||||
builtins.event_sleep_time = 0.05
|
||||
|
@@ -12,12 +12,14 @@ from gi.repository import Gtk
|
||||
from gi.repository import GLib
|
||||
|
||||
# Application imports
|
||||
from widgets.context_menu_widget import ContextMenuWidget
|
||||
from widgets.rename_widget import RenameWidget
|
||||
from widgets.file_exists_widget import FileExistsWidget
|
||||
from widgets.context_menu_widget import ContextMenuWidget
|
||||
from shellfm.windows.controller import WindowController
|
||||
from plugins.plugins_controller import PluginsController
|
||||
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
class State:
|
||||
wid: int = None
|
||||
@@ -40,6 +42,7 @@ class Controller_Data:
|
||||
self.keybindings = settings.get_keybindings()
|
||||
|
||||
RenameWidget()
|
||||
FileExistsWidget()
|
||||
ContextMenuWidget()
|
||||
|
||||
self.fm_controller = WindowController()
|
||||
|
@@ -17,35 +17,6 @@ class ShowHideMixin:
|
||||
def stop_file_searching(self, widget=None, eve=None):
|
||||
self.is_searching = False
|
||||
|
||||
def show_exists_page(self, widget=None, eve=None):
|
||||
response = self.file_exists_dialog.run()
|
||||
self.file_exists_dialog.hide()
|
||||
|
||||
if response == Gtk.ResponseType.OK:
|
||||
return "rename"
|
||||
if response == Gtk.ResponseType.ACCEPT:
|
||||
return "rename_auto"
|
||||
if response == Gtk.ResponseType.CLOSE:
|
||||
return "rename_auto_all"
|
||||
if response == Gtk.ResponseType.YES:
|
||||
return "overwrite"
|
||||
if response == Gtk.ResponseType.APPLY:
|
||||
return "overwrite_all"
|
||||
if response == Gtk.ResponseType.NO:
|
||||
return "skip"
|
||||
if response == Gtk.ResponseType.REJECT:
|
||||
return "skip_all"
|
||||
|
||||
def hide_exists_page_rename(self, widget=None, eve=None):
|
||||
self.file_exists_dialog.response(Gtk.ResponseType.OK)
|
||||
|
||||
def hide_exists_page_auto_rename(self, widget=None, eve=None):
|
||||
self.file_exists_dialog.response(Gtk.ResponseType.ACCEPT)
|
||||
|
||||
def hide_exists_page_auto_rename_all(self, widget=None, eve=None):
|
||||
self.file_exists_dialog.response(Gtk.ResponseType.CLOSE)
|
||||
|
||||
|
||||
def show_about_page(self, widget=None, eve=None):
|
||||
about_page = self.builder.get_object("about_page")
|
||||
response = about_page.run()
|
||||
|
@@ -20,13 +20,6 @@ from widgets.io_widget import IOWidget
|
||||
class FileActionSignalsMixin:
|
||||
"""docstring for FileActionSignalsMixin"""
|
||||
|
||||
def sizeof_fmt(self, num, suffix="B"):
|
||||
for unit in ["", "K", "M", "G", "T", "Pi", "Ei", "Zi"]:
|
||||
if abs(num) < 1024.0:
|
||||
return f"{num:3.1f} {unit}{suffix}"
|
||||
num /= 1024.0
|
||||
return f"{num:.1f} Yi{suffix}"
|
||||
|
||||
def get_dir_size(self, sdir):
|
||||
"""Get the size of a directory. Based on code found online."""
|
||||
size = os.path.getsize(sdir)
|
||||
@@ -274,8 +267,8 @@ class FileActionSignalsMixin:
|
||||
|
||||
if _file.query_exists():
|
||||
if not overwrite_all and not rename_auto_all:
|
||||
self.setup_exists_data(file, _file)
|
||||
response = self.show_exists_page()
|
||||
event_system.emit("setup_exists_data", (file, _file))
|
||||
response = event_system.emit_and_await("show_exists_page")
|
||||
|
||||
if response == "overwrite_all":
|
||||
overwrite_all = True
|
||||
@@ -359,47 +352,6 @@ class FileActionSignalsMixin:
|
||||
|
||||
self.exists_file_rename_bttn.set_sensitive(False)
|
||||
|
||||
|
||||
def setup_exists_data(self, from_file, to_file):
|
||||
from_info = from_file.query_info("standard::*,time::modified", 0, cancellable=None)
|
||||
to_info = to_file.query_info("standard::*,time::modified", 0, cancellable=None)
|
||||
exists_file_diff_from = self.builder.get_object("exists_file_diff_from")
|
||||
exists_file_diff_to = self.builder.get_object("exists_file_diff_to")
|
||||
exists_file_from = self.builder.get_object("exists_file_from")
|
||||
exists_file_to = self.builder.get_object("exists_file_to")
|
||||
from_date = from_info.get_modification_date_time()
|
||||
to_date = to_info.get_modification_date_time()
|
||||
from_size = from_info.get_size()
|
||||
to_size = to_info.get_size()
|
||||
|
||||
exists_file_from.set_label(from_file.get_parent().get_path())
|
||||
exists_file_to.set_label(to_file.get_parent().get_path())
|
||||
self.exists_file_label.set_label(to_file.get_basename())
|
||||
self.exists_file_field.set_text(to_file.get_basename())
|
||||
|
||||
# Returns: -1, 0 or 1 if dt1 is less than, equal to or greater than dt2.
|
||||
age = GLib.DateTime.compare(from_date, to_date)
|
||||
age_text = "( same time )"
|
||||
if age == -1:
|
||||
age_text = "older"
|
||||
if age == 1:
|
||||
age_text = "newer"
|
||||
|
||||
size_text = "( same size )"
|
||||
if from_size < to_size:
|
||||
size_text = "smaller"
|
||||
if from_size > to_size:
|
||||
size_text = "larger"
|
||||
|
||||
from_label_text = f"{age_text} & {size_text}"
|
||||
if age_text != "( same time )" or size_text != "( same size )":
|
||||
from_label_text = f"{from_date.format('%F %R')} {self.sizeof_fmt(from_size)} ( {from_size} bytes ) ( {age_text} & {size_text} )"
|
||||
to_label_text = f"{to_date.format('%F %R')} {self.sizeof_fmt(to_size)} ( {to_size} bytes )"
|
||||
|
||||
exists_file_diff_from.set_text(from_label_text)
|
||||
exists_file_diff_to.set_text(to_label_text)
|
||||
|
||||
|
||||
def rename_proc(self, gio_file):
|
||||
full_path = gio_file.get_path()
|
||||
base_path = gio_file.get_parent().get_path()
|
||||
@@ -427,16 +379,3 @@ class FileActionSignalsMixin:
|
||||
i += 1
|
||||
|
||||
return target
|
||||
|
||||
|
||||
def exists_rename_field_changed(self, widget):
|
||||
nfile_name = widget.get_text().strip()
|
||||
ofile_name = self.exists_file_label.get_label()
|
||||
|
||||
if nfile_name:
|
||||
if nfile_name == ofile_name:
|
||||
self.exists_file_rename_bttn.set_sensitive(False)
|
||||
else:
|
||||
self.exists_file_rename_bttn.set_sensitive(True)
|
||||
else:
|
||||
self.exists_file_rename_bttn.set_sensitive(False)
|
||||
|
@@ -90,8 +90,8 @@ class WindowMixin(TabMixin):
|
||||
current_directory = tab.get_current_directory()
|
||||
path_file = Gio.File.new_for_path(current_directory)
|
||||
mount_file = path_file.query_filesystem_info(attributes="filesystem::*", cancellable=None)
|
||||
formatted_mount_free = self.sizeof_fmt( int(mount_file.get_attribute_as_string("filesystem::free")) )
|
||||
formatted_mount_size = self.sizeof_fmt( int(mount_file.get_attribute_as_string("filesystem::size")) )
|
||||
formatted_mount_free = sizeof_fmt( int(mount_file.get_attribute_as_string("filesystem::free")) )
|
||||
formatted_mount_size = sizeof_fmt( int(mount_file.get_attribute_as_string("filesystem::size")) )
|
||||
|
||||
# NOTE: Hides empty trash and other desired buttons based on context.
|
||||
if self.trash_files_path == current_directory:
|
||||
@@ -117,7 +117,7 @@ class WindowMixin(TabMixin):
|
||||
print(repr(e))
|
||||
|
||||
|
||||
formatted_size = self.sizeof_fmt(combined_size)
|
||||
formatted_size = sizeof_fmt(combined_size)
|
||||
if tab.is_hiding_hidden():
|
||||
self.bottom_path_label.set_label(f" {len(uris)} / {tab.get_files_count()} ({formatted_size})")
|
||||
else:
|
||||
|
@@ -28,3 +28,15 @@ class EventSystem:
|
||||
fn(data)
|
||||
else:
|
||||
fn()
|
||||
|
||||
# NOTE: Should be used when signal has only one listener and vis-a-vis
|
||||
def emit_and_await(self, event_type, data = None):
|
||||
if event_type in self.subscribers:
|
||||
for fn in self.subscribers[event_type]:
|
||||
if data:
|
||||
if hasattr(data, '__iter__') and not type(data) is str:
|
||||
return fn(*data)
|
||||
else:
|
||||
return fn(data)
|
||||
else:
|
||||
return fn()
|
||||
|
@@ -0,0 +1,141 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import inspect
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import GLib
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
class FileExistsWidget:
|
||||
"""docstring for FileExistsWidget."""
|
||||
|
||||
def __init__(self):
|
||||
super(FileExistsWidget, self).__init__()
|
||||
_GLADE_FILE = f"{settings.get_ui_widgets_path()}/file_exists_ui.glade"
|
||||
builder = settings.get_builder()
|
||||
self._builder = Gtk.Builder()
|
||||
|
||||
self._builder.add_from_file(_GLADE_FILE)
|
||||
|
||||
self.file_exists_dialog = self._builder.get_object("file_exists_dialog")
|
||||
self._exists_file_label = self._builder.get_object("exists_file_label")
|
||||
self._exists_file_diff_from = self._builder.get_object("exists_file_diff_from")
|
||||
self._exists_file_diff_to = self._builder.get_object("exists_file_diff_to")
|
||||
self._exists_file_field = self._builder.get_object("exists_file_field")
|
||||
self._exists_file_from = self._builder.get_object("exists_file_from")
|
||||
self._exists_file_to = self._builder.get_object("exists_file_to")
|
||||
self._exists_file_rename_bttn = self._builder.get_object("exists_file_rename_bttn")
|
||||
|
||||
builder.expose_object(f"file_exists_dialog", self.file_exists_dialog)
|
||||
builder.expose_object(f"exists_file_diff_from", self._exists_file_diff_from)
|
||||
builder.expose_object(f"exists_file_diff_to", self._exists_file_diff_to)
|
||||
builder.expose_object(f"exists_file_field", self._exists_file_field)
|
||||
builder.expose_object(f"exists_file_rename_bttn", self._exists_file_rename_bttn)
|
||||
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._load_widgets()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
...
|
||||
|
||||
def _setup_signals(self):
|
||||
event_system.subscribe("setup_exists_data", self.setup_exists_data)
|
||||
event_system.subscribe("show_exists_page", self.show_exists_page)
|
||||
|
||||
|
||||
classes = [self]
|
||||
handlers = {}
|
||||
for c in classes:
|
||||
methods = None
|
||||
try:
|
||||
methods = inspect.getmembers(c, predicate=inspect.ismethod)
|
||||
handlers.update(methods)
|
||||
except Exception as e:
|
||||
print(repr(e))
|
||||
|
||||
self._builder.connect_signals(handlers)
|
||||
|
||||
def _load_widgets(self):
|
||||
...
|
||||
|
||||
def show_exists_page(self, widget=None, eve=None):
|
||||
response = self.file_exists_dialog.run()
|
||||
self.file_exists_dialog.hide()
|
||||
|
||||
if response == Gtk.ResponseType.OK:
|
||||
return "rename"
|
||||
if response == Gtk.ResponseType.ACCEPT:
|
||||
return "rename_auto"
|
||||
if response == Gtk.ResponseType.CLOSE:
|
||||
return "rename_auto_all"
|
||||
if response == Gtk.ResponseType.YES:
|
||||
return "overwrite"
|
||||
if response == Gtk.ResponseType.APPLY:
|
||||
return "overwrite_all"
|
||||
if response == Gtk.ResponseType.NO:
|
||||
return "skip"
|
||||
if response == Gtk.ResponseType.REJECT:
|
||||
return "skip_all"
|
||||
|
||||
def hide_exists_page_rename(self, widget=None, eve=None):
|
||||
self.file_exists_dialog.response(Gtk.ResponseType.OK)
|
||||
|
||||
def hide_exists_page_auto_rename(self, widget=None, eve=None):
|
||||
self.file_exists_dialog.response(Gtk.ResponseType.ACCEPT)
|
||||
|
||||
def hide_exists_page_auto_rename_all(self, widget=None, eve=None):
|
||||
self.file_exists_dialog.response(Gtk.ResponseType.CLOSE)
|
||||
|
||||
def setup_exists_data(self, from_file, to_file):
|
||||
from_info = from_file.query_info("standard::*,time::modified", 0, cancellable=None)
|
||||
to_info = to_file.query_info("standard::*,time::modified", 0, cancellable=None)
|
||||
from_date = from_info.get_modification_date_time()
|
||||
to_date = to_info.get_modification_date_time()
|
||||
from_size = from_info.get_size()
|
||||
to_size = to_info.get_size()
|
||||
|
||||
self._exists_file_from.set_label(from_file.get_parent().get_path())
|
||||
self._exists_file_to.set_label(to_file.get_parent().get_path())
|
||||
self._exists_file_label.set_label(to_file.get_basename())
|
||||
self._exists_file_field.set_text(to_file.get_basename())
|
||||
|
||||
# Returns: -1, 0 or 1 if dt1 is less than, equal to or greater than dt2.
|
||||
age = GLib.DateTime.compare(from_date, to_date)
|
||||
age_text = "( same time )"
|
||||
if age == -1:
|
||||
age_text = "older"
|
||||
if age == 1:
|
||||
age_text = "newer"
|
||||
|
||||
size_text = "( same size )"
|
||||
if from_size < to_size:
|
||||
size_text = "smaller"
|
||||
if from_size > to_size:
|
||||
size_text = "larger"
|
||||
|
||||
from_label_text = f"{age_text} & {size_text}"
|
||||
if age_text != "( same time )" or size_text != "( same size )":
|
||||
from_label_text = f"{from_date.format('%F %R')} {sizeof_fmt(from_size)} ( {from_size} bytes ) ( {age_text} & {size_text} )"
|
||||
to_label_text = f"{to_date.format('%F %R')} {sizeof_fmt(to_size)} ( {to_size} bytes )"
|
||||
|
||||
self._exists_file_diff_from.set_text(from_label_text)
|
||||
self._exists_file_diff_to.set_text(to_label_text)
|
||||
|
||||
|
||||
def exists_rename_field_changed(self, widget):
|
||||
nfile_name = widget.get_text().strip()
|
||||
ofile_name = self._exists_file_label.get_label()
|
||||
|
||||
if nfile_name:
|
||||
if nfile_name == ofile_name:
|
||||
self._exists_file_rename_bttn.set_sensitive(False)
|
||||
else:
|
||||
self._exists_file_rename_bttn.set_sensitive(True)
|
||||
else:
|
||||
self._exists_file_rename_bttn.set_sensitive(False)
|
@@ -4,7 +4,6 @@
|
||||
import inspect
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
gi.require_version('Gdk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import Gdk
|
||||
|
Reference in New Issue
Block a user