#!/usr/bin/python3 import sys from PyQt5.QtCore import Qt from PyQt5.QtWidgets import QApplication, QDialog, QMainWindow from PyQt5.QtWidgets import QTableWidgetItem, QFileDialog, QListWidgetItem from threading import Timer from tinytag import TinyTag from main_window_ui import Ui_MainWindow from dlg_search_database_ui import Ui_Dialog from model import Tracks class RepeatedTimer: def __init__(self, interval, function, *args, **kwargs): self._timer = None self.interval = interval self.function = function self.args = args self.kwargs = kwargs self.is_running = False self.start() def _run(self): self.is_running = False self.start() self.function(*self.args, **self.kwargs) def start(self): if not self.is_running: self._timer = Timer(self.interval, self._run) self._timer.start() self.is_running = True def stop(self): self._timer.cancel() self.is_running = False def ms_to_mmss(ms, decimals=0): if not ms: return "-" if ms < 0: sign = "-" else: sign = "" minutes, remainder = divmod(ms, 60 * 1000) seconds = remainder / 1000 return f"{sign}{minutes:.0f}:{seconds:02.{decimals}f}" class Window(QMainWindow, Ui_MainWindow): def __init__(self, parent=None): super().__init__(parent) self.setupUi(self) self.connectSignalsSlots() self.resize(1599, 981) self.playlist.setColumnWidth(0, 0) self.playlist.setColumnWidth(1, 70) self.playlist.setColumnWidth(2, 381) self.playlist.setColumnWidth(3, 322) self.playlist.setColumnWidth(4, 78) self.playlist.setColumnWidth(5, 68) self.playlist.setColumnWidth(6, 47) self.playlist.setColumnWidth(7, 577) def __del__(self): for column in range(self.playlist.columnCount()): print(f"Column {column}: {self.playlist.columnWidth(column)}") print(f"Window height: {self.height()} Window width: {self.width()}") def connectSignalsSlots(self): self.fileButton.clicked.connect(self.selectFile) self.databaseButton.clicked.connect(self.selectDatabase) self.actionPlay_selected.triggered.connect(self.play_selected) def selectDatabase(self): dlg = DbDialog(self) dlg.exec() def play_selected(self): if self.playlist.selectionModel().hasSelection(): row = self.playlist.currentRow() print(f"Play id={self.playlist.item(row, 0).text()}") def selectFile(self): dlg = QFileDialog() dlg.setFileMode(QFileDialog.ExistingFile) dlg.setViewMode(QFileDialog.Detail) ROOT = "/home/kae/music/" dlg.setDirectory(ROOT) dlg.setNameFilter("Music files (*.flac *.mp3)") if dlg.exec_(): pass # TODO Add to database # for fname in dlg.selectedFiles(): # track = Track(fname) # self.add_to_playlist(track) def add_to_playlist(self, track): """ Add track to playlist track is an instance of Track """ pl = self.playlist row = pl.rowCount() pl.insertRow(row) item = QTableWidgetItem(str(track.id)) pl.setItem(row, 0, item) item = QTableWidgetItem(str(track.start_gap)) pl.setItem(row, 1, item) item = QTableWidgetItem(track.title) pl.setItem(row, 2, item) item = QTableWidgetItem(track.artist) pl.setItem(row, 3, item) item = QTableWidgetItem(ms_to_mmss(track.duration)) pl.setItem(row, 4, item) item = QTableWidgetItem(track.path) pl.setItem(row, 7, item) class DbDialog(QDialog): def __init__(self, parent=None): super().__init__(parent) self.ui = Ui_Dialog() self.ui.setupUi(self) self.ui.lineEdit.textEdited.connect(self.chars_typed) self.ui.listWidget.itemDoubleClicked.connect(self.listdclick) def chars_typed(self, s): if len(s) >= 3: matches = Tracks.search_titles(s) self.ui.listWidget.clear() if matches: for track in matches: t = QListWidgetItem() t.setText( f"{track.title} - {track.artist} " f"[{ms_to_mmss(track.duration)}]" ) t.setData(Qt.UserRole, track.id) self.ui.listWidget.addItem(t) def listdclick(self, entry): track_id = entry.data(Qt.UserRole) track = Tracks.track_from_id(track_id) self.parent().add_to_playlist(track) if __name__ == "__main__": app = QApplication(sys.argv) win = Window() win.show() sys.exit(app.exec())