diff --git a/app/musicmuster.py b/app/musicmuster.py index 9df8eb2..0e22a3f 100755 --- a/app/musicmuster.py +++ b/app/musicmuster.py @@ -2308,7 +2308,10 @@ class Window(QMainWindow): session.commit() self.preview_manager.set_intro(intro) self.current.base_model.refresh_row(session, row_number) - self.current.base_model.invalidate_row(row_number) + roles = [ + Qt.ItemDataRole.DisplayRole, + ] + self.current.base_model.invalidate_row(row_number, roles) def preview_start(self) -> None: """Restart preview""" diff --git a/app/playlistmodel.py b/app/playlistmodel.py index 04205a5..4be929f 100644 --- a/app/playlistmodel.py +++ b/app/playlistmodel.py @@ -173,11 +173,17 @@ class PlaylistModel(QAbstractTableModel): # Update local copy self.refresh_row(session, row_number) # Repaint row - self.invalidate_row(row_number) + roles = [ + Qt.ItemDataRole.BackgroundRole, + Qt.ItemDataRole.DisplayRole, + Qt.ItemDataRole.FontRole, + Qt.ItemDataRole.ForegroundRole, + ] + # only invalidate required roles + self.invalidate_row(row_number, roles) self.signals.resize_rows_signal.emit(self.playlist_id) - # @line_profiler.profile def background_role(self, row: int, column: int, rat: RowAndTrack) -> QBrush: """Return background setting""" @@ -295,11 +301,16 @@ class PlaylistModel(QAbstractTableModel): ) # Update colour and times for current row - self.invalidate_row(row_number) + # only invalidate required roles + roles = [ + Qt.ItemDataRole.DisplayRole + ] + self.invalidate_row(row_number, roles) # Update previous row in case we're hiding played rows if track_sequence.previous and track_sequence.previous.row_number: - self.invalidate_row(track_sequence.previous.row_number) + # only invalidate required roles + self.invalidate_row(track_sequence.previous.row_number, roles) # Update all other track times self.update_track_times() @@ -320,7 +331,6 @@ class PlaylistModel(QAbstractTableModel): if next_row is not None: self.set_next_row(next_row) - # @line_profiler.profile def data( self, index: QModelIndex, role: int = Qt.ItemDataRole.DisplayRole ) -> QVariant | QFont | QBrush | str: @@ -329,7 +339,8 @@ class PlaylistModel(QAbstractTableModel): if ( not index.isValid() or not (0 <= index.row() < len(self.playlist_rows)) - or role in [ + or role + in [ Qt.ItemDataRole.DecorationRole, Qt.ItemDataRole.StatusTipRole, Qt.ItemDataRole.WhatsThisRole, @@ -392,7 +403,6 @@ class PlaylistModel(QAbstractTableModel): self.reset_track_sequence_row_numbers() self.update_track_times() - # @line_profiler.profile def display_role(self, row: int, column: int, rat: RowAndTrack) -> str: """ Return text for display @@ -468,7 +478,6 @@ class PlaylistModel(QAbstractTableModel): super().endResetModel() self.reset_track_sequence_row_numbers() - # @line_profiler.profile def edit_role(self, row: int, column: int, rat: RowAndTrack) -> str: """ Return text for editing @@ -490,17 +499,17 @@ class PlaylistModel(QAbstractTableModel): return "" - # @line_profiler.profile def foreground_role(self, row: int, column: int, rat: RowAndTrack) -> QBrush: """Return header foreground colour or QBrush() if none""" if self.is_header_row(row): - with db.Session() as session: - note_foreground = NoteColours.get_colour( - session, rat.note, foreground=True - ) - if note_foreground: - return QBrush(QColor(note_foreground)) + if rat.row_fg is None: + with db.Session() as session: + rat.row_fg = NoteColours.get_colour( + session, rat.note, foreground=True + ) + if rat.row_fg: + return QBrush(QColor(rat.row_fg)) return QBrush() @@ -527,7 +536,6 @@ class PlaylistModel(QAbstractTableModel): return default - # @line_profiler.profile def font_role(self, row: int, column: int, rat: RowAndTrack) -> QFont: """ Return font @@ -704,7 +712,11 @@ class PlaylistModel(QAbstractTableModel): self.played_tracks_hidden = hide for row_number in range(len(self.playlist_rows)): if self.is_played_row(row_number): - self.invalidate_row(row_number) + # only invalidate required roles + roles = [ + Qt.ItemDataRole.DisplayRole, + ] + self.invalidate_row(row_number, roles) def insert_row( self, @@ -736,11 +748,16 @@ class PlaylistModel(QAbstractTableModel): self.signals.resize_rows_signal.emit(self.playlist_id) self.reset_track_sequence_row_numbers() - self.invalidate_rows(list(range(new_row_number, len(self.playlist_rows)))) + # only invalidate required roles + roles = [ + Qt.ItemDataRole.BackgroundRole, + Qt.ItemDataRole.DisplayRole, + Qt.ItemDataRole.FontRole, + Qt.ItemDataRole.ForegroundRole, + ] + self.invalidate_rows(list(range(new_row_number, len(self.playlist_rows))), roles) - # Keep this decorator for now - # @line_profiler.profile - def invalidate_row(self, modified_row: int) -> None: + def invalidate_row(self, modified_row: int, roles: list[Qt.ItemDataRole]) -> None: """ Signal to view to refresh invalidated row """ @@ -750,11 +767,10 @@ class PlaylistModel(QAbstractTableModel): self.dataChanged.emit( self.index(modified_row, 0), self.index(modified_row, self.columnCount() - 1), + roles ) - # Keep this decorator for now - # @line_profiler.profile - def invalidate_rows(self, modified_rows: list[int]) -> None: + def invalidate_rows(self, modified_rows: list[int], roles: list[Qt.ItemDataRole]) -> None: """ Signal to view to refresh invlidated rows """ @@ -762,7 +778,8 @@ class PlaylistModel(QAbstractTableModel): log.debug(f"issue285: {self}: invalidate_rows({modified_rows=})") for modified_row in modified_rows: - self.invalidate_row(modified_row) + # only invalidate required roles + self.invalidate_row(modified_row, roles) def is_header_row(self, row_number: int) -> bool: """ @@ -837,7 +854,11 @@ class PlaylistModel(QAbstractTableModel): self.refresh_row(session, row_number) self.update_track_times() - self.invalidate_rows(row_numbers) + # only invalidate required roles + roles = [ + Qt.ItemDataRole.FontRole, + ] + self.invalidate_rows(row_numbers, roles) def move_rows(self, from_rows: list[int], to_row_number: int) -> None: """ @@ -902,7 +923,11 @@ class PlaylistModel(QAbstractTableModel): # Update display self.reset_track_sequence_row_numbers() self.update_track_times() - self.invalidate_rows(list(row_map.keys())) + # only invalidate required roles + roles = [ + Qt.ItemDataRole.DisplayRole, + ] + self.invalidate_rows(list(row_map.keys()), roles) def move_rows_between_playlists( self, @@ -1079,7 +1104,11 @@ class PlaylistModel(QAbstractTableModel): return # Update display - self.invalidate_row(track_sequence.previous.row_number) + # only invalidate required roles + roles = [ + Qt.ItemDataRole.BackgroundRole, + ] + self.invalidate_row(track_sequence.previous.row_number, roles) def refresh_data(self, session: Session) -> None: """ @@ -1132,7 +1161,11 @@ class PlaylistModel(QAbstractTableModel): playlist_row.track_id = None session.commit() self.refresh_row(session, row_number) - self.invalidate_row(row_number) + # only invalidate required roles + roles = [ + Qt.ItemDataRole.DisplayRole, + ] + self.invalidate_row(row_number, roles) def rescan_track(self, row_number: int) -> None: """ @@ -1146,7 +1179,12 @@ class PlaylistModel(QAbstractTableModel): set_track_metadata(track) self.refresh_row(session, row_number) self.update_track_times() - self.invalidate_row(row_number) + roles = [ + Qt.ItemDataRole.BackgroundRole, + Qt.ItemDataRole.DisplayRole, + ] + # only invalidate required roles + self.invalidate_row(row_number, roles) self.signals.resize_rows_signal.emit(self.playlist_id) session.commit() @@ -1206,7 +1244,13 @@ class PlaylistModel(QAbstractTableModel): # self.playlist_rows directly. self.playlist_rows[row_number].note = "" session.commit() - self.invalidate_rows(row_numbers) + # only invalidate required roles + roles = [ + Qt.ItemDataRole.BackgroundRole, + Qt.ItemDataRole.DisplayRole, + Qt.ItemDataRole.ForegroundRole, + ] + self.invalidate_rows(row_numbers, roles) def _reversed_contiguous_row_groups( self, row_numbers: list[int] @@ -1415,9 +1459,14 @@ class PlaylistModel(QAbstractTableModel): self.signals.search_songfacts_signal.emit( self.playlist_rows[row_number].title ) + roles = [ + Qt.ItemDataRole.BackgroundRole, + ] if old_next_row is not None: - self.invalidate_row(old_next_row) - self.invalidate_row(row_number) + # only invalidate required roles + self.invalidate_row(old_next_row, roles) + # only invalidate required roles + self.invalidate_row(row_number, roles) self.signals.next_track_changed_signal.emit() self.update_track_times() @@ -1567,7 +1616,6 @@ class PlaylistModel(QAbstractTableModel): def supportedDropActions(self) -> Qt.DropAction: return Qt.DropAction.MoveAction | Qt.DropAction.CopyAction - # @line_profiler.profile def tooltip_role(self, row: int, column: int, rat: RowAndTrack) -> str: """ Return tooltip. Currently only used for last_played column. @@ -1600,7 +1648,14 @@ class PlaylistModel(QAbstractTableModel): with db.Session() as session: for row in track_rows: self.refresh_row(session, row) - self.invalidate_rows(track_rows) + # only invalidate required roles + roles = [ + Qt.ItemDataRole.BackgroundRole, + Qt.ItemDataRole.DisplayRole, + Qt.ItemDataRole.FontRole, + Qt.ItemDataRole.ForegroundRole, + ] + self.invalidate_rows(track_rows, roles) else: self.insert_row(proposed_row_number=row_number, track_id=track_id) @@ -1749,9 +1804,13 @@ class PlaylistProxyModel(QSortFilterProxyModel): # milliseconds so that it hides then. We add # 100mS on so that the if clause above is # true next time through. + # only invalidate required roles + roles = [ + Qt.ItemDataRole.DisplayRole, + ] QTimer.singleShot( Config.HIDE_AFTER_PLAYING_OFFSET + 100, - lambda: self.sourceModel().invalidate_row(source_row), + lambda: self.sourceModel().invalidate_row(source_row, roles), ) return True # Next track not playing yet so don't hide previous