PyExplorer/src/IO/UI.py
2026-07-02 19:32:29 +02:00

78 lines
2.5 KiB
Python

from __future__ import annotations
import stat
from typing import TYPE_CHECKING
import curses
from ..items.Symlink import Symlink
from ..items.AItems import AItem
if TYPE_CHECKING:
from .App import App
class UI:
def __init__(self, app: App):
self._app = app
HEADER_ROWS = 2
ERROR_COLOR = 5
def _get_attr(self, item: any, index: int) -> str:
attr = curses.color_pair(item.color_pair)
if index == self.app.navigator.cursor.pos:
attr |= curses.A_REVERSE
return attr
def render(self, stdscr: curses.window) -> None:
stdscr.erase()
height, width = stdscr.getmaxyx()
navigator = self.app.navigator
stdscr.addstr(0, 0, str(navigator.history[-1])[:width - 1])
if navigator.error:
stdscr.addstr(1, 0, navigator.error[:width - 1],
curses.color_pair(self.ERROR_COLOR))
items = navigator.items
available = max(0, height - self.HEADER_ROWS)
for index in range(min(available, len(items))):
item = items[index]
self._render_item(stdscr, item, index, index + self.HEADER_ROWS, width)
SIZE_UNITS = ("", "K", "M", "G", "T", "P")
@staticmethod
def _format_size(size: int) -> str:
value = float(size)
for unit in UI.SIZE_UNITS:
if value < 1024:
return str(int(value)) if unit == "" else f"{value:.1f}{unit}"
value /= 1024
return f"{value:.1f}E"
ARROW = " -> "
ARROW_LEN = len(ARROW)
def _render_item(self, stdscr: curses.window, item: AItem, index: int,
row: int, width: int) -> None:
name, size, perm = item.fields()
name_len = len(name)
col_width = int(width / 3)
attr = self._get_attr(item, index)
stdscr.addstr(row, 0, name.ljust(col_width), attr)
if type(item) is Symlink:
attr_arrow = curses.color_pair(0)
attr_target = curses.color_pair(Symlink.target_color(item.point_to))
if index == self.app.navigator.cursor.pos:
attr_arrow |= curses.A_REVERSE
attr_target |= curses.A_REVERSE
stdscr.addstr(row, name_len, self.ARROW, attr_arrow)
stdscr.addstr(row, name_len + self.ARROW_LEN, str(item.point_to), attr_target)
stdscr.addstr(row, col_width, self._format_size(size).ljust(col_width * 2), attr)
stdscr.addstr(row, col_width * 2, stat.filemode(perm), attr)
@property
def app(self) -> App:
return self._app