Playlist creation and changing fragilely working
This commit is contained in:
parent
15a540234e
commit
67b3b804e1
37
app/model.py
37
app/model.py
@ -147,13 +147,26 @@ class Playlists(Base):
|
|||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return (f"<Playlist(id={self.id}, name={self.name}>")
|
return (f"<Playlist(id={self.id}, name={self.name}>")
|
||||||
|
|
||||||
# Currently we only support one playlist, so make that obvious from
|
@staticmethod
|
||||||
# function name
|
def new(name):
|
||||||
@classmethod
|
DEBUG(f"Playlists.new({name})")
|
||||||
def get_playlist_by_name(cls, name):
|
pl = Playlists()
|
||||||
"Returns a playlist object for named playlist"
|
pl.name = name
|
||||||
|
session.add(pl)
|
||||||
|
session.commit()
|
||||||
|
return pl.id
|
||||||
|
|
||||||
return session.query(Playlists).filter(Playlists.name == name).one()
|
@staticmethod
|
||||||
|
def get_all_playlists():
|
||||||
|
"Returns a list of (id, name) of all playlists"
|
||||||
|
|
||||||
|
return session.query(Playlists).all()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_playlist_by_id(cls, plid):
|
||||||
|
"Returns a playlist object for playlist id"
|
||||||
|
|
||||||
|
return session.query(Playlists).filter(Playlists.id == plid).one()
|
||||||
|
|
||||||
def add_track(self, track, row):
|
def add_track(self, track, row):
|
||||||
glue = PlaylistTracks(row=row)
|
glue = PlaylistTracks(row=row)
|
||||||
@ -178,14 +191,18 @@ class PlaylistTracks(Base):
|
|||||||
playlists = relationship("Playlists", back_populates="tracks")
|
playlists = relationship("Playlists", back_populates="tracks")
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def update_track_row(playlist_id, track_id, row):
|
def update_track_row(playlist_id, track_id, old_row, new_row):
|
||||||
DEBUG(f"update_track({id}, {row})")
|
DEBUG(
|
||||||
|
f"update_track_row({playlist_id}, "
|
||||||
|
f"{track_id}, {old_row}, {new_row})"
|
||||||
|
)
|
||||||
|
|
||||||
plt = session.query(PlaylistTracks).filter(
|
plt = session.query(PlaylistTracks).filter(
|
||||||
PlaylistTracks.playlist_id == playlist_id,
|
PlaylistTracks.playlist_id == playlist_id,
|
||||||
PlaylistTracks.track_id == track_id
|
PlaylistTracks.track_id == track_id,
|
||||||
|
PlaylistTracks.row == old_row
|
||||||
).one()
|
).one()
|
||||||
plt.row = row
|
plt.row = new_row
|
||||||
session.commit()
|
session.commit()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|||||||
@ -7,21 +7,19 @@ import music
|
|||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
# from log import DEBUG
|
# from log import DEBUG
|
||||||
|
|
||||||
from PyQt5.QtCore import Qt, QTimer
|
from PyQt5.QtCore import QTimer
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
QApplication,
|
QApplication,
|
||||||
QDialog,
|
|
||||||
QFileDialog,
|
QFileDialog,
|
||||||
QInputDialog,
|
QInputDialog,
|
||||||
QListWidgetItem,
|
QLabel,
|
||||||
QMainWindow,
|
QMainWindow,
|
||||||
)
|
)
|
||||||
|
|
||||||
import helpers
|
import helpers
|
||||||
|
|
||||||
from config import Config
|
from config import Config
|
||||||
from model import Playlists, Settings, Tracks
|
from model import Settings
|
||||||
from ui.dlg_search_database_ui import Ui_Dialog
|
|
||||||
from ui.main_window_ui import Ui_MainWindow
|
from ui.main_window_ui import Ui_MainWindow
|
||||||
|
|
||||||
|
|
||||||
@ -47,10 +45,15 @@ class Window(QMainWindow, Ui_MainWindow):
|
|||||||
height = record.f_int or 981
|
height = record.f_int or 981
|
||||||
self.setGeometry(x, y, width, height)
|
self.setGeometry(x, y, width, height)
|
||||||
|
|
||||||
# Hard code to the only playlist we have for now
|
# Hard code to the first playlist for now
|
||||||
if self.playlist.load_playlist("Default"):
|
# TODO
|
||||||
|
if self.playlist.load_playlist(1):
|
||||||
self.update_headers()
|
self.update_headers()
|
||||||
self.enable_play_next_controls()
|
self.enable_play_next_controls()
|
||||||
|
|
||||||
|
self.plLabel = QLabel(f"Playlist: {self.playlist.playlist_name}")
|
||||||
|
self.statusbar.addPermanentWidget(self.plLabel)
|
||||||
|
|
||||||
self.timer.start(Config.TIMER_MS)
|
self.timer.start(Config.TIMER_MS)
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
@ -90,6 +93,8 @@ class Window(QMainWindow, Ui_MainWindow):
|
|||||||
def connect_signals_slots(self):
|
def connect_signals_slots(self):
|
||||||
self.action_Clear_selection.triggered.connect(self.clear_selection)
|
self.action_Clear_selection.triggered.connect(self.clear_selection)
|
||||||
self.actionFade.triggered.connect(self.fade)
|
self.actionFade.triggered.connect(self.fade)
|
||||||
|
self.actionNewPlaylist.triggered.connect(self.create_playlist)
|
||||||
|
self.actionSelectPlaylist.triggered.connect(self.select_playlist)
|
||||||
self.actionPlay_next.triggered.connect(self.play_next)
|
self.actionPlay_next.triggered.connect(self.play_next)
|
||||||
self.actionSearch_database.triggered.connect(self.search_database)
|
self.actionSearch_database.triggered.connect(self.search_database)
|
||||||
self.actionSkip_next.triggered.connect(self.play_next)
|
self.actionSkip_next.triggered.connect(self.play_next)
|
||||||
@ -102,6 +107,17 @@ class Window(QMainWindow, Ui_MainWindow):
|
|||||||
|
|
||||||
self.timer.timeout.connect(self.tick)
|
self.timer.timeout.connect(self.tick)
|
||||||
|
|
||||||
|
def create_playlist(self):
|
||||||
|
"Create new playlist"
|
||||||
|
|
||||||
|
dlg = QInputDialog(self)
|
||||||
|
dlg.setInputMode(QInputDialog.TextInput)
|
||||||
|
dlg.setLabelText("Playlist name:")
|
||||||
|
dlg.resize(500, 100)
|
||||||
|
ok = dlg.exec()
|
||||||
|
if ok:
|
||||||
|
self.playlist.create_playlist(dlg.textValue())
|
||||||
|
|
||||||
def disable_play_next_controls(self):
|
def disable_play_next_controls(self):
|
||||||
self.actionPlay_next.setEnabled(False)
|
self.actionPlay_next.setEnabled(False)
|
||||||
|
|
||||||
@ -143,8 +159,10 @@ class Window(QMainWindow, Ui_MainWindow):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def search_database(self):
|
def search_database(self):
|
||||||
dlg = DbDialog(self)
|
self.playlist.search_database()
|
||||||
dlg.exec()
|
|
||||||
|
def select_playlist(self):
|
||||||
|
self.playlist.select_playlist()
|
||||||
|
|
||||||
def set_next_track(self):
|
def set_next_track(self):
|
||||||
"Set selected track as next"
|
"Set selected track as next"
|
||||||
@ -237,62 +255,8 @@ class Window(QMainWindow, Ui_MainWindow):
|
|||||||
f"{self.playlist.get_next_artist()}"
|
f"{self.playlist.get_next_artist()}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def update_statusbar(self):
|
||||||
class AddNoteDialog(QDialog):
|
pass
|
||||||
def __init__(self, parent=None):
|
|
||||||
super().__init__(parent)
|
|
||||||
self.ui = Ui_dlgAddNote()
|
|
||||||
self.ui.setupUi(self)
|
|
||||||
|
|
||||||
|
|
||||||
class DbDialog(QDialog):
|
|
||||||
def __init__(self, parent=None):
|
|
||||||
super().__init__(parent)
|
|
||||||
self.ui = Ui_Dialog()
|
|
||||||
self.ui.setupUi(self)
|
|
||||||
self.ui.searchString.textEdited.connect(self.chars_typed)
|
|
||||||
self.ui.matchList.itemDoubleClicked.connect(self.listdclick)
|
|
||||||
|
|
||||||
record = Settings.get_int("dbdialog_width")
|
|
||||||
width = record.f_int or 800
|
|
||||||
record = Settings.get_int("dbdialog_height")
|
|
||||||
height = record.f_int or 600
|
|
||||||
self.resize(width, height)
|
|
||||||
|
|
||||||
def __del__(self):
|
|
||||||
record = Settings.get_int("dbdialog_height")
|
|
||||||
if record.f_int != self.height():
|
|
||||||
record.update({'f_int': self.height()})
|
|
||||||
|
|
||||||
record = Settings.get_int("dbdialog_width")
|
|
||||||
if record.f_int != self.width():
|
|
||||||
record.update({'f_int': self.width()})
|
|
||||||
|
|
||||||
def chars_typed(self, s):
|
|
||||||
if len(s) >= 3:
|
|
||||||
matches = Tracks.search_titles(s)
|
|
||||||
self.ui.matchList.clear()
|
|
||||||
if matches:
|
|
||||||
for track in matches:
|
|
||||||
t = QListWidgetItem()
|
|
||||||
t.setText(
|
|
||||||
f"{track.title} - {track.artist} "
|
|
||||||
f"[{helpers.ms_to_mmss(track.duration)}]"
|
|
||||||
)
|
|
||||||
t.setData(Qt.UserRole, track.id)
|
|
||||||
self.ui.matchList.addItem(t)
|
|
||||||
|
|
||||||
def listdclick(self, entry):
|
|
||||||
track_id = entry.data(Qt.UserRole)
|
|
||||||
track = Tracks.track_from_id(track_id)
|
|
||||||
|
|
||||||
# Store in current playlist in database
|
|
||||||
db_playlist = Playlists.get_only_playlist()
|
|
||||||
# TODO: hack position to be at end of list
|
|
||||||
db_playlist.add_track(track, 99999)
|
|
||||||
|
|
||||||
# Add to on-screen playlist
|
|
||||||
self.parent().add_to_playlist(track)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|||||||
110
app/playlists.py
110
app/playlists.py
@ -5,7 +5,9 @@ from PyQt5.QtGui import QColor, QDropEvent
|
|||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
QAbstractItemView,
|
QAbstractItemView,
|
||||||
QApplication,
|
QApplication,
|
||||||
|
QDialog,
|
||||||
QHBoxLayout,
|
QHBoxLayout,
|
||||||
|
QListWidgetItem,
|
||||||
QMenu,
|
QMenu,
|
||||||
QMessageBox,
|
QMessageBox,
|
||||||
QTableWidget,
|
QTableWidget,
|
||||||
@ -19,6 +21,8 @@ from config import Config
|
|||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from log import DEBUG, ERROR
|
from log import DEBUG, ERROR
|
||||||
from model import Notes, Playdates, Playlists, PlaylistTracks, Settings, Tracks
|
from model import Notes, Playdates, Playlists, PlaylistTracks, Settings, Tracks
|
||||||
|
from ui.dlg_search_database_ui import Ui_Dialog
|
||||||
|
from ui.dlg_SelectPlaylist_ui import Ui_dlgSelectPlaylist
|
||||||
|
|
||||||
|
|
||||||
class Playlist(QTableWidget):
|
class Playlist(QTableWidget):
|
||||||
@ -199,6 +203,12 @@ class Playlist(QTableWidget):
|
|||||||
if repaint:
|
if repaint:
|
||||||
self.repaint()
|
self.repaint()
|
||||||
|
|
||||||
|
def create_playlist(self, name):
|
||||||
|
"Create new playlist"
|
||||||
|
|
||||||
|
new_id = Playlists.new(name)
|
||||||
|
self.load_playlist(new_id)
|
||||||
|
|
||||||
def drop_on(self, event):
|
def drop_on(self, event):
|
||||||
index = self.indexAt(event.pos())
|
index = self.indexAt(event.pos())
|
||||||
if not index.isValid():
|
if not index.isValid():
|
||||||
@ -327,21 +337,21 @@ class Playlist(QTableWidget):
|
|||||||
and pos.y() >= rect.center().y() # noqa W503
|
and pos.y() >= rect.center().y() # noqa W503
|
||||||
)
|
)
|
||||||
|
|
||||||
def load_playlist(self, name):
|
def load_playlist(self, plid):
|
||||||
"""
|
"""
|
||||||
Load tracks and notes from named playlist.
|
Load tracks and notes from playlist id.
|
||||||
|
|
||||||
Set first track as next track to play.
|
Set first track as next track to play.
|
||||||
|
|
||||||
Return True if successful else False.
|
Return True if successful else False.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
DEBUG(f"load_playlist({name})")
|
DEBUG(f"load_playlist({plid})")
|
||||||
|
|
||||||
self.playlist_name = name
|
p = Playlists.get_playlist_by_id(plid)
|
||||||
|
self.playlist_id = plid
|
||||||
p = Playlists.get_playlist_by_name(name)
|
self.playlist_name = p.name
|
||||||
self.playlist_id = p.id
|
self.parent().parent().update_statusbar()
|
||||||
|
|
||||||
# We need to retrieve playlist tracks and playlist notes, then
|
# We need to retrieve playlist tracks and playlist notes, then
|
||||||
# add them in row order. We don't mandate that an item will be
|
# add them in row order. We don't mandate that an item will be
|
||||||
@ -354,6 +364,9 @@ class Playlist(QTableWidget):
|
|||||||
for n in p.notes:
|
for n in p.notes:
|
||||||
data.append(([n.row], n))
|
data.append(([n.row], n))
|
||||||
|
|
||||||
|
# Clear playlist
|
||||||
|
self.setRowCount(0)
|
||||||
|
|
||||||
# Now add data in row order
|
# Now add data in row order
|
||||||
for item in sorted(data, key=lambda x: x[0]):
|
for item in sorted(data, key=lambda x: x[0]):
|
||||||
DEBUG(f"Adding {item}")
|
DEBUG(f"Adding {item}")
|
||||||
@ -516,6 +529,14 @@ class Playlist(QTableWidget):
|
|||||||
# Update display
|
# Update display
|
||||||
self.tracks_changed()
|
self.tracks_changed()
|
||||||
|
|
||||||
|
def search_database(self):
|
||||||
|
dlg = DbDialog(self)
|
||||||
|
dlg.exec()
|
||||||
|
|
||||||
|
def select_playlist(self):
|
||||||
|
dlg = SelectPlaylistDialog(self)
|
||||||
|
dlg.exec()
|
||||||
|
|
||||||
def set_selected_as_next(self):
|
def set_selected_as_next(self):
|
||||||
"""
|
"""
|
||||||
Sets the selected track as the next track.
|
Sets the selected track as the next track.
|
||||||
@ -647,7 +668,7 @@ class Playlist(QTableWidget):
|
|||||||
# Get tracks and notes from database
|
# Get tracks and notes from database
|
||||||
db_tracks = {}
|
db_tracks = {}
|
||||||
db_notes = {}
|
db_notes = {}
|
||||||
p = Playlists.get_playlist_by_name(self.playlist_name)
|
p = Playlists.get_playlist_by_id(self.playlist_id)
|
||||||
|
|
||||||
for track in p.tracks:
|
for track in p.tracks:
|
||||||
db_tracks[track.track_id] = track.row
|
db_tracks[track.track_id] = track.row
|
||||||
@ -682,7 +703,8 @@ class Playlist(QTableWidget):
|
|||||||
if tracks[id] != db_tracks[id]:
|
if tracks[id] != db_tracks[id]:
|
||||||
DEBUG(f"Update db track.id={id} in database")
|
DEBUG(f"Update db track.id={id} in database")
|
||||||
PlaylistTracks.update_track_row(
|
PlaylistTracks.update_track_row(
|
||||||
self.playlist_id, id, row=tracks[id]
|
self.playlist_id, track_id=id,
|
||||||
|
old_row=db_tracks[id], new_row=tracks[id]
|
||||||
)
|
)
|
||||||
|
|
||||||
def set_row_bold(self, row):
|
def set_row_bold(self, row):
|
||||||
@ -749,6 +771,76 @@ class Playlist(QTableWidget):
|
|||||||
self.repaint()
|
self.repaint()
|
||||||
|
|
||||||
|
|
||||||
|
class DbDialog(QDialog):
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
self.ui = Ui_Dialog()
|
||||||
|
self.ui.setupUi(self)
|
||||||
|
self.ui.searchString.textEdited.connect(self.chars_typed)
|
||||||
|
self.ui.matchList.itemDoubleClicked.connect(self.listdclick)
|
||||||
|
|
||||||
|
record = Settings.get_int("dbdialog_width")
|
||||||
|
width = record.f_int or 800
|
||||||
|
record = Settings.get_int("dbdialog_height")
|
||||||
|
height = record.f_int or 600
|
||||||
|
self.resize(width, height)
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
record = Settings.get_int("dbdialog_height")
|
||||||
|
if record.f_int != self.height():
|
||||||
|
record.update({'f_int': self.height()})
|
||||||
|
|
||||||
|
record = Settings.get_int("dbdialog_width")
|
||||||
|
if record.f_int != self.width():
|
||||||
|
record.update({'f_int': self.width()})
|
||||||
|
|
||||||
|
def chars_typed(self, s):
|
||||||
|
if len(s) >= 3:
|
||||||
|
matches = Tracks.search_titles(s)
|
||||||
|
self.ui.matchList.clear()
|
||||||
|
if matches:
|
||||||
|
for track in matches:
|
||||||
|
t = QListWidgetItem()
|
||||||
|
t.setText(
|
||||||
|
f"{track.title} - {track.artist} "
|
||||||
|
f"[{helpers.ms_to_mmss(track.duration)}]"
|
||||||
|
)
|
||||||
|
t.setData(Qt.UserRole, track.id)
|
||||||
|
self.ui.matchList.addItem(t)
|
||||||
|
|
||||||
|
def listdclick(self, entry):
|
||||||
|
track_id = entry.data(Qt.UserRole)
|
||||||
|
track = Tracks.track_from_id(track_id)
|
||||||
|
|
||||||
|
# Store in current playlist in database
|
||||||
|
db_playlist = Playlists.get_playlist_by_id(self.parent().playlist_id)
|
||||||
|
# TODO: hack position to be at end of list
|
||||||
|
db_playlist.add_track(track, 99999)
|
||||||
|
|
||||||
|
# Add to on-screen playlist
|
||||||
|
self.parent().add_to_playlist(track)
|
||||||
|
|
||||||
|
|
||||||
|
class SelectPlaylistDialog(QDialog):
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
self.ui = Ui_dlgSelectPlaylist()
|
||||||
|
self.ui.setupUi(self)
|
||||||
|
self.ui.lstPlaylists.itemDoubleClicked.connect(self.listdclick)
|
||||||
|
|
||||||
|
for (plid, plname) in [
|
||||||
|
(a.id, a.name) for a in Playlists.get_all_playlists()
|
||||||
|
]:
|
||||||
|
p = QListWidgetItem()
|
||||||
|
p.setText(plname)
|
||||||
|
p.setData(Qt.UserRole, plid)
|
||||||
|
self.ui.lstPlaylists.addItem(p)
|
||||||
|
|
||||||
|
def listdclick(self, entry):
|
||||||
|
plid = entry.data(Qt.UserRole)
|
||||||
|
self.parent().load_playlist(plid)
|
||||||
|
|
||||||
|
|
||||||
class Window(QWidget):
|
class Window(QWidget):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(Window, self).__init__()
|
super(Window, self).__init__()
|
||||||
|
|||||||
67
app/ui/dlg_SelectPlaylist.ui
Normal file
67
app/ui/dlg_SelectPlaylist.ui
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>dlgSelectPlaylist</class>
|
||||||
|
<widget class="QDialog" name="dlgSelectPlaylist">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>276</width>
|
||||||
|
<height>150</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Dialog</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QListWidget" name="lstPlaylists"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>accepted()</signal>
|
||||||
|
<receiver>dlgSelectPlaylist</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>dlgSelectPlaylist</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>
|
||||||
@ -6,7 +6,7 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>768</width>
|
<width>931</width>
|
||||||
<height>600</height>
|
<height>600</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
@ -710,7 +710,7 @@ border: 1px solid rgb(85, 87, 83);</string>
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>768</width>
|
<width>931</width>
|
||||||
<height>18</height>
|
<height>18</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
@ -724,19 +724,26 @@ border: 1px solid rgb(85, 87, 83);</string>
|
|||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Pla&ylist</string>
|
<string>Pla&ylist</string>
|
||||||
</property>
|
</property>
|
||||||
<addaction name="actionPlay_next"/>
|
|
||||||
<addaction name="actionSkip_next"/>
|
|
||||||
<addaction name="actionSearch_database"/>
|
<addaction name="actionSearch_database"/>
|
||||||
<addaction name="actionAdd_file"/>
|
<addaction name="actionAdd_file"/>
|
||||||
|
<addaction name="action_Clear_selection"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
|
<addaction name="actionSelectPlaylist"/>
|
||||||
|
<addaction name="actionNewPlaylist"/>
|
||||||
|
</widget>
|
||||||
|
<widget class="QMenu" name="menu_Tracks">
|
||||||
|
<property name="title">
|
||||||
|
<string>&Tracks</string>
|
||||||
|
</property>
|
||||||
|
<addaction name="actionPlay_next"/>
|
||||||
|
<addaction name="actionSkip_next"/>
|
||||||
<addaction name="actionFade"/>
|
<addaction name="actionFade"/>
|
||||||
<addaction name="actionS_top"/>
|
<addaction name="actionS_top"/>
|
||||||
<addaction name="separator"/>
|
|
||||||
<addaction name="action_Resume_previous"/>
|
<addaction name="action_Resume_previous"/>
|
||||||
<addaction name="action_Clear_selection"/>
|
|
||||||
</widget>
|
</widget>
|
||||||
<addaction name="menuFile"/>
|
<addaction name="menuFile"/>
|
||||||
<addaction name="menuPlaylist"/>
|
<addaction name="menuPlaylist"/>
|
||||||
|
<addaction name="menu_Tracks"/>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QStatusBar" name="statusbar">
|
<widget class="QStatusBar" name="statusbar">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
@ -833,6 +840,16 @@ border: 1px solid rgb(85, 87, 83);</string>
|
|||||||
<string>&Test</string>
|
<string>&Test</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionSelectPlaylist">
|
||||||
|
<property name="text">
|
||||||
|
<string>Select &playlist</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="actionNewPlaylist">
|
||||||
|
<property name="text">
|
||||||
|
<string>&New playlist</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user