Optionally remove header colour directives from header
This commit is contained in:
parent
f7f4cdc622
commit
0391eed88e
@ -34,6 +34,7 @@ class NoteColoursTable(Model):
|
||||
is_regex: Mapped[bool] = mapped_column(default=False, index=False)
|
||||
is_casesensitive: Mapped[bool] = mapped_column(default=False, index=False)
|
||||
order: Mapped[Optional[int]] = mapped_column(index=True)
|
||||
strip_substring: Mapped[bool] = mapped_column(default=True, index=False)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return (
|
||||
|
||||
@ -333,6 +333,32 @@ def normalise_track(path: str) -> None:
|
||||
os.remove(temp_path)
|
||||
|
||||
|
||||
def remove_substring_case_insensitive(parent_string: str, substring: str) -> str:
|
||||
"""
|
||||
Remove all instances of substring from parent string, case insensitively
|
||||
"""
|
||||
|
||||
# Convert both strings to lowercase for case-insensitive comparison
|
||||
lower_parent = parent_string.lower()
|
||||
lower_substring = substring.lower()
|
||||
|
||||
# Initialize the result string
|
||||
result = parent_string
|
||||
|
||||
# Continue removing the substring until it's no longer found
|
||||
while lower_substring in lower_parent:
|
||||
# Find the index of the substring
|
||||
index = lower_parent.find(lower_substring)
|
||||
|
||||
# Remove the substring
|
||||
result = result[:index] + result[index + len(substring):]
|
||||
|
||||
# Update the lowercase versions
|
||||
lower_parent = result.lower()
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def send_mail(to_addr: str, from_addr: str, subj: str, body: str) -> None:
|
||||
# From https://docs.python.org/3/library/email.examples.html
|
||||
|
||||
|
||||
@ -22,9 +22,9 @@ from sqlalchemy.orm import joinedload
|
||||
from sqlalchemy.orm.session import Session
|
||||
|
||||
# App imports
|
||||
from config import Config
|
||||
from dbmanager import DatabaseManager
|
||||
import dbtables
|
||||
from config import Config
|
||||
from log import log
|
||||
|
||||
|
||||
@ -83,7 +83,9 @@ class NoteColours(dbtables.NoteColoursTable):
|
||||
match = False
|
||||
for rec in session.scalars(
|
||||
select(NoteColours)
|
||||
.filter(NoteColours.enabled.is_(True))
|
||||
.where(
|
||||
NoteColours.enabled.is_(True),
|
||||
)
|
||||
.order_by(NoteColours.order)
|
||||
).all():
|
||||
if rec.is_regex:
|
||||
|
||||
@ -45,6 +45,7 @@ from helpers import (
|
||||
get_embedded_time,
|
||||
get_relative_date,
|
||||
ms_to_mmss,
|
||||
remove_substring_case_insensitive,
|
||||
set_track_metadata,
|
||||
)
|
||||
from log import log
|
||||
@ -452,7 +453,9 @@ class PlaylistModel(QAbstractTableModel):
|
||||
|
||||
if self.is_header_row(row):
|
||||
with db.Session() as session:
|
||||
note_foreground = NoteColours.get_colour(session, rat.note, foreground=True)
|
||||
note_foreground = NoteColours.get_colour(
|
||||
session, rat.note, foreground=True
|
||||
)
|
||||
if note_foreground:
|
||||
return QBrush(QColor(note_foreground))
|
||||
|
||||
@ -738,6 +741,36 @@ class PlaylistModel(QAbstractTableModel):
|
||||
|
||||
return None
|
||||
|
||||
def load_data(
|
||||
self, session: db.session, dummy_for_profiling: Optional[int] = None
|
||||
) -> None:
|
||||
"""
|
||||
Same as refresh data, but only used when creating playslit.
|
||||
Distinguishes profile time between initial load and other
|
||||
refreshes.
|
||||
"""
|
||||
|
||||
# We used to clear self.playlist_rows each time but that's
|
||||
# expensive and slow on big playlists
|
||||
|
||||
# Note where each playlist_id is
|
||||
plid_to_row: dict[int, int] = {}
|
||||
for oldrow in self.playlist_rows:
|
||||
plrdata = self.playlist_rows[oldrow]
|
||||
plid_to_row[plrdata.playlistrow_id] = plrdata.row_number
|
||||
|
||||
# build a new playlist_rows
|
||||
new_playlist_rows: dict[int, RowAndTrack] = {}
|
||||
for p in PlaylistRows.get_playlist_rows(session, self.playlist_id):
|
||||
if p.id not in plid_to_row:
|
||||
new_playlist_rows[p.row_number] = RowAndTrack(p)
|
||||
else:
|
||||
new_playlist_rows[p.row_number] = self.playlist_rows[plid_to_row[p.id]]
|
||||
new_playlist_rows[p.row_number].row_number = p.row_number
|
||||
|
||||
# Copy to self.playlist_rows
|
||||
self.playlist_rows = new_playlist_rows
|
||||
|
||||
def mark_unplayed(self, row_numbers: list[int]) -> None:
|
||||
"""
|
||||
Mark row as unplayed
|
||||
@ -1007,7 +1040,9 @@ class PlaylistModel(QAbstractTableModel):
|
||||
self.invalidate_row(track_sequence.previous.row_number)
|
||||
|
||||
@line_profiler.profile
|
||||
def refresh_data(self, session: db.session, dummy_for_profiling=None) -> None:
|
||||
def refresh_data(
|
||||
self, session: db.session, dummy_for_profiling: Optional[int] = None
|
||||
) -> None:
|
||||
"""
|
||||
Populate self.playlist_rows with playlist data
|
||||
|
||||
@ -1037,66 +1072,6 @@ class PlaylistModel(QAbstractTableModel):
|
||||
# Copy to self.playlist_rows
|
||||
self.playlist_rows = new_playlist_rows
|
||||
|
||||
# Same as refresh data, but only used when creating playslit.
|
||||
# Distinguishes profile time between initial load and other
|
||||
# refreshes.
|
||||
def load_data(
|
||||
self, session: db.session, dummy_for_profiling: Optional[int] = None
|
||||
) -> None:
|
||||
"""Populate self.playlist_rows with playlist data"""
|
||||
|
||||
# Same as refresh data, but only used when creating playslit.
|
||||
# Distinguishes profile time between initial load and other
|
||||
# refreshes.
|
||||
|
||||
# We used to clear self.playlist_rows each time but that's
|
||||
# expensive and slow on big playlists
|
||||
|
||||
# Note where each playlist_id is
|
||||
plid_to_row: dict[int, int] = {}
|
||||
for oldrow in self.playlist_rows:
|
||||
plrdata = self.playlist_rows[oldrow]
|
||||
plid_to_row[plrdata.playlistrow_id] = plrdata.row_number
|
||||
|
||||
# build a new playlist_rows
|
||||
new_playlist_rows: dict[int, RowAndTrack] = {}
|
||||
for p in PlaylistRows.get_playlist_rows(session, self.playlist_id):
|
||||
if p.id not in plid_to_row:
|
||||
new_playlist_rows[p.row_number] = RowAndTrack(p)
|
||||
else:
|
||||
new_playlist_rows[p.row_number] = self.playlist_rows[plid_to_row[p.id]]
|
||||
new_playlist_rows[p.row_number].row_number = p.row_number
|
||||
|
||||
# Copy to self.playlist_rows
|
||||
self.playlist_rows = new_playlist_rows
|
||||
|
||||
# Same as refresh data, but only used when creating playslit.
|
||||
# Distinguishes profile time between initial load and other
|
||||
# refreshes.
|
||||
def load_data(self, session: db.session, dummy_for_profiling=None) -> None:
|
||||
"""Populate self.playlist_rows with playlist data"""
|
||||
|
||||
# We used to clear self.playlist_rows each time but that's
|
||||
# expensive and slow on big playlists
|
||||
|
||||
# Note where each playlist_id is
|
||||
plid_to_row: dict[int, int] = {}
|
||||
for oldrow in self.playlist_rows:
|
||||
plrdata = self.playlist_rows[oldrow]
|
||||
plid_to_row[plrdata.playlistrow_id] = plrdata.row_number
|
||||
|
||||
# build a new playlist_rows
|
||||
new_playlist_rows: dict[int, RowAndTrack] = {}
|
||||
for p in PlaylistRows.get_playlist_rows(session, self.playlist_id):
|
||||
if p.id not in plid_to_row:
|
||||
new_playlist_rows[p.row_number] = RowAndTrack(p)
|
||||
else:
|
||||
new_playlist_rows[p.row_number] = self.playlist_rows[plid_to_row[p.id]]
|
||||
new_playlist_rows[p.row_number].row_number = p.row_number
|
||||
|
||||
# Copy to self.playlist_rows
|
||||
self.playlist_rows = new_playlist_rows
|
||||
|
||||
def refresh_row(self, session, row_number):
|
||||
"""Populate dict for one row from database"""
|
||||
|
||||
@ -1172,7 +1147,7 @@ class PlaylistModel(QAbstractTableModel):
|
||||
# Safety check
|
||||
if not ask_yes_no(
|
||||
title="Remove comments",
|
||||
question=f"Remove comments from {len(row_numbers)} rows?"
|
||||
question=f"Remove comments from {len(row_numbers)} rows?",
|
||||
):
|
||||
return
|
||||
|
||||
@ -1227,7 +1202,12 @@ class PlaylistModel(QAbstractTableModel):
|
||||
def remove_section_timer_markers(self, header_text: str) -> str:
|
||||
"""
|
||||
Remove characters used to mark section timeings from
|
||||
passed header text. Return header text witout markers
|
||||
passed header text.
|
||||
|
||||
Remove text using to signal header colours if colour entry
|
||||
is so marked.
|
||||
|
||||
Return header text witout markers
|
||||
"""
|
||||
|
||||
while header_text.endswith(Config.SECTION_STARTS):
|
||||
@ -1235,6 +1215,31 @@ class PlaylistModel(QAbstractTableModel):
|
||||
while header_text.endswith(Config.SECTION_ENDINGS):
|
||||
header_text = header_text[0:-1]
|
||||
|
||||
# Parse passed header text and remove the first colour match string
|
||||
with db.Session() as session:
|
||||
for rec in NoteColours.get_all(session):
|
||||
if not rec.strip_substring:
|
||||
continue
|
||||
if rec.is_regex:
|
||||
flags = re.UNICODE
|
||||
if not rec.is_casesensitive:
|
||||
flags |= re.IGNORECASE
|
||||
p = re.compile(rec.substring, flags)
|
||||
if p.match(header_text):
|
||||
header_text = re.sub(p, "", header_text)
|
||||
break
|
||||
else:
|
||||
if rec.is_casesensitive:
|
||||
if rec.substring.lower() in header_text.lower():
|
||||
header_text = remove_substring_case_insensitive(
|
||||
header_text, rec.substring
|
||||
)
|
||||
break
|
||||
else:
|
||||
if rec.substring in header_text:
|
||||
header_text = header_text.replace(rec.substring, "")
|
||||
break
|
||||
|
||||
return header_text
|
||||
|
||||
def rowCount(self, index: QModelIndex = QModelIndex()) -> int:
|
||||
|
||||
@ -0,0 +1,44 @@
|
||||
"""Add strip_substring to NoteColoursTable
|
||||
|
||||
Revision ID: a524796269fa
|
||||
Revises: 708a21f5c271
|
||||
Create Date: 2024-12-14 12:42:45.214707
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'a524796269fa'
|
||||
down_revision = '708a21f5c271'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade(engine_name: str) -> None:
|
||||
globals()["upgrade_%s" % engine_name]()
|
||||
|
||||
|
||||
def downgrade(engine_name: str) -> None:
|
||||
globals()["downgrade_%s" % engine_name]()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def upgrade_() -> None:
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
with op.batch_alter_table('notecolours', schema=None) as batch_op:
|
||||
batch_op.add_column(sa.Column('strip_substring', sa.Boolean(), nullable=False))
|
||||
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade_() -> None:
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
with op.batch_alter_table('notecolours', schema=None) as batch_op:
|
||||
batch_op.drop_column('strip_substring')
|
||||
|
||||
# ### end Alembic commands ###
|
||||
|
||||
Loading…
Reference in New Issue
Block a user