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 textual import events
from textual.css.query import NoMatches
from textual.screen import Screen
from textual.widgets import Header, Footer, Static, Button, Input, DataTable, TextArea
from textual.containers import Grid
@@ -153,6 +154,13 @@ class PatternDetailsScreen(Screen):
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.__trackRowData = {}
@@ -160,6 +168,7 @@ class PatternDetailsScreen(Screen):
tracks = self.getCurrentTrackDescriptors()
typeCounter = {}
restoredRowIndex = None
td: TrackDescriptor
for td in tracks:
@@ -189,9 +198,72 @@ class PatternDetailsScreen(Screen):
row_key = self.tracksTable.add_row(*map(str, row))
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
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]:
if self.__pattern is not None:
@@ -482,7 +554,7 @@ class PatternDetailsScreen(Screen):
yield Static(t("Streams"))
yield Button(t("Add"), id="button_add_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 Button(t("Up"), id="button_track_up")

View File

@@ -76,6 +76,12 @@ class FakeTagTable:
def select_row(self, 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):
return self._row_order.index(row_key)
@@ -110,6 +116,12 @@ class FakeValueWidget:
self.disabled = False
class FakeButtonWidget:
def __init__(self):
self.disabled = False
self.variant = "default"
class FakeInputWidget:
def __init__(self, value):
self.value = value
@@ -379,6 +391,7 @@ class TagTableScreenStateTests(unittest.TestCase):
def test_pattern_details_screen_toggles_draft_track_drop_state(self):
first_track = make_track_descriptor(0, 0, TrackType.VIDEO)
second_track = make_track_descriptor(1, 0, TrackType.SUBTITLE)
drop_button = FakeButtonWidget()
screen = object.__new__(PatternDetailsScreen)
screen.context = {"logger": get_ffx_logger()}
@@ -386,6 +399,7 @@ class TagTableScreenStateTests(unittest.TestCase):
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()
screen.tracksTable.select_row("row-1")
@@ -395,6 +409,39 @@ class TagTableScreenStateTests(unittest.TestCase):
self.assertFalse(first_track.isDropped())
self.assertTrue(second_track.isDropped())
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):
class _FakePattern: