Add widget to seek through songs on an album

This commit is contained in:
2025-11-19 22:33:32 -07:00
parent 3df5097e60
commit bcb791c205
14 changed files with 304 additions and 71 deletions

View File

@@ -0,0 +1,42 @@
#include "tracklistwidget.h"
#include <QFileInfo>
#include <QVBoxLayout>
#include "src/data/cleanerScripts.h"
TrackListWidget::TrackListWidget(const QStringList& audioFiles, QWidget* parent)
: QWidget(parent)
{
list_ = new QListWidget(this);
QVBoxLayout* layout = new QVBoxLayout(this);
layout->addWidget(list_);
int trackNum = 1;
for (const QString& f : audioFiles) {
// Extract just the filename
QString fileName = QFileInfo(f).fileName();
// Run through your cleaner
QString songTitle = cleanTrackTitle(fileName);
// Format display text: "1. Song Title"
QString display = QString("%1. %2")
.arg(trackNum++)
.arg(songTitle);
list_->addItem(display);
}
// Emit signal when clicked
connect(list_, &QListWidget::itemClicked, this, [=](QListWidgetItem* item){
int index = list_->row(item);
emit trackSelected(index);
});
}
void TrackListWidget::setCurrentRow(int row)
{
list_->setCurrentRow(row);
}

View File

@@ -0,0 +1,23 @@
#ifndef TRACKLISTWIDGET_H
#define TRACKLISTWIDGET_H
#include <QWidget>
#include <QListWidget>
class TrackListWidget : public QWidget
{
Q_OBJECT
public:
explicit TrackListWidget(const QStringList& audioFiles, QWidget* parent = nullptr);
void setCurrentRow(int row); // <-- THIS must be here
signals:
void trackSelected(int index);
private:
QListWidget* list_;
};
#endif // TRACKLISTWIDGET_H

View File

@@ -1,7 +1,5 @@
#include "playerWindow.h"
#include <QVBoxLayout>
#include <QPainter>
#include <QPainterPath>
#include <QFileInfo>
#include <QCloseEvent>
#include "src/data/cleanerScripts.h"
@@ -9,24 +7,31 @@
PlayerWindow::PlayerWindow(const AlbumData& item, QWidget* parent)
: QWidget(parent), item_(item)
{
this->setWindowTitle("Now Playing");
this->resize(300, 370);
setWindowTitle("Now Playing");
resize(350, 500);
QVBoxLayout* layout = new QVBoxLayout(this);
// SUPER SIMPLE now:
// Album artwork
spinningArt_ = new SpinningAlbumArt(item.imagePath, 250);
layout->addWidget(spinningArt_);
layout->addWidget(spinningArt_, 0, Qt::AlignCenter);
trackLabel_ = new QLabel("Track 1");
// Track label
trackLabel_ = new QLabel("Track");
trackLabel_->setAlignment(Qt::AlignCenter);
trackLabel_->setStyleSheet("font-size: 14px; font-weight: 500;");
layout->addWidget(trackLabel_);
// Track list widget
trackList_ = new TrackListWidget(item_.audioFiles, this);
layout->addWidget(trackList_);
// Audio backend
player_ = new QMediaPlayer(this);
audio_ = new QAudioOutput(this);
player_->setAudioOutput(audio_);
// Spin album art based on playback
connect(player_, &QMediaPlayer::playbackStateChanged, this,
[this](QMediaPlayer::PlaybackState st){
if (st == QMediaPlayer::PlayingState)
@@ -35,35 +40,60 @@ PlayerWindow::PlayerWindow(const AlbumData& item, QWidget* parent)
spinningArt_->stop();
});
playNext();
// When a track finishes, auto-play next
connect(player_, &QMediaPlayer::mediaStatusChanged, this,
[this](QMediaPlayer::MediaStatus st){
if (st == QMediaPlayer::EndOfMedia)
handleTrackFinished();
});
// When a track is clicked
connect(trackList_, &TrackListWidget::trackSelected, this,
[this](int i){
index_ = i;
playTrack(index_);
});
// Start with track 0
playTrack(index_);
}
void PlayerWindow::playNext()
void PlayerWindow::playTrack(int idx)
{
if (index_ >= item_.audioFiles.size()) {
this->close();
if (idx < 0 || idx >= item_.audioFiles.size())
return;
}
QString filePath = item_.audioFiles[index_];
index_ = idx;
QString filePath = item_.audioFiles[idx];
QString fileName = QFileInfo(filePath).fileName();
QString title = cleanTrackTitle(fileName);
trackLabel_->setText(
QString("Track %1: %2").arg(index_ + 1).arg(title)
);
trackLabel_->setText(QString("Track %1: %2").arg(idx + 1).arg(title));
player_->setSource(QUrl::fromLocalFile(filePath));
player_->play();
index_++;
// Highlight in the list
trackList_->setCurrentRow(idx);
}
void PlayerWindow::handleTrackFinished()
{
int nextIndex = index_ + 1;
if (nextIndex >= item_.audioFiles.size()) {
close();
return;
}
playTrack(nextIndex);
}
void PlayerWindow::closeEvent(QCloseEvent* event)
{
if (player_) {
if (player_)
player_->stop();
spinTimer_->stop();
}
QWidget::closeEvent(event);
}

View File

@@ -1,4 +1,5 @@
#pragma once
#ifndef PLAYERWINDOW_H
#define PLAYERWINDOW_H
#include <QWidget>
#include <QLabel>
@@ -7,33 +8,32 @@
#include <QTimer>
#include "src/data/albumInformation.h"
#include "src/components/spinningalbumart/spinningAlbumArt.h"
#include "src/components/tracklistWidget/tracklistwidget.h"
class PlayerWindow : public QWidget {
class PlayerWindow : public QWidget
{
Q_OBJECT
SpinningAlbumArt* spinningArt_;
public:
explicit PlayerWindow(const AlbumData& item, QWidget* parent = nullptr);
void setCurrentRow(int row);
protected:
void closeEvent(QCloseEvent* event) override;
private slots:
void playNext();
private:
void playTrack(int index);
void handleTrackFinished();
AlbumData item_;
int index_ = 0;
int index_ = 0; // active track index
SpinningAlbumArt* spinningArt_;
QLabel* trackLabel_;
TrackListWidget* trackList_;
QMediaPlayer* player_;
QAudioOutput* audio_;
QLabel* artLabel_;
QLabel* trackLabel_;
QPixmap discArt_; // circular cropped album art
QPixmap overlayArt_; // optional overlay (not required)
qreal rotationAngle_ = 0;
QTimer* spinTimer_;
};
#endif