parent
e1800328fd
commit
cf7930190e
@ -186,7 +186,7 @@ class Playdates(Base):
|
||||
id: int = Column(Integer, primary_key=True, autoincrement=True)
|
||||
lastplayed: datetime = Column(DateTime, index=True, default=None)
|
||||
track_id: int = Column(Integer, ForeignKey('tracks.id'))
|
||||
tracks: RelationshipProperty = relationship(
|
||||
track: RelationshipProperty = relationship(
|
||||
"Tracks", back_populates="playdates", lazy="joined")
|
||||
|
||||
def __init__(self, session: Session, track_id: int) -> None:
|
||||
@ -212,6 +212,13 @@ class Playdates(Base):
|
||||
else:
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def played_after(session: Session, since: datetime) -> List["Playdates"]:
|
||||
"""Return a list of Playdates objects since passed time"""
|
||||
|
||||
return session.query(Playdates).filter(
|
||||
Playdates.lastplayed >= since).all()
|
||||
|
||||
@staticmethod
|
||||
def remove_track(session: Session, track_id: int) -> None:
|
||||
"""
|
||||
@ -478,7 +485,8 @@ class Tracks(Base):
|
||||
back_populates="tracks",
|
||||
lazy="joined")
|
||||
playdates: RelationshipProperty = relationship("Playdates",
|
||||
back_populates="tracks",
|
||||
back_populates="track"
|
||||
"",
|
||||
lazy="joined")
|
||||
|
||||
def __init__(
|
||||
|
||||
@ -11,7 +11,7 @@ from datetime import datetime
|
||||
from log import DEBUG, EXCEPTION
|
||||
from typing import Callable, Dict, List, Optional, Tuple
|
||||
|
||||
from PyQt5.QtCore import QEvent, QProcess, Qt, QTimer, QUrl
|
||||
from PyQt5.QtCore import QDate, QEvent, QProcess, Qt, QTime, QTimer, QUrl
|
||||
from PyQt5.QtGui import QColor
|
||||
from PyQt5.QtWebEngineWidgets import QWebEngineView as QWebView
|
||||
from PyQt5.QtWidgets import (
|
||||
@ -36,6 +36,7 @@ from playlists import PlaylistTab
|
||||
from sqlalchemy.orm.exc import DetachedInstanceError
|
||||
from ui.dlg_search_database_ui import Ui_Dialog
|
||||
from ui.dlg_SelectPlaylist_ui import Ui_dlgSelectPlaylist
|
||||
from ui.downloadcsv_ui import Ui_DateSelect
|
||||
from ui.main_window_ui import Ui_MainWindow
|
||||
from utilities import create_track_from_file
|
||||
|
||||
@ -170,6 +171,8 @@ class Window(QMainWindow, Ui_MainWindow):
|
||||
self.actionAdd_note.triggered.connect(self.create_note)
|
||||
self.action_Clear_selection.triggered.connect(self.clear_selection)
|
||||
self.actionClosePlaylist.triggered.connect(self.close_playlist_tab)
|
||||
self.actionDownload_CSV_of_played_tracks.triggered.connect(
|
||||
self.download_played_tracks)
|
||||
self.actionEnable_controls.triggered.connect(
|
||||
self.enable_play_next_controls)
|
||||
self.actionExport_playlist.triggered.connect(self.export_playlist_tab)
|
||||
@ -279,6 +282,32 @@ class Window(QMainWindow, Ui_MainWindow):
|
||||
self.actionPlay_next.setEnabled(False)
|
||||
self.statusbar.showMessage("Play controls: Disabled", 0)
|
||||
|
||||
def download_played_tracks(self) -> None:
|
||||
"""Download a CSV of played tracks"""
|
||||
|
||||
dlg = DownloadCSV(self)
|
||||
if dlg.exec():
|
||||
start_dt = dlg.ui.dateTimeEdit.dateTime().toPyDateTime()
|
||||
# Get output filename
|
||||
pathspec: Tuple[str, str] = QFileDialog.getSaveFileName(
|
||||
self, 'Save CSV of tracks played',
|
||||
directory="/tmp/playlist.csv",
|
||||
filter="CSV files (*.csv)"
|
||||
)
|
||||
if not pathspec:
|
||||
return
|
||||
|
||||
path: str = pathspec[0]
|
||||
if not path.endswith(".csv"):
|
||||
path += ".csv"
|
||||
|
||||
with open(path, "w") as f:
|
||||
with Session() as session:
|
||||
for playdate in Playdates.played_after(session, start_dt):
|
||||
f.write(
|
||||
f"{playdate.track.artist},{playdate.track.title}\n"
|
||||
)
|
||||
|
||||
def enable_play_next_controls(self) -> None:
|
||||
"""
|
||||
Enable "play next" keyboard controls
|
||||
@ -957,6 +986,18 @@ class DbDialog(QDialog):
|
||||
self.ui.dbPath.setText(track.path)
|
||||
|
||||
|
||||
class DownloadCSV(QDialog):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
|
||||
self.ui = Ui_DateSelect()
|
||||
self.ui.setupUi(self)
|
||||
self.ui.dateTimeEdit.setDate(QDate.currentDate())
|
||||
self.ui.dateTimeEdit.setTime(QTime(19, 59, 0))
|
||||
self.ui.buttonBox.accepted.connect(self.accept)
|
||||
self.ui.buttonBox.rejected.connect(self.reject)
|
||||
|
||||
|
||||
class SelectPlaylistDialog(QDialog):
|
||||
def __init__(self, parent=None, playlists=None, session=None):
|
||||
super().__init__(parent)
|
||||
|
||||
107
app/ui/downloadcsv.ui
Normal file
107
app/ui/downloadcsv.ui
Normal file
@ -0,0 +1,107 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>DateSelect</class>
|
||||
<widget class="QDialog" name="DateSelect">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>280</width>
|
||||
<height>166</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>70</x>
|
||||
<y>110</y>
|
||||
<width>191</width>
|
||||
<height>32</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QDateTimeEdit" name="dateTimeEdit">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>70</x>
|
||||
<y>60</y>
|
||||
<width>194</width>
|
||||
<height>28</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="calendarPopup">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>20</y>
|
||||
<width>261</width>
|
||||
<height>19</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Download CSV of tracks played</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>15</x>
|
||||
<y>66</y>
|
||||
<width>51</width>
|
||||
<height>19</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Since:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>DateSelect</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>DateSelect</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
43
app/ui/downloadcsv_ui.py
Normal file
43
app/ui/downloadcsv_ui.py
Normal file
@ -0,0 +1,43 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'ui/downloadcsv.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.15.6
|
||||
#
|
||||
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
||||
# run again. Do not edit this file unless you know what you are doing.
|
||||
|
||||
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
|
||||
|
||||
class Ui_DateSelect(object):
|
||||
def setupUi(self, DateSelect):
|
||||
DateSelect.setObjectName("DateSelect")
|
||||
DateSelect.resize(280, 166)
|
||||
self.buttonBox = QtWidgets.QDialogButtonBox(DateSelect)
|
||||
self.buttonBox.setGeometry(QtCore.QRect(70, 110, 191, 32))
|
||||
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
|
||||
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
|
||||
self.buttonBox.setObjectName("buttonBox")
|
||||
self.dateTimeEdit = QtWidgets.QDateTimeEdit(DateSelect)
|
||||
self.dateTimeEdit.setGeometry(QtCore.QRect(70, 60, 194, 28))
|
||||
self.dateTimeEdit.setCalendarPopup(True)
|
||||
self.dateTimeEdit.setObjectName("dateTimeEdit")
|
||||
self.label = QtWidgets.QLabel(DateSelect)
|
||||
self.label.setGeometry(QtCore.QRect(10, 20, 261, 19))
|
||||
self.label.setObjectName("label")
|
||||
self.label_2 = QtWidgets.QLabel(DateSelect)
|
||||
self.label_2.setGeometry(QtCore.QRect(15, 66, 51, 19))
|
||||
self.label_2.setObjectName("label_2")
|
||||
|
||||
self.retranslateUi(DateSelect)
|
||||
self.buttonBox.accepted.connect(DateSelect.accept) # type: ignore
|
||||
self.buttonBox.rejected.connect(DateSelect.reject) # type: ignore
|
||||
QtCore.QMetaObject.connectSlotsByName(DateSelect)
|
||||
|
||||
def retranslateUi(self, DateSelect):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
DateSelect.setWindowTitle(_translate("DateSelect", "Dialog"))
|
||||
self.label.setText(_translate("DateSelect", "Download CSV of tracks played"))
|
||||
self.label_2.setText(_translate("DateSelect", "Since:"))
|
||||
@ -786,6 +786,7 @@ border: 1px solid rgb(85, 87, 83);</string>
|
||||
<addaction name="actionSelect_played_tracks"/>
|
||||
<addaction name="actionMoveSelected"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionDownload_CSV_of_played_tracks"/>
|
||||
<addaction name="actionExport_playlist"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menu_Music">
|
||||
@ -1022,6 +1023,11 @@ border: 1px solid rgb(85, 87, 83);</string>
|
||||
<string>Ctrl+Shift+I</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDownload_CSV_of_played_tracks">
|
||||
<property name="text">
|
||||
<string>Download CSV of played tracks...</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="icons.qrc"/>
|
||||
|
||||
@ -443,6 +443,8 @@ class Ui_MainWindow(object):
|
||||
self.actionEnable_controls.setObjectName("actionEnable_controls")
|
||||
self.actionImport = QtWidgets.QAction(MainWindow)
|
||||
self.actionImport.setObjectName("actionImport")
|
||||
self.actionDownload_CSV_of_played_tracks = QtWidgets.QAction(MainWindow)
|
||||
self.actionDownload_CSV_of_played_tracks.setObjectName("actionDownload_CSV_of_played_tracks")
|
||||
self.menuFile.addAction(self.actionImport)
|
||||
self.menuFile.addSeparator()
|
||||
self.menuFile.addAction(self.actionE_xit)
|
||||
@ -465,6 +467,7 @@ class Ui_MainWindow(object):
|
||||
self.menuPlaylist.addAction(self.actionSelect_played_tracks)
|
||||
self.menuPlaylist.addAction(self.actionMoveSelected)
|
||||
self.menuPlaylist.addSeparator()
|
||||
self.menuPlaylist.addAction(self.actionDownload_CSV_of_played_tracks)
|
||||
self.menuPlaylist.addAction(self.actionExport_playlist)
|
||||
self.menu_Music.addAction(self.actionPlay_next)
|
||||
self.menu_Music.addAction(self.actionSkip_next)
|
||||
@ -553,4 +556,5 @@ class Ui_MainWindow(object):
|
||||
self.actionEnable_controls.setText(_translate("MainWindow", "Enable controls"))
|
||||
self.actionImport.setText(_translate("MainWindow", "Import..."))
|
||||
self.actionImport.setShortcut(_translate("MainWindow", "Ctrl+Shift+I"))
|
||||
self.actionDownload_CSV_of_played_tracks.setText(_translate("MainWindow", "Download CSV of played tracks..."))
|
||||
import icons_rc
|
||||
|
||||
Loading…
Reference in New Issue
Block a user