Fix create playlist from template and tab handlding
Tab restore code rewritten.
This commit is contained in:
parent
199f0e27fa
commit
8f2ab98be0
@ -25,7 +25,6 @@ from sqlalchemy import (
|
||||
from sqlalchemy.orm import (
|
||||
DeclarativeBase,
|
||||
joinedload,
|
||||
lazyload,
|
||||
Mapped,
|
||||
mapped_column,
|
||||
relationship,
|
||||
@ -217,7 +216,8 @@ class Playlists(Base):
|
||||
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
|
||||
name: Mapped[str] = mapped_column(String(32), unique=True)
|
||||
last_used: Mapped[Optional[datetime]] = mapped_column(DateTime, default=None)
|
||||
tab: Mapped[Optional[int]] = mapped_column(default=None, unique=True)
|
||||
tab: Mapped[Optional[int]] = mapped_column(default=None)
|
||||
open: Mapped[bool] = mapped_column(default=False)
|
||||
is_template: Mapped[bool] = mapped_column(default=False)
|
||||
deleted: Mapped[bool] = mapped_column(default=False)
|
||||
rows: Mapped[List["PlaylistRows"]] = relationship(
|
||||
@ -230,7 +230,7 @@ class Playlists(Base):
|
||||
def __repr__(self) -> str:
|
||||
return (
|
||||
f"<Playlists(id={self.id}, name={self.name}, "
|
||||
f"is_templatee={self.is_template}>"
|
||||
f"is_templatee={self.is_template}, open={self.open}>"
|
||||
)
|
||||
|
||||
def __init__(self, session: scoped_session, name: str):
|
||||
@ -238,19 +238,10 @@ class Playlists(Base):
|
||||
session.add(self)
|
||||
session.flush()
|
||||
|
||||
def close(self, session: scoped_session) -> None:
|
||||
def close(self) -> None:
|
||||
"""Mark playlist as unloaded"""
|
||||
|
||||
closed_idx = self.tab
|
||||
self.tab = None
|
||||
|
||||
# Closing this tab will mean all higher-number tabs have moved
|
||||
# down by one
|
||||
session.execute(
|
||||
update(Playlists)
|
||||
.where(Playlists.tab > closed_idx)
|
||||
.values(tab=Playlists.tab - 1)
|
||||
)
|
||||
self.open = False
|
||||
|
||||
@classmethod
|
||||
def create_playlist_from_template(
|
||||
@ -283,7 +274,7 @@ class Playlists(Base):
|
||||
return session.scalars(
|
||||
select(cls)
|
||||
.filter(cls.is_template.is_(False))
|
||||
.order_by(cls.tab.desc(), cls.last_used.desc())
|
||||
.order_by(cls.last_used.desc())
|
||||
).all()
|
||||
|
||||
@classmethod
|
||||
@ -301,7 +292,7 @@ class Playlists(Base):
|
||||
return session.scalars(
|
||||
select(cls)
|
||||
.filter(
|
||||
cls.tab.is_(None),
|
||||
cls.open.is_(False),
|
||||
cls.is_template.is_(False),
|
||||
cls.deleted.is_(False),
|
||||
)
|
||||
@ -311,32 +302,18 @@ class Playlists(Base):
|
||||
@classmethod
|
||||
def get_open(cls, session: scoped_session) -> Sequence[Optional["Playlists"]]:
|
||||
"""
|
||||
Return a list of loaded playlists ordered by tab order.
|
||||
Return a list of loaded playlists ordered by tab.
|
||||
"""
|
||||
|
||||
return session.scalars(
|
||||
select(cls).where(cls.tab.is_not(None)).order_by(cls.tab)
|
||||
select(cls).where(cls.open.is_(True))
|
||||
.order_by(cls.tab)
|
||||
).all()
|
||||
|
||||
def mark_open(self, session: scoped_session, tab_index: int) -> None:
|
||||
def mark_open(self) -> None:
|
||||
"""Mark playlist as loaded and used now"""
|
||||
|
||||
self.tab = tab_index
|
||||
self.last_used = datetime.now()
|
||||
|
||||
@staticmethod
|
||||
def move_tab(session: scoped_session, frm: int, to: int) -> None:
|
||||
"""Move tabs"""
|
||||
|
||||
row_frm = session.execute(select(Playlists).filter_by(tab=frm)).scalar_one()
|
||||
|
||||
row_to = session.execute(select(Playlists).filter_by(tab=to)).scalar_one()
|
||||
|
||||
row_frm.tab = None
|
||||
row_to.tab = None
|
||||
session.commit()
|
||||
row_to.tab = frm
|
||||
row_frm.tab = to
|
||||
self.open = True
|
||||
|
||||
def rename(self, session: scoped_session, new_name: str) -> None:
|
||||
"""
|
||||
@ -684,7 +661,6 @@ class Settings(Base):
|
||||
f_string: Mapped[Optional[str]] = mapped_column(String(128), default=None)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
value = self.f_datetime or self.f_int or self.f_string
|
||||
return (
|
||||
f"<Settings(id={self.id}, name={self.name}, "
|
||||
f"f_datetime={self.f_datetime}, f_int={self.f_int}, f_string={self.f_string}>"
|
||||
|
||||
@ -442,6 +442,14 @@ class Window(QMainWindow, Ui_MainWindow):
|
||||
if record.f_int != splitter_bottom:
|
||||
record.update(session, {"f_int": splitter_bottom})
|
||||
|
||||
# Save tab number of open playlists
|
||||
for idx in range(self.tabPlaylist.count()):
|
||||
playlist_id = self.tabPlaylist.widget(idx).playlist_id
|
||||
playlist = session.get(Playlists, playlist_id)
|
||||
if playlist:
|
||||
playlist.tab = idx
|
||||
session.flush()
|
||||
|
||||
# Save current tab
|
||||
record = settings["active_tab"]
|
||||
record.update(session, {"f_int": self.tabPlaylist.currentIndex()})
|
||||
@ -475,7 +483,7 @@ class Window(QMainWindow, Ui_MainWindow):
|
||||
with Session() as session:
|
||||
playlist = session.get(Playlists, closing_tab_playlist_id)
|
||||
if playlist:
|
||||
playlist.close(session)
|
||||
playlist.close()
|
||||
|
||||
# Close playlist and remove tab
|
||||
self.tabPlaylist.widget(tab_index).close()
|
||||
@ -535,10 +543,8 @@ class Window(QMainWindow, Ui_MainWindow):
|
||||
self.btnStop.clicked.connect(self.stop)
|
||||
self.hdrCurrentTrack.clicked.connect(self.show_current)
|
||||
self.hdrNextTrack.clicked.connect(self.show_next)
|
||||
self.tabPlaylist.currentChanged.connect(self.tab_change)
|
||||
self.tabPlaylist.tabCloseRequested.connect(self.close_tab)
|
||||
self.tabBar = self.tabPlaylist.tabBar()
|
||||
self.tabBar.tabMoved.connect(self.move_tab)
|
||||
self.txtSearch.returnPressed.connect(self.search_playlist_return)
|
||||
|
||||
self.signals.enable_escape_signal.connect(self.enable_escape)
|
||||
@ -566,9 +572,9 @@ class Window(QMainWindow, Ui_MainWindow):
|
||||
with Session() as session:
|
||||
playlist = self.create_playlist(session)
|
||||
if playlist:
|
||||
self.create_playlist_tab(session, playlist)
|
||||
self.create_playlist_tab(playlist)
|
||||
|
||||
def create_playlist_tab(self, session: scoped_session, playlist: Playlists) -> int:
|
||||
def create_playlist_tab(self, playlist: Playlists) -> int:
|
||||
"""
|
||||
Take the passed playlist database object, create a playlist tab and
|
||||
add tab to display. Return index number of tab.
|
||||
@ -869,7 +875,7 @@ class Window(QMainWindow, Ui_MainWindow):
|
||||
with Session() as session:
|
||||
for playlist in Playlists.get_open(session):
|
||||
if playlist:
|
||||
_ = self.create_playlist_tab(session, playlist)
|
||||
_ = self.create_playlist_tab(playlist)
|
||||
# Set active tab
|
||||
record = Settings.get_int_settings(session, "active_tab")
|
||||
if record.f_int and record.f_int >= 0:
|
||||
@ -963,12 +969,6 @@ class Window(QMainWindow, Ui_MainWindow):
|
||||
|
||||
self.move_playlist_rows(session, selected_plrs)
|
||||
|
||||
def move_tab(self, frm: int, to: int) -> None:
|
||||
"""Handle tabs being moved"""
|
||||
|
||||
with Session() as session:
|
||||
Playlists.move_tab(session, frm, to)
|
||||
|
||||
def move_unplayed(self) -> None:
|
||||
"""
|
||||
Move unplayed rows to another playlist
|
||||
@ -997,12 +997,16 @@ class Window(QMainWindow, Ui_MainWindow):
|
||||
playlist = Playlists.create_playlist_from_template(
|
||||
session, template, playlist_name
|
||||
)
|
||||
if not playlist:
|
||||
return
|
||||
tab_index = self.create_playlist_tab(session, playlist)
|
||||
playlist.mark_open(session, tab_index)
|
||||
|
||||
def open_playlist(self):
|
||||
# Need to ensure that the new playlist is committed to
|
||||
# the database before it is opened by the model.
|
||||
|
||||
session.commit()
|
||||
if playlist:
|
||||
playlist.mark_open()
|
||||
self.create_playlist_tab(playlist)
|
||||
|
||||
def open_playlist(self) -> None:
|
||||
"""Open existing playlist"""
|
||||
|
||||
with Session() as session:
|
||||
@ -1011,8 +1015,8 @@ class Window(QMainWindow, Ui_MainWindow):
|
||||
dlg.exec()
|
||||
playlist = dlg.playlist
|
||||
if playlist:
|
||||
tab_index = self.create_playlist_tab(session, playlist)
|
||||
playlist.mark_open(session, tab_index)
|
||||
self.create_playlist_tab(playlist)
|
||||
playlist.mark_open()
|
||||
|
||||
def paste_rows(self) -> None:
|
||||
"""
|
||||
@ -1460,15 +1464,6 @@ class Window(QMainWindow, Ui_MainWindow):
|
||||
# Enable controls
|
||||
self.enable_play_next_controls()
|
||||
|
||||
def tab_change(self):
|
||||
"""Called when active tab changed"""
|
||||
|
||||
try:
|
||||
self.tabPlaylist.currentWidget().tab_visible()
|
||||
except AttributeError:
|
||||
# May also be called when last tab is closed
|
||||
pass
|
||||
|
||||
def set_next_plr_id(
|
||||
self, next_plr_id: Optional[int], playlist_tab: PlaylistTab
|
||||
) -> None:
|
||||
|
||||
@ -124,6 +124,9 @@ class PlaylistModel(QAbstractTableModel):
|
||||
self.signals.add_track_to_playlist_signal.connect(self.add_track)
|
||||
|
||||
with Session() as session:
|
||||
# Ensure row numbers in playlist are contiguous
|
||||
PlaylistRows.fixup_rownumbers(session, playlist_id)
|
||||
# Populate self.playlist_rows
|
||||
self.refresh_data(session)
|
||||
self.update_track_times()
|
||||
|
||||
|
||||
@ -0,0 +1,60 @@
|
||||
"""Add 'open' field to Playlists
|
||||
|
||||
Revision ID: 5bb2c572e1e5
|
||||
Revises: 3a53a9fb26ab
|
||||
Create Date: 2023-11-18 14:19:02.643914
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.dialects import mysql
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '5bb2c572e1e5'
|
||||
down_revision = '3a53a9fb26ab'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.alter_column('carts', 'duration',
|
||||
existing_type=mysql.INTEGER(display_width=11),
|
||||
nullable=True)
|
||||
op.alter_column('carts', 'path',
|
||||
existing_type=mysql.VARCHAR(length=2048),
|
||||
nullable=True)
|
||||
op.alter_column('carts', 'enabled',
|
||||
existing_type=mysql.TINYINT(display_width=1),
|
||||
nullable=True)
|
||||
op.alter_column('playlist_rows', 'note',
|
||||
existing_type=mysql.VARCHAR(length=2048),
|
||||
nullable=False)
|
||||
op.add_column('playlists', sa.Column('open', sa.Boolean(), nullable=False))
|
||||
op.alter_column('settings', 'name',
|
||||
existing_type=mysql.VARCHAR(length=32),
|
||||
type_=sa.String(length=64),
|
||||
existing_nullable=False)
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.alter_column('settings', 'name',
|
||||
existing_type=sa.String(length=64),
|
||||
type_=mysql.VARCHAR(length=32),
|
||||
existing_nullable=False)
|
||||
op.drop_column('playlists', 'open')
|
||||
op.alter_column('playlist_rows', 'note',
|
||||
existing_type=mysql.VARCHAR(length=2048),
|
||||
nullable=True)
|
||||
op.alter_column('carts', 'enabled',
|
||||
existing_type=mysql.TINYINT(display_width=1),
|
||||
nullable=False)
|
||||
op.alter_column('carts', 'path',
|
||||
existing_type=mysql.VARCHAR(length=2048),
|
||||
nullable=False)
|
||||
op.alter_column('carts', 'duration',
|
||||
existing_type=mysql.INTEGER(display_width=11),
|
||||
nullable=False)
|
||||
# ### end Alembic commands ###
|
||||
Loading…
Reference in New Issue
Block a user