diff --git a/dist/renamer-0.6.9-py3-none-any.whl b/dist/renamer-0.6.9-py3-none-any.whl new file mode 100644 index 0000000..9b3d0ba Binary files /dev/null and b/dist/renamer-0.6.9-py3-none-any.whl differ diff --git a/pyproject.toml b/pyproject.toml index 5376431..c14f9c9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "renamer" -version = "0.6.8" +version = "0.6.9" description = "Terminal-based media file renamer and metadata viewer" readme = "README.md" requires-python = ">=3.11" diff --git a/renamer/app.py b/renamer/app.py index 720878e..86f35f5 100644 --- a/renamer/app.py +++ b/renamer/app.py @@ -160,6 +160,31 @@ class RenamerApp(App): self.tree_expanded = False # Sub-levels are collapsed self.set_focus(tree) + def _get_file_icon(self, file_path: Path) -> str: + """Get icon for file based on extension. + + Args: + file_path: Path to the file + + Returns: + Icon character for the file type + """ + ext = file_path.suffix.lower().lstrip('.') + + # File type icons + icons = { + 'mkv': '📹', # Video camera for MKV + 'mk3d': '🎬', # Clapper board for 3D + 'avi': '🎞️', # Film frames for AVI + 'mp4': '📹', # Video camera + 'mov': '📹', # Video camera + 'wmv': '📹', # Video camera + 'webm': '📹', # Video camera + 'm4v': '📹', # Video camera + } + + return icons.get(ext, '📄') # Default to document icon + def build_tree(self, path: Path, node): try: for item in sorted(path.iterdir()): @@ -167,13 +192,18 @@ class RenamerApp(App): if item.is_dir(): if item.name.startswith(".") or item.name == "lost+found": continue - subnode = node.add(escape(item.name), data=item) + # Add folder icon before directory name + label = f"📁 {escape(item.name)}" + subnode = node.add(label, data=item) self.build_tree(item, subnode) elif item.is_file() and item.suffix.lower() in { f".{ext}" for ext in MEDIA_TYPES }: logging.info(f"Adding file to tree: {item.name!r} (full path: {item})") - node.add(escape(item.name), data=item) + # Add file type icon before filename + icon = self._get_file_icon(item) + label = f"{icon} {escape(item.name)}" + node.add(label, data=item) except PermissionError: pass except PermissionError: @@ -452,7 +482,9 @@ By Category:""" node = find_node(tree.root) if node: logging.info(f"Found node for {old_path}, updating to {new_path.name}") - node.label = escape(new_path.name) + # Update label with icon + icon = self._get_file_icon(new_path) + node.label = f"{icon} {escape(new_path.name)}" node.data = new_path logging.info(f"After update: node.data = {node.data}, node.label = {node.label}") # Ensure cursor stays on the renamed file @@ -513,6 +545,10 @@ By Category:""" if parent_node: logging.info(f"Found parent node for {parent_dir}, adding file {file_path.name}") + # Get icon for the file + icon = self._get_file_icon(file_path) + label = f"{icon} {escape(file_path.name)}" + # Add the new file node in alphabetically sorted position new_node = None inserted = False @@ -522,14 +558,14 @@ By Category:""" # Compare filenames for sorting if child.data.name > file_path.name: # Insert before this child - new_node = parent_node.add(escape(file_path.name), data=file_path, before=i) + new_node = parent_node.add(label, data=file_path, before=i) inserted = True logging.info(f"Inserted file before {child.data.name}") break # If not inserted, add at the end if not inserted: - new_node = parent_node.add(escape(file_path.name), data=file_path) + new_node = parent_node.add(label, data=file_path) logging.info(f"Added file at end of directory") # Select the new node and show its details diff --git a/renamer/extractors/extractor.py b/renamer/extractors/extractor.py index 7980592..5922de5 100644 --- a/renamer/extractors/extractor.py +++ b/renamer/extractors/extractor.py @@ -200,6 +200,12 @@ class MediaExtractor: ("Default", "extract_subtitle_tracks"), ], }, + "genres": { + "sources": [ + ("TMDB", "extract_genres"), + ("Default", "extract_genres"), + ], + }, } def get(self, key: str, source: str | None = None): diff --git a/renamer/views/media_panel.py b/renamer/views/media_panel.py index bd76907..ee494c5 100644 --- a/renamer/views/media_panel.py +++ b/renamer/views/media_panel.py @@ -35,6 +35,7 @@ class MediaPanelView: self._props.title("Media Info Summary"), self._props.media_title, self._props.media_year, + self._props.media_genres, self._props.media_duration, self._props.media_file_size, self._props.media_file_extension, @@ -70,6 +71,7 @@ class MediaPanelView: self._props.tmdb_title, self._props.tmdb_original_title, self._props.tmdb_year, + self._props.tmdb_genres, self._props.tmdb_database_info, self._props.tmdb_url, ] diff --git a/renamer/views/media_panel_properties.py b/renamer/views/media_panel_properties.py index 591ea38..7e2e8a6 100644 --- a/renamer/views/media_panel_properties.py +++ b/renamer/views/media_panel_properties.py @@ -122,6 +122,15 @@ class MediaPanelProperties: def tmdb_year(self) -> str: """Get TMDB year formatted with label.""" return self._extractor.get("year", "TMDB") + + @property + @text_decorators.blue() + @conditional_decorators.wrap("Genres: ") + @text_decorators.yellow() + @conditional_decorators.default("") + def tmdb_genres(self) -> str: + """Get TMDB genres formatted with label.""" + return self._extractor.get("genres", "TMDB") @property @text_decorators.blue() @@ -328,7 +337,7 @@ class MediaPanelProperties: return self._extractor.get("movie_db", "Filename") # ============================================================ - # Joined Data Properties + # Media Data Properties # ============================================================ @property @@ -367,6 +376,15 @@ class MediaPanelProperties: """Get selected year formatted with label.""" return self._extractor.get("year") + @property + @text_decorators.blue() + @conditional_decorators.wrap("Genres: ") + @text_decorators.cyan() + @conditional_decorators.default("") + def media_genres(self) -> str: + """Get TMDB genres formatted with label.""" + return self._extractor.get("genres") + @property @text_decorators.blue() @conditional_decorators.wrap("File size: ") diff --git a/uv.lock b/uv.lock index 04c2cee..aed43f0 100644 --- a/uv.lock +++ b/uv.lock @@ -462,7 +462,7 @@ wheels = [ [[package]] name = "renamer" -version = "0.6.8" +version = "0.6.9" source = { editable = "." } dependencies = [ { name = "langcodes" },