From 12310942aeaf113e8ae244b08053dcd843134ae6 Mon Sep 17 00:00:00 2001 From: Javanaut Date: Fri, 24 Apr 2026 10:34:43 +0200 Subject: [PATCH] Fix inspect attachment subtracks --- src/ffx/media_workflow_screen_base.py | 13 +++- src/ffx/pattern_details_screen.py | 28 ++++++++- tests/unit/test_tag_table_screen_state.py | 77 ++++++++++++++++++++++- 3 files changed, 112 insertions(+), 6 deletions(-) diff --git a/src/ffx/media_workflow_screen_base.py b/src/ffx/media_workflow_screen_base.py index 38274d7..7a2b79e 100644 --- a/src/ffx/media_workflow_screen_base.py +++ b/src/ffx/media_workflow_screen_base.py @@ -6,6 +6,7 @@ from textual.screen import Screen from textual.widgets import DataTable from textual.widgets._data_table import CellDoesNotExist +from ffx.attachment_format import AttachmentFormat from ffx.audio_layout import AudioLayout from ffx.file_properties import FileProperties from ffx.helper import DIFF_ADDED_KEY, DIFF_CHANGED_KEY, DIFF_REMOVED_KEY @@ -127,9 +128,17 @@ class MediaWorkflowScreenBase(Screen): def _track_codec_cell_value(self, trackDescriptor: TrackDescriptor) -> str: if trackDescriptor.getType() == TrackType.ATTACHMENT: - return " " + attachmentFormat = trackDescriptor.getAttachmentFormat() + if attachmentFormat == AttachmentFormat.UNKNOWN: + return attachmentFormat.identifier() + return attachmentFormat.label() return trackDescriptor.getFormatDescriptor().label() + def _track_language_cell_value(self, trackDescriptor: TrackDescriptor) -> str: + if trackDescriptor.getType() == TrackType.ATTACHMENT: + return " " + return trackDescriptor.getLanguage().label() + def _track_disposition_cell_value( self, trackDescriptor: TrackDescriptor, @@ -244,7 +253,7 @@ class MediaWorkflowScreenBase(Screen): if trackType == TrackType.AUDIO and audioLayout != AudioLayout.LAYOUT_UNDEFINED else " ", - trackDescriptor.getLanguage().label(), + self._track_language_cell_value(trackDescriptor), trackTitle, self._track_disposition_cell_value( trackDescriptor, diff --git a/src/ffx/pattern_details_screen.py b/src/ffx/pattern_details_screen.py index ffd541a..db4426e 100644 --- a/src/ffx/pattern_details_screen.py +++ b/src/ffx/pattern_details_screen.py @@ -88,6 +88,9 @@ class PatternDetailsScreen(Screen): .three { column-span: 3; } + .two { + column-span: 2; + } .four { column-span: 4; @@ -114,7 +117,7 @@ class PatternDetailsScreen(Screen): } .yellow { - tint: yellow 40%; + color: yellow; } """ @@ -331,6 +334,7 @@ class PatternDetailsScreen(Screen): if not self.__showDescriptor is None: self.query_one("#showlabel", Static).update(f"{self.__showDescriptor.getId()} - {self.__showDescriptor.getName()} ({self.__showDescriptor.getYear()})") + self.updateShowQualityHint() if self.__pattern is not None: @@ -350,6 +354,7 @@ class PatternDetailsScreen(Screen): if not hasattr(self, "tracksTable") or not hasattr(self, "tagsTable"): return + self.updateShowQualityHint() self.updateTags() self.updateTracks() @@ -415,7 +420,9 @@ class PatternDetailsScreen(Screen): # Row 4 yield Static(t("Quality")) yield Input(type="integer", id="quality_input") - yield Static(' ', classes="five") + yield Static(" ") + yield Static("", id="show_quality_hint", classes="two yellow") + yield Static(' ', classes="two") # Row 5 @@ -504,6 +511,23 @@ class PatternDetailsScreen(Screen): def getPatternFromInput(self): return str(self.query_one("#pattern_input", Input).value) + def getShowQualityHintText(self): + if self.__showDescriptor is None: + return "" + + showQuality = int(self.__showDescriptor.getQuality() or 0) + if showQuality <= 0: + return "" + + patternQuality = int(getattr(self.__pattern, "quality", 0) or 0) + if patternQuality > 0: + return "" + + return f"{t('Show')}: {showQuality}" + + def updateShowQualityHint(self): + self.query_one("#show_quality_hint", Static).update(self.getShowQualityHintText()) + def getQualityFromInput(self): try: return int(self.query_one("#quality_input", Input).value) diff --git a/tests/unit/test_tag_table_screen_state.py b/tests/unit/test_tag_table_screen_state.py index a7c8660..3bf0b71 100644 --- a/tests/unit/test_tag_table_screen_state.py +++ b/tests/unit/test_tag_table_screen_state.py @@ -548,6 +548,11 @@ class TagTableScreenStateTests(unittest.TestCase): screen.tagsTable = FakeTagTable() screen.shiftedSeasonsTable = FakeTagTable() screen._PatternDetailsScreen__pattern = object() + screen._PatternDetailsScreen__showDescriptor = None + widgets = { + "#show_quality_hint": FakeStaticWidget(), + } + screen.query_one = lambda selector, _type=None: widgets[selector] calls = [] screen.updateTags = lambda: calls.append("updateTags") @@ -561,6 +566,48 @@ class TagTableScreenStateTests(unittest.TestCase): calls, ) + def test_pattern_details_screen_on_mount_shows_show_quality_hint_for_new_pattern(self): + set_current_language("en") + + screen = object.__new__(PatternDetailsScreen) + screen.context = {} + screen._PatternDetailsScreen__showDescriptor = ShowDescriptor( + id=7, + name="Demo", + year=1999, + quality=23, + ) + screen._PatternDetailsScreen__pattern = None + + widgets = { + "#showlabel": FakeStaticWidget(), + "#show_quality_hint": FakeStaticWidget(), + } + screen.query_one = lambda selector, _type=None: widgets[selector] + + screen.on_mount() + + self.assertEqual("7 - Demo (1999)", widgets["#showlabel"].value) + self.assertEqual("Show: 23", widgets["#show_quality_hint"].value) + + def test_pattern_details_screen_show_quality_hint_is_hidden_when_pattern_quality_exists(self): + set_current_language("en") + + screen = object.__new__(PatternDetailsScreen) + screen._PatternDetailsScreen__showDescriptor = ShowDescriptor( + id=7, + name="Demo", + year=1999, + quality=23, + ) + screen._PatternDetailsScreen__pattern = type( + "_Pattern", + (), + {"quality": 19}, + )() + + self.assertEqual("", screen.getShowQualityHintText()) + def test_inspect_details_screen_handle_edit_pattern_refreshes_even_without_result(self): screen = object.__new__(InspectDetailsScreen) @@ -722,7 +769,7 @@ class TagTableScreenStateTests(unittest.TestCase): self.assertIn("English Full", screen.tracksTable.rows["row-0"]) self.assertIs(target_track, screen.getSelectedTrackDescriptor()) - def test_inspect_details_screen_update_tracks_blanks_irrelevant_attachment_fields(self): + def test_inspect_details_screen_update_tracks_shows_attachment_format_and_blanks_language(self): attachment_track = TrackDescriptor( index=4, source_index=4, @@ -745,10 +792,36 @@ class TagTableScreenStateTests(unittest.TestCase): row = screen.tracksTable.rows["row-0"] self.assertEqual("4", row[0]) - self.assertEqual(" ", row[3]) + self.assertEqual("TTF", row[3]) + self.assertEqual(" ", row[5]) self.assertEqual(" ", row[7]) self.assertEqual(" ", row[8]) + def test_inspect_details_screen_update_tracks_shows_unknown_for_unknown_attachment_format(self): + attachment_track = TrackDescriptor( + index=5, + source_index=5, + sub_index=0, + track_type=TrackType.ATTACHMENT, + attachment_format=AttachmentFormat.UNKNOWN, + tags={"filename": "blob.bin", "mimetype": "application/octet-stream"}, + ) + + screen = object.__new__(InspectDetailsScreen) + screen.tracksTable = FakeTagTable() + screen._sourceMediaDescriptor = FakeMediaDescriptor([attachment_track]) + screen._targetMediaDescriptor = None + screen._currentPattern = None + screen._trackRowData = {} + screen._applyNormalization = False + + screen.updateTracks() + + row = screen.tracksTable.rows["row-0"] + + self.assertEqual("unknown", row[3]) + self.assertEqual(" ", row[5]) + def test_inspect_details_screen_maps_target_selection_back_to_source_track(self): source_track = TrackDescriptor( index=3,