Refactor directory navigation
This commit is contained in:
parent
2fd45b556f
commit
b0375c863e
2 changed files with 59 additions and 62 deletions
lazy_player
|
@ -34,7 +34,7 @@ class MainWindow(Gtk.ApplicationWindow):
|
|||
super().__init__(*args, **kwargs)
|
||||
|
||||
# Directory history stack
|
||||
self.directory_history: list[str] = []
|
||||
self.directory_history: list[Path] = []
|
||||
|
||||
# For overlay text timeout
|
||||
self.overlay_hide_time = 0.0
|
||||
|
@ -151,31 +151,7 @@ class MainWindow(Gtk.ApplicationWindow):
|
|||
file_item = cast(FileItem, selected_item)
|
||||
|
||||
if file_item.file_type == FileType.DIRECTORY:
|
||||
target_path = os.path.abspath(file_item.full_path)
|
||||
|
||||
# Check if we have history and if target is where we came from
|
||||
if self.directory_history and os.path.samefile(
|
||||
os.path.dirname(target_path), self.directory_history[-1]
|
||||
):
|
||||
# Use history instead
|
||||
prev_dir = self.directory_history.pop()
|
||||
current_dir_name = Path(os.getcwd()).name
|
||||
os.chdir(prev_dir)
|
||||
self._populate_file_list()
|
||||
|
||||
# Find and select the directory we came from
|
||||
for i in range(self.list_store.get_n_items()):
|
||||
item = self.list_store.get_item(i)
|
||||
if item and cast(FileItem, item).name == current_dir_name:
|
||||
self.list_view.scroll_to(
|
||||
i, Gtk.ListScrollFlags.SELECT | Gtk.ListScrollFlags.FOCUS, None
|
||||
)
|
||||
break
|
||||
else:
|
||||
# Regular directory navigation
|
||||
self.directory_history.append(os.getcwd())
|
||||
os.chdir(file_item.full_path)
|
||||
self._populate_file_list()
|
||||
self._navigate_to(file_item.full_path)
|
||||
return
|
||||
|
||||
position = file_item.load_attribute("position", 0)
|
||||
|
@ -287,6 +263,46 @@ class MainWindow(Gtk.ApplicationWindow):
|
|||
item.connect("notify::attrs-changed", update_icon)
|
||||
update_icon()
|
||||
|
||||
def _navigate_to(self, path: Path):
|
||||
# Check if we have history and if target is where we came from
|
||||
if self.directory_history:
|
||||
print(path, "vs", self.directory_history[-1])
|
||||
if path == self.directory_history[-1]:
|
||||
print("navigate back")
|
||||
self._navigate_back()
|
||||
return
|
||||
|
||||
print("navigate to", path)
|
||||
# Regular directory navigation
|
||||
self.directory_history.append(Path(os.getcwd()))
|
||||
os.chdir(path)
|
||||
self._populate_file_list()
|
||||
|
||||
def _navigate_back(self):
|
||||
if not self.directory_history:
|
||||
return
|
||||
|
||||
prev_dir = self.directory_history.pop()
|
||||
current_dir = Path(os.getcwd())
|
||||
os.chdir(prev_dir)
|
||||
self._populate_file_list()
|
||||
|
||||
# Find and select the directory we came from
|
||||
for i in range(self.list_store.get_n_items()):
|
||||
item = self.list_store.get_item(i)
|
||||
if not item:
|
||||
continue
|
||||
|
||||
file_item = cast(FileItem, item)
|
||||
|
||||
if current_dir == file_item.full_path:
|
||||
self.list_view.scroll_to(
|
||||
i, Gtk.ListScrollFlags.SELECT | Gtk.ListScrollFlags.FOCUS, None
|
||||
)
|
||||
break
|
||||
|
||||
return True
|
||||
|
||||
def _on_selection_changed(
|
||||
self,
|
||||
selection_model: Gtk.SingleSelection,
|
||||
|
@ -299,7 +315,7 @@ class MainWindow(Gtk.ApplicationWindow):
|
|||
selected_item = selection_model.get_selected_item()
|
||||
if selected_item:
|
||||
file_item = cast(FileItem, selected_item)
|
||||
self.file_info_label.set_text(file_item.full_path)
|
||||
self.file_info_label.set_text(file_item.name)
|
||||
|
||||
def _toggle_play_pause(self) -> None:
|
||||
"""Toggle between play and pause states"""
|
||||
|
@ -396,20 +412,7 @@ class MainWindow(Gtk.ApplicationWindow):
|
|||
return True
|
||||
|
||||
elif keyval == Gdk.keyval_from_name("BackSpace"):
|
||||
if self.directory_history:
|
||||
prev_dir = self.directory_history.pop()
|
||||
current_dir_name = Path(os.getcwd()).name
|
||||
os.chdir(prev_dir)
|
||||
self._populate_file_list()
|
||||
|
||||
# Find and select the directory we came from
|
||||
for i in range(self.list_store.get_n_items()):
|
||||
item = self.list_store.get_item(i)
|
||||
if item and cast(FileItem, item).name == current_dir_name:
|
||||
self.list_view.scroll_to(
|
||||
i, Gtk.ListScrollFlags.SELECT | Gtk.ListScrollFlags.FOCUS, None
|
||||
)
|
||||
break
|
||||
self._navigate_back()
|
||||
return True
|
||||
|
||||
return False
|
||||
|
@ -537,20 +540,15 @@ class MainWindow(Gtk.ApplicationWindow):
|
|||
items: list[FileItem] = []
|
||||
|
||||
# Add parent directory
|
||||
items.append(FileItem("..", FileType.DIRECTORY, "../"))
|
||||
items.append(FileItem("..", FileType.DIRECTORY, Path("..").resolve()))
|
||||
|
||||
with os.scandir(".") as it:
|
||||
for entry in it:
|
||||
if entry.name != ".." and not entry.name.startswith("."):
|
||||
if not entry.name.startswith("."):
|
||||
try:
|
||||
if entry.is_dir():
|
||||
items.append(FileItem(entry.name, FileType.DIRECTORY, entry.name + "/"))
|
||||
else:
|
||||
file_item = FileItem.from_path(entry.name)
|
||||
items.append(file_item)
|
||||
items.append(FileItem.from_path(entry.name))
|
||||
except ValueError:
|
||||
# Skip unsupported file types
|
||||
continue
|
||||
continue # Skip unsupported file types
|
||||
|
||||
# Sort directories first, then files, both alphabetically
|
||||
items.sort(key=lambda x: (x.file_type != FileType.DIRECTORY, x.name.lower()))
|
||||
|
@ -562,7 +560,7 @@ class MainWindow(Gtk.ApplicationWindow):
|
|||
self.list_store.append(item)
|
||||
|
||||
if items:
|
||||
self.file_info_label.set_text(items[0].full_path)
|
||||
self.file_info_label.set_text(items[0].name)
|
||||
|
||||
|
||||
class App(Gtk.Application):
|
||||
|
|
|
@ -2,6 +2,7 @@ from __future__ import annotations
|
|||
|
||||
import os
|
||||
from enum import Enum, auto
|
||||
from pathlib import Path
|
||||
from typing import overload
|
||||
|
||||
import gi
|
||||
|
@ -17,13 +18,13 @@ class FileType(Enum):
|
|||
|
||||
class FileItem(GObject.Object):
|
||||
file_type: FileType
|
||||
full_path: str
|
||||
full_path: Path
|
||||
|
||||
__gtype_name__ = "FileItem"
|
||||
|
||||
attrs_changed = GObject.Property(type=int, default=0)
|
||||
|
||||
def __init__(self, name: str, file_type: FileType, full_path: str):
|
||||
def __init__(self, name: str, file_type: FileType, full_path: Path):
|
||||
super().__init__()
|
||||
self.attrs_changed = 0
|
||||
self.name = name
|
||||
|
@ -31,18 +32,16 @@ class FileItem(GObject.Object):
|
|||
self.full_path = full_path
|
||||
|
||||
@staticmethod
|
||||
def from_path(path: str) -> FileItem:
|
||||
name = os.path.basename(path)
|
||||
if path.endswith("/"):
|
||||
return FileItem(name, FileType.DIRECTORY, path)
|
||||
def from_path(path: str | Path) -> FileItem:
|
||||
full_path = Path(path).resolve()
|
||||
|
||||
parts = name.split(".")
|
||||
suffix = parts[-1].lower() if len(parts) >= 2 else ""
|
||||
if full_path.is_dir():
|
||||
return FileItem(full_path.name, FileType.DIRECTORY, full_path)
|
||||
|
||||
if suffix in ("mkv", "mp4", "avi"):
|
||||
return FileItem(name, FileType.VIDEO, path)
|
||||
if full_path.suffix in (".mkv", ".mp4", ".avi"):
|
||||
return FileItem(full_path.name, FileType.VIDEO, full_path)
|
||||
|
||||
raise ValueError(f"Unsupported file type: {path}")
|
||||
raise ValueError(f"Unsupported file type: {full_path}")
|
||||
|
||||
@overload
|
||||
def load_attribute(self, name: str, dfl: str) -> str: ...
|
||||
|
|
Loading…
Reference in a new issue