Compare commits
No commits in common. "37ccf7c325d0f0c73adae38e19758cc3b782f4f6" and "c5f51553323bdd0def45e5470cb1a3e0fde8e49e" have entirely different histories.
37ccf7c325
...
c5f5155332
14
app/model.py
14
app/model.py
@ -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
|
||||||
|
|||||||
@ -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_visible_playlist_tab:
|
if destination_playlist:
|
||||||
destination_visible_playlist_tab.repaint()
|
destination_playlist.add_track(
|
||||||
|
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()
|
||||||
|
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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():
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user