Compare commits

..

6 Commits

Author SHA1 Message Date
Keith Edmunds
37ccf7c325 Fix moving tracks between playlists 2021-06-06 15:57:32 +01:00
Keith Edmunds
823d0b6628 Fix error closing playlist 2021-06-06 14:51:46 +01:00
Keith Edmunds
ec760ca0d4 Allow adding more than one file at a time 2021-06-06 14:48:58 +01:00
Keith Edmunds
0ca9bfec0a Segregate adding notes, tracks to onscreen playlist and database 2021-06-06 14:47:14 +01:00
Keith Edmunds
e14bed34bd Improve repr for mode:Playlists 2021-06-06 14:44:15 +01:00
Keith Edmunds
6677577df5 Wire up Tracks, Stop menu. Fixed #6. 2021-06-06 14:43:27 +01:00
5 changed files with 79 additions and 57 deletions

View File

@ -164,7 +164,7 @@ class Playlists(Base):
back_populates="playlists")
def __repr__(self):
return (f"<Playlist(id={self.id}, name={self.name}>")
return (f"<Playlists(id={self.id}, name={self.name}>")
def add_track(self, session, track, row=None):
"""
@ -175,6 +175,8 @@ class Playlists(Base):
if not row:
row = PlaylistTracks.new_row(session, self.id)
DEBUG(f"Playlists:add_track({session=}, {track=}, {row=})")
glue = PlaylistTracks(row=row)
glue.track_id = track.id
self.tracks.append(glue)
@ -284,10 +286,14 @@ class PlaylistTracks(Base):
f"{from_playlist_id}, row={row}, "
f"to_playlist_id={to_playlist_id})"
)
new_row = (
session.query(func.max(PlaylistTracks.row)).filter(
max_row = session.query(func.max(PlaylistTracks.row)).filter(
PlaylistTracks.playlist_id == to_playlist_id).scalar()
) + 1
if max_row is None:
# 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(
PlaylistTracks.playlist_id == from_playlist_id,
PlaylistTracks.row == row

View File

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

View File

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

View File

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

View File

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