Compare commits

..

No commits in common. "37ccf7c325d0f0c73adae38e19758cc3b782f4f6" and "c5f51553323bdd0def45e5470cb1a3e0fde8e49e" have entirely different histories.

5 changed files with 58 additions and 80 deletions

View File

@ -164,7 +164,7 @@ class Playlists(Base):
back_populates="playlists") back_populates="playlists")
def __repr__(self): def __repr__(self):
return (f"<Playlists(id={self.id}, name={self.name}>") return (f"<Playlist(id={self.id}, name={self.name}>")
def add_track(self, session, track, row=None): def add_track(self, session, track, row=None):
""" """
@ -175,8 +175,6 @@ class Playlists(Base):
if not row: if not row:
row = PlaylistTracks.new_row(session, self.id) row = PlaylistTracks.new_row(session, self.id)
DEBUG(f"Playlists:add_track({session=}, {track=}, {row=})")
glue = PlaylistTracks(row=row) glue = PlaylistTracks(row=row)
glue.track_id = track.id glue.track_id = track.id
self.tracks.append(glue) self.tracks.append(glue)
@ -286,14 +284,10 @@ class PlaylistTracks(Base):
f"{from_playlist_id}, row={row}, " f"{from_playlist_id}, row={row}, "
f"to_playlist_id={to_playlist_id})" f"to_playlist_id={to_playlist_id})"
) )
max_row = session.query(func.max(PlaylistTracks.row)).filter( new_row = (
session.query(func.max(PlaylistTracks.row)).filter(
PlaylistTracks.playlist_id == to_playlist_id).scalar() PlaylistTracks.playlist_id == to_playlist_id).scalar()
if max_row is None: ) + 1
# Destination playlist is empty; use row 0
new_row = 0
else:
# Destination playlist has tracks; add to end
new_row = max_row + 1
record = session.query(PlaylistTracks).filter( record = session.query(PlaylistTracks).filter(
PlaylistTracks.playlist_id == from_playlist_id, PlaylistTracks.playlist_id == from_playlist_id,
PlaylistTracks.row == row PlaylistTracks.row == row

View File

@ -28,7 +28,7 @@ from config import Config
from model import (Notes, Playdates, Playlists, PlaylistTracks, from model import (Notes, Playdates, Playlists, PlaylistTracks,
Session, Settings, Tracks) Session, Settings, Tracks)
from playlists import Playlist from playlists import Playlist
from songdb import create_track_from_file from songdb import add_path_to_db
from ui.dlg_search_database_ui import Ui_Dialog from ui.dlg_search_database_ui import Ui_Dialog
from ui.dlg_SelectPlaylist_ui import Ui_dlgSelectPlaylist from ui.dlg_SelectPlaylist_ui import Ui_dlgSelectPlaylist
from ui.main_window_ui import Ui_MainWindow from ui.main_window_ui import Ui_MainWindow
@ -65,7 +65,7 @@ class Window(QMainWindow, Ui_MainWindow):
def add_file(self): def add_file(self):
dlg = QFileDialog() dlg = QFileDialog()
dlg.setFileMode(QFileDialog.ExistingFiles) dlg.setFileMode(QFileDialog.ExistingFile)
dlg.setViewMode(QFileDialog.Detail) dlg.setViewMode(QFileDialog.Detail)
dlg.setDirectory(Config.ROOT) dlg.setDirectory(Config.ROOT)
dlg.setNameFilter("Music files (*.flac *.mp3)") dlg.setNameFilter("Music files (*.flac *.mp3)")
@ -73,14 +73,10 @@ class Window(QMainWindow, Ui_MainWindow):
if dlg.exec_(): if dlg.exec_():
with Session() as session: with Session() as session:
for fname in dlg.selectedFiles(): for fname in dlg.selectedFiles():
track = create_track_from_file(session, fname) track = add_path_to_db(session, fname)
# Add to playlist on screen self.visible_playlist().add_to_playlist(session, track)
# If we don't specify "repaint=False", playlist will
# also be saved to database
self.visible_playlist().insert_track(session, track)
def set_main_window_size(self): def set_main_window_size(self):
"Set size of window from database"
with Session() as session: with Session() as session:
record = Settings.get_int(session, "mainwindow_x") record = Settings.get_int(session, "mainwindow_x")
@ -144,7 +140,6 @@ class Window(QMainWindow, Ui_MainWindow):
self.actionSkip_next.triggered.connect(self.play_next) self.actionSkip_next.triggered.connect(self.play_next)
self.actionSkipToEnd.triggered.connect(self.test_skip_to_end) self.actionSkipToEnd.triggered.connect(self.test_skip_to_end)
self.actionSkipToFade.triggered.connect(self.test_skip_to_fade) self.actionSkipToFade.triggered.connect(self.test_skip_to_fade)
self.actionStop.triggered.connect(self.stop)
self.actionTestFunction.triggered.connect(self.test_function) self.actionTestFunction.triggered.connect(self.test_function)
self.btnAddFile.clicked.connect(self.add_file) self.btnAddFile.clicked.connect(self.add_file)
self.btnAddNote.clicked.connect(self.insert_note) self.btnAddNote.clicked.connect(self.insert_note)
@ -181,9 +176,7 @@ class Window(QMainWindow, Ui_MainWindow):
def close_playlist(self): def close_playlist(self):
with Session() as session: with Session() as session:
playlist_db = session.query(Playlists).filter( self.visible_playlist().db.close(session)
Playlists.id == self.visible_playlist().id).one()
playlist_db.close(session)
index = self.tabPlaylist.currentIndex() index = self.tabPlaylist.currentIndex()
self.tabPlaylist.removeTab(index) self.tabPlaylist.removeTab(index)
@ -203,7 +196,7 @@ class Window(QMainWindow, Ui_MainWindow):
DEBUG(f"musicmuster.create_note(text={text}): row={row}") DEBUG(f"musicmuster.create_note(text={text}): row={row}")
note = Notes.add_note( note = Notes.add_note(
session, self.visible_playlist().id, row, text) session, self.visible_playlist().db.id, row, text)
return note return note
@ -273,7 +266,7 @@ class Window(QMainWindow, Ui_MainWindow):
if ok: if ok:
with Session() as session: with Session() as session:
note = self.create_note(session, dlg.textValue()) note = self.create_note(session, dlg.textValue())
self.visible_playlist().insert_note(session, note) self.visible_playlist().add_note(session, note)
def load_last_playlists(self): def load_last_playlists(self):
"Load the playlists that we loaded at end of last session" "Load the playlists that we loaded at end of last session"
@ -300,8 +293,10 @@ class Window(QMainWindow, Ui_MainWindow):
"Move selected rows to another playlist" "Move selected rows to another playlist"
with Session() as session: with Session() as session:
playlists = [p for p in Playlists.get_all_playlists(session) playlists = list(
if p.id != self.visible_playlist().id] set(Playlists.get_all_playlists(session)) -
{self.visible_playlist().db}
)
dlg = SelectPlaylistDialog(self, playlists=playlists) dlg = SelectPlaylistDialog(self, playlists=playlists)
dlg.exec() dlg.exec()
if not dlg.plid: if not dlg.plid:
@ -310,30 +305,23 @@ class Window(QMainWindow, Ui_MainWindow):
# If destination playlist is visible, we need to add the moved # If destination playlist is visible, we need to add the moved
# tracks to it. If not, they will be automatically loaded when # tracks to it. If not, they will be automatically loaded when
# the playlistis opened. # the playlistis opened.
destination_visible_playlist_tab = None destination_playlist = None
for tab in range(self.tabPlaylist.count()): for tab in range(self.tabPlaylist.count()):
if self.tabPlaylist.widget(tab).id == dlg.plid: if self.tabPlaylist.widget(tab).db.id == dlg.plid:
destination_visible_playlist_tab = ( destination_playlist = self.tabPlaylist.widget(tab)
self.tabPlaylist.widget(tab))
break break
rows = [] rows = []
for (row, track_id) in ( for (row, track_id) in (
self.visible_playlist().get_selected_rows_and_tracks()): self.visible_playlist().get_selected_rows_and_tracks()):
rows.append(row) rows.append(row)
track = Tracks.track_from_id(session, track_id)
if destination_visible_playlist_tab:
# Insert with repaint=False to not update database
destination_visible_playlist_tab.insert_track(
session, track, repaint=False)
# Update database # Update database
PlaylistTracks.move_track( PlaylistTracks.move_track(
session, self.visible_playlist().id, row, dlg.plid) session, self.visible_playlist().db.id, row, dlg.plid)
# Update destination playlist if visible
# Update destination playlist if visible if destination_playlist:
if destination_visible_playlist_tab: destination_playlist.add_track(
destination_visible_playlist_tab.repaint() session, Tracks.track_from_id(session, track_id))
# Update source playlist # Update source playlist
self.visible_playlist().remove_rows(rows) self.visible_playlist().remove_rows(rows)
@ -699,11 +687,7 @@ class DbDialog(QDialog):
def add_track(self, track_id): def add_track(self, track_id):
track = Tracks.track_from_id(self.session, track_id) track = Tracks.track_from_id(self.session, track_id)
# Add to playlist on screen self.parent().visible_playlist().add_to_playlist(self.session, track)
# If we don't specify "repaint=False", playlist will
# also be saved to database
self.parent().visible_playlist().insert_track(
self.session, track)
# Select search text to make it easier for next search # Select search text to make it easier for next search
self.select_searchtext() self.select_searchtext()

View File

@ -167,21 +167,19 @@ class Playlist(QTableWidget):
# ########## Externally called functions ########## # ########## Externally called functions ##########
def insert_note(self, session, note, repaint=True): def add_note(self, session, note, repaint=True):
""" """
Add note to playlist Add note to playlist
If a row is selected, add note above. Otherwise, add to end of If a row is selected, add note above. Otherwise, add to end of
playlist. playlist.
Return the row number that track is now in.
""" """
if self.selectionModel().hasSelection(): if self.selectionModel().hasSelection():
row = self.currentRow() row = self.currentRow()
else: else:
row = self.rowCount() row = self.rowCount()
DEBUG(f"playlist.inset_note(): row={row}") DEBUG(f"playlist.add_note(): row={row}")
# Does note end with a time? # Does note end with a time?
start_time = None start_time = None
@ -218,26 +216,38 @@ class Playlist(QTableWidget):
self._save_playlist(session) self._save_playlist(session)
self._repaint(clear_selection=False) self._repaint(clear_selection=False)
return row def add_to_playlist(self, session, data, repaint=True):
def insert_track(self, session, track, repaint=True):
""" """
Insert track into on-screen playlist. Add data to playlist. Data may be either a Tracks object or a
Notes object.
"""
DEBUG(f"playlists.add_to_playlist(session={session}, data={data})")
if isinstance(data, Tracks):
self.add_track(session, data, repaint=repaint)
elif isinstance(data, Notes):
self.add_note(session, data, repaint=repaint)
def add_track(self, session, track, repaint=True):
"""
Add track to playlist
If a row is selected, add track above. Otherwise, add to end of If a row is selected, add track above. Otherwise, add to end of
playlist. playlist.
Return the row number that track is now in.
""" """
if self.selectionModel().hasSelection(): if self.selectionModel().hasSelection():
row = self.currentRow() row = self.currentRow()
else: else:
row = self.rowCount() row = self.rowCount()
DEBUG( DEBUG(f"playlists.add_track(track={track}), row={row}")
f"playlists.insert_track({session=}, {track=}, {repaint=}), "
f"{row=}" # We need to add ourself to the session
) playlist_db = session.query(Playlists).filter(
Playlists.id == self.id).one()
playlist_db.add_track(session, track, row)
self.insertRow(row) self.insertRow(row)
@ -265,8 +275,6 @@ class Playlist(QTableWidget):
self._save_playlist(session) self._save_playlist(session)
self._repaint(clear_selection=False) self._repaint(clear_selection=False)
return row
def clear_current(self): def clear_current(self):
"Clear current track" "Clear current track"
@ -376,12 +384,8 @@ class Playlist(QTableWidget):
self.setRowCount(0) self.setRowCount(0)
# Now add data in row order # Now add data in row order
for i in sorted(data, key=lambda x: x[0]): for item in sorted(data, key=lambda x: x[0]):
item = i[1] self.add_to_playlist(session, item[1], repaint=False)
if isinstance(item, Tracks):
self.insert_track(session, item, repaint=False)
elif isinstance(item, Notes):
self.insert_note(session, item, repaint=False)
# Scroll to top # Scroll to top
scroll_to = self.item(0, self.COL_INDEX) scroll_to = self.item(0, self.COL_INDEX)

View File

@ -34,12 +34,8 @@ def main():
INFO("Finished") INFO("Finished")
def create_track_from_file(session, path): def add_path_to_db(session, path):
""" "Add passed path to database along with metadata"
Create track in database from passed path.
Return track.
"""
track = Tracks.get_or_create(session, path) track = Tracks.get_or_create(session, path)
tag = TinyTag.get(path) tag = TinyTag.get(path)
@ -65,7 +61,7 @@ def create_track_from_file(session, path):
fd, temp_path = tempfile.mkstemp() fd, temp_path = tempfile.mkstemp()
shutil.copyfile(path, temp_path) shutil.copyfile(path, temp_path)
except Exception as err: except Exception as err:
DEBUG(f"songdb.create_track_from_file({path}): err1: {str(err)}") DEBUG(f"songdb.add_path_to_db({path}): err1: {str(err)}")
return return
# Overwrite original file with normalised output # Overwrite original file with normalised output
@ -82,7 +78,7 @@ def create_track_from_file(session, path):
dst[tag] = src[tag] dst[tag] = src[tag]
dst.save() dst.save()
except Exception as err: except Exception as err:
DEBUG(f"songdb.create_track_from_file({path}): err2: {str(err)}") DEBUG(f"songdb.add_path_to_db({path}): err2: {str(err)}")
# Restore original file # Restore original file
shutil.copyfile(path, temp_path) shutil.copyfile(path, temp_path)
finally: finally:
@ -194,7 +190,7 @@ def update_db(session):
for path in list(os_paths - db_paths): for path in list(os_paths - db_paths):
# TODO # TODO
INFO(f"Adding to dataabase: {path}") INFO(f"Adding to dataabase: {path}")
create_track_from_file(session, path) add_path_to_db(session, path)
if __name__ == '__main__' and '__file__' in globals(): if __name__ == '__main__' and '__file__' in globals():

View File

@ -734,7 +734,7 @@ border: 1px solid rgb(85, 87, 83);</string>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>1164</width> <width>1164</width>
<height>29</height> <height>26</height>
</rect> </rect>
</property> </property>
<widget class="QMenu" name="menuFile"> <widget class="QMenu" name="menuFile">
@ -771,7 +771,7 @@ border: 1px solid rgb(85, 87, 83);</string>
<addaction name="actionPlay_next"/> <addaction name="actionPlay_next"/>
<addaction name="actionSkip_next"/> <addaction name="actionSkip_next"/>
<addaction name="actionFade"/> <addaction name="actionFade"/>
<addaction name="actionStop"/> <addaction name="actionS_top"/>
<addaction name="action_Resume_previous"/> <addaction name="action_Resume_previous"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionSetNext"/> <addaction name="actionSetNext"/>
@ -858,7 +858,7 @@ border: 1px solid rgb(85, 87, 83);</string>
<string>Ctrl+S</string> <string>Ctrl+S</string>
</property> </property>
</action> </action>
<action name="actionStop"> <action name="actionS_top">
<property name="icon"> <property name="icon">
<iconset resource="icons.qrc"> <iconset resource="icons.qrc">
<normaloff>:/icons/stop</normaloff>:/icons/stop</iconset> <normaloff>:/icons/stop</normaloff>:/icons/stop</iconset>