758 lines
32 KiB
Python
758 lines
32 KiB
Python
import os, click, re
|
|
|
|
from textual.screen import Screen
|
|
from textual.widgets import Header, Footer, Static, Button, Input, DataTable
|
|
from textual.containers import Grid
|
|
|
|
from ffx.audio_layout import AudioLayout
|
|
|
|
from .pattern_controller import PatternController
|
|
from .show_controller import ShowController
|
|
from .track_controller import TrackController
|
|
from .tag_controller import TagController
|
|
|
|
from .show_details_screen import ShowDetailsScreen
|
|
from .pattern_details_screen import PatternDetailsScreen
|
|
|
|
from ffx.track_type import TrackType
|
|
from ffx.track_codec import TrackCodec
|
|
from ffx.model.track import Track
|
|
|
|
from ffx.track_disposition import TrackDisposition
|
|
from ffx.track_descriptor import TrackDescriptor
|
|
from ffx.show_descriptor import ShowDescriptor
|
|
|
|
from textual.widgets._data_table import CellDoesNotExist
|
|
|
|
from ffx.media_descriptor import MediaDescriptor
|
|
from ffx.file_properties import FileProperties
|
|
|
|
from ffx.media_descriptor_change_set import MediaDescriptorChangeSet
|
|
|
|
from ffx.helper import formatRichColor, DIFF_ADDED_KEY, DIFF_CHANGED_KEY, DIFF_REMOVED_KEY, DIFF_UNCHANGED_KEY
|
|
|
|
|
|
# Screen[dict[int, str, int]]
|
|
class MediaDetailsScreen(Screen):
|
|
|
|
CSS = """
|
|
|
|
Grid {
|
|
grid-size: 5 8;
|
|
grid-rows: 8 2 2 2 2 8 2 2 8;
|
|
grid-columns: 15 25 90 10 105;
|
|
height: 100%;
|
|
width: 100%;
|
|
padding: 1;
|
|
}
|
|
|
|
DataTable .datatable--cursor {
|
|
background: darkorange;
|
|
color: black;
|
|
}
|
|
|
|
DataTable .datatable--header {
|
|
background: steelblue;
|
|
color: white;
|
|
}
|
|
|
|
Input {
|
|
border: none;
|
|
}
|
|
Button {
|
|
border: none;
|
|
}
|
|
|
|
DataTable {
|
|
min-height: 40;
|
|
}
|
|
|
|
#toplabel {
|
|
height: 1;
|
|
}
|
|
.two {
|
|
column-span: 2;
|
|
}
|
|
.three {
|
|
column-span: 3;
|
|
}
|
|
|
|
.four {
|
|
column-span: 4;
|
|
}
|
|
.five {
|
|
column-span: 5;
|
|
}
|
|
|
|
.triple {
|
|
row-span: 3;
|
|
}
|
|
|
|
.box {
|
|
height: 100%;
|
|
border: solid green;
|
|
}
|
|
|
|
.purple {
|
|
tint: purple 40%;
|
|
}
|
|
|
|
.yellow {
|
|
tint: yellow 40%;
|
|
}
|
|
|
|
#differences-table {
|
|
row-span: 8;
|
|
/* tint: magenta 40%; */
|
|
}
|
|
|
|
/* #pattern_input {
|
|
tint: red 40%;
|
|
}*/
|
|
"""
|
|
|
|
|
|
TRACKS_TABLE_INDEX_COLUMN_LABEL = "Index"
|
|
TRACKS_TABLE_TYPE_COLUMN_LABEL = "Type"
|
|
TRACKS_TABLE_SUB_INDEX_COLUMN_LABEL = "SubIndex"
|
|
TRACKS_TABLE_CODEC_COLUMN_LABEL = "Codec"
|
|
TRACKS_TABLE_LAYOUT_COLUMN_LABEL = "Layout"
|
|
TRACKS_TABLE_LANGUAGE_COLUMN_LABEL = "Language"
|
|
TRACKS_TABLE_TITLE_COLUMN_LABEL = "Title"
|
|
TRACKS_TABLE_DEFAULT_COLUMN_LABEL = "Default"
|
|
TRACKS_TABLE_FORCED_COLUMN_LABEL = "Forced"
|
|
|
|
DIFFERENCES_TABLE_DIFFERENCES_COLUMN_LABEL = 'Differences (file->db/output)'
|
|
|
|
|
|
BINDINGS = [
|
|
("n", "new_pattern", "New Pattern"),
|
|
("u", "update_pattern", "Update Pattern"),
|
|
("e", "edit_pattern", "Edit Pattern"),
|
|
]
|
|
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
|
|
self.context = self.app.getContext()
|
|
self.Session = self.context['database']['session'] # convenience
|
|
|
|
|
|
self.__configurationData = self.context['config'].getData()
|
|
|
|
metadataConfiguration = self.__configurationData['metadata'] if 'metadata' in self.__configurationData.keys() else {}
|
|
|
|
self.__signatureTags = metadataConfiguration['signature'] if 'signature' in metadataConfiguration.keys() else {}
|
|
self.__removeGlobalKeys = metadataConfiguration['remove'] if 'remove' in metadataConfiguration.keys() else []
|
|
self.__ignoreGlobalKeys = metadataConfiguration['ignore'] if 'ignore' in metadataConfiguration.keys() else []
|
|
self.__removeTrackKeys = (metadataConfiguration['streams']['remove']
|
|
if 'streams' in metadataConfiguration.keys()
|
|
and 'remove' in metadataConfiguration['streams'].keys() else [])
|
|
self.__ignoreTrackKeys = (metadataConfiguration['streams']['ignore']
|
|
if 'streams' in metadataConfiguration.keys()
|
|
and 'ignore' in metadataConfiguration['streams'].keys() else [])
|
|
|
|
|
|
self.__pc = PatternController(context = self.context)
|
|
self.__sc = ShowController(context = self.context)
|
|
self.__tc = TrackController(context = self.context)
|
|
self.__tac = TagController(context = self.context)
|
|
|
|
if not 'command' in self.context.keys() or self.context['command'] != 'inspect':
|
|
raise click.ClickException(f"MediaDetailsScreen.__init__(): Can only perform command 'inspect'")
|
|
|
|
if not 'arguments' in self.context.keys() or not 'filename' in self.context['arguments'].keys() or not self.context['arguments']['filename']:
|
|
raise click.ClickException(f"MediaDetailsScreen.__init__(): Argument 'filename' is required to be provided for command 'inspect'")
|
|
|
|
self.__mediaFilename = self.context['arguments']['filename']
|
|
|
|
if not os.path.isfile(self.__mediaFilename):
|
|
raise click.ClickException(f"MediaDetailsScreen.__init__(): Media file {self.__mediaFilename} does not exist")
|
|
|
|
self.loadProperties()
|
|
|
|
|
|
def removeShow(self, showId : int = -1):
|
|
"""Remove show entry from DataTable.
|
|
Removes the <New show> entry if showId is not set"""
|
|
|
|
for rowKey, row in self.showsTable.rows.items(): # dict[RowKey, Row]
|
|
|
|
rowData = self.showsTable.get_row(rowKey)
|
|
|
|
try:
|
|
if (showId == -1 and rowData[0] == ' '
|
|
or showId == int(rowData[0])):
|
|
self.showsTable.remove_row(rowKey)
|
|
return
|
|
except:
|
|
continue
|
|
|
|
|
|
|
|
def getRowIndexFromShowId(self, showId : int = -1) -> int:
|
|
"""Find the index of the row where the value in the specified column matches the target_value."""
|
|
|
|
for rowKey, row in self.showsTable.rows.items(): # dict[RowKey, Row]
|
|
|
|
rowData = self.showsTable.get_row(rowKey)
|
|
|
|
try:
|
|
if ((showId == -1 and rowData[0] == ' ')
|
|
or showId == int(rowData[0])):
|
|
return int(self.showsTable.get_row_index(rowKey))
|
|
except:
|
|
continue
|
|
|
|
return None
|
|
|
|
|
|
def loadProperties(self):
|
|
|
|
self.__mediaFileProperties = FileProperties(self.context, self.__mediaFilename)
|
|
self.__sourceMediaDescriptor = self.__mediaFileProperties.getMediaDescriptor()
|
|
|
|
#HINT: This is None if the filename did not match anything in database
|
|
self.__currentPattern = self.__mediaFileProperties.getPattern()
|
|
|
|
# keine tags vorhanden
|
|
self.__targetMediaDescriptor = self.__currentPattern.getMediaDescriptor(self.context) if self.__currentPattern is not None else None
|
|
|
|
# Enumerating differences between media descriptors
|
|
# from file (=current) vs from stored in database (=target)
|
|
try:
|
|
mdcs = MediaDescriptorChangeSet(self.context,
|
|
self.__targetMediaDescriptor,
|
|
self.__sourceMediaDescriptor)
|
|
|
|
self.__mediaChangeSetObj = mdcs.getChangeSetObj()
|
|
except ValueError:
|
|
self.__mediaChangeSetObj = {}
|
|
|
|
|
|
def updateDifferences(self):
|
|
|
|
self.loadProperties()
|
|
|
|
self.differencesTable.clear()
|
|
|
|
|
|
if MediaDescriptorChangeSet.TAGS_KEY in self.__mediaChangeSetObj.keys():
|
|
|
|
if DIFF_ADDED_KEY in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TAGS_KEY].keys():
|
|
for tagKey, tagValue in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TAGS_KEY][DIFF_ADDED_KEY].items():
|
|
if tagKey not in self.__ignoreGlobalKeys:
|
|
row = (f"add media tag: key='{tagKey}' value='{tagValue}'",)
|
|
self.differencesTable.add_row(*map(str, row))
|
|
|
|
if DIFF_REMOVED_KEY in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TAGS_KEY].keys():
|
|
for tagKey, tagValue in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TAGS_KEY][DIFF_REMOVED_KEY].items():
|
|
if tagKey not in self.__ignoreGlobalKeys and tagKey not in self.__removeGlobalKeys:
|
|
row = (f"remove media tag: key='{tagKey}' value='{tagValue}'",)
|
|
self.differencesTable.add_row(*map(str, row))
|
|
|
|
if DIFF_CHANGED_KEY in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TAGS_KEY].keys():
|
|
for tagKey, tagValue in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TAGS_KEY][DIFF_CHANGED_KEY].items():
|
|
if tagKey not in self.__ignoreGlobalKeys:
|
|
row = (f"change media tag: key='{tagKey}' value='{tagValue}'",)
|
|
self.differencesTable.add_row(*map(str, row))
|
|
|
|
|
|
if MediaDescriptorChangeSet.TRACKS_KEY in self.__mediaChangeSetObj.keys():
|
|
|
|
if DIFF_ADDED_KEY in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TRACKS_KEY].keys():
|
|
|
|
trackDescriptor: TrackDescriptor
|
|
for trackIndex, trackDescriptor in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TRACKS_KEY][DIFF_ADDED_KEY].items():
|
|
row = (f"add {trackDescriptor.getType().label()} track: index={trackDescriptor.getIndex()} lang={trackDescriptor.getLanguage().threeLetter()}",)
|
|
self.differencesTable.add_row(*map(str, row))
|
|
|
|
if DIFF_REMOVED_KEY in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TRACKS_KEY].keys():
|
|
for trackIndex, trackDescriptor in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TRACKS_KEY][DIFF_REMOVED_KEY].items():
|
|
row = (f"remove stream #{trackIndex}",)
|
|
self.differencesTable.add_row(*map(str, row))
|
|
|
|
if DIFF_CHANGED_KEY in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TRACKS_KEY].keys():
|
|
|
|
changedTracks: dict = self.__mediaChangeSetObj[MediaDescriptorChangeSet.TRACKS_KEY][DIFF_CHANGED_KEY]
|
|
|
|
targetTrackDescriptors = self.__targetMediaDescriptor.getTrackDescriptors()
|
|
|
|
trackDiffObj: dict
|
|
for trackIndex, trackDiffObj in changedTracks.items():
|
|
|
|
ttd: TrackDescriptor = targetTrackDescriptors[trackIndex]
|
|
|
|
|
|
if MediaDescriptorChangeSet.TAGS_KEY in trackDiffObj.keys():
|
|
|
|
removedTags = (trackDiffObj[MediaDescriptorChangeSet.TAGS_KEY][DIFF_REMOVED_KEY]
|
|
if DIFF_REMOVED_KEY in trackDiffObj[MediaDescriptorChangeSet.TAGS_KEY].keys() else {})
|
|
for tagKey, tagValue in removedTags.items():
|
|
row = (f"change stream #{ttd.getIndex()} ({ttd.getType().label()}:{ttd.getSubIndex()}) remove key={tagKey} value={tagValue}",)
|
|
self.differencesTable.add_row(*map(str, row))
|
|
|
|
addedTags = (trackDiffObj[MediaDescriptorChangeSet.TAGS_KEY][DIFF_ADDED_KEY]
|
|
if DIFF_ADDED_KEY in trackDiffObj[MediaDescriptorChangeSet.TAGS_KEY].keys() else {})
|
|
for tagKey, tagValue in addedTags.items():
|
|
row = (f"change stream #{ttd.getIndex()} ({ttd.getType().label()}:{ttd.getSubIndex()}) add key={tagKey} value={tagValue}",)
|
|
self.differencesTable.add_row(*map(str, row))
|
|
|
|
changedTags = (trackDiffObj[MediaDescriptorChangeSet.TAGS_KEY][DIFF_CHANGED_KEY]
|
|
if DIFF_CHANGED_KEY in trackDiffObj[MediaDescriptorChangeSet.TAGS_KEY].keys() else {})
|
|
for tagKey, tagValue in changedTags.items():
|
|
row = (f"change stream #{ttd.getIndex()} ({ttd.getType().label()}:{ttd.getSubIndex()}) change key={tagKey} value={tagValue}",)
|
|
self.differencesTable.add_row(*map(str, row))
|
|
|
|
|
|
if MediaDescriptorChangeSet.DISPOSITION_SET_KEY in trackDiffObj.keys():
|
|
|
|
addedDispositions = (trackDiffObj[MediaDescriptorChangeSet.DISPOSITION_SET_KEY][DIFF_ADDED_KEY]
|
|
if DIFF_ADDED_KEY in trackDiffObj[MediaDescriptorChangeSet.DISPOSITION_SET_KEY].keys() else set())
|
|
for ad in addedDispositions:
|
|
row = (f"change stream #{ttd.getIndex()} ({ttd.getType().label()}:{ttd.getSubIndex()}) add disposition={ad.label()}",)
|
|
self.differencesTable.add_row(*map(str, row))
|
|
|
|
removedDispositions = (trackDiffObj[MediaDescriptorChangeSet.DISPOSITION_SET_KEY][DIFF_REMOVED_KEY]
|
|
if DIFF_REMOVED_KEY in trackDiffObj[MediaDescriptorChangeSet.DISPOSITION_SET_KEY].keys() else set())
|
|
for rd in removedDispositions:
|
|
row = (f"change stream #{ttd.getIndex()} ({ttd.getType().label()}:{ttd.getSubIndex()}) remove disposition={rd.label()}",)
|
|
self.differencesTable.add_row(*map(str, row))
|
|
|
|
|
|
def on_mount(self):
|
|
|
|
if self.__currentPattern is None:
|
|
row = (' ', '<New show>', ' ') # Convert each element to a string before adding
|
|
self.showsTable.add_row(*map(str, row))
|
|
|
|
for show in self.__sc.getAllShows():
|
|
row = (int(show.id), show.name, show.year) # Convert each element to a string before adding
|
|
self.showsTable.add_row(*map(str, row))
|
|
|
|
for mediaTagKey, mediaTagValue in self.__sourceMediaDescriptor.getTags().items():
|
|
|
|
textColor = None
|
|
if mediaTagKey in self.__ignoreGlobalKeys:
|
|
textColor = 'blue'
|
|
if mediaTagKey in self.__removeGlobalKeys:
|
|
textColor = 'red'
|
|
|
|
row = (formatRichColor(mediaTagKey, textColor), formatRichColor(mediaTagValue, textColor)) # Convert each element to a string before adding
|
|
self.mediaTagsTable.add_row(*map(str, row))
|
|
|
|
self.updateTracks()
|
|
|
|
|
|
if self.__currentPattern is not None:
|
|
|
|
showIdentifier = self.__currentPattern.getShowId()
|
|
showRowIndex = self.getRowIndexFromShowId(showIdentifier)
|
|
if showRowIndex is not None:
|
|
self.showsTable.move_cursor(row=showRowIndex)
|
|
|
|
self.query_one("#pattern_input", Input).value = self.__currentPattern.getPattern()
|
|
|
|
self.updateDifferences()
|
|
|
|
else:
|
|
|
|
self.query_one("#pattern_input", Input).value = self.__mediaFilename
|
|
self.highlightPattern(True)
|
|
|
|
|
|
def highlightPattern(self, state : bool):
|
|
if state:
|
|
self.query_one("#pattern_input", Input).styles.background = 'red'
|
|
else:
|
|
self.query_one("#pattern_input", Input).styles.background = None
|
|
|
|
|
|
def updateTracks(self):
|
|
|
|
self.tracksTable.clear()
|
|
|
|
# trackDescriptorList = self.__sourceMediaDescriptor.getAllTrackDescriptors()
|
|
trackDescriptorList = self.__sourceMediaDescriptor.getTrackDescriptors()
|
|
|
|
typeCounter = {}
|
|
|
|
for td in trackDescriptorList:
|
|
|
|
trackType = td.getType()
|
|
if not trackType in typeCounter.keys():
|
|
typeCounter[trackType] = 0
|
|
|
|
dispoSet = td.getDispositionSet()
|
|
audioLayout = td.getAudioLayout()
|
|
row = (td.getIndex(),
|
|
trackType.label(),
|
|
typeCounter[trackType],
|
|
td.getCodec().label(),
|
|
audioLayout.label() if trackType == TrackType.AUDIO
|
|
and audioLayout != AudioLayout.LAYOUT_UNDEFINED else ' ',
|
|
td.getLanguage().label(),
|
|
td.getTitle(),
|
|
'Yes' if TrackDisposition.DEFAULT in dispoSet else 'No',
|
|
'Yes' if TrackDisposition.FORCED in dispoSet else 'No')
|
|
|
|
self.tracksTable.add_row(*map(str, row))
|
|
|
|
typeCounter[trackType] += 1
|
|
|
|
|
|
def compose(self):
|
|
|
|
# Create the DataTable widget
|
|
self.showsTable = DataTable(classes="two")
|
|
|
|
# Define the columns with headers
|
|
self.column_key_show_id = self.showsTable.add_column("ID", width=10)
|
|
self.column_key_show_name = self.showsTable.add_column("Name", width=80)
|
|
self.column_key_show_year = self.showsTable.add_column("Year", width=10)
|
|
|
|
self.showsTable.cursor_type = 'row'
|
|
|
|
|
|
self.mediaTagsTable = DataTable(classes="two")
|
|
|
|
# Define the columns with headers
|
|
self.column_key_track_tag_key = self.mediaTagsTable.add_column("Key", width=30)
|
|
self.column_key_track_tag_value = self.mediaTagsTable.add_column("Value", width=70)
|
|
|
|
self.mediaTagsTable.cursor_type = 'row'
|
|
|
|
|
|
self.tracksTable = DataTable(classes="two")
|
|
|
|
# Define the columns with headers
|
|
self.column_key_track_index = self.tracksTable.add_column(MediaDetailsScreen.TRACKS_TABLE_INDEX_COLUMN_LABEL, width=5)
|
|
self.column_key_track_type = self.tracksTable.add_column(MediaDetailsScreen.TRACKS_TABLE_TYPE_COLUMN_LABEL, width=10)
|
|
self.column_key_track_sub_index = self.tracksTable.add_column(MediaDetailsScreen.TRACKS_TABLE_SUB_INDEX_COLUMN_LABEL, width=8)
|
|
self.column_key_track_codec = self.tracksTable.add_column(MediaDetailsScreen.TRACKS_TABLE_CODEC_COLUMN_LABEL, width=10)
|
|
self.column_key_track_layout = self.tracksTable.add_column(MediaDetailsScreen.TRACKS_TABLE_LAYOUT_COLUMN_LABEL, width=10)
|
|
self.column_key_track_language = self.tracksTable.add_column(MediaDetailsScreen.TRACKS_TABLE_LANGUAGE_COLUMN_LABEL, width=15)
|
|
self.column_key_track_title = self.tracksTable.add_column(MediaDetailsScreen.TRACKS_TABLE_TITLE_COLUMN_LABEL, width=48)
|
|
self.column_key_track_default = self.tracksTable.add_column(MediaDetailsScreen.TRACKS_TABLE_DEFAULT_COLUMN_LABEL, width=8)
|
|
self.column_key_track_forced = self.tracksTable.add_column(MediaDetailsScreen.TRACKS_TABLE_FORCED_COLUMN_LABEL, width=8)
|
|
|
|
self.tracksTable.cursor_type = 'row'
|
|
|
|
|
|
# Create the DataTable widget
|
|
self.differencesTable = DataTable(id='differences-table') # classes="triple"
|
|
|
|
# Define the columns with headers
|
|
self.column_key_differences = self.differencesTable.add_column(MediaDetailsScreen.DIFFERENCES_TABLE_DIFFERENCES_COLUMN_LABEL, width=100)
|
|
|
|
self.differencesTable.cursor_type = 'row'
|
|
|
|
yield Header()
|
|
|
|
with Grid():
|
|
|
|
# 1
|
|
yield Static("Show")
|
|
yield self.showsTable
|
|
yield Static(" ")
|
|
yield self.differencesTable
|
|
|
|
# 2
|
|
yield Static(" ", classes="four")
|
|
|
|
# 3
|
|
yield Static(" ")
|
|
yield Button("Substitute", id="pattern_button")
|
|
yield Static(" ", classes="two")
|
|
|
|
# 4
|
|
yield Static("Pattern")
|
|
yield Input(type="text", id='pattern_input', classes="two")
|
|
|
|
yield Static(" ")
|
|
|
|
# 5
|
|
yield Static(" ", classes="four")
|
|
|
|
# 6
|
|
yield Static("Media Tags")
|
|
yield self.mediaTagsTable
|
|
yield Static(" ")
|
|
|
|
# 7
|
|
yield Static(" ", classes="four")
|
|
|
|
# 8
|
|
yield Static(" ")
|
|
yield Button("Set Default", id="select_default_button")
|
|
yield Button("Set Forced", id="select_forced_button")
|
|
yield Static(" ")
|
|
# 9
|
|
yield Static("Streams")
|
|
yield self.tracksTable
|
|
yield Static(" ")
|
|
|
|
yield Footer()
|
|
|
|
|
|
def getPatternObjFromInput(self):
|
|
"""Returns show id and pattern as obj from corresponding inputs"""
|
|
patternObj = {}
|
|
try:
|
|
patternObj['show_id'] = self.getSelectedShowDescriptor().getId()
|
|
patternObj['pattern'] = str(self.query_one("#pattern_input", Input).value)
|
|
except:
|
|
return {}
|
|
return patternObj
|
|
|
|
|
|
def on_button_pressed(self, event: Button.Pressed) -> None:
|
|
|
|
if event.button.id == "pattern_button":
|
|
|
|
pattern = self.query_one("#pattern_input", Input).value
|
|
|
|
patternMatch = re.search(FileProperties.SE_INDICATOR_PATTERN, pattern)
|
|
|
|
if patternMatch:
|
|
self.query_one("#pattern_input", Input).value = pattern.replace(patternMatch.group(1), FileProperties.SE_INDICATOR_PATTERN)
|
|
|
|
|
|
if event.button.id == "select_default_button":
|
|
selectedTrackDescriptor = self.getSelectedTrackDescriptor()
|
|
self.__sourceMediaDescriptor.setDefaultSubTrack(selectedTrackDescriptor.getType(), selectedTrackDescriptor.getSubIndex())
|
|
self.updateTracks()
|
|
|
|
if event.button.id == "select_forced_button":
|
|
selectedTrackDescriptor = self.getSelectedTrackDescriptor()
|
|
self.__sourceMediaDescriptor.setForcedSubTrack(selectedTrackDescriptor.getType(), selectedTrackDescriptor.getSubIndex())
|
|
self.updateTracks()
|
|
|
|
|
|
def getSelectedTrackDescriptor(self):
|
|
"""Returns a partial track descriptor"""
|
|
try:
|
|
|
|
# Fetch the currently selected row when 'Enter' is pressed
|
|
#selected_row_index = self.table.cursor_row
|
|
row_key, col_key = self.tracksTable.coordinate_to_cell_key(self.tracksTable.cursor_coordinate)
|
|
|
|
if row_key is not None:
|
|
selected_track_data = self.tracksTable.get_row(row_key)
|
|
|
|
kwargs = {}
|
|
kwargs[TrackDescriptor.CONTEXT_KEY] = self.context
|
|
kwargs[TrackDescriptor.INDEX_KEY] = int(selected_track_data[0])
|
|
kwargs[TrackDescriptor.TRACK_TYPE_KEY] = TrackType.fromLabel(selected_track_data[1])
|
|
kwargs[TrackDescriptor.SUB_INDEX_KEY] = int(selected_track_data[2])
|
|
kwargs[TrackDescriptor.CODEC_KEY] = TrackCodec.fromLabel(selected_track_data[3])
|
|
kwargs[TrackDescriptor.AUDIO_LAYOUT_KEY] = AudioLayout.fromLabel(selected_track_data[4])
|
|
|
|
return TrackDescriptor(**kwargs)
|
|
else:
|
|
return None
|
|
|
|
except CellDoesNotExist:
|
|
return None
|
|
|
|
|
|
def getSelectedShowDescriptor(self) -> ShowDescriptor:
|
|
|
|
try:
|
|
|
|
row_key, col_key = self.showsTable.coordinate_to_cell_key(self.showsTable.cursor_coordinate)
|
|
|
|
if row_key is not None:
|
|
selected_row_data = self.showsTable.get_row(row_key)
|
|
|
|
try:
|
|
kwargs = {}
|
|
|
|
kwargs[ShowDescriptor.ID_KEY] = int(selected_row_data[0])
|
|
kwargs[ShowDescriptor.NAME_KEY] = str(selected_row_data[1])
|
|
kwargs[ShowDescriptor.YEAR_KEY] = int(selected_row_data[2])
|
|
|
|
return ShowDescriptor(**kwargs)
|
|
|
|
except ValueError:
|
|
return None
|
|
|
|
except CellDoesNotExist:
|
|
return None
|
|
|
|
|
|
def handle_new_pattern(self, showDescriptor: ShowDescriptor):
|
|
""""""
|
|
|
|
if type(showDescriptor) is not ShowDescriptor:
|
|
raise TypeError("MediaDetailsScreen.handle_new_pattern(): Argument 'showDescriptor' has to be of type ShowDescriptor")
|
|
|
|
self.removeShow()
|
|
|
|
showRowIndex = self.getRowIndexFromShowId(showDescriptor.getId())
|
|
if showRowIndex is None:
|
|
show = (showDescriptor.getId(), showDescriptor.getName(), showDescriptor.getYear())
|
|
self.showsTable.add_row(*map(str, show))
|
|
|
|
showRowIndex = self.getRowIndexFromShowId(showDescriptor.getId())
|
|
if showRowIndex is not None:
|
|
self.showsTable.move_cursor(row=showRowIndex)
|
|
|
|
patternObj = self.getPatternObjFromInput()
|
|
|
|
if patternObj:
|
|
patternId = self.__pc.addPattern(patternObj)
|
|
if patternId:
|
|
self.highlightPattern(False)
|
|
|
|
for tagKey, tagValue in self.__sourceMediaDescriptor.getTags().items():
|
|
|
|
# Filter tags that make no sense to preserve
|
|
if tagKey not in self.__ignoreGlobalKeys and not tagKey in self.__removeGlobalKeys:
|
|
self.__tac.updateMediaTag(patternId, tagKey, tagValue)
|
|
|
|
# for trackDescriptor in self.__sourceMediaDescriptor.getAllTrackDescriptors():
|
|
for trackDescriptor in self.__sourceMediaDescriptor.getTrackDescriptors():
|
|
self.__tc.addTrack(trackDescriptor, patternId = patternId)
|
|
|
|
|
|
def action_new_pattern(self):
|
|
"""Adding new patterns
|
|
|
|
If the corresponding show does not exists in DB it is added beforehand"""
|
|
|
|
selectedShowDescriptor = self.getSelectedShowDescriptor()
|
|
|
|
#HINT: Callback is invoked after this method has exited. As a workaround the callback is executed directly
|
|
# from here with a mock-up screen result containing the necessary part of keys to perform correctly.
|
|
if selectedShowDescriptor is None:
|
|
self.app.push_screen(ShowDetailsScreen(), self.handle_new_pattern)
|
|
else:
|
|
self.handle_new_pattern(selectedShowDescriptor)
|
|
|
|
|
|
def action_update_pattern(self):
|
|
"""Updating patterns
|
|
|
|
When updating the database the actions must reverse the difference (eq to diff db->file)"""
|
|
|
|
if self.__currentPattern is not None:
|
|
patternObj = self.getPatternObjFromInput()
|
|
if (patternObj
|
|
and self.__currentPattern.getPattern() != patternObj['pattern']):
|
|
return self.__pc.updatePattern(self.__currentPattern.getId(), patternObj)
|
|
|
|
self.loadProperties()
|
|
|
|
# __mediaChangeSetObj is file vs database
|
|
if MediaDescriptorChangeSet.TAGS_KEY in self.__mediaChangeSetObj.keys():
|
|
|
|
if DIFF_ADDED_KEY in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TAGS_KEY].keys():
|
|
for addedTagKey in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TAGS_KEY][DIFF_ADDED_KEY].keys():
|
|
# click.ClickException(f"delete media tag patternId={self.__currentPattern.getId()} addedTagKey={addedTagKey}")
|
|
self.__tac.deleteMediaTagByKey(self.__currentPattern.getId(), addedTagKey)
|
|
|
|
if DIFF_REMOVED_KEY in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TAGS_KEY].keys():
|
|
for removedTagKey in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TAGS_KEY][DIFF_REMOVED_KEY].keys():
|
|
currentTags = self.__sourceMediaDescriptor.getTags()
|
|
# click.ClickException(f"delete media tag patternId={self.__currentPattern.getId()} removedTagKey={removedTagKey} currentTags={currentTags[removedTagKey]}")
|
|
self.__tac.updateMediaTag(self.__currentPattern.getId(), removedTagKey, currentTags[removedTagKey])
|
|
|
|
if DIFF_CHANGED_KEY in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TAGS_KEY].keys():
|
|
for changedTagKey in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TAGS_KEY][DIFF_CHANGED_KEY].keys():
|
|
currentTags = self.__sourceMediaDescriptor.getTags()
|
|
# click.ClickException(f"delete media tag patternId={self.__currentPattern.getId()} changedTagKey={changedTagKey} currentTags={currentTags[changedTagKey]}")
|
|
self.__tac.updateMediaTag(self.__currentPattern.getId(), changedTagKey, currentTags[changedTagKey])
|
|
|
|
if MediaDescriptorChangeSet.TRACKS_KEY in self.__mediaChangeSetObj.keys():
|
|
|
|
if DIFF_ADDED_KEY in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TRACKS_KEY].keys():
|
|
|
|
for trackIndex, trackDescriptor in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TRACKS_KEY][DIFF_ADDED_KEY].items():
|
|
#targetTracks = [t for t in self.__targetMediaDescriptor.getAllTrackDescriptors() if t.getIndex() == addedTrackIndex]
|
|
# if targetTracks:
|
|
# self.__tc.deleteTrack(targetTracks[0].getId()) # id
|
|
# self.__tc.deleteTrack(targetTracks[0].getId())
|
|
self.__tc.addTrack(trackDescriptor, patternId = self.__currentPattern.getId())
|
|
|
|
if DIFF_REMOVED_KEY in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TRACKS_KEY].keys():
|
|
trackDescriptor: TrackDescriptor
|
|
for trackIndex, trackDescriptor in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TRACKS_KEY][DIFF_REMOVED_KEY].items():
|
|
# Track per inspect/update hinzufügen
|
|
#self.__tc.addTrack(removedTrack, patternId = self.__currentPattern.getId())
|
|
self.__tc.deleteTrack(trackDescriptor.getId())
|
|
|
|
if DIFF_CHANGED_KEY in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TRACKS_KEY].keys():
|
|
|
|
# [vsTracks[tp].getIndex()] = trackDiff
|
|
for trackIndex, trackDiff in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TRACKS_KEY][DIFF_CHANGED_KEY].items():
|
|
|
|
targetTracks = [t for t in self.__targetMediaDescriptor.getTrackDescriptors() if t.getIndex() == trackIndex]
|
|
targetTrackId = targetTracks[0].getId() if targetTracks else None
|
|
targetTrackIndex = targetTracks[0].getIndex() if targetTracks else None
|
|
|
|
changedCurrentTracks = [t for t in self.__sourceMediaDescriptor.getTrackDescriptors() if t.getIndex() == trackIndex]
|
|
# changedCurrentTrackId #HINT: Undefined as track descriptors do not come from file with track_id
|
|
|
|
if TrackDescriptor.TAGS_KEY in trackDiff.keys():
|
|
tagsDiff = trackDiff[TrackDescriptor.TAGS_KEY]
|
|
|
|
if DIFF_ADDED_KEY in tagsDiff.keys():
|
|
for tagKey, tagValue in tagsDiff[DIFF_ADDED_KEY].items():
|
|
|
|
# if targetTracks:
|
|
# self.__tac.deleteTrackTagByKey(targetTrackId, addedTrackTagKey)
|
|
self.__tac.updateTrackTag(targetTrackId, tagKey, tagValue)
|
|
|
|
|
|
if DIFF_REMOVED_KEY in tagsDiff.keys():
|
|
for tagKey, tagValue in tagsDiff[DIFF_REMOVED_KEY].items():
|
|
# if changedCurrentTracks:
|
|
# self.__tac.updateTrackTag(targetTrackId, removedTrackTagKey, changedCurrentTracks[0].getTags()[removedTrackTagKey])
|
|
self.__tac.deleteTrackTagByKey(targetTrackId, tagKey)
|
|
|
|
if DIFF_CHANGED_KEY in tagsDiff.keys():
|
|
for tagKey, tagValue in tagsDiff[DIFF_CHANGED_KEY].items():
|
|
# if changedCurrentTracks:
|
|
# self.__tac.updateTrackTag(targetTrackId, changedTrackTagKey, changedCurrentTracks[0].getTags()[changedTrackTagKey])
|
|
self.__tac.updateTrackTag(targetTrackId, tagKey, tagValue)
|
|
|
|
|
|
if TrackDescriptor.DISPOSITION_SET_KEY in trackDiff.keys():
|
|
changedTrackDispositionDiff = trackDiff[TrackDescriptor.DISPOSITION_SET_KEY]
|
|
|
|
if DIFF_ADDED_KEY in changedTrackDispositionDiff.keys():
|
|
for changedDisposition in changedTrackDispositionDiff[DIFF_ADDED_KEY]:
|
|
if targetTrackIndex is not None:
|
|
self.__tc.setDispositionState(self.__currentPattern.getId(), targetTrackIndex, changedDisposition, True)
|
|
|
|
if DIFF_REMOVED_KEY in changedTrackDispositionDiff.keys():
|
|
for changedDisposition in changedTrackDispositionDiff[DIFF_REMOVED_KEY]:
|
|
if targetTrackIndex is not None:
|
|
self.__tc.setDispositionState(self.__currentPattern.getId(), targetTrackIndex, changedDisposition, False)
|
|
|
|
|
|
self.updateDifferences()
|
|
|
|
|
|
|
|
def action_edit_pattern(self):
|
|
|
|
patternObj = self.getPatternObjFromInput()
|
|
|
|
if patternObj['pattern']:
|
|
|
|
selectedPatternId = self.__pc.findPattern(patternObj)
|
|
|
|
if selectedPatternId is None:
|
|
raise click.ClickException(f"MediaDetailsScreen.action_edit_pattern(): Pattern to edit has no id")
|
|
|
|
self.app.push_screen(PatternDetailsScreen(patternId = selectedPatternId, showId = self.getSelectedShowDescriptor().getId()), self.handle_edit_pattern) # <-
|
|
|
|
|
|
def handle_edit_pattern(self, screenResult):
|
|
self.query_one("#pattern_input", Input).value = screenResult['pattern']
|
|
self.updateDifferences()
|
|
|