inc update diffs mwe
This commit is contained in:
@@ -193,8 +193,10 @@ class FileProperties():
|
|||||||
|
|
||||||
|
|
||||||
def getShowId(self) -> int:
|
def getShowId(self) -> int:
|
||||||
|
"""Result is -1 if the filename did not match anything in database"""
|
||||||
return self.__pattern.getShowId() if self.__pattern is not None else -1
|
return self.__pattern.getShowId() if self.__pattern is not None else -1
|
||||||
|
|
||||||
def getPattern(self) -> Pattern:
|
def getPattern(self) -> Pattern:
|
||||||
|
"""Result is None if the filename did not match anything in database"""
|
||||||
return self.__pattern
|
return self.__pattern
|
||||||
|
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
DIFF_ADDED_KEY = 'added'
|
||||||
|
DIFF_REMOVED_KEY = 'removed'
|
||||||
|
DIFF_CHANGED_KEY = 'changed'
|
||||||
|
|
||||||
def dictDiff(a : dict, b : dict):
|
def dictDiff(a : dict, b : dict):
|
||||||
|
|
||||||
a_keys = set(a.keys())
|
a_keys = set(a.keys())
|
||||||
|
|||||||
@@ -5,12 +5,14 @@ from typing import List, Self
|
|||||||
from ffx.track_type import TrackType
|
from ffx.track_type import TrackType
|
||||||
from ffx.track_descriptor import TrackDescriptor
|
from ffx.track_descriptor import TrackDescriptor
|
||||||
|
|
||||||
from ffx.helper import dictDiff
|
from ffx.helper import dictDiff, DIFF_ADDED_KEY, DIFF_CHANGED_KEY, DIFF_REMOVED_KEY
|
||||||
|
|
||||||
class MediaDescriptor():
|
class MediaDescriptor():
|
||||||
"""This class represents the structural content of a media file including streams and metadata"""
|
"""This class represents the structural content of a media file including streams and metadata"""
|
||||||
|
|
||||||
TAGS_KEY = 'tags'
|
TAGS_KEY = 'tags'
|
||||||
|
TRACKS_KEY = 'tracks'
|
||||||
|
|
||||||
TRACK_DESCRIPTOR_LIST_KEY = 'track_descriptors'
|
TRACK_DESCRIPTOR_LIST_KEY = 'track_descriptors'
|
||||||
CLEAR_TAGS_KEY = 'clear_tags'
|
CLEAR_TAGS_KEY = 'clear_tags'
|
||||||
|
|
||||||
@@ -18,7 +20,6 @@ class MediaDescriptor():
|
|||||||
FFPROBE_TAGS_KEY = 'tags'
|
FFPROBE_TAGS_KEY = 'tags'
|
||||||
FFPROBE_CODEC_TYPE_KEY = 'codec_type'
|
FFPROBE_CODEC_TYPE_KEY = 'codec_type'
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
|
|
||||||
if MediaDescriptor.TAGS_KEY in kwargs.keys():
|
if MediaDescriptor.TAGS_KEY in kwargs.keys():
|
||||||
@@ -101,12 +102,12 @@ class MediaDescriptor():
|
|||||||
if not isinstance(vsMediaDescriptor, self.__class__):
|
if not isinstance(vsMediaDescriptor, self.__class__):
|
||||||
raise click.ClickException(f"MediaDescriptor.compare(): Argument is required to be of type {self.__class__}")
|
raise click.ClickException(f"MediaDescriptor.compare(): Argument is required to be of type {self.__class__}")
|
||||||
|
|
||||||
mediaTagsResult = dictDiff(vsMediaDescriptor.getTags(), self.getTags())
|
tagsDiff = dictDiff(vsMediaDescriptor.getTags(), self.getTags())
|
||||||
|
|
||||||
compareResult = {}
|
compareResult = {}
|
||||||
|
|
||||||
if mediaTagsResult:
|
if tagsDiff:
|
||||||
compareResult['tags'] = mediaTagsResult
|
compareResult[MediaDescriptor.TAGS_KEY] = tagsDiff
|
||||||
|
|
||||||
|
|
||||||
# Target track configuration (from DB)
|
# Target track configuration (from DB)
|
||||||
@@ -127,27 +128,27 @@ class MediaDescriptor():
|
|||||||
|
|
||||||
# Will trigger if tracks are missing in file
|
# Will trigger if tracks are missing in file
|
||||||
if tp > (numVsTracks - 1):
|
if tp > (numVsTracks - 1):
|
||||||
if 'removed' not in trackCompareResult.keys():
|
if DIFF_REMOVED_KEY not in trackCompareResult.keys():
|
||||||
trackCompareResult['removed'] = set()
|
trackCompareResult[DIFF_REMOVED_KEY] = set()
|
||||||
trackCompareResult['removed'].add(tracks[tp].getIndex())
|
trackCompareResult[DIFF_REMOVED_KEY].add(tracks[tp].getIndex())
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Will trigger if tracks are missing in DB definition
|
# Will trigger if tracks are missing in DB definition
|
||||||
if tp > (numTracks - 1):
|
if tp > (numTracks - 1):
|
||||||
if 'added' not in trackCompareResult.keys():
|
if DIFF_ADDED_KEY not in trackCompareResult.keys():
|
||||||
trackCompareResult['added'] = {}
|
trackCompareResult[DIFF_ADDED_KEY] = {}
|
||||||
trackCompareResult['added'][vsTracks[tp].getIndex()] = vsTracks[tp]
|
trackCompareResult[DIFF_ADDED_KEY][vsTracks[tp].getIndex()] = vsTracks[tp]
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# assumption is made here that the track order will not change for all files of a sequence
|
# assumption is made here that the track order will not change for all files of a sequence
|
||||||
tdiff = tracks[tp].compare(vsTracks[tp])
|
tdiff = tracks[tp].compare(vsTracks[tp])
|
||||||
|
|
||||||
if tdiff:
|
if tdiff:
|
||||||
if 'changed' not in trackCompareResult.keys():
|
if DIFF_CHANGED_KEY not in trackCompareResult.keys():
|
||||||
trackCompareResult['changed'] = {}
|
trackCompareResult[DIFF_CHANGED_KEY] = {}
|
||||||
trackCompareResult['changed'][vsTracks[tp].getIndex()] = tdiff
|
trackCompareResult[DIFF_CHANGED_KEY][vsTracks[tp].getIndex()] = tdiff
|
||||||
|
|
||||||
if trackCompareResult:
|
if trackCompareResult:
|
||||||
compareResult['tracks'] = trackCompareResult
|
compareResult[MediaDescriptor.TRACKS_KEY] = trackCompareResult
|
||||||
|
|
||||||
return compareResult
|
return compareResult
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ from ffx.model.pattern import Pattern
|
|||||||
from .pattern_controller import PatternController
|
from .pattern_controller import PatternController
|
||||||
from .show_controller import ShowController
|
from .show_controller import ShowController
|
||||||
from .track_controller import TrackController
|
from .track_controller import TrackController
|
||||||
|
from .tag_controller import TagController
|
||||||
|
|
||||||
from .track_details_screen import TrackDetailsScreen
|
from .track_details_screen import TrackDetailsScreen
|
||||||
from .track_delete_screen import TrackDeleteScreen
|
from .track_delete_screen import TrackDeleteScreen
|
||||||
@@ -27,6 +28,8 @@ from textual.widgets._data_table import CellDoesNotExist
|
|||||||
from ffx.media_descriptor import MediaDescriptor
|
from ffx.media_descriptor import MediaDescriptor
|
||||||
from ffx.file_properties import FileProperties
|
from ffx.file_properties import FileProperties
|
||||||
|
|
||||||
|
from ffx.helper import DIFF_ADDED_KEY, DIFF_CHANGED_KEY, DIFF_REMOVED_KEY
|
||||||
|
|
||||||
|
|
||||||
# Screen[dict[int, str, int]]
|
# Screen[dict[int, str, int]]
|
||||||
class MediaDetailsScreen(Screen):
|
class MediaDetailsScreen(Screen):
|
||||||
@@ -108,6 +111,7 @@ class MediaDetailsScreen(Screen):
|
|||||||
self.__pc = PatternController(context = self.context)
|
self.__pc = PatternController(context = self.context)
|
||||||
self.__sc = ShowController(context = self.context)
|
self.__sc = ShowController(context = self.context)
|
||||||
self.__tc = TrackController(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':
|
if not 'command' in self.context.keys() or self.context['command'] != 'inspect':
|
||||||
raise click.ClickException(f"MediaDetailsScreen.__init__(): Can only perform command 'inspect'")
|
raise click.ClickException(f"MediaDetailsScreen.__init__(): Can only perform command 'inspect'")
|
||||||
@@ -120,14 +124,8 @@ class MediaDetailsScreen(Screen):
|
|||||||
if not os.path.isfile(self.__mediaFilename):
|
if not os.path.isfile(self.__mediaFilename):
|
||||||
raise click.ClickException(f"MediaDetailsScreen.__init__(): Media file {self.__mediaFilename} does not exist")
|
raise click.ClickException(f"MediaDetailsScreen.__init__(): Media file {self.__mediaFilename} does not exist")
|
||||||
|
|
||||||
self.__mediaFileProperties = FileProperties(self.context, self.__mediaFilename)
|
|
||||||
self.__mediaDescriptor = self.__mediaFileProperties.getMediaDescriptor()
|
|
||||||
|
|
||||||
self.__mediaFilenamePattern = self.__mediaFileProperties.getPattern()
|
|
||||||
|
|
||||||
self.__storedMediaFilenamePattern = self.__mediaFilenamePattern.getMediaDescriptor() if self.__mediaFilenamePattern is not None else None
|
|
||||||
|
|
||||||
|
|
||||||
|
self.loadProperties()
|
||||||
# def loadTracks(self, show_id):
|
# def loadTracks(self, show_id):
|
||||||
#
|
#
|
||||||
# try:
|
# try:
|
||||||
@@ -206,9 +204,83 @@ class MediaDetailsScreen(Screen):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def loadProperties(self):
|
||||||
|
|
||||||
|
self.__mediaFileProperties = FileProperties(self.context, self.__mediaFilename)
|
||||||
|
self.__currentMediaDescriptor = self.__mediaFileProperties.getMediaDescriptor()
|
||||||
|
|
||||||
|
#HINT: This is None if the filename did not match anything in database
|
||||||
|
self.__currentPattern = self.__mediaFileProperties.getPattern()
|
||||||
|
|
||||||
|
self.__targetMediaDescriptor = self.__currentPattern.getMediaDescriptor() if self.__currentPattern is not None else None
|
||||||
|
|
||||||
|
# Enumerating differences between media descriptors
|
||||||
|
# from file (=current) vs from stored in database (=target)
|
||||||
|
self.__mediaDifferences = self.__targetMediaDescriptor.compare(self.__currentMediaDescriptor) if self.__currentPattern is not None else {}
|
||||||
|
|
||||||
|
|
||||||
|
def updateDifferences(self):
|
||||||
|
|
||||||
|
self.loadProperties()
|
||||||
|
|
||||||
|
self.differencesTable.clear()
|
||||||
|
|
||||||
|
if 'tags' in self.__mediaDifferences.keys():
|
||||||
|
|
||||||
|
currentTags = self.__currentMediaDescriptor.getTags()
|
||||||
|
targetTags = self.__targetMediaDescriptor.getTags()
|
||||||
|
|
||||||
|
if 'added' in self.__mediaDifferences['tags'].keys():
|
||||||
|
for addedTagKey in self.__mediaDifferences['tags']['added']:
|
||||||
|
row = (f"added media tag: key='{addedTagKey}' value='{targetTags[addedTagKey]}'",)
|
||||||
|
self.differencesTable.add_row(*map(str, row))
|
||||||
|
|
||||||
|
if 'removed' in self.__mediaDifferences['tags'].keys():
|
||||||
|
for removedTagKey in self.__mediaDifferences['tags']['removed']:
|
||||||
|
row = (f"removed media tag: key='{removedTagKey}' value='{currentTags[removedTagKey]}'",)
|
||||||
|
self.differencesTable.add_row(*map(str, row))
|
||||||
|
|
||||||
|
|
||||||
|
if 'tracks' in self.__mediaDifferences.keys():
|
||||||
|
|
||||||
|
currentTracks = self.__currentMediaDescriptor.getAllTracks() # 0,1,2,3
|
||||||
|
targetTracks = self.__targetMediaDescriptor.getAllTracks() # 0 <- from DB
|
||||||
|
|
||||||
|
if 'added' in self.__mediaDifferences['tracks'].keys():
|
||||||
|
for addedTrackIndex in self.__mediaDifferences['tracks']['added'].keys():
|
||||||
|
addedTrack : Track = currentTracks[addedTrackIndex]
|
||||||
|
row = (f"added {addedTrack.getType().label()} track: index={addedTrackIndex} lang={addedTrack.getLanguage().threeLetter()}",)
|
||||||
|
self.differencesTable.add_row(*map(str, row))
|
||||||
|
|
||||||
|
if 'removed' in self.__mediaDifferences['tracks'].keys():
|
||||||
|
for removedTrackIndex in self.__mediaDifferences['tracks']['removed']:
|
||||||
|
row = (f"removed track: index={removedTrackIndex}",)
|
||||||
|
self.differencesTable.add_row(*map(str, row))
|
||||||
|
|
||||||
|
if 'changed' in self.__mediaDifferences['tracks'].keys():
|
||||||
|
for changedTrackIndex in self.__mediaDifferences['tracks']['changed'].keys():
|
||||||
|
|
||||||
|
changedTrack : Track = targetTracks[changedTrackIndex]
|
||||||
|
changedTrackDiff : dict = self.__mediaDifferences['tracks']['changed'][changedTrackIndex]
|
||||||
|
|
||||||
|
if 'tags' in changedTrackDiff.keys():
|
||||||
|
|
||||||
|
if 'added' in changedTrackDiff['tags']:
|
||||||
|
for addedTagKey in changedTrackDiff['tags']['added']:
|
||||||
|
|
||||||
|
addedTagValue = changedTrack.getTags()[addedTagKey]
|
||||||
|
row = (f"changed {changedTrack.getType().label()} track index={changedTrackIndex} added key={addedTagKey} value={addedTagValue}",)
|
||||||
|
self.differencesTable.add_row(*map(str, row))
|
||||||
|
|
||||||
|
if 'removed' in changedTrackDiff['tags']:
|
||||||
|
for removedTagKey in changedTrackDiff['tags']['removed']:
|
||||||
|
row = (f"changed {changedTrack.getType().label()} track index={changedTrackIndex} removed key={removedTagKey}",)
|
||||||
|
self.differencesTable.add_row(*map(str, row))
|
||||||
|
|
||||||
|
|
||||||
def on_mount(self):
|
def on_mount(self):
|
||||||
|
|
||||||
if self.__mediaFilenamePattern is None:
|
if self.__currentPattern is None:
|
||||||
row = (' ', '<New show>', ' ') # Convert each element to a string before adding
|
row = (' ', '<New show>', ' ') # Convert each element to a string before adding
|
||||||
self.showsTable.add_row(*map(str, row))
|
self.showsTable.add_row(*map(str, row))
|
||||||
|
|
||||||
@@ -216,78 +288,23 @@ class MediaDetailsScreen(Screen):
|
|||||||
row = (int(show.id), show.name, show.year) # Convert each element to a string before adding
|
row = (int(show.id), show.name, show.year) # Convert each element to a string before adding
|
||||||
self.showsTable.add_row(*map(str, row))
|
self.showsTable.add_row(*map(str, row))
|
||||||
|
|
||||||
for mediaTagKey, mediaTagValue in self.__mediaDescriptor.getTags().items():
|
for mediaTagKey, mediaTagValue in self.__currentMediaDescriptor.getTags().items():
|
||||||
row = (mediaTagKey, mediaTagValue) # Convert each element to a string before adding
|
row = (mediaTagKey, mediaTagValue) # Convert each element to a string before adding
|
||||||
self.mediaTagsTable.add_row(*map(str, row))
|
self.mediaTagsTable.add_row(*map(str, row))
|
||||||
|
|
||||||
#self.updateAudioTracks(self.__mediaDescriptor.getAudioTracks())
|
|
||||||
#self.updateSubtitleTracks(self.__mediaDescriptor.getSubtitleTracks())
|
|
||||||
self.updateTracks()
|
self.updateTracks()
|
||||||
|
|
||||||
if self.__mediaFilenamePattern is not None:
|
|
||||||
|
|
||||||
showIdentifier = self.__mediaFilenamePattern.getShowId()
|
if self.__currentPattern is not None:
|
||||||
|
|
||||||
|
showIdentifier = self.__currentPattern.getShowId()
|
||||||
showRowIndex = self.getRowIndexFromShowId(showIdentifier)
|
showRowIndex = self.getRowIndexFromShowId(showIdentifier)
|
||||||
if showRowIndex is not None:
|
if showRowIndex is not None:
|
||||||
self.showsTable.move_cursor(row=showRowIndex)
|
self.showsTable.move_cursor(row=showRowIndex)
|
||||||
|
|
||||||
|
self.query_one("#pattern_input", Input).value = self.__currentPattern.getPattern()
|
||||||
|
|
||||||
self.query_one("#pattern_input", Input).value = self.__mediaFilenamePattern.getPattern()
|
self.updateDifferences()
|
||||||
|
|
||||||
# Enumerating differences between media descriptor from file vs from stored in database
|
|
||||||
targetMediaDescriptor = self.__mediaFilenamePattern.getMediaDescriptor()
|
|
||||||
mediaDifferences = targetMediaDescriptor.compare(self.__mediaDescriptor)
|
|
||||||
|
|
||||||
if 'tags' in mediaDifferences.keys():
|
|
||||||
|
|
||||||
mediaTags = self.__mediaDescriptor.getTags()
|
|
||||||
|
|
||||||
if 'added' in mediaDifferences['tags'].keys():
|
|
||||||
for addedTagKey in mediaDifferences['tags']['added']:
|
|
||||||
row = (f"added media tag: key='{addedTagKey}' value='{mediaTags[addedTagKey]}'",)
|
|
||||||
self.differencesTable.add_row(*map(str, row))
|
|
||||||
|
|
||||||
if 'removed' in mediaDifferences['tags'].keys():
|
|
||||||
for removedTagKey in mediaDifferences['tags']['removed']:
|
|
||||||
row = (f"removed media tag: key='{removedTagKey}' value='{mediaTags[removedTagKey]}'",)
|
|
||||||
self.differencesTable.add_row(*map(str, row))
|
|
||||||
|
|
||||||
|
|
||||||
if 'tracks' in mediaDifferences.keys():
|
|
||||||
|
|
||||||
currentTracks = self.__mediaDescriptor.getAllTracks() # 0,1,2,3
|
|
||||||
targetTracks = targetMediaDescriptor.getAllTracks() # 0 <- from DB
|
|
||||||
|
|
||||||
if 'added' in mediaDifferences['tracks'].keys():
|
|
||||||
for addedTrackIndex in mediaDifferences['tracks']['added'].keys():
|
|
||||||
addedTrack : Track = currentTracks[addedTrackIndex]
|
|
||||||
row = (f"added {addedTrack.getType().label()} track: index={addedTrackIndex} subIndex={addedTrack.getSubIndex()} lang={addedTrack.getLanguage().threeLetter()}",)
|
|
||||||
self.differencesTable.add_row(*map(str, row))
|
|
||||||
|
|
||||||
if 'removed' in mediaDifferences['tracks'].keys():
|
|
||||||
for removedTrackIndex in mediaDifferences['tracks']['removed']:
|
|
||||||
row = (f"removed track: index={removedTrackIndex}",)
|
|
||||||
self.differencesTable.add_row(*map(str, row))
|
|
||||||
|
|
||||||
if 'changed' in mediaDifferences['tracks'].keys():
|
|
||||||
for changedTrackIndex in mediaDifferences['tracks']['changed'].keys():
|
|
||||||
|
|
||||||
changedTrack : Track = targetTracks[changedTrackIndex]
|
|
||||||
changedTrackDiff : dict = mediaDifferences['tracks']['changed'][changedTrackIndex]
|
|
||||||
|
|
||||||
if 'tags' in changedTrackDiff.keys():
|
|
||||||
|
|
||||||
if 'added' in changedTrackDiff['tags']:
|
|
||||||
for addedTagKey in changedTrackDiff['tags']['added']:
|
|
||||||
|
|
||||||
addedTagValue = changedTrack.getTags()[addedTagKey]
|
|
||||||
row = (f"changed {changedTrack.getType().label()} track index={changedTrackIndex} added key={addedTagKey} value={addedTagValue}",)
|
|
||||||
self.differencesTable.add_row(*map(str, row))
|
|
||||||
|
|
||||||
if 'removed' in changedTrackDiff['tags']:
|
|
||||||
for removedTagKey in changedTrackDiff['tags']['removed']:
|
|
||||||
row = (f"changed {changedTrack.getType().label()} track index={changedTrackIndex} removed key={removedTagKey}",)
|
|
||||||
self.differencesTable.add_row(*map(str, row))
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
||||||
@@ -300,7 +317,7 @@ class MediaDetailsScreen(Screen):
|
|||||||
|
|
||||||
self.tracksTable.clear()
|
self.tracksTable.clear()
|
||||||
|
|
||||||
trackDescriptorList = self.__mediaDescriptor.getAllTracks()
|
trackDescriptorList = self.__currentMediaDescriptor.getAllTracks()
|
||||||
|
|
||||||
typeCounter = {}
|
typeCounter = {}
|
||||||
|
|
||||||
@@ -369,7 +386,7 @@ class MediaDetailsScreen(Screen):
|
|||||||
self.differencesTable = DataTable(id='differences-table') # classes="triple"
|
self.differencesTable = DataTable(id='differences-table') # classes="triple"
|
||||||
|
|
||||||
# Define the columns with headers
|
# Define the columns with headers
|
||||||
self.column_key_differences = self.differencesTable.add_column("Differences", width=70)
|
self.column_key_differences = self.differencesTable.add_column("Differences (file->db)", width=70)
|
||||||
|
|
||||||
self.differencesTable.cursor_type = 'row'
|
self.differencesTable.cursor_type = 'row'
|
||||||
|
|
||||||
@@ -667,3 +684,39 @@ class MediaDetailsScreen(Screen):
|
|||||||
#
|
#
|
||||||
# except CellDoesNotExist:
|
# except CellDoesNotExist:
|
||||||
# pass
|
# pass
|
||||||
|
|
||||||
|
|
||||||
|
def action_new_pattern(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def action_update_pattern(self):
|
||||||
|
"""When updating the database the actions must reverse the difference (eq to diff db->file)"""
|
||||||
|
|
||||||
|
if MediaDescriptor.TAGS_KEY in self.__mediaDifferences.keys():
|
||||||
|
if DIFF_ADDED_KEY in self.__mediaDifferences[MediaDescriptor.TAGS_KEY].keys():
|
||||||
|
for addedTagKey in self.__mediaDifferences[MediaDescriptor.TAGS_KEY][DIFF_ADDED_KEY]:
|
||||||
|
self.__tac.deleteMediaTagByKey(self.__currentPattern.getId(), addedTagKey)
|
||||||
|
if DIFF_REMOVED_KEY in self.__mediaDifferences[MediaDescriptor.TAGS_KEY].keys():
|
||||||
|
for removedTagKey in self.__mediaDifferences[MediaDescriptor.TAGS_KEY][DIFF_REMOVED_KEY]:
|
||||||
|
mediaTags = self.__currentMediaDescriptor.getTags()
|
||||||
|
self.__tac.updateMediaTag(self.__currentPattern.getId(), removedTagKey, mediaTags[removedTagKey])
|
||||||
|
if DIFF_CHANGED_KEY in self.__mediaDifferences[MediaDescriptor.TAGS_KEY].keys():
|
||||||
|
for changedTagKey in self.__mediaDifferences[MediaDescriptor.TAGS_KEY][DIFF_CHANGED_KEY]:
|
||||||
|
pass
|
||||||
|
if MediaDescriptor.TRACKS_KEY in self.__mediaDifferences.keys():
|
||||||
|
if DIFF_ADDED_KEY in self.__mediaDifferences[MediaDescriptor.TRACKS_KEY].keys():
|
||||||
|
for addedTrackKey in self.__mediaDifferences[MediaDescriptor.TRACKS_KEY][DIFF_ADDED_KEY]:
|
||||||
|
pass
|
||||||
|
if DIFF_REMOVED_KEY in self.__mediaDifferences[MediaDescriptor.TRACKS_KEY].keys():
|
||||||
|
for removedTrackKey in self.__mediaDifferences[MediaDescriptor.TRACKS_KEY][DIFF_REMOVED_KEY]:
|
||||||
|
pass
|
||||||
|
if DIFF_CHANGED_KEY in self.__mediaDifferences[MediaDescriptor.TRACKS_KEY].keys():
|
||||||
|
for changedTrackKey in self.__mediaDifferences[MediaDescriptor.TRACKS_KEY][DIFF_CHANGED_KEY]:
|
||||||
|
pass
|
||||||
|
|
||||||
|
self.updateDifferences()
|
||||||
|
|
||||||
|
|
||||||
|
def action_edit_pattern(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|||||||
@@ -134,7 +134,6 @@ class PatternController():
|
|||||||
finally:
|
finally:
|
||||||
s.close()
|
s.close()
|
||||||
|
|
||||||
|
|
||||||
def getMediaDescriptor(self, patternId):
|
def getMediaDescriptor(self, patternId):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -142,9 +141,9 @@ class PatternController():
|
|||||||
q = s.query(Pattern).filter(Pattern.id == int(patternId))
|
q = s.query(Pattern).filter(Pattern.id == int(patternId))
|
||||||
|
|
||||||
if q.count():
|
if q.count():
|
||||||
pattern = q.first()
|
return q.first().getMediaDescriptor()
|
||||||
#return self.getPatternDict(pattern)
|
else:
|
||||||
return pattern.getMediaDescriptor()
|
return None
|
||||||
|
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
raise click.ClickException(f"PatternController.getPatternDescriptor(): {repr(ex)}")
|
raise click.ClickException(f"PatternController.getPatternDescriptor(): {repr(ex)}")
|
||||||
|
|||||||
@@ -13,10 +13,14 @@ from ffx.model.track import Track
|
|||||||
from .pattern_controller import PatternController
|
from .pattern_controller import PatternController
|
||||||
from .show_controller import ShowController
|
from .show_controller import ShowController
|
||||||
from .track_controller import TrackController
|
from .track_controller import TrackController
|
||||||
|
from .tag_controller import TagController
|
||||||
|
|
||||||
from .track_details_screen import TrackDetailsScreen
|
from .track_details_screen import TrackDetailsScreen
|
||||||
from .track_delete_screen import TrackDeleteScreen
|
from .track_delete_screen import TrackDeleteScreen
|
||||||
|
|
||||||
|
from .tag_details_screen import TagDetailsScreen
|
||||||
|
from .tag_delete_screen import TagDeleteScreen
|
||||||
|
|
||||||
from ffx.track_type import TrackType
|
from ffx.track_type import TrackType
|
||||||
|
|
||||||
from ffx.track_disposition import TrackDisposition
|
from ffx.track_disposition import TrackDisposition
|
||||||
@@ -31,8 +35,8 @@ class PatternDetailsScreen(Screen):
|
|||||||
CSS = """
|
CSS = """
|
||||||
|
|
||||||
Grid {
|
Grid {
|
||||||
grid-size: 5 9;
|
grid-size: 5 13;
|
||||||
grid-rows: 2 2 2 2 2 6 2 2 2;
|
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;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -73,6 +77,10 @@ class PatternDetailsScreen(Screen):
|
|||||||
#tracks_table {
|
#tracks_table {
|
||||||
row-span: 4;
|
row-span: 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.yellow {
|
||||||
|
tint: yellow 40%;
|
||||||
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, patternId = None, showId = None):
|
def __init__(self, patternId = None, showId = None):
|
||||||
@@ -84,6 +92,7 @@ class PatternDetailsScreen(Screen):
|
|||||||
self.__pc = PatternController(context = self.context)
|
self.__pc = PatternController(context = self.context)
|
||||||
self.__sc = ShowController(context = self.context)
|
self.__sc = ShowController(context = self.context)
|
||||||
self.__tc = TrackController(context = self.context)
|
self.__tc = TrackController(context = self.context)
|
||||||
|
self.__tac = TagController(context = self.context)
|
||||||
|
|
||||||
self.__pattern : Pattern = self.__pc.getPattern(patternId) if patternId is not None else None
|
self.__pattern : Pattern = self.__pc.getPattern(patternId) if patternId is not None else None
|
||||||
|
|
||||||
@@ -143,6 +152,22 @@ class PatternDetailsScreen(Screen):
|
|||||||
|
|
||||||
typeCounter[trackType] += 1
|
typeCounter[trackType] += 1
|
||||||
|
|
||||||
|
def updateTags(self):
|
||||||
|
|
||||||
|
self.tagsTable.clear()
|
||||||
|
|
||||||
|
if self.__pattern is not None:
|
||||||
|
|
||||||
|
# raise click.ClickException(f"patternid={self.__pattern.getId()}") # 1
|
||||||
|
|
||||||
|
tags = self.__tac.findAllMediaTags(self.__pattern.getId())
|
||||||
|
|
||||||
|
#raise click.ClickException(f"tags={tags}") # encoder:blah
|
||||||
|
|
||||||
|
for tagKey, tagValue in tags.items():
|
||||||
|
row = (tagKey, tagValue)
|
||||||
|
self.tagsTable.add_row(*map(str, row))
|
||||||
|
|
||||||
|
|
||||||
def on_mount(self):
|
def on_mount(self):
|
||||||
|
|
||||||
@@ -153,10 +178,21 @@ class PatternDetailsScreen(Screen):
|
|||||||
|
|
||||||
self.query_one("#pattern_input", Input).value = str(self.__pattern.getPattern())
|
self.query_one("#pattern_input", Input).value = str(self.__pattern.getPattern())
|
||||||
|
|
||||||
|
self.updateTags()
|
||||||
self.updateTracks()
|
self.updateTracks()
|
||||||
|
|
||||||
def compose(self):
|
def compose(self):
|
||||||
|
|
||||||
|
|
||||||
|
self.tagsTable = DataTable(classes="five")
|
||||||
|
|
||||||
|
# Define the columns with headers
|
||||||
|
self.column_key_tag_key = self.tagsTable.add_column("Key", width=10)
|
||||||
|
self.column_key_tag_value = self.tagsTable.add_column("Value", width=100)
|
||||||
|
|
||||||
|
self.tagsTable.cursor_type = 'row'
|
||||||
|
|
||||||
|
|
||||||
self.tracksTable = DataTable(id="tracks_table", classes="five")
|
self.tracksTable = DataTable(id="tracks_table", classes="five")
|
||||||
|
|
||||||
self.column_key_track_index = self.tracksTable.add_column("Index", width=5)
|
self.column_key_track_index = self.tracksTable.add_column("Index", width=5)
|
||||||
@@ -191,6 +227,24 @@ class PatternDetailsScreen(Screen):
|
|||||||
yield Static(" ", classes="five")
|
yield Static(" ", classes="five")
|
||||||
|
|
||||||
# 5
|
# 5
|
||||||
|
yield Static("Media Tags")
|
||||||
|
yield Static(" ")
|
||||||
|
|
||||||
|
if self.__pattern is not None:
|
||||||
|
yield Button("Add", id="button_add_tag")
|
||||||
|
yield Button("Edit", id="button_edit_tag")
|
||||||
|
yield Button("Delete", id="button_delete_tag")
|
||||||
|
else:
|
||||||
|
yield Static("")
|
||||||
|
yield Static("")
|
||||||
|
yield Static("")
|
||||||
|
# 6
|
||||||
|
yield self.tagsTable
|
||||||
|
|
||||||
|
# 7
|
||||||
|
yield Static(" ", classes="five")
|
||||||
|
|
||||||
|
# 8
|
||||||
yield Static("Streams")
|
yield Static("Streams")
|
||||||
yield Static(" ")
|
yield Static(" ")
|
||||||
|
|
||||||
@@ -202,19 +256,22 @@ class PatternDetailsScreen(Screen):
|
|||||||
yield Static("")
|
yield Static("")
|
||||||
yield Static("")
|
yield Static("")
|
||||||
yield Static("")
|
yield Static("")
|
||||||
# 6
|
# 9
|
||||||
yield self.tracksTable
|
yield self.tracksTable
|
||||||
|
|
||||||
# 7
|
# 10
|
||||||
yield Static(" ", classes="five")
|
yield Static(" ", classes="five")
|
||||||
|
|
||||||
# 8
|
# 11
|
||||||
yield Static(" ", classes="five")
|
yield Static(" ", classes="five")
|
||||||
|
|
||||||
# 9
|
# 12
|
||||||
yield Button("Save", id="save_button")
|
yield Button("Save", id="save_button")
|
||||||
yield Button("Cancel", id="cancel_button")
|
yield Button("Cancel", id="cancel_button")
|
||||||
|
|
||||||
|
# 13
|
||||||
|
yield Static(" ", classes="five")
|
||||||
|
|
||||||
yield Footer()
|
yield Footer()
|
||||||
|
|
||||||
|
|
||||||
@@ -249,6 +306,31 @@ class PatternDetailsScreen(Screen):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def getSelectedTag(self):
|
||||||
|
|
||||||
|
try:
|
||||||
|
|
||||||
|
# Fetch the currently selected row when 'Enter' is pressed
|
||||||
|
#selected_row_index = self.table.cursor_row
|
||||||
|
row_key, col_key = self.tagsTable.coordinate_to_cell_key(self.tagsTable.cursor_coordinate)
|
||||||
|
|
||||||
|
if row_key is not None:
|
||||||
|
selected_tag_data = self.tagsTable.get_row(row_key)
|
||||||
|
|
||||||
|
tagKey = str(selected_tag_data[0])
|
||||||
|
tagValue = str(selected_tag_data[1])
|
||||||
|
|
||||||
|
return tagKey, tagValue
|
||||||
|
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
except CellDoesNotExist:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Event handler for button press
|
# Event handler for button press
|
||||||
def on_button_pressed(self, event: Button.Pressed) -> None:
|
def on_button_pressed(self, event: Button.Pressed) -> None:
|
||||||
# Check if the button pressed is the one we are interested in
|
# Check if the button pressed is the one we are interested in
|
||||||
@@ -276,7 +358,6 @@ class PatternDetailsScreen(Screen):
|
|||||||
self.app.pop_screen()
|
self.app.pop_screen()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if event.button.id == "cancel_button":
|
if event.button.id == "cancel_button":
|
||||||
self.app.pop_screen()
|
self.app.pop_screen()
|
||||||
|
|
||||||
@@ -296,6 +377,20 @@ class PatternDetailsScreen(Screen):
|
|||||||
if event.button.id == "button_delete_track":
|
if event.button.id == "button_delete_track":
|
||||||
self.app.push_screen(TrackDeleteScreen(trackDescriptor = selectedTrack), self.handle_delete_track)
|
self.app.push_screen(TrackDeleteScreen(trackDescriptor = selectedTrack), self.handle_delete_track)
|
||||||
|
|
||||||
|
|
||||||
|
if event.button.id == "button_add_tag":
|
||||||
|
if self.__pattern is not None:
|
||||||
|
self.app.push_screen(TagDetailsScreen(), self.handle_update_tag)
|
||||||
|
|
||||||
|
if event.button.id == "button_edit_tag":
|
||||||
|
tagKey, tagValue = self.getSelectedTag()
|
||||||
|
self.app.push_screen(TagDetailsScreen(key=tagKey, value=tagValue), self.handle_update_tag)
|
||||||
|
|
||||||
|
if event.button.id == "button_delete_tag":
|
||||||
|
tagKey, tagValue = self.getSelectedTag()
|
||||||
|
self.app.push_screen(TagDeleteScreen(key=tagKey, value=tagValue), self.handle_delete_tag)
|
||||||
|
|
||||||
|
|
||||||
if event.button.id == "pattern_button":
|
if event.button.id == "pattern_button":
|
||||||
|
|
||||||
INDICATOR_PATTERN = '([sS][0-9]+[eE][0-9]+)'
|
INDICATOR_PATTERN = '([sS][0-9]+[eE][0-9]+)'
|
||||||
@@ -346,3 +441,21 @@ class PatternDetailsScreen(Screen):
|
|||||||
|
|
||||||
def handle_delete_track(self, trackDescriptor : TrackDescriptor):
|
def handle_delete_track(self, trackDescriptor : TrackDescriptor):
|
||||||
self.updateTracks()
|
self.updateTracks()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def handle_update_tag(self, tag):
|
||||||
|
|
||||||
|
if self.__pattern is None:
|
||||||
|
raise click.ClickException(f"PatternDetailsScreen.handle_update_tag: pattern not set")
|
||||||
|
|
||||||
|
if self.__tac.updateMediaTag(self.__pattern.getId(), tag[0], tag[1]) is not None:
|
||||||
|
self.updateTags()
|
||||||
|
|
||||||
|
def handle_delete_tag(self, tag):
|
||||||
|
|
||||||
|
if self.__pattern is None:
|
||||||
|
raise click.ClickException(f"PatternDetailsScreen.handle_delete_tag: pattern not set")
|
||||||
|
|
||||||
|
if self.__tac.deleteMediaTagByKey(self.__pattern.getId(), tag[0]):
|
||||||
|
self.updateTags()
|
||||||
|
|||||||
@@ -14,19 +14,19 @@ class TagController():
|
|||||||
self.Session = self.context['database']['session'] # convenience
|
self.Session = self.context['database']['session'] # convenience
|
||||||
|
|
||||||
|
|
||||||
def updateMediaTag(self, trackId, tagKey, tagValue):
|
def updateMediaTag(self, patternId, tagKey, tagValue):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
s = self.Session()
|
s = self.Session()
|
||||||
|
|
||||||
q = s.query(MediaTag).filter(MediaTag.track_id == int(trackId),
|
q = s.query(MediaTag).filter(MediaTag.pattern_id == int(patternId),
|
||||||
MediaTag.key == str(tagKey),
|
MediaTag.key == str(tagKey),
|
||||||
MediaTag.value == str(tagValue))
|
MediaTag.value == str(tagValue))
|
||||||
tag = q.first()
|
tag = q.first()
|
||||||
if tag:
|
if tag:
|
||||||
tag.value = str(tagValue)
|
tag.value = str(tagValue)
|
||||||
else:
|
else:
|
||||||
tag = MediaTag(track_id = int(trackId),
|
tag = MediaTag(pattern_id = int(patternId),
|
||||||
key = str(tagKey),
|
key = str(tagKey),
|
||||||
value = str(tagValue))
|
value = str(tagValue))
|
||||||
s.add(tag)
|
s.add(tag)
|
||||||
@@ -64,13 +64,52 @@ class TagController():
|
|||||||
finally:
|
finally:
|
||||||
s.close()
|
s.close()
|
||||||
|
|
||||||
|
def deleteMediaTagByKey(self, patternId, tagKey):
|
||||||
|
|
||||||
def findAllMediaTags(self, trackId) -> dict:
|
try:
|
||||||
|
s = self.Session()
|
||||||
|
|
||||||
|
q = s.query(MediaTag).filter(MediaTag.pattern_id == int(patternId),
|
||||||
|
MediaTag.key == str(tagKey))
|
||||||
|
if q.count():
|
||||||
|
tag = q.first()
|
||||||
|
s.delete(tag)
|
||||||
|
s.commit()
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
except Exception as ex:
|
||||||
|
raise click.ClickException(f"TagController.deleteMediaTagByKey(): {repr(ex)}")
|
||||||
|
finally:
|
||||||
|
s.close()
|
||||||
|
|
||||||
|
def deleteTrackTagByKey(self, trackId, tagKey):
|
||||||
|
|
||||||
|
try:
|
||||||
|
s = self.Session()
|
||||||
|
|
||||||
|
q = s.query(TrackTag).filter(TrackTag.track_id == int(trackId),
|
||||||
|
TrackTag.key == str(tagKey))
|
||||||
|
tag = q.first()
|
||||||
|
if tag:
|
||||||
|
s.delete(tag)
|
||||||
|
s.commit()
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
except Exception as ex:
|
||||||
|
raise click.ClickException(f"TagController.deleteTrackTagByKey(): {repr(ex)}")
|
||||||
|
finally:
|
||||||
|
s.close()
|
||||||
|
|
||||||
|
def findAllMediaTags(self, patternId) -> dict:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
s = self.Session()
|
s = self.Session()
|
||||||
|
|
||||||
q = s.query(MediaTag).filter(MediaTag.track_id == int(trackId))
|
q = s.query(MediaTag).filter(MediaTag.pattern_id == int(patternId))
|
||||||
|
|
||||||
if q.count():
|
if q.count():
|
||||||
return {t.key:t.value for t in q.all()}
|
return {t.key:t.value for t in q.all()}
|
||||||
|
|||||||
@@ -383,7 +383,7 @@ class TrackDetailsScreen(Screen):
|
|||||||
trackId = self.__trackDescriptor.getId()
|
trackId = self.__trackDescriptor.getId()
|
||||||
|
|
||||||
if trackId == -1:
|
if trackId == -1:
|
||||||
raise click.ClickException(f"TrackDetailsScreen.handle_add_tag: trackId not set (-1) trackDescriptor={self.__trackDescriptor}")
|
raise click.ClickException(f"TrackDetailsScreen.handle_update_tag: trackId not set (-1) trackDescriptor={self.__trackDescriptor}")
|
||||||
|
|
||||||
if self.__tac.updateTrackTag(trackId, tag[0], tag[1]) is not None:
|
if self.__tac.updateTrackTag(trackId, tag[0], tag[1]) is not None:
|
||||||
self.updateTags()
|
self.updateTags()
|
||||||
|
|||||||
Reference in New Issue
Block a user