mirror of
https://github.com/shadoll/moma.git
synced 2026-08-28 03:27:34 +00:00
feat: Enhance renamer app with help screen, rename confirmation, and special info formatting
This commit is contained in:
+71
-6
@@ -4,16 +4,18 @@ from textual.containers import Horizontal, Container, ScrollableContainer, Verti
|
||||
from pathlib import Path
|
||||
import threading
|
||||
import time
|
||||
import concurrent.futures
|
||||
|
||||
from .constants import MEDIA_TYPES
|
||||
from .screens import OpenScreen
|
||||
from .screens import OpenScreen, HelpScreen, RenameConfirmScreen
|
||||
from .extractor import MediaExtractor
|
||||
from .formatters.media_formatter import MediaFormatter
|
||||
from .formatters.proposed_name_formatter import ProposedNameFormatter
|
||||
from .formatters.text_formatter import TextFormatter
|
||||
|
||||
|
||||
VERSION = "0.2.0"
|
||||
|
||||
|
||||
class RenamerApp(App):
|
||||
CSS = """
|
||||
#left {
|
||||
@@ -30,12 +32,16 @@ class RenamerApp(App):
|
||||
("q", "quit", "Quit"),
|
||||
("o", "open", "Open directory"),
|
||||
("s", "scan", "Scan"),
|
||||
("r", "refresh", "Refresh"),
|
||||
("f", "refresh", "Refresh"),
|
||||
("r", "rename", "Rename"),
|
||||
("p", "expand", "Toggle Tree"),
|
||||
("h", "help", "Help"),
|
||||
]
|
||||
|
||||
def __init__(self, scan_dir):
|
||||
super().__init__()
|
||||
self.scan_dir = Path(scan_dir) if scan_dir else None
|
||||
self.tree_expanded = False
|
||||
|
||||
def compose(self) -> ComposeResult:
|
||||
with Horizontal():
|
||||
@@ -57,14 +63,15 @@ class RenamerApp(App):
|
||||
self.scan_files()
|
||||
|
||||
def scan_files(self):
|
||||
if not self.scan_dir.exists() or not self.scan_dir.is_dir():
|
||||
if not self.scan_dir or not self.scan_dir.exists() or not self.scan_dir.is_dir():
|
||||
details = self.query_one("#details", Static)
|
||||
details.update("Error: Directory does not exist or is not a directory")
|
||||
return
|
||||
tree = self.query_one("#file_tree", Tree)
|
||||
tree.clear()
|
||||
self.build_tree(self.scan_dir, tree.root)
|
||||
tree.root.expand()
|
||||
tree.root.expand() # Expand root level
|
||||
self.tree_expanded = False # Sub-levels are collapsed
|
||||
self.set_focus(tree)
|
||||
|
||||
def build_tree(self, path: Path, node):
|
||||
@@ -122,7 +129,7 @@ class RenamerApp(App):
|
||||
self.call_later(
|
||||
self._update_details,
|
||||
MediaFormatter(extractor).file_info_panel(),
|
||||
ProposedNameFormatter(extractor).rename_line_formatted(),
|
||||
ProposedNameFormatter(extractor).rename_line_formatted(file_path),
|
||||
)
|
||||
except Exception as e:
|
||||
self.call_later(
|
||||
@@ -158,6 +165,64 @@ class RenamerApp(App):
|
||||
target=self._extract_and_show_details, args=(node.data,)
|
||||
).start()
|
||||
|
||||
async def action_help(self):
|
||||
self.push_screen(HelpScreen())
|
||||
|
||||
async def action_rename(self):
|
||||
tree = self.query_one("#file_tree", Tree)
|
||||
node = tree.cursor_node
|
||||
if node and node.data and isinstance(node.data, Path) and node.data.is_file():
|
||||
# Get the proposed name from the extractor
|
||||
extractor = MediaExtractor(node.data)
|
||||
proposed_formatter = ProposedNameFormatter(extractor)
|
||||
new_name = str(proposed_formatter)
|
||||
if new_name and new_name != node.data.name:
|
||||
self.push_screen(RenameConfirmScreen(node.data, new_name))
|
||||
|
||||
async def action_expand(self):
|
||||
tree = self.query_one("#file_tree", Tree)
|
||||
if self.tree_expanded:
|
||||
# Collapse all sub-levels, keep root expanded
|
||||
def collapse_sub(node):
|
||||
if node != tree.root:
|
||||
node.collapse()
|
||||
for child in node.children:
|
||||
collapse_sub(child)
|
||||
collapse_sub(tree.root)
|
||||
self.tree_expanded = False
|
||||
else:
|
||||
# Expand all
|
||||
def expand_all(node):
|
||||
node.expand()
|
||||
for child in node.children:
|
||||
expand_all(child)
|
||||
expand_all(tree.root)
|
||||
self.tree_expanded = True
|
||||
|
||||
def update_renamed_file(self, old_path: Path, new_path: Path):
|
||||
"""Update the tree node for a renamed file."""
|
||||
tree = self.query_one("#file_tree", Tree)
|
||||
|
||||
def find_node(node):
|
||||
if node.data == old_path:
|
||||
return node
|
||||
for child in node.children:
|
||||
found = find_node(child)
|
||||
if found:
|
||||
return found
|
||||
return None
|
||||
|
||||
node = find_node(tree.root)
|
||||
if node:
|
||||
node.label = new_path.name
|
||||
node.data = new_path
|
||||
# If this node is currently selected, refresh the details
|
||||
if tree.cursor_node == node:
|
||||
self._start_loading_animation()
|
||||
threading.Thread(
|
||||
target=self._extract_and_show_details, args=(new_path,)
|
||||
).start()
|
||||
|
||||
def on_key(self, event):
|
||||
if event.key == "right":
|
||||
tree = self.query_one("#file_tree", Tree)
|
||||
|
||||
Reference in New Issue
Block a user