diff --git a/app/model.py b/app/model.py index 0fc72cf..06dc8ef 100644 --- a/app/model.py +++ b/app/model.py @@ -63,18 +63,27 @@ class Notes(Base): @staticmethod def delete_note(id): - DEBUG(f"delete_note(id={id}") + DEBUG(f"delete_note(id={id}") session.query(Notes).filter(Notes.id == id).delete() session.commit() + @staticmethod + def get_note(id): + return session.query(Notes).filter(Notes.id == id).one() + @classmethod - def update_note(cls, id, row, text): + def update_note(cls, id, row, text=None): + """ + Update note details. If text=None, don't change text. + """ + DEBUG(f"update_note(id={id}, row={row}, text={text})") note = session.query(cls).filter(cls.id == id).one() note.row = row - note.note = text + if text: + note.note = text session.commit() diff --git a/app/playlists.py b/app/playlists.py index b975142..64d2ddf 100644 --- a/app/playlists.py +++ b/app/playlists.py @@ -192,7 +192,10 @@ class Playlist(QTableWidget): note.note[-9:], " %H:%M:%S").time() DEBUG(f"Note contains valid time={start_time}") except ValueError: - DEBUG("Note does not contain valid time") + DEBUG( + f"Note on row {row} ('{note.note}') " + "does not contain valid time" + ) item = QTableWidgetItem(str(note.id)) self.setItem(row, self.COL_INDEX, item) @@ -588,7 +591,7 @@ class Playlist(QTableWidget): def repaint(self, clear_selection=True): "Set row colours, fonts, etc, and save playlist" - self.save() + self.save_playlist() if clear_selection: self.clearSelection() @@ -641,7 +644,7 @@ class Playlist(QTableWidget): self.item(row, self.COL_ENDTIME).text(), "%H:%M:%S" ) except ValueError: - DEBUG("Note does not contain valid time") + pass # Set colour self.set_row_colour( row, QColor(Config.COLOUR_NOTES_PLAYLIST) @@ -676,72 +679,101 @@ class Playlist(QTableWidget): # Headers might need updating self.parent().parent().update_headers() - def save(self): + def save_playlist(self): """ - Save playlist to database. - - Notes are also saved. + Save playlist to database. Add missing notes/tracks; remove any that + are in database but not playlist. Correct row number in database if + necessary. """ - # Create list of current tracks (row, track_id) for this playlst and - # compare with actual playlist. Fix as required. - # Repeat for notes (row, id, text) - - tracks = {} - notes = {} note_rows = self.meta_get_notes() + playlist = Playlists.get_playlist_by_id(self.playlist_id) + # Create dictionaries indexed by track/note id + playlist_notes = {} + playlist_tracks = {} + database_notes = {} + database_tracks = {} + + # Playlist for row in range(self.rowCount()): + # Get id of item if self.item(row, self.COL_INDEX): id = int(self.item(row, self.COL_INDEX).text()) else: - DEBUG(f"(playlist.save(): no COL_INDEX data in row {row}") + DEBUG(f"(save_playlist(): no COL_INDEX data in row {row}") continue if row in note_rows: - notes[id] = (row, self.item(row, self.COL_NOTE).text()) + playlist_notes[id] = row else: - tracks[id] = row + playlist_tracks[id] = row - # Get tracks and notes from database - db_tracks = {} - db_notes = {} - p = Playlists.get_playlist_by_id(self.playlist_id) + # Database + for note in playlist.notes: + database_notes[note.id] = note.row + for track in playlist.tracks: + database_tracks[track.track_id] = track.row - for track in p.tracks: - db_tracks[track.track_id] = track.row + # Notes to remove from playlist in database + for note_id in set(database_notes.keys()) - set(playlist_notes.keys()): + DEBUG( + f"save_playlist(): Delete note.id={id} " + f"from playlist {playlist} in database" + ) + Notes.delete_note(note_id) - for note in p.notes: - db_notes[note.id] = (note.row, note.note) + # Tracks to remove from playlist in database + for track_id in ( + set(database_tracks.keys()) - set(playlist_tracks.keys()) + ): + DEBUG( + f"save_playlist(): Delete track.id={track_id} " + f"from playlist {playlist} in database" + ) + PlaylistTracks.remove_track(playlist.id, track_id) - # Note ids to remove from db - for id in set(db_notes.keys()) - set(notes.keys()): - DEBUG(f"playlist.save(): Delete note.id={id} from database") + # Notes to add to playlist database + # This should never be needed as notes are added to a specific + # playlist upon creation + for note_id in set(playlist_notes.keys()) - set(database_notes.keys()): + ERROR( + f"save_playlist(): Note.id={note_id} " + f"missing from playlist {playlist} in database" + ) - # Note ids to add to db - for id in set(notes.keys()) - set(db_notes.keys()): - DEBUG(f"playlist.save(): Add note.id={id} to database") + # Notes to remove from playlist database + for note_id in set(database_notes.keys()) - set(playlist_notes.keys()): + DEBUG( + f"save_playlist(): Remove note.id={note_id} " + f"from playlist {playlist} in database" + ) + Notes.delete_note(note_id) - # Notes to update in db - for id in set(notes.keys()) & set(db_notes.keys()): - if notes[id] != db_notes[id]: - DEBUG(f"playlist.save(): Update db note.id={id} in database") - Notes.update_note(id, row=notes[id][0], text=notes[id][1]) + # Note rows to update in playlist database + for note_id in set(playlist_notes.keys()) & set(database_notes.keys()): + if playlist_notes[note_id] != database_notes[note_id]: + DEBUG( + f"save_playlist(): Set database note.id {note_id} " + f"row={playlist_notes[note_id]} " + f"in playlist {playlist} in database" + ) + Notes.update_note(note_id, playlist_notes[note_id]) - # Track ids to remove from db - for id in set(db_tracks.keys()) - set(tracks.keys()): - DEBUG(f"playlist.save(): Delete track.id={id} from database") - - # Track ids to add to db - for id in set(tracks.keys()) - set(db_tracks.keys()): - DEBUG(f"playlist.save(): Add track.id={id} to database") - - # Tracks to update in db - for id in set(tracks.keys()) & set(db_tracks.keys()): - if tracks[id] != db_tracks[id]: - DEBUG(f"playlist.save(): Update db track.id={id} in database") + # Track rows to update in playlist database + for track_id in ( + set(playlist_tracks.keys()) & set(database_tracks.keys()) + ): + if playlist_tracks[track_id] != database_tracks[track_id]: + DEBUG( + f"save_playlist(): Set database track.id {track_id} " + f"row={playlist_tracks[track_id]} " + f"in playlist {playlist} in database" + ) PlaylistTracks.update_track_row( - self.playlist_id, track_id=id, - old_row=db_tracks[id], new_row=tracks[id] + playlist_id=self.playlist_id, + track_id=track_id, + old_row=database_tracks[track_id], + new_row=playlist_tracks[track_id] ) def set_column_widths(self):