Compare commits
No commits in common. "00d3add0d37d196cda0929778f693a567dcaec4d" and "5d3d373abc68cba3999926f169355d43879346da" have entirely different histories.
00d3add0d3
...
5d3d373abc
@ -41,7 +41,9 @@ prepend_sys_path = .
|
|||||||
|
|
||||||
sqlalchemy.url = SET
|
sqlalchemy.url = SET
|
||||||
# sqlalchemy.url = mysql+mysqldb://musicmuster:musicmuster@localhost/musicmuster_prod
|
# sqlalchemy.url = mysql+mysqldb://musicmuster:musicmuster@localhost/musicmuster_prod
|
||||||
# sqlalchemy.url = mysql+mysqldb://dev_musicmuster:dev_musicmuster@localhost/dev_musicmuster
|
# sqlalchemy.url = mysql+mysqldb://musicmuster:musicmuster@localhost/musicmuster_dev
|
||||||
|
# sqlalchemy.url = mysql+mysqldb://musicmuster:musicmuster@localhost/musicmuster_v2
|
||||||
|
# sqlalchemy.url = mysql+mysqldb://musicmusterv3:musicmusterv3@localhost/musicmuster_dev_v3
|
||||||
|
|
||||||
[post_write_hooks]
|
[post_write_hooks]
|
||||||
# post_write_hooks defines scripts or Python functions that are run
|
# post_write_hooks defines scripts or Python functions that are run
|
||||||
|
|||||||
@ -325,12 +325,6 @@ def set_track_metadata(session, track):
|
|||||||
session.commit()
|
session.commit()
|
||||||
|
|
||||||
|
|
||||||
def show_OK(title: str, msg: str) -> None:
|
|
||||||
"""Display a message to user"""
|
|
||||||
|
|
||||||
QMessageBox.information(None, title, msg, buttons=QMessageBox.Ok)
|
|
||||||
|
|
||||||
|
|
||||||
def show_warning(title: str, msg: str) -> None:
|
def show_warning(title: str, msg: str) -> None:
|
||||||
"""Display a warning to user"""
|
"""Display a warning to user"""
|
||||||
|
|
||||||
|
|||||||
@ -202,8 +202,7 @@ class Playlists(Base):
|
|||||||
id: int = Column(Integer, primary_key=True, autoincrement=True)
|
id: int = Column(Integer, primary_key=True, autoincrement=True)
|
||||||
name: str = Column(String(32), nullable=False, unique=True)
|
name: str = Column(String(32), nullable=False, unique=True)
|
||||||
last_used = Column(DateTime, default=None, nullable=True)
|
last_used = Column(DateTime, default=None, nullable=True)
|
||||||
loaded = Column(Boolean, default=True, nullable=False)
|
loaded: bool = Column(Boolean, default=True, nullable=False)
|
||||||
is_template = Column(Boolean, default=False, nullable=False)
|
|
||||||
rows = relationship(
|
rows = relationship(
|
||||||
"PlaylistRows",
|
"PlaylistRows",
|
||||||
back_populates="playlist",
|
back_populates="playlist",
|
||||||
@ -212,10 +211,7 @@ class Playlists(Base):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return (
|
return f"<Playlists(id={self.id}, name={self.name}>"
|
||||||
f"<Playlists(id={self.id}, name={self.name}, "
|
|
||||||
f"is_templatee={self.is_template}>"
|
|
||||||
)
|
|
||||||
|
|
||||||
def __init__(self, session: Session, name: str) -> None:
|
def __init__(self, session: Session, name: str) -> None:
|
||||||
self.name = name
|
self.name = name
|
||||||
@ -240,19 +236,6 @@ class Playlists(Base):
|
|||||||
|
|
||||||
self.loaded = False
|
self.loaded = False
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def create_playlist_from_template(cls,
|
|
||||||
session: Session,
|
|
||||||
template: "Playlists",
|
|
||||||
playlist_name: str) \
|
|
||||||
-> "Playlists":
|
|
||||||
"""Create a new playlist from template"""
|
|
||||||
|
|
||||||
playlist = cls(session, playlist_name)
|
|
||||||
PlaylistRows.copy_playlist(session, template.id, playlist.id)
|
|
||||||
|
|
||||||
return playlist
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_all(cls, session: Session) -> List["Playlists"]:
|
def get_all(cls, session: Session) -> List["Playlists"]:
|
||||||
"""Returns a list of all playlists ordered by last use"""
|
"""Returns a list of all playlists ordered by last use"""
|
||||||
@ -260,27 +243,12 @@ class Playlists(Base):
|
|||||||
return (
|
return (
|
||||||
session.execute(
|
session.execute(
|
||||||
select(cls)
|
select(cls)
|
||||||
.filter(cls.is_template.is_(False))
|
|
||||||
.order_by(cls.loaded.desc(), cls.last_used.desc())
|
.order_by(cls.loaded.desc(), cls.last_used.desc())
|
||||||
)
|
)
|
||||||
.scalars()
|
.scalars()
|
||||||
.all()
|
.all()
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def get_all_templates(cls, session: Session) -> List["Playlists"]:
|
|
||||||
"""Returns a list of all templates ordered by name"""
|
|
||||||
|
|
||||||
return (
|
|
||||||
session.execute(
|
|
||||||
select(cls)
|
|
||||||
.filter(cls.is_template.is_(True))
|
|
||||||
.order_by(cls.name)
|
|
||||||
)
|
|
||||||
.scalars()
|
|
||||||
.all()
|
|
||||||
)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_closed(cls, session: Session) -> List["Playlists"]:
|
def get_closed(cls, session: Session) -> List["Playlists"]:
|
||||||
"""Returns a list of all closed playlists ordered by last use"""
|
"""Returns a list of all closed playlists ordered by last use"""
|
||||||
@ -288,10 +256,7 @@ class Playlists(Base):
|
|||||||
return (
|
return (
|
||||||
session.execute(
|
session.execute(
|
||||||
select(cls)
|
select(cls)
|
||||||
.filter(
|
.filter(cls.loaded.is_(False))
|
||||||
cls.loaded.is_(False),
|
|
||||||
cls.is_template.is_(False)
|
|
||||||
)
|
|
||||||
.order_by(cls.last_used.desc())
|
.order_by(cls.last_used.desc())
|
||||||
)
|
)
|
||||||
.scalars()
|
.scalars()
|
||||||
@ -320,16 +285,20 @@ class Playlists(Base):
|
|||||||
self.loaded = True
|
self.loaded = True
|
||||||
self.last_used = datetime.now()
|
self.last_used = datetime.now()
|
||||||
|
|
||||||
@staticmethod
|
# def remove_track(self, session: Session, row: int) -> None:
|
||||||
def save_as_template(session: Session,
|
# log.debug(f"Playlist.remove_track({self.id=}, {row=})")
|
||||||
playlist_id: int, template_name: str) -> None:
|
#
|
||||||
"""Save passed playlist as new template"""
|
# # Refresh self first (this is necessary when calling
|
||||||
|
# remove_track
|
||||||
template = Playlists(session, template_name)
|
# # multiple times before session.commit())
|
||||||
template.is_template = True
|
# session.refresh(self)
|
||||||
session.commit()
|
# # Get tracks collection for this playlist
|
||||||
|
# # Tracks are a dictionary of tracks keyed on row
|
||||||
PlaylistRows.copy_playlist(session, playlist_id, template.id)
|
# # number. Remove the relevant row.
|
||||||
|
# del self.tracks[row]
|
||||||
|
# # Save the new tracks collection
|
||||||
|
# session.flush()
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
class PlaylistRows(Base):
|
class PlaylistRows(Base):
|
||||||
@ -351,37 +320,17 @@ class PlaylistRows(Base):
|
|||||||
f"note={self.note} row_number={self.row_number}>"
|
f"note={self.note} row_number={self.row_number}>"
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(
|
||||||
session: Session,
|
self, session: Session, playlist_id: int, track_id: int,
|
||||||
playlist_id: int,
|
row_number: int) -> None:
|
||||||
track_id: int,
|
|
||||||
row_number: int,
|
|
||||||
note: Optional[str] = None
|
|
||||||
) -> None:
|
|
||||||
"""Create PlaylistRows object"""
|
"""Create PlaylistRows object"""
|
||||||
|
|
||||||
self.playlist_id = playlist_id
|
self.playlist_id = playlist_id
|
||||||
self.track_id = track_id
|
self.track_id = track_id
|
||||||
self.row_number = row_number
|
self.row_number = row_number
|
||||||
self.note = note
|
|
||||||
session.add(self)
|
session.add(self)
|
||||||
session.flush()
|
session.flush()
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def copy_playlist(session: Session,
|
|
||||||
src_id: int,
|
|
||||||
dst_id: int) -> None:
|
|
||||||
"""Copy playlist entries"""
|
|
||||||
|
|
||||||
src_rows = session.execute(
|
|
||||||
select(PlaylistRows)
|
|
||||||
.filter(PlaylistRows.playlist_id == src_id)
|
|
||||||
).scalars().all()
|
|
||||||
|
|
||||||
for plr in src_rows:
|
|
||||||
PlaylistRows(session, dst_id, plr.track_id, plr.row_number,
|
|
||||||
plr.note)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def delete_higher_rows(session: Session, playlist_id: int, row: int) \
|
def delete_higher_rows(session: Session, playlist_id: int, row: int) \
|
||||||
-> None:
|
-> None:
|
||||||
|
|||||||
@ -199,11 +199,9 @@ class Window(QMainWindow, Ui_MainWindow):
|
|||||||
self.actionInsertSectionHeader.triggered.connect(self.insert_header)
|
self.actionInsertSectionHeader.triggered.connect(self.insert_header)
|
||||||
self.actionInsertTrack.triggered.connect(self.insert_track)
|
self.actionInsertTrack.triggered.connect(self.insert_track)
|
||||||
self.actionMoveSelected.triggered.connect(self.move_selected)
|
self.actionMoveSelected.triggered.connect(self.move_selected)
|
||||||
self.actionNew_from_template.triggered.connect(self.new_from_template)
|
self.actionNewPlaylist.triggered.connect(self.create_playlist)
|
||||||
self.actionNewPlaylist.triggered.connect(self.create_and_show_playlist)
|
|
||||||
self.actionOpenPlaylist.triggered.connect(self.open_playlist)
|
self.actionOpenPlaylist.triggered.connect(self.open_playlist)
|
||||||
self.actionPlay_next.triggered.connect(self.play_next)
|
self.actionPlay_next.triggered.connect(self.play_next)
|
||||||
self.actionSave_as_template.triggered.connect(self.save_as_template)
|
|
||||||
self.actionSearch.triggered.connect(self.search_playlist)
|
self.actionSearch.triggered.connect(self.search_playlist)
|
||||||
self.actionSelect_next_track.triggered.connect(self.select_next_row)
|
self.actionSelect_next_track.triggered.connect(self.select_next_row)
|
||||||
self.actionSelect_previous_track.triggered.connect(
|
self.actionSelect_previous_track.triggered.connect(
|
||||||
@ -226,23 +224,18 @@ class Window(QMainWindow, Ui_MainWindow):
|
|||||||
|
|
||||||
self.timer.timeout.connect(self.tick)
|
self.timer.timeout.connect(self.tick)
|
||||||
|
|
||||||
def create_playlist(self,
|
def create_playlist(self) -> None:
|
||||||
session: Session,
|
|
||||||
playlist_name: Optional[str] = None) -> Playlists:
|
|
||||||
"""Create new playlist"""
|
"""Create new playlist"""
|
||||||
|
|
||||||
if not playlist_name:
|
dlg = QInputDialog(self)
|
||||||
playlist_name = self.solicit_playlist_name()
|
dlg.setInputMode(QInputDialog.TextInput)
|
||||||
|
dlg.setLabelText("Playlist name:")
|
||||||
playlist = Playlists(session, playlist_name)
|
dlg.resize(500, 100)
|
||||||
return playlist
|
ok = dlg.exec()
|
||||||
|
if ok:
|
||||||
def create_and_show_playlist(self) -> None:
|
with Session() as session:
|
||||||
"""Create new playlist and display it"""
|
playlist = Playlists(session, dlg.textValue())
|
||||||
|
self.create_playlist_tab(session, playlist)
|
||||||
with Session() as session:
|
|
||||||
playlist = self.create_playlist(session)
|
|
||||||
self.create_playlist_tab(session, playlist)
|
|
||||||
|
|
||||||
def create_playlist_tab(self, session: Session,
|
def create_playlist_tab(self, session: Session,
|
||||||
playlist: Playlists) -> None:
|
playlist: Playlists) -> None:
|
||||||
@ -616,24 +609,6 @@ class Window(QMainWindow, Ui_MainWindow):
|
|||||||
session, playlist_id)
|
session, playlist_id)
|
||||||
self.move_playlist_rows(session, unplayed_playlist_rows)
|
self.move_playlist_rows(session, unplayed_playlist_rows)
|
||||||
|
|
||||||
def new_from_template(self) -> None:
|
|
||||||
"""Create new playlist from template"""
|
|
||||||
|
|
||||||
with Session() as session:
|
|
||||||
templates = Playlists.get_all_templates(session)
|
|
||||||
dlg = SelectPlaylistDialog(self, playlists=templates,
|
|
||||||
session=session)
|
|
||||||
dlg.exec()
|
|
||||||
template = dlg.playlist
|
|
||||||
if template:
|
|
||||||
playlist_name = self.solicit_playlist_name()
|
|
||||||
if not playlist_name:
|
|
||||||
return
|
|
||||||
playlist = Playlists.create_playlist_from_template(
|
|
||||||
session, template, playlist_name)
|
|
||||||
playlist.mark_open(session)
|
|
||||||
self.create_playlist_tab(session, playlist)
|
|
||||||
|
|
||||||
def open_playlist(self):
|
def open_playlist(self):
|
||||||
"""Open existing playlist"""
|
"""Open existing playlist"""
|
||||||
|
|
||||||
@ -731,35 +706,6 @@ class Window(QMainWindow, Ui_MainWindow):
|
|||||||
self.label_end_time.setText(
|
self.label_end_time.setText(
|
||||||
self.current_track_end_time.strftime(Config.TRACK_TIME_FORMAT))
|
self.current_track_end_time.strftime(Config.TRACK_TIME_FORMAT))
|
||||||
|
|
||||||
def save_as_template(self) -> None:
|
|
||||||
"""Save current playlist as template"""
|
|
||||||
|
|
||||||
with Session() as session:
|
|
||||||
template_names = [
|
|
||||||
a.name for a in Playlists.get_all_templates(session)
|
|
||||||
]
|
|
||||||
|
|
||||||
while True:
|
|
||||||
# Get name for new template
|
|
||||||
dlg = QInputDialog(self)
|
|
||||||
dlg.setInputMode(QInputDialog.TextInput)
|
|
||||||
dlg.setLabelText("Template name:")
|
|
||||||
dlg.resize(500, 100)
|
|
||||||
ok = dlg.exec()
|
|
||||||
if not ok:
|
|
||||||
return
|
|
||||||
|
|
||||||
template_name = dlg.textValue()
|
|
||||||
if template_name not in template_names:
|
|
||||||
break
|
|
||||||
helpers.show_warning("Duplicate template",
|
|
||||||
"Template name already in use"
|
|
||||||
)
|
|
||||||
Playlists.save_as_template(session,
|
|
||||||
self.visible_playlist_tab().playlist_id,
|
|
||||||
template_name)
|
|
||||||
helpers.show_OK("Template", "Template saved")
|
|
||||||
|
|
||||||
def search_playlist(self) -> None:
|
def search_playlist(self) -> None:
|
||||||
"""Show text box to search playlist"""
|
"""Show text box to search playlist"""
|
||||||
|
|
||||||
@ -838,19 +784,6 @@ class Window(QMainWindow, Ui_MainWindow):
|
|||||||
self.tabPlaylist.setCurrentWidget(self.next_track_playlist_tab)
|
self.tabPlaylist.setCurrentWidget(self.next_track_playlist_tab)
|
||||||
self.tabPlaylist.currentWidget().scroll_next_to_top()
|
self.tabPlaylist.currentWidget().scroll_next_to_top()
|
||||||
|
|
||||||
def solicit_playlist_name(self) -> Optional[str]:
|
|
||||||
"""Get name of playlist from user"""
|
|
||||||
|
|
||||||
dlg = QInputDialog(self)
|
|
||||||
dlg.setInputMode(QInputDialog.TextInput)
|
|
||||||
dlg.setLabelText("Playlist name:")
|
|
||||||
dlg.resize(500, 100)
|
|
||||||
ok = dlg.exec()
|
|
||||||
if ok:
|
|
||||||
return dlg.textValue()
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def stop(self) -> None:
|
def stop(self) -> None:
|
||||||
"""Stop playing immediately"""
|
"""Stop playing immediately"""
|
||||||
|
|
||||||
|
|||||||
@ -572,7 +572,8 @@ class PlaylistTab(QTableWidget):
|
|||||||
# can be reset by calling PlaylistRows.fixup_rownumbers() later,
|
# can be reset by calling PlaylistRows.fixup_rownumbers() later,
|
||||||
# so just fudge a row number for now.
|
# so just fudge a row number for now.
|
||||||
row_number = 0
|
row_number = 0
|
||||||
plr = PlaylistRows(session, self.playlist_id, None, row_number, note)
|
plr = PlaylistRows(session, self.playlist_id, None, row_number)
|
||||||
|
plr.note = note
|
||||||
self.insert_row(session, plr)
|
self.insert_row(session, plr)
|
||||||
PlaylistRows.fixup_rownumbers(session, self.playlist_id)
|
PlaylistRows.fixup_rownumbers(session, self.playlist_id)
|
||||||
if repaint:
|
if repaint:
|
||||||
@ -1234,11 +1235,6 @@ class PlaylistTab(QTableWidget):
|
|||||||
plr = session.get(PlaylistRows, self._get_playlistrow_id(row))
|
plr = session.get(PlaylistRows, self._get_playlistrow_id(row))
|
||||||
plr.track_id = track.id
|
plr.track_id = track.id
|
||||||
session.commit()
|
session.commit()
|
||||||
|
|
||||||
# Reset row span
|
|
||||||
for column in range(len(columns)):
|
|
||||||
self.setSpan(row, column, 1, 1)
|
|
||||||
|
|
||||||
# Update attributes of row
|
# Update attributes of row
|
||||||
self.item(row, USERDATA).setData(self.ROW_TRACK_ID, track.id)
|
self.item(row, USERDATA).setData(self.ROW_TRACK_ID, track.id)
|
||||||
self.item(row, START_GAP).setText(str(track.start_gap))
|
self.item(row, START_GAP).setText(str(track.start_gap))
|
||||||
@ -1249,6 +1245,9 @@ class PlaylistTab(QTableWidget):
|
|||||||
last_played_str = get_relative_date(last_playtime)
|
last_played_str = get_relative_date(last_playtime)
|
||||||
self.item(row, LASTPLAYED).setText(last_played_str)
|
self.item(row, LASTPLAYED).setText(last_played_str)
|
||||||
|
|
||||||
|
# Reset row span
|
||||||
|
self.setSpan(row, 1, 1, 1)
|
||||||
|
|
||||||
self.update_display(session)
|
self.update_display(session)
|
||||||
|
|
||||||
def _calculate_end_time(self, start: Optional[datetime],
|
def _calculate_end_time(self, start: Optional[datetime],
|
||||||
@ -1689,14 +1688,14 @@ class PlaylistTab(QTableWidget):
|
|||||||
# Clear track text items
|
# Clear track text items
|
||||||
for i in range(2, len(columns)):
|
for i in range(2, len(columns)):
|
||||||
self.item(row, i).setText("")
|
self.item(row, i).setText("")
|
||||||
|
# Set note text in correct column for section head
|
||||||
|
self.item(row, HEADER_NOTES_COLUMN).setText(plr.note)
|
||||||
# Remove row duration
|
# Remove row duration
|
||||||
self._set_row_duration(row, 0)
|
self._set_row_duration(row, 0)
|
||||||
# Remote track_id from row
|
# Remote track_id from row
|
||||||
self.item(row, USERDATA).setData(self.ROW_TRACK_ID, 0)
|
self.item(row, USERDATA).setData(self.ROW_TRACK_ID, 0)
|
||||||
# Span the rows
|
# Span the rows
|
||||||
self.setSpan(row, HEADER_NOTES_COLUMN, 1, len(columns) - 1)
|
self.setSpan(row, 1, 1, len(columns))
|
||||||
# Set note text in correct column for section head
|
|
||||||
self.item(row, HEADER_NOTES_COLUMN).setText(plr.note)
|
|
||||||
# And refresh display
|
# And refresh display
|
||||||
self.update_display(session)
|
self.update_display(session)
|
||||||
|
|
||||||
|
|||||||
@ -761,7 +761,7 @@ text-align: left;</string>
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>1280</width>
|
<width>1280</width>
|
||||||
<height>26</height>
|
<height>24</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QMenu" name="menuFile">
|
<widget class="QMenu" name="menuFile">
|
||||||
@ -775,14 +775,12 @@ text-align: left;</string>
|
|||||||
<addaction name="actionExport_playlist"/>
|
<addaction name="actionExport_playlist"/>
|
||||||
<addaction name="actionDeletePlaylist"/>
|
<addaction name="actionDeletePlaylist"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="actionNew_from_template"/>
|
|
||||||
<addaction name="actionSave_as_template"/>
|
|
||||||
<addaction name="separator"/>
|
|
||||||
<addaction name="actionMoveSelected"/>
|
<addaction name="actionMoveSelected"/>
|
||||||
<addaction name="actionMoveUnplayed"/>
|
<addaction name="actionMoveUnplayed"/>
|
||||||
<addaction name="actionDownload_CSV_of_played_tracks"/>
|
<addaction name="actionDownload_CSV_of_played_tracks"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="actionE_xit"/>
|
<addaction name="actionE_xit"/>
|
||||||
|
<addaction name="separator"/>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenu" name="menuPlaylist">
|
<widget class="QMenu" name="menuPlaylist">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
@ -1095,16 +1093,6 @@ text-align: left;</string>
|
|||||||
<string>&About</string>
|
<string>&About</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="actionSave_as_template">
|
|
||||||
<property name="text">
|
|
||||||
<string>Save as template...</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="actionNew_from_template">
|
|
||||||
<property name="text">
|
|
||||||
<string>New from template...</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
</widget>
|
</widget>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
|
|||||||
@ -348,7 +348,7 @@ class Ui_MainWindow(object):
|
|||||||
self.gridLayout_4.addWidget(self.frame_5, 3, 0, 1, 1)
|
self.gridLayout_4.addWidget(self.frame_5, 3, 0, 1, 1)
|
||||||
MainWindow.setCentralWidget(self.centralwidget)
|
MainWindow.setCentralWidget(self.centralwidget)
|
||||||
self.menubar = QtWidgets.QMenuBar(MainWindow)
|
self.menubar = QtWidgets.QMenuBar(MainWindow)
|
||||||
self.menubar.setGeometry(QtCore.QRect(0, 0, 1280, 26))
|
self.menubar.setGeometry(QtCore.QRect(0, 0, 1280, 24))
|
||||||
self.menubar.setObjectName("menubar")
|
self.menubar.setObjectName("menubar")
|
||||||
self.menuFile = QtWidgets.QMenu(self.menubar)
|
self.menuFile = QtWidgets.QMenu(self.menubar)
|
||||||
self.menuFile.setObjectName("menuFile")
|
self.menuFile.setObjectName("menuFile")
|
||||||
@ -458,10 +458,6 @@ class Ui_MainWindow(object):
|
|||||||
self.actionFind_previous.setObjectName("actionFind_previous")
|
self.actionFind_previous.setObjectName("actionFind_previous")
|
||||||
self.action_About = QtWidgets.QAction(MainWindow)
|
self.action_About = QtWidgets.QAction(MainWindow)
|
||||||
self.action_About.setObjectName("action_About")
|
self.action_About.setObjectName("action_About")
|
||||||
self.actionSave_as_template = QtWidgets.QAction(MainWindow)
|
|
||||||
self.actionSave_as_template.setObjectName("actionSave_as_template")
|
|
||||||
self.actionNew_from_template = QtWidgets.QAction(MainWindow)
|
|
||||||
self.actionNew_from_template.setObjectName("actionNew_from_template")
|
|
||||||
self.menuFile.addAction(self.actionNewPlaylist)
|
self.menuFile.addAction(self.actionNewPlaylist)
|
||||||
self.menuFile.addAction(self.actionOpenPlaylist)
|
self.menuFile.addAction(self.actionOpenPlaylist)
|
||||||
self.menuFile.addAction(self.actionClosePlaylist)
|
self.menuFile.addAction(self.actionClosePlaylist)
|
||||||
@ -469,14 +465,12 @@ class Ui_MainWindow(object):
|
|||||||
self.menuFile.addAction(self.actionExport_playlist)
|
self.menuFile.addAction(self.actionExport_playlist)
|
||||||
self.menuFile.addAction(self.actionDeletePlaylist)
|
self.menuFile.addAction(self.actionDeletePlaylist)
|
||||||
self.menuFile.addSeparator()
|
self.menuFile.addSeparator()
|
||||||
self.menuFile.addAction(self.actionNew_from_template)
|
|
||||||
self.menuFile.addAction(self.actionSave_as_template)
|
|
||||||
self.menuFile.addSeparator()
|
|
||||||
self.menuFile.addAction(self.actionMoveSelected)
|
self.menuFile.addAction(self.actionMoveSelected)
|
||||||
self.menuFile.addAction(self.actionMoveUnplayed)
|
self.menuFile.addAction(self.actionMoveUnplayed)
|
||||||
self.menuFile.addAction(self.actionDownload_CSV_of_played_tracks)
|
self.menuFile.addAction(self.actionDownload_CSV_of_played_tracks)
|
||||||
self.menuFile.addSeparator()
|
self.menuFile.addSeparator()
|
||||||
self.menuFile.addAction(self.actionE_xit)
|
self.menuFile.addAction(self.actionE_xit)
|
||||||
|
self.menuFile.addSeparator()
|
||||||
self.menuPlaylist.addSeparator()
|
self.menuPlaylist.addSeparator()
|
||||||
self.menuPlaylist.addAction(self.actionPlay_next)
|
self.menuPlaylist.addAction(self.actionPlay_next)
|
||||||
self.menuPlaylist.addAction(self.actionFade)
|
self.menuPlaylist.addAction(self.actionFade)
|
||||||
@ -593,7 +587,5 @@ class Ui_MainWindow(object):
|
|||||||
self.actionFind_previous.setText(_translate("MainWindow", "Find previous"))
|
self.actionFind_previous.setText(_translate("MainWindow", "Find previous"))
|
||||||
self.actionFind_previous.setShortcut(_translate("MainWindow", "P"))
|
self.actionFind_previous.setShortcut(_translate("MainWindow", "P"))
|
||||||
self.action_About.setText(_translate("MainWindow", "&About"))
|
self.action_About.setText(_translate("MainWindow", "&About"))
|
||||||
self.actionSave_as_template.setText(_translate("MainWindow", "Save as template..."))
|
|
||||||
self.actionNew_from_template.setText(_translate("MainWindow", "New from template..."))
|
|
||||||
from infotabs import InfoTabs
|
from infotabs import InfoTabs
|
||||||
import icons_rc
|
import icons_rc
|
||||||
|
|||||||
@ -1,32 +0,0 @@
|
|||||||
"""Add templates
|
|
||||||
|
|
||||||
Revision ID: b4f524e2140c
|
|
||||||
Revises: ed3100326c38
|
|
||||||
Create Date: 2022-10-01 13:30:21.663287
|
|
||||||
|
|
||||||
"""
|
|
||||||
from alembic import op
|
|
||||||
import sqlalchemy as sa
|
|
||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
|
||||||
revision = 'b4f524e2140c'
|
|
||||||
down_revision = 'ed3100326c38'
|
|
||||||
branch_labels = None
|
|
||||||
depends_on = None
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade():
|
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
|
||||||
op.create_foreign_key(None, 'playlist_rows', 'tracks', ['track_id'], ['id'])
|
|
||||||
op.create_foreign_key(None, 'playlist_rows', 'playlists', ['playlist_id'], ['id'])
|
|
||||||
op.add_column('playlists', sa.Column('is_template', sa.Boolean(), nullable=False))
|
|
||||||
# ### end Alembic commands ###
|
|
||||||
|
|
||||||
|
|
||||||
def downgrade():
|
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
|
||||||
op.drop_column('playlists', 'is_template')
|
|
||||||
op.drop_constraint(None, 'playlist_rows', type_='foreignkey')
|
|
||||||
op.drop_constraint(None, 'playlist_rows', type_='foreignkey')
|
|
||||||
# ### end Alembic commands ###
|
|
||||||
Loading…
Reference in New Issue
Block a user