Source code for simvx.ide.panels.file_browser

"""IDE File Browser -- project directory tree sidebar."""

from pathlib import Path
from typing import TYPE_CHECKING

from simvx.core.git_status import GitStatusProvider
from simvx.core.ui.file_browser import FileBrowserPanel as _BaseFileBrowserPanel

if TYPE_CHECKING:
    from ..state import State

__all__ = ["FileBrowserPanel"]

[docs] class FileBrowserPanel(_BaseFileBrowserPanel): """IDE file browser that opens files via goto_requested. Constructs a ``GitStatusProvider`` rooted at ``state.project_root`` when that path exists, wiring ``state.dirty_paths`` so unsaved buffers show as yellow ``Status.MODIFIED_UNSAVED`` dots. Pass ``git_status=`` to override. """ def __init__( self, state: State, *, git_status: GitStatusProvider | None = None, **kwargs, ): if git_status is None and state.project_root: project_root = Path(state.project_root) if project_root.is_dir(): # The provider tolerates corrupt/partial .git directories # (worktree pointers, fresh init with no HEAD, missing git # binary) internally — see GitStatusProvider docs. git_status = GitStatusProvider( project_root, dirty_paths_callback=state.dirty_paths, ) super().__init__( title="Files", show_icons=True, drag_enabled=False, git_status=git_status, **kwargs, ) self.name = "Files" self._state = state # Wire file activation to IDE goto self.file_activated.connect(self._on_file_activated) def _on_file_activated(self, path: str): """Open file in IDE editor via goto_requested.""" self._state.goto_requested.emit(path, 0, 0) # Override _on_item_selected to also match original IDE behaviour # where single-click on a file triggers file_selected + goto_requested def _on_item_activated(self, item): """IDE-compat: single-click on file triggers file_selected and goto. Called from tests that simulate the original IDE item_selected callback. """ if not item.data: return path = item.data.get("path", "") is_dir = item.data.get("is_dir", False) if not is_dir and path: self.file_selected.emit(path) self._state.goto_requested.emit(path, 0, 0)
[docs] def exit_tree(self): """Stop the polling thread when the panel is removed from the tree.""" provider = self.__dict__.get("_git_status") if provider is not None: provider.stop() if hasattr(super(), "exit_tree"): super().exit_tree()