Only invalidate required roles

This commit is contained in:
Keith Edmunds 2025-03-08 21:36:09 +00:00
parent 963da0b5d0
commit 74402f640f
2 changed files with 99 additions and 37 deletions

View File

@ -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"""

View File

@ -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