visualizer, darkmode, components, etc

This commit is contained in:
billypom on debian 2024-01-19 20:55:09 -05:00
parent 695c1884bd
commit b85cd47844
4 changed files with 229 additions and 151 deletions

View File

@ -1,24 +1,97 @@
import DBA import DBA
from PyQt5.QtGui import QStandardItem, QStandardItemModel from PyQt5.QtGui import QStandardItem, QStandardItemModel
from PyQt5.QtWidgets import QTableView from PyQt5.QtWidgets import QTableView, QApplication
from PyQt5.QtCore import QTimer
from tinytag import TinyTag
class MusicTable(QTableView): class MusicTable(QTableView):
def __init__(self): def __init__(self, parent=None, qapp=None):
super().__init__() QTableView.__init__(self, parent)
self.headers = ['title', 'artist', 'album', 'genre', 'codec', 'year', 'path']
self.model = QStandardItemModel()
self.model.setHorizontalHeaderLabels(self.headers)
self.songChanged = None
self.selected_song_filepath = None
self.current_song_filepath = None
self.qapp = None
# self.tableView.resizeColumnsToContents()
self.clicked.connect(self.set_selected_song_filepath) # These are faster than the click/double determination
self.doubleClicked.connect(self.set_current_song_filepath) # These are faster than the click/double determination
self.fetch_library()
def mousePressEvent(self, event):
self.last = "Click"
QTableView.mousePressEvent(self, event) # Keep original functionality
def mouseReleaseEvent(self, event):
if self.last == "Click":
QTimer.singleShot(self.qapp.instance().doubleClickInterval(),
self.performSingleClickAction)
else:
# Perform double click action.
self.set_current_song_filepath
self.message = "Double Click"
self.update()
QTableView.mouseReleaseEvent(self, event) # Keep original functionality
def mouseDoubleClickEvent(self, event):
self.last = "Double Click"
self.doubleClicked.emit(self.selectionModel().currentIndex())
QTableView.mouseDoubleClickEvent(self, event) # Keep original functionality
def performSingleClickAction(self):
if self.last == "Click":
self.message = "Click"
self.update()
def get_selected_rows(self):
"""Returns a list of indexes for every selected row"""
rows = []
for idx in self.selectionModel().siblingAtColumn():
rows.append(idx.row())
return rows
def set_selected_song_filepath(self):
"""Sets the filepath of the currently selected song"""
self.selected_song_filepath = self.currentIndex().siblingAtColumn(self.headers.index('path')).data()
print(f'Selected song: {self.selected_song_filepath}')
def set_current_song_filepath(self):
"""Sets the filepath of the currently playing/chosen song"""
self.current_song_filepath = self.currentIndex().siblingAtColumn(self.headers.index('path')).data()
print(f'Current song: {self.current_song_filepath}')
def get_selected_song_filepath(self):
"""Returns the selected song filepath"""
return self.selected_song_filepath
def get_selected_song_metadata(self):
"""Returns the current/chosen song's ID3 tags"""
return TinyTag.get(self.selected_song_filepath)
def get_current_song_filepath(self):
"""Returns the current/chosen song filepath"""
return self.current_song_filepath
def get_current_song_metadata(self):
"""Returns the current/chosen song's ID3 tags"""
return TinyTag.get(self.current_song_filepath)
def fetch_library(self):
# Fetch library data # Fetch library data
with DBA.DBAccess() as db: # returns a tuple, 1 row just for metadata purposes with DBA.DBAccess() as db:
data = db.query('SELECT title, artist, album, genre, codec, album_date, filepath FROM library;', ()) data = db.query('SELECT title, artist, album, genre, codec, album_date, filepath FROM library;', ())
headers = ['title', 'artist', 'album', 'genre', 'codec', 'year', 'path']
# Create a model
model = QStandardItemModel()
model.setHorizontalHeaderLabels(headers)
# Populate the model # Populate the model
for row_data in data: for row_data in data:
items = [QStandardItem(str(item)) for item in row_data] items = [QStandardItem(str(item)) for item in row_data]
model.appendRow(items) self.model.appendRow(items)
# Set the model to the tableView # Set the model to the tableView (we are the tableview)
self.tableView.setModel(model) self.setModel(self.model)
# self.tableView.resizeColumnsToContents()
self.music_table.clicked.connect(self.set_clicked_cell_filepath) def load_qapp(self, qapp):
self.qapp = qapp

83
main.py
View File

@ -9,24 +9,29 @@ from utils import scan_for_music
from utils import initialize_library_database from utils import initialize_library_database
from utils import AudioVisualizer from utils import AudioVisualizer
from pyqtgraph import mkBrush from pyqtgraph import mkBrush
from components import MusicTable
class ApplicationWindow(QMainWindow, Ui_MainWindow): class ApplicationWindow(QMainWindow, Ui_MainWindow):
def __init__(self): def __init__(self, qapp):
super(ApplicationWindow, self).__init__() super(ApplicationWindow, self).__init__()
self.setupUi(self) self.setupUi(self)
self.setWindowTitle('MusicPom') self.setWindowTitle('MusicPom')
self.selected_song_filepath = None self.selected_song_filepath = None
self.current_song_filepath = None self.current_song_filepath = None
self.current_song_metadata = None
self.qapp = qapp
print(f'ApplicationWindow self.qapp: {self.qapp}')
self.tableView.load_qapp(self.qapp)
global stopped global stopped
stopped = False stopped = False
# Initialization # Initialization
self.player = QMediaPlayer(None, QMediaPlayer.VideoSurface) # Audio player self.player = QMediaPlayer() # Audio player
self.probe = QAudioProbe() # Get audio data self.probe = QAudioProbe() # Get audio data
self.timer = QTimer(self) # Audio timing things self.timer = QTimer(self) # Audio timing things
self.model = QStandardItemModel() # Table library listing # self.model = QStandardItemModel() # Table library listing
self.audio_visualizer = AudioVisualizer(self.player) self.audio_visualizer = AudioVisualizer(self.player)
self.current_volume = 50 self.current_volume = 50
self.player.setVolume(self.current_volume) self.player.setVolume(self.current_volume)
@ -36,33 +41,6 @@ class ApplicationWindow(QMainWindow, Ui_MainWindow):
self.probe.setSource(self.player) self.probe.setSource(self.player)
self.probe.audioBufferProbed.connect(self.process_probe) self.probe.audioBufferProbed.connect(self.process_probe)
# Probably move all the table logic to its own class
# Promote the wigdet to my custom class from utils
# inherit from QTableView
# then i can handle click events for editing metadata in a class
# current song should also be its own class
# selected song should be its own class too...
# ______________
# | |
# | Table making |
# | |
# |______________|
# Fetch library data
with DBA.DBAccess() as db:
data = db.query('SELECT title, artist, album, genre, codec, album_date, filepath FROM library;', ())
headers = ['title', 'artist', 'album', 'genre', 'codec', 'year', 'path']
self.model.setHorizontalHeaderLabels(headers)
for row_data in data: # Populate the model
items = [QStandardItem(str(item)) for item in row_data]
self.model.appendRow(items)
# Set the model to the tableView
self.tableView.setModel(self.model)
# self.tableView.resizeColumnsToContents()
# Slider Timer (realtime playback feedback horizontal bar) # Slider Timer (realtime playback feedback horizontal bar)
self.timer.start(150) # 150ms update interval solved problem with drag seeking halting playback self.timer.start(150) # 150ms update interval solved problem with drag seeking halting playback
self.timer.timeout.connect(self.move_slider) self.timer.timeout.connect(self.move_slider)
@ -79,27 +57,39 @@ class ApplicationWindow(QMainWindow, Ui_MainWindow):
# Connections # Connections
self.playbackSlider.sliderMoved[int].connect(lambda: self.player.setPosition(self.playbackSlider.value())) # ! FIXME moving the slider while playing is happening frequently causes playback to halt - the pyqtgraph is also affected by this
self.volumeSlider.sliderMoved[int].connect(lambda: self.volume_changed()) self.playbackSlider.sliderMoved[int].connect(lambda: self.player.setPosition(self.playbackSlider.value())) # Move slidet to adjust playback time
self.playButton.clicked.connect(self.on_play_clicked) self.volumeSlider.sliderMoved[int].connect(lambda: self.volume_changed()) # Move slider to adjust volume
self.playButton.clicked.connect(self.on_play_clicked) # Click to play/pause
# self.pauseButton.clicked.connect(self.on_pause_clicked) # self.pauseButton.clicked.connect(self.on_pause_clicked)
self.previousButton.clicked.connect(self.on_previous_clicked) self.previousButton.clicked.connect(self.on_previous_clicked) # Click to previous song
self.nextButton.clicked.connect(self.on_next_clicked) self.nextButton.clicked.connect(self.on_next_clicked) # Click to next song
self.tableView.clicked.connect(self.set_clicked_cell_filepath) # self.tableView.clicked.connect(self.set_clicked_cell_filepath)
self.actionPreferences.triggered.connect(self.actionPreferencesClicked) self.actionPreferences.triggered.connect(self.actionPreferencesClicked) # Open preferences menu
self.actionScanLibraries.triggered.connect(self.scan_libraries) self.actionScanLibraries.triggered.connect(self.scan_libraries) # Scan library
self.actionClearDatabase.triggered.connect(initialize_library_database) self.actionClearDatabase.triggered.connect(initialize_library_database) # Clear database
self.tableView.doubleClicked.connect(self.play_audio_file) # Double click to play song
def play_audio_file(self): def play_audio_file(self):
"""Start playback of selected track & move playback slider""" """Start playback of selected track & moves playback slider"""
self.current_song_filepath = self.selected_song_filepath self.current_song_metadata = self.tableView.get_current_song_metadata() # get metadata
url = QUrl.fromLocalFile(self.current_song_filepath) # read the file url = QUrl.fromLocalFile(self.tableView.get_current_song_filepath()) # read the file
content = QMediaContent(url) # load the audio content content = QMediaContent(url) # load the audio content
self.player.setMedia(content) # what content to play self.player.setMedia(content) # what content to play
self.player.play() # play self.player.play() # play
self.move_slider() # mover self.move_slider() # mover
# assign metadata
# FIXME when i change tinytag to something else
artist = self.current_song_metadata.artist
album = self.current_song_metadata.album
title = self.current_song_metadata.title
# edit labels
self.artistLabel.setText(artist)
self.albumLabel.setText(album)
self.titleLabel.setText(title)
def update_audio_visualization(self): def update_audio_visualization(self):
"""Handles upading points on the pyqtgraph visual""" """Handles upading points on the pyqtgraph visual"""
self.clear_audio_visualization() self.clear_audio_visualization()
@ -149,10 +139,6 @@ class ApplicationWindow(QMainWindow, Ui_MainWindow):
else: else:
self.play_audio_file() self.play_audio_file()
self.playButton.setText("⏸️") self.playButton.setText("⏸️")
def set_clicked_cell_filepath(self):
"""Sets the filepath of the currently selected song"""
self.selected_song_filepath = self.tableView.currentIndex().siblingAtColumn(6).data()
def on_previous_clicked(self): def on_previous_clicked(self):
"""""" """"""
@ -178,7 +164,8 @@ class ApplicationWindow(QMainWindow, Ui_MainWindow):
if __name__ == "__main__": if __name__ == "__main__":
import sys import sys
app = QApplication(sys.argv) app = QApplication(sys.argv)
print(f'main.py app: {app}')
qdarktheme.setup_theme() qdarktheme.setup_theme()
ui = ApplicationWindow() ui = ApplicationWindow(app)
ui.show() ui.show()
sys.exit(app.exec_()) sys.exit(app.exec_())

72
ui.py
View File

@ -14,12 +14,12 @@ from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object): class Ui_MainWindow(object):
def setupUi(self, MainWindow): def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow") MainWindow.setObjectName("MainWindow")
MainWindow.resize(1061, 795) MainWindow.resize(1062, 795)
MainWindow.setStatusTip("") MainWindow.setStatusTip("")
self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget") self.centralwidget.setObjectName("centralwidget")
self.frame = QtWidgets.QFrame(self.centralwidget) self.frame = QtWidgets.QFrame(self.centralwidget)
self.frame.setGeometry(QtCore.QRect(0, 160, 1061, 501)) self.frame.setGeometry(QtCore.QRect(0, 160, 1061, 461))
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Ignored) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Ignored)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0) sizePolicy.setVerticalStretch(0)
@ -28,8 +28,8 @@ class Ui_MainWindow(object):
self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel) self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame.setFrameShadow(QtWidgets.QFrame.Raised) self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame.setObjectName("frame") self.frame.setObjectName("frame")
self.tableView = QtWidgets.QTableView(self.frame) self.tableView = MusicTable(self.frame)
self.tableView.setGeometry(QtCore.QRect(0, 0, 1061, 501)) self.tableView.setGeometry(QtCore.QRect(0, 0, 1061, 461))
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0) sizePolicy.setVerticalStretch(0)
@ -37,6 +37,7 @@ class Ui_MainWindow(object):
self.tableView.setSizePolicy(sizePolicy) self.tableView.setSizePolicy(sizePolicy)
self.tableView.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) self.tableView.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.tableView.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents) self.tableView.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents)
self.tableView.setEditTriggers(QtWidgets.QAbstractItemView.AnyKeyPressed|QtWidgets.QAbstractItemView.EditKeyPressed)
self.tableView.setAlternatingRowColors(True) self.tableView.setAlternatingRowColors(True)
self.tableView.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection) self.tableView.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
self.tableView.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows) self.tableView.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
@ -77,37 +78,15 @@ class Ui_MainWindow(object):
self.PlotWidget = PlotWidget(self.frame_4) self.PlotWidget = PlotWidget(self.frame_4)
self.PlotWidget.setGeometry(QtCore.QRect(0, 0, 521, 121)) self.PlotWidget.setGeometry(QtCore.QRect(0, 0, 521, 121))
self.PlotWidget.setObjectName("PlotWidget") self.PlotWidget.setObjectName("PlotWidget")
self.horizontalLayoutWidget_2 = QtWidgets.QWidget(self.centralwidget)
self.horizontalLayoutWidget_2.setGeometry(QtCore.QRect(0, 660, 1061, 60))
self.horizontalLayoutWidget_2.setObjectName("horizontalLayoutWidget_2")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget_2)
self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.previousButton = QtWidgets.QPushButton(self.horizontalLayoutWidget_2)
font = QtGui.QFont()
font.setPointSize(28)
self.previousButton.setFont(font)
self.previousButton.setObjectName("previousButton")
self.horizontalLayout_2.addWidget(self.previousButton)
self.playButton = QtWidgets.QPushButton(self.horizontalLayoutWidget_2)
font = QtGui.QFont()
font.setPointSize(28)
self.playButton.setFont(font)
self.playButton.setObjectName("playButton")
self.horizontalLayout_2.addWidget(self.playButton)
self.nextButton = QtWidgets.QPushButton(self.horizontalLayoutWidget_2)
font = QtGui.QFont()
font.setPointSize(28)
self.nextButton.setFont(font)
self.nextButton.setObjectName("nextButton")
self.horizontalLayout_2.addWidget(self.nextButton)
self.frame_3 = QtWidgets.QFrame(self.centralwidget) self.frame_3 = QtWidgets.QFrame(self.centralwidget)
self.frame_3.setGeometry(QtCore.QRect(0, 720, 1061, 31)) self.frame_3.setGeometry(QtCore.QRect(0, 680, 1061, 61))
self.frame_3.setFrameShape(QtWidgets.QFrame.StyledPanel) self.frame_3.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_3.setFrameShadow(QtWidgets.QFrame.Raised) self.frame_3.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame_3.setObjectName("frame_3") self.frame_3.setObjectName("frame_3")
self.volumeSlider = QtWidgets.QSlider(self.frame_3) self.volumeSlider = QtWidgets.QSlider(self.frame_3)
self.volumeSlider.setGeometry(QtCore.QRect(10, 0, 181, 31)) self.volumeSlider.setGeometry(QtCore.QRect(10, 10, 181, 31))
self.volumeSlider.setMaximum(100)
self.volumeSlider.setProperty("value", 50)
self.volumeSlider.setOrientation(QtCore.Qt.Horizontal) self.volumeSlider.setOrientation(QtCore.Qt.Horizontal)
self.volumeSlider.setObjectName("volumeSlider") self.volumeSlider.setObjectName("volumeSlider")
self.frame_5 = QtWidgets.QFrame(self.centralwidget) self.frame_5 = QtWidgets.QFrame(self.centralwidget)
@ -144,9 +123,33 @@ class Ui_MainWindow(object):
self.albumLabel.setFont(font) self.albumLabel.setFont(font)
self.albumLabel.setObjectName("albumLabel") self.albumLabel.setObjectName("albumLabel")
self.verticalLayout.addWidget(self.albumLabel) self.verticalLayout.addWidget(self.albumLabel)
self.horizontalLayoutWidget_2 = QtWidgets.QWidget(self.centralwidget)
self.horizontalLayoutWidget_2.setGeometry(QtCore.QRect(0, 620, 1061, 60))
self.horizontalLayoutWidget_2.setObjectName("horizontalLayoutWidget_2")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget_2)
self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.previousButton = QtWidgets.QPushButton(self.horizontalLayoutWidget_2)
font = QtGui.QFont()
font.setPointSize(28)
self.previousButton.setFont(font)
self.previousButton.setObjectName("previousButton")
self.horizontalLayout_2.addWidget(self.previousButton)
self.playButton = QtWidgets.QPushButton(self.horizontalLayoutWidget_2)
font = QtGui.QFont()
font.setPointSize(28)
self.playButton.setFont(font)
self.playButton.setObjectName("playButton")
self.horizontalLayout_2.addWidget(self.playButton)
self.nextButton = QtWidgets.QPushButton(self.horizontalLayoutWidget_2)
font = QtGui.QFont()
font.setPointSize(28)
self.nextButton.setFont(font)
self.nextButton.setObjectName("nextButton")
self.horizontalLayout_2.addWidget(self.nextButton)
MainWindow.setCentralWidget(self.centralwidget) MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow) self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 1061, 24)) self.menubar.setGeometry(QtCore.QRect(0, 0, 1062, 24))
self.menubar.setObjectName("menubar") self.menubar.setObjectName("menubar")
self.menuFile = QtWidgets.QMenu(self.menubar) self.menuFile = QtWidgets.QMenu(self.menubar)
self.menuFile.setObjectName("menuFile") self.menuFile.setObjectName("menuFile")
@ -183,12 +186,12 @@ class Ui_MainWindow(object):
self.startTimeLabel.setText(_translate("MainWindow", "00:00")) self.startTimeLabel.setText(_translate("MainWindow", "00:00"))
self.slashLabel.setText(_translate("MainWindow", "/")) self.slashLabel.setText(_translate("MainWindow", "/"))
self.endTimeLabel.setText(_translate("MainWindow", "00:00")) self.endTimeLabel.setText(_translate("MainWindow", "00:00"))
self.previousButton.setText(_translate("MainWindow", "⏮️"))
self.playButton.setText(_translate("MainWindow", "▶️"))
self.nextButton.setText(_translate("MainWindow", "⏭️"))
self.artistLabel.setText(_translate("MainWindow", "artist")) self.artistLabel.setText(_translate("MainWindow", "artist"))
self.titleLabel.setText(_translate("MainWindow", "song title")) self.titleLabel.setText(_translate("MainWindow", "song title"))
self.albumLabel.setText(_translate("MainWindow", "album")) self.albumLabel.setText(_translate("MainWindow", "album"))
self.previousButton.setText(_translate("MainWindow", "⏮️"))
self.playButton.setText(_translate("MainWindow", "▶️"))
self.nextButton.setText(_translate("MainWindow", "⏭️"))
self.menuFile.setTitle(_translate("MainWindow", "File")) self.menuFile.setTitle(_translate("MainWindow", "File"))
self.menuEdit.setTitle(_translate("MainWindow", "Edit")) self.menuEdit.setTitle(_translate("MainWindow", "Edit"))
self.menuView.setTitle(_translate("MainWindow", "View")) self.menuView.setTitle(_translate("MainWindow", "View"))
@ -197,4 +200,5 @@ class Ui_MainWindow(object):
self.actionPreferences.setStatusTip(_translate("MainWindow", "Open preferences")) self.actionPreferences.setStatusTip(_translate("MainWindow", "Open preferences"))
self.actionScanLibraries.setText(_translate("MainWindow", "Scan libraries")) self.actionScanLibraries.setText(_translate("MainWindow", "Scan libraries"))
self.actionClearDatabase.setText(_translate("MainWindow", "Clear Database")) self.actionClearDatabase.setText(_translate("MainWindow", "Clear Database"))
from components import MusicTable
from pyqtgraph import PlotWidget from pyqtgraph import PlotWidget

126
ui.ui
View File

@ -6,7 +6,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>1061</width> <width>1062</width>
<height>795</height> <height>795</height>
</rect> </rect>
</property> </property>
@ -23,7 +23,7 @@
<x>0</x> <x>0</x>
<y>160</y> <y>160</y>
<width>1061</width> <width>1061</width>
<height>501</height> <height>461</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
@ -38,13 +38,13 @@
<property name="frameShadow"> <property name="frameShadow">
<enum>QFrame::Raised</enum> <enum>QFrame::Raised</enum>
</property> </property>
<widget class="QTableView" name="tableView"> <widget class="MusicTable" name="tableView">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>1061</width> <width>1061</width>
<height>501</height> <height>461</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
@ -59,6 +59,9 @@
<property name="sizeAdjustPolicy"> <property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContents</enum> <enum>QAbstractScrollArea::AdjustToContents</enum>
</property> </property>
<property name="editTriggers">
<set>QAbstractItemView::AnyKeyPressed|QAbstractItemView::EditKeyPressed</set>
</property>
<property name="alternatingRowColors"> <property name="alternatingRowColors">
<bool>true</bool> <bool>true</bool>
</property> </property>
@ -165,61 +168,13 @@
</property> </property>
</widget> </widget>
</widget> </widget>
<widget class="QWidget" name="horizontalLayoutWidget_2">
<property name="geometry">
<rect>
<x>0</x>
<y>660</y>
<width>1061</width>
<height>60</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QPushButton" name="previousButton">
<property name="font">
<font>
<pointsize>28</pointsize>
</font>
</property>
<property name="text">
<string>⏮️</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="playButton">
<property name="font">
<font>
<pointsize>28</pointsize>
</font>
</property>
<property name="text">
<string>▶️</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="nextButton">
<property name="font">
<font>
<pointsize>28</pointsize>
</font>
</property>
<property name="text">
<string>⏭️</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QFrame" name="frame_3"> <widget class="QFrame" name="frame_3">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
<y>720</y> <y>680</y>
<width>1061</width> <width>1061</width>
<height>31</height> <height>61</height>
</rect> </rect>
</property> </property>
<property name="frameShape"> <property name="frameShape">
@ -232,11 +187,17 @@
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>10</x> <x>10</x>
<y>0</y> <y>10</y>
<width>181</width> <width>181</width>
<height>31</height> <height>31</height>
</rect> </rect>
</property> </property>
<property name="maximum">
<number>100</number>
</property>
<property name="value">
<number>50</number>
</property>
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
@ -311,13 +272,61 @@
</layout> </layout>
</widget> </widget>
</widget> </widget>
<widget class="QWidget" name="horizontalLayoutWidget_2">
<property name="geometry">
<rect>
<x>0</x>
<y>620</y>
<width>1061</width>
<height>60</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QPushButton" name="previousButton">
<property name="font">
<font>
<pointsize>28</pointsize>
</font>
</property>
<property name="text">
<string>⏮️</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="playButton">
<property name="font">
<font>
<pointsize>28</pointsize>
</font>
</property>
<property name="text">
<string>▶️</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="nextButton">
<property name="font">
<font>
<pointsize>28</pointsize>
</font>
</property>
<property name="text">
<string>⏭️</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget> </widget>
<widget class="QMenuBar" name="menubar"> <widget class="QMenuBar" name="menubar">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>1061</width> <width>1062</width>
<height>24</height> <height>24</height>
</rect> </rect>
</property> </property>
@ -376,6 +385,11 @@
<header>pyqtgraph</header> <header>pyqtgraph</header>
<container>1</container> <container>1</container>
</customwidget> </customwidget>
<customwidget>
<class>MusicTable</class>
<extends>QTableView</extends>
<header>components</header>
</customwidget>
</customwidgets> </customwidgets>
<resources/> <resources/>
<connections/> <connections/>