|
|
|
@ -1,4 +1,5 @@
|
|
|
|
|
import click, re
|
|
|
|
|
from typing import List
|
|
|
|
|
|
|
|
|
|
from textual import events
|
|
|
|
|
from textual.app import App, ComposeResult
|
|
|
|
@ -29,6 +30,7 @@ from ffx.track_descriptor import TrackDescriptor
|
|
|
|
|
from textual.widgets._data_table import CellDoesNotExist
|
|
|
|
|
|
|
|
|
|
from ffx.file_properties import FileProperties
|
|
|
|
|
from ffx.iso_language import IsoLanguage
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Screen[dict[int, str, int]]
|
|
|
|
@ -37,9 +39,9 @@ class PatternDetailsScreen(Screen):
|
|
|
|
|
CSS = """
|
|
|
|
|
|
|
|
|
|
Grid {
|
|
|
|
|
grid-size: 5 13;
|
|
|
|
|
grid-size: 7 13;
|
|
|
|
|
grid-rows: 2 2 2 2 2 8 2 2 8 2 2 2 2;
|
|
|
|
|
grid-columns: 25 25 25 25 25;
|
|
|
|
|
grid-columns: 25 25 25 25 25 25 25;
|
|
|
|
|
height: 100%;
|
|
|
|
|
width: 100%;
|
|
|
|
|
padding: 1;
|
|
|
|
@ -70,6 +72,12 @@ class PatternDetailsScreen(Screen):
|
|
|
|
|
.five {
|
|
|
|
|
column-span: 5;
|
|
|
|
|
}
|
|
|
|
|
.six {
|
|
|
|
|
column-span: 6;
|
|
|
|
|
}
|
|
|
|
|
.seven {
|
|
|
|
|
column-span: 7;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.box {
|
|
|
|
|
height: 100%;
|
|
|
|
@ -126,6 +134,7 @@ class PatternDetailsScreen(Screen):
|
|
|
|
|
|
|
|
|
|
typeCounter = {}
|
|
|
|
|
|
|
|
|
|
tr: Track
|
|
|
|
|
for tr in tracks:
|
|
|
|
|
|
|
|
|
|
td : TrackDescriptor = tr.getDescriptor(self.context)
|
|
|
|
@ -136,19 +145,59 @@ class PatternDetailsScreen(Screen):
|
|
|
|
|
|
|
|
|
|
dispoSet = td.getDispositionSet()
|
|
|
|
|
|
|
|
|
|
trackLanguage = td.getLanguage()
|
|
|
|
|
row = (td.getIndex(),
|
|
|
|
|
trackType.label(),
|
|
|
|
|
typeCounter[trackType],
|
|
|
|
|
td.getCodec(),
|
|
|
|
|
td.getAudioLayout().label() if trackType == TrackType.AUDIO else ' ',
|
|
|
|
|
td.getLanguage().label(),
|
|
|
|
|
trackLanguage.label() if trackLanguage != IsoLanguage.UNDEFINED else ' ',
|
|
|
|
|
td.getTitle(),
|
|
|
|
|
'Yes' if TrackDisposition.DEFAULT in dispoSet else 'No',
|
|
|
|
|
'Yes' if TrackDisposition.FORCED in dispoSet else 'No')
|
|
|
|
|
'Yes' if TrackDisposition.FORCED in dispoSet else 'No',
|
|
|
|
|
td.getSourceIndex())
|
|
|
|
|
|
|
|
|
|
self.tracksTable.add_row(*map(str, row))
|
|
|
|
|
|
|
|
|
|
typeCounter[trackType] += 1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def swapTracks(self, trackIndex1: int, trackIndex2: int):
|
|
|
|
|
|
|
|
|
|
ti1 = int(trackIndex1)
|
|
|
|
|
ti2 = int(trackIndex2)
|
|
|
|
|
|
|
|
|
|
siblingDescriptors: List[TrackDescriptor] = self.__tc.findSiblingDescriptors(self.__pattern.getId())
|
|
|
|
|
|
|
|
|
|
numSiblings = len(siblingDescriptors)
|
|
|
|
|
|
|
|
|
|
if ti1 < 0 or ti1 >= numSiblings:
|
|
|
|
|
raise ValueError(f"PatternDetailsScreen.swapTracks(): trackIndex1 ({ti1}) is out of range ({numSiblings})")
|
|
|
|
|
|
|
|
|
|
if ti2 < 0 or ti2 >= numSiblings:
|
|
|
|
|
raise ValueError(f"PatternDetailsScreen.swapTracks(): trackIndex2 ({ti2}) is out of range ({numSiblings})")
|
|
|
|
|
|
|
|
|
|
sibling1 = siblingDescriptors[trackIndex1]
|
|
|
|
|
sibling2 = siblingDescriptors[trackIndex2]
|
|
|
|
|
|
|
|
|
|
# raise click.ClickException(f"siblings id1={sibling1.getId()} id2={sibling2.getId()}")
|
|
|
|
|
|
|
|
|
|
subIndex2 = sibling2.getSubIndex()
|
|
|
|
|
|
|
|
|
|
sibling2.setIndex(sibling1.getIndex())
|
|
|
|
|
sibling2.setSubIndex(sibling1.getSubIndex())
|
|
|
|
|
|
|
|
|
|
sibling1.setIndex(trackIndex2)
|
|
|
|
|
sibling1.setSubIndex(subIndex2)
|
|
|
|
|
|
|
|
|
|
if not self.__tc.updateTrack(sibling1.getId(), sibling1):
|
|
|
|
|
raise click.ClickException('Update sibling1 failed')
|
|
|
|
|
if not self.__tc.updateTrack(sibling2.getId(), sibling2):
|
|
|
|
|
raise click.ClickException('Update sibling2 failed')
|
|
|
|
|
|
|
|
|
|
self.updateTracks()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def updateTags(self):
|
|
|
|
|
|
|
|
|
|
self.tagsTable.clear()
|
|
|
|
@ -181,7 +230,7 @@ class PatternDetailsScreen(Screen):
|
|
|
|
|
def compose(self):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.tagsTable = DataTable(classes="five")
|
|
|
|
|
self.tagsTable = DataTable(classes="seven")
|
|
|
|
|
|
|
|
|
|
# Define the columns with headers
|
|
|
|
|
self.column_key_tag_key = self.tagsTable.add_column("Key", width=10)
|
|
|
|
@ -190,16 +239,18 @@ class PatternDetailsScreen(Screen):
|
|
|
|
|
self.tagsTable.cursor_type = 'row'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.tracksTable = DataTable(id="tracks_table", classes="five")
|
|
|
|
|
self.tracksTable = DataTable(id="tracks_table", classes="seven")
|
|
|
|
|
|
|
|
|
|
self.column_key_track_index = self.tracksTable.add_column("Index", width=5)
|
|
|
|
|
self.column_key_track_type = self.tracksTable.add_column("Type", width=10)
|
|
|
|
|
self.column_key_track_sub_index = self.tracksTable.add_column("Subindex", width=5)
|
|
|
|
|
self.column_key_track_sub_index = self.tracksTable.add_column("SubIndex", width=8)
|
|
|
|
|
self.column_key_track_codec = self.tracksTable.add_column("Codec", width=10)
|
|
|
|
|
self.column_key_track_audio_layout = self.tracksTable.add_column("Layout", width=10)
|
|
|
|
|
self.column_key_track_language = self.tracksTable.add_column("Language", width=15)
|
|
|
|
|
self.column_key_track_title = self.tracksTable.add_column("Title", width=48)
|
|
|
|
|
self.column_key_track_default = self.tracksTable.add_column("Default", width=8)
|
|
|
|
|
self.column_key_track_forced = self.tracksTable.add_column("Forced", width=8)
|
|
|
|
|
self.column_key_track_source_index = self.tracksTable.add_column("SrcIndex", width=8)
|
|
|
|
|
|
|
|
|
|
self.tracksTable.cursor_type = 'row'
|
|
|
|
|
|
|
|
|
@ -210,21 +261,21 @@ class PatternDetailsScreen(Screen):
|
|
|
|
|
|
|
|
|
|
# 1
|
|
|
|
|
yield Static("Edit filename pattern" if self.__pattern is not None else "New filename pattern", id="toplabel")
|
|
|
|
|
yield Input(type="text", id="pattern_input", classes="four")
|
|
|
|
|
yield Input(type="text", id="pattern_input", classes="six")
|
|
|
|
|
|
|
|
|
|
# 2
|
|
|
|
|
yield Static("from show")
|
|
|
|
|
yield Static("", id="showlabel", classes="three")
|
|
|
|
|
yield Static("", id="showlabel", classes="five")
|
|
|
|
|
yield Button("Substitute pattern", id="pattern_button")
|
|
|
|
|
|
|
|
|
|
# 3
|
|
|
|
|
yield Static(" ", classes="five")
|
|
|
|
|
yield Static(" ", classes="seven")
|
|
|
|
|
# 4
|
|
|
|
|
yield Static(" ", classes="five")
|
|
|
|
|
yield Static(" ", classes="seven")
|
|
|
|
|
|
|
|
|
|
# 5
|
|
|
|
|
yield Static("Media Tags")
|
|
|
|
|
yield Static(" ")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.__pattern is not None:
|
|
|
|
|
yield Button("Add", id="button_add_tag")
|
|
|
|
@ -234,15 +285,20 @@ class PatternDetailsScreen(Screen):
|
|
|
|
|
yield Static(" ")
|
|
|
|
|
yield Static(" ")
|
|
|
|
|
yield Static(" ")
|
|
|
|
|
|
|
|
|
|
yield Static(" ")
|
|
|
|
|
yield Static(" ")
|
|
|
|
|
yield Static(" ")
|
|
|
|
|
|
|
|
|
|
# 6
|
|
|
|
|
yield self.tagsTable
|
|
|
|
|
|
|
|
|
|
# 7
|
|
|
|
|
yield Static(" ", classes="five")
|
|
|
|
|
yield Static(" ", classes="seven")
|
|
|
|
|
|
|
|
|
|
# 8
|
|
|
|
|
yield Static("Streams")
|
|
|
|
|
yield Static(" ")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if self.__pattern is not None:
|
|
|
|
|
yield Button("Add", id="button_add_track")
|
|
|
|
@ -252,22 +308,27 @@ class PatternDetailsScreen(Screen):
|
|
|
|
|
yield Static(" ")
|
|
|
|
|
yield Static(" ")
|
|
|
|
|
yield Static(" ")
|
|
|
|
|
|
|
|
|
|
yield Static(" ")
|
|
|
|
|
yield Button("Up", id="button_track_up")
|
|
|
|
|
yield Button("Down", id="button_track_down")
|
|
|
|
|
|
|
|
|
|
# 9
|
|
|
|
|
yield self.tracksTable
|
|
|
|
|
|
|
|
|
|
# 10
|
|
|
|
|
yield Static(" ", classes="five")
|
|
|
|
|
yield Static(" ", classes="seven")
|
|
|
|
|
|
|
|
|
|
# 11
|
|
|
|
|
yield Static(" ", classes="five")
|
|
|
|
|
yield Static(" ", classes="seven")
|
|
|
|
|
|
|
|
|
|
# 12
|
|
|
|
|
yield Button("Save", id="save_button")
|
|
|
|
|
yield Button("Cancel", id="cancel_button")
|
|
|
|
|
yield Static(" ", classes="three")
|
|
|
|
|
yield Static(" ", classes="five")
|
|
|
|
|
|
|
|
|
|
# 13
|
|
|
|
|
yield Static(" ", classes="five")
|
|
|
|
|
yield Static(" ", classes="seven")
|
|
|
|
|
|
|
|
|
|
yield Footer()
|
|
|
|
|
|
|
|
|
@ -397,6 +458,27 @@ class PatternDetailsScreen(Screen):
|
|
|
|
|
self.query_one("#pattern_input", Input).value = pattern.replace(patternMatch.group(1),
|
|
|
|
|
FileProperties.SE_INDICATOR_PATTERN)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if event.button.id == "button_track_up":
|
|
|
|
|
|
|
|
|
|
selectedTrackDescriptor = self.getSelectedTrackDescriptor()
|
|
|
|
|
selectedTrackIndex = selectedTrackDescriptor.getIndex()
|
|
|
|
|
|
|
|
|
|
if selectedTrackIndex > 0 and selectedTrackIndex < self.tracksTable.row_count:
|
|
|
|
|
correspondingTrackIndex = selectedTrackIndex - 1
|
|
|
|
|
self.swapTracks(selectedTrackIndex, correspondingTrackIndex)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if event.button.id == "button_track_down":
|
|
|
|
|
|
|
|
|
|
selectedTrackDescriptor = self.getSelectedTrackDescriptor()
|
|
|
|
|
selectedTrackIndex = selectedTrackDescriptor.getIndex()
|
|
|
|
|
|
|
|
|
|
if selectedTrackIndex >= 0 and selectedTrackIndex < (self.tracksTable.row_count - 1):
|
|
|
|
|
correspondingTrackIndex = selectedTrackIndex + 1
|
|
|
|
|
self.swapTracks(selectedTrackIndex, correspondingTrackIndex)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def handle_add_track(self, trackDescriptor : TrackDescriptor):
|
|
|
|
|
|
|
|
|
|
dispoSet = trackDescriptor.getDispositionSet()
|
|
|
|
|