This commit is contained in:
Javanaut
2026-07-08 09:47:07 +02:00
parent f49d6f4838
commit 6f09c80aaf
2 changed files with 120 additions and 1 deletions

View File

@@ -2,6 +2,7 @@ import click, re
from typing import List from typing import List
from textual import events from textual import events
from textual.css.query import NoMatches
from textual.screen import Screen from textual.screen import Screen
from textual.widgets import Header, Footer, Static, Button, Input, DataTable, TextArea from textual.widgets import Header, Footer, Static, Button, Input, DataTable, TextArea
from textual.containers import Grid from textual.containers import Grid
@@ -153,6 +154,13 @@ class PatternDetailsScreen(Screen):
def updateTracks(self): def updateTracks(self):
selectedTrack = self.getSelectedTrackDescriptor()
selectedTrackIndex = (
self._track_row_index(selectedTrack)
if selectedTrack is not None
else None
)
selectedCursorColumn = getattr(self.tracksTable.cursor_coordinate, "column", 0)
self.tracksTable.clear() self.tracksTable.clear()
self.__trackRowData = {} self.__trackRowData = {}
@@ -160,6 +168,7 @@ class PatternDetailsScreen(Screen):
tracks = self.getCurrentTrackDescriptors() tracks = self.getCurrentTrackDescriptors()
typeCounter = {} typeCounter = {}
restoredRowIndex = None
td: TrackDescriptor td: TrackDescriptor
for td in tracks: for td in tracks:
@@ -189,9 +198,72 @@ class PatternDetailsScreen(Screen):
row_key = self.tracksTable.add_row(*map(str, row)) row_key = self.tracksTable.add_row(*map(str, row))
self.__trackRowData[row_key] = td self.__trackRowData[row_key] = td
if (
selectedTrack is not None
and self._descriptor_refs_same_track(td, selectedTrack)
):
restoredRowIndex = len(self.__trackRowData) - 1
typeCounter[trackType] += 1 typeCounter[trackType] += 1
if restoredRowIndex is None and selectedTrackIndex is not None and self.__trackRowData:
restoredRowIndex = min(selectedTrackIndex, len(self.__trackRowData) - 1)
if restoredRowIndex is not None:
self.tracksTable.move_cursor(
row=restoredRowIndex,
column=selectedCursorColumn,
animate=False,
scroll=False,
)
self.updateTrackDropButtonState()
def _track_row_index(self, trackDescriptor: TrackDescriptor | None):
if trackDescriptor is None:
return None
for rowIndex, descriptor in enumerate(self.__trackRowData.values()):
if self._descriptor_refs_same_track(descriptor, trackDescriptor):
return rowIndex
return None
def _descriptor_refs_same_track(
self,
descriptor: TrackDescriptor,
otherDescriptor: TrackDescriptor,
) -> bool:
if descriptor.getId() != -1 and otherDescriptor.getId() != -1:
return descriptor.getId() == otherDescriptor.getId()
return (
descriptor.getPatternId() == otherDescriptor.getPatternId()
and descriptor.getIndex() == otherDescriptor.getIndex()
and descriptor.getSubIndex() == otherDescriptor.getSubIndex()
and descriptor.getType() == otherDescriptor.getType()
)
def updateTrackDropButtonState(self):
try:
button = self.query_one("#button_toggle_track_drop", Button)
except (NoMatches, AttributeError):
return
selectedTrack = self.getSelectedTrackDescriptor()
button.disabled = selectedTrack is None
button.variant = (
"warning"
if selectedTrack is not None and selectedTrack.isDropped()
else "default"
)
def on_data_table_row_highlighted(
self,
event: DataTable.RowHighlighted,
) -> None:
if event.data_table.id == "tracks_table":
self.updateTrackDropButtonState()
def getCurrentTrackDescriptors(self) -> List[TrackDescriptor]: def getCurrentTrackDescriptors(self) -> List[TrackDescriptor]:
if self.__pattern is not None: if self.__pattern is not None:
@@ -482,7 +554,7 @@ class PatternDetailsScreen(Screen):
yield Static(t("Streams")) yield Static(t("Streams"))
yield Button(t("Add"), id="button_add_track") yield Button(t("Add"), id="button_add_track")
yield Button(t("Edit"), id="button_edit_track") yield Button(t("Edit"), id="button_edit_track")
yield Button(t("Drop / Undrop"), id="button_toggle_track_drop") yield Button(t("Drop"), id="button_toggle_track_drop")
yield Static(" ") yield Static(" ")
yield Button(t("Up"), id="button_track_up") yield Button(t("Up"), id="button_track_up")

View File

@@ -76,6 +76,12 @@ class FakeTagTable:
def select_row(self, row_key): def select_row(self, row_key):
self._selected_row_key = row_key self._selected_row_key = row_key
def move_cursor(self, *, row=None, column=None, animate=False, scroll=True):
if row is not None and self._row_order:
self._selected_row_key = self._row_order[int(row)]
if column is not None:
self.cursor_coordinate = (self.cursor_coordinate[0], int(column))
def get_row_index(self, row_key): def get_row_index(self, row_key):
return self._row_order.index(row_key) return self._row_order.index(row_key)
@@ -110,6 +116,12 @@ class FakeValueWidget:
self.disabled = False self.disabled = False
class FakeButtonWidget:
def __init__(self):
self.disabled = False
self.variant = "default"
class FakeInputWidget: class FakeInputWidget:
def __init__(self, value): def __init__(self, value):
self.value = value self.value = value
@@ -379,6 +391,7 @@ class TagTableScreenStateTests(unittest.TestCase):
def test_pattern_details_screen_toggles_draft_track_drop_state(self): def test_pattern_details_screen_toggles_draft_track_drop_state(self):
first_track = make_track_descriptor(0, 0, TrackType.VIDEO) first_track = make_track_descriptor(0, 0, TrackType.VIDEO)
second_track = make_track_descriptor(1, 0, TrackType.SUBTITLE) second_track = make_track_descriptor(1, 0, TrackType.SUBTITLE)
drop_button = FakeButtonWidget()
screen = object.__new__(PatternDetailsScreen) screen = object.__new__(PatternDetailsScreen)
screen.context = {"logger": get_ffx_logger()} screen.context = {"logger": get_ffx_logger()}
@@ -386,6 +399,7 @@ class TagTableScreenStateTests(unittest.TestCase):
screen._PatternDetailsScreen__draftTracks = [first_track, second_track] screen._PatternDetailsScreen__draftTracks = [first_track, second_track]
screen._PatternDetailsScreen__pattern = None screen._PatternDetailsScreen__pattern = None
screen._PatternDetailsScreen__trackRowData = {} screen._PatternDetailsScreen__trackRowData = {}
screen.query_one = lambda selector, _widget_type=None: drop_button
screen.updateTracks() screen.updateTracks()
screen.tracksTable.select_row("row-1") screen.tracksTable.select_row("row-1")
@@ -395,6 +409,39 @@ class TagTableScreenStateTests(unittest.TestCase):
self.assertFalse(first_track.isDropped()) self.assertFalse(first_track.isDropped())
self.assertTrue(second_track.isDropped()) self.assertTrue(second_track.isDropped())
self.assertEqual("Ja", list(screen.tracksTable.rows.values())[1][9]) self.assertEqual("Ja", list(screen.tracksTable.rows.values())[1][9])
self.assertIs(second_track, screen.getSelectedTrackDescriptor())
self.assertEqual("warning", drop_button.variant)
def test_pattern_details_screen_updates_drop_button_for_selected_track(self):
first_track = make_track_descriptor(0, 0, TrackType.VIDEO)
second_track = make_track_descriptor(
1,
0,
TrackType.SUBTITLE,
dropped=True,
)
drop_button = FakeButtonWidget()
screen = object.__new__(PatternDetailsScreen)
screen.tracksTable = FakeTagTable()
screen._PatternDetailsScreen__draftTracks = [first_track, second_track]
screen._PatternDetailsScreen__pattern = None
screen._PatternDetailsScreen__trackRowData = {}
screen.query_one = lambda selector, _widget_type=None: drop_button
screen.updateTracks()
self.assertEqual("default", drop_button.variant)
screen.tracksTable.select_row("row-1")
screen.updateTrackDropButtonState()
self.assertEqual("warning", drop_button.variant)
screen.tracksTable.select_row("row-0")
screen.updateTrackDropButtonState()
self.assertEqual("default", drop_button.variant)
def test_pattern_details_screen_toggles_persisted_track_drop_state(self): def test_pattern_details_screen_toggles_persisted_track_drop_state(self):
class _FakePattern: class _FakePattern: