Part of a larger restructure, added MusicPlayer which is the main controller and a structure for the song queue
This commit is contained in:
71
src/View/Layouts/QOverlayout.cpp
Executable file
71
src/View/Layouts/QOverlayout.cpp
Executable file
@@ -0,0 +1,71 @@
|
||||
#include "QOverlayout.h"
|
||||
|
||||
#include <QLayout>
|
||||
#include <QtWidgets>
|
||||
|
||||
int QOverlayout::count( )const {
|
||||
return list.size( );
|
||||
}
|
||||
|
||||
QLayoutItem* QOverlayout::itemAt(int idx)const {
|
||||
return list.value(idx);
|
||||
}
|
||||
|
||||
QLayoutItem* QOverlayout::takeAt(int idx) {
|
||||
return idx >= 0 && idx < list.size( ) ? list.takeAt(idx) : 0;
|
||||
}
|
||||
|
||||
void QOverlayout::addItem(QLayoutItem* item) {
|
||||
list.append(item);
|
||||
}
|
||||
|
||||
QOverlayout::QOverlayout(QWidget* parent) : QLayout(parent) { }
|
||||
|
||||
QOverlayout::~QOverlayout( ) {
|
||||
QLayoutItem* item;
|
||||
while ((item = takeAt(0)))
|
||||
delete item;
|
||||
}
|
||||
|
||||
void QOverlayout::setGeometry(const QRect& r) {
|
||||
QLayout::setGeometry(r);
|
||||
|
||||
if (list.size( ) == 0) return;
|
||||
|
||||
int w = r.width( );
|
||||
int h = r.height( );
|
||||
|
||||
int i = 0;
|
||||
while (i < list.size( )) {
|
||||
list.at(i)->setGeometry(QRect(r.x( ), r.y( ), w, h));
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
QSize QOverlayout::sizeHint( ) const {
|
||||
QSize s(0, 0);
|
||||
int n = list.count( );
|
||||
if (n > 0)
|
||||
s = QSize(100, 70);
|
||||
int i = 0;
|
||||
while (i < n) {
|
||||
QLayoutItem* o = list.at(i);
|
||||
s = s.expandedTo(o->sizeHint( ));
|
||||
++i;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
QSize QOverlayout::minimumSize( ) const {
|
||||
QSize s(0, 0);
|
||||
int n = list.count( );
|
||||
|
||||
int i = 0;
|
||||
while (i < n) {
|
||||
QLayoutItem* o = list.at(i);
|
||||
s = s.expandedTo(o->sizeHint( ));
|
||||
++i;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
21
src/View/Layouts/QOverlayout.h
Executable file
21
src/View/Layouts/QOverlayout.h
Executable file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <QLayout>
|
||||
#include <QList>
|
||||
#include <QLayoutItem>
|
||||
|
||||
class QOverlayout : public QLayout {
|
||||
private:
|
||||
QList<QLayoutItem*> list;
|
||||
public:
|
||||
QOverlayout(QWidget* parent);
|
||||
~QOverlayout( );
|
||||
|
||||
void addItem(QLayoutItem* item) override;
|
||||
QSize sizeHint( ) const override;
|
||||
QSize minimumSize( ) const override;
|
||||
int count( ) const override;
|
||||
QLayoutItem* itemAt(int) const override;
|
||||
QLayoutItem* takeAt(int) override;
|
||||
void setGeometry(const QRect& rect) override;
|
||||
};
|
||||
68
src/View/MainWidget.cpp
Normal file
68
src/View/MainWidget.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
#include "MainWidget.h"
|
||||
|
||||
void MainWidget::setupMainWidget( ) {
|
||||
setContentsMargins(10, 10, 10, 10);
|
||||
|
||||
QOverlayout* ol = new QOverlayout(this);
|
||||
setLayout(ol);
|
||||
|
||||
QVBoxLayout* vbox = new QVBoxLayout( );
|
||||
vbox->addWidget(floatingControlls, 0, Qt::AlignBottom);
|
||||
|
||||
QHBoxLayout* hbox = new QHBoxLayout( );
|
||||
QVBoxLayout* vbox2 = new QVBoxLayout( );
|
||||
vbox2->addWidget(pageNav);
|
||||
vbox2->addWidget(playlistNav);
|
||||
hbox->addLayout(vbox2);
|
||||
QHBoxLayout* stackedLayout = new QHBoxLayout( );
|
||||
|
||||
stackedLayout->addWidget(homePage);
|
||||
stackedLayout->addWidget(playlistPage);
|
||||
|
||||
playlistPage->setVisible(false);
|
||||
|
||||
hbox->addLayout(stackedLayout, 0);
|
||||
|
||||
hbox->setSpacing(10);
|
||||
vbox2->setSpacing(10);
|
||||
|
||||
ol->addItem(hbox);
|
||||
ol->addItem(vbox);
|
||||
|
||||
connect(pageNav, &PageNavModule::SelectChanged, [this, stackedLayout](PageNavigator* pn) {
|
||||
if (pn->GetText( ).toStdString( ) == "Home") {
|
||||
//stackedLayout->setCurrentIndex(0);
|
||||
stackedLayout->itemAt(0)->widget( )->setVisible(true);
|
||||
stackedLayout->itemAt(1)->widget( )->setVisible(false);
|
||||
}
|
||||
else if (pn->GetText( ).toStdString( ) == "Playlist") {
|
||||
//stackedLayout->setCurrentIndex(1);
|
||||
stackedLayout->itemAt(0)->widget( )->setVisible(false);
|
||||
stackedLayout->itemAt(1)->widget( )->setVisible(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void MainWidget::PageChangedAction( ) { }
|
||||
|
||||
MainWidget::MainWidget(QWidget* parent)
|
||||
: QWidget(parent),
|
||||
pageNav(new PageNavModule(this)),
|
||||
playlistNav(new PlaylistNavModule(this)),
|
||||
playlistPage(new PlaylistPage(this)),
|
||||
homePage(new HomePage(this)),
|
||||
floatingControlls(new FloatingControls(this)) {
|
||||
setupMainWidget( );
|
||||
}
|
||||
|
||||
MainWidget::MainWidget(std::filesystem::path path, QWidget* parent)
|
||||
: QWidget(parent),
|
||||
pageNav(new PageNavModule(this)),
|
||||
playlistNav(new PlaylistNavModule(this)),
|
||||
playlistPage(new PlaylistPage(this)),
|
||||
homePage(new HomePage(this)),
|
||||
floatingControlls(new FloatingControls(this, path)) {
|
||||
setupMainWidget( );
|
||||
}
|
||||
|
||||
MainWidget::~MainWidget( ) { }
|
||||
38
src/View/MainWidget.h
Normal file
38
src/View/MainWidget.h
Normal file
@@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include <QLayout>
|
||||
#include <filesystem>
|
||||
#include <QStackedLayout>
|
||||
|
||||
#include "Layouts/QOverlayout.h"
|
||||
#include "Modules/FloatingControls/FloatingControls.h"
|
||||
#include "Modules/PageNavModule/PageNavModule.h"
|
||||
#include "Modules/PlaylistNavModule/PlaylistNavModule.h"
|
||||
#include "Pages/Playlist/PlaylistPage.h"
|
||||
#include "Pages/Home/HomePage.h"
|
||||
|
||||
class MainWidget : public QWidget {
|
||||
Q_OBJECT
|
||||
private:
|
||||
|
||||
PageNavModule* pageNav;
|
||||
PlaylistNavModule* playlistNav;
|
||||
|
||||
PlaylistPage* playlistPage;
|
||||
HomePage* homePage;
|
||||
|
||||
FloatingControls* floatingControlls;
|
||||
|
||||
void setupMainWidget( );
|
||||
|
||||
public:
|
||||
MainWidget(QWidget* parent = nullptr);
|
||||
MainWidget(std::filesystem::path path, QWidget* parent = nullptr);
|
||||
~MainWidget( );
|
||||
|
||||
private slots:
|
||||
void PageChangedAction( );
|
||||
|
||||
|
||||
};
|
||||
27
src/View/MainWindow.cpp
Executable file
27
src/View/MainWindow.cpp
Executable file
@@ -0,0 +1,27 @@
|
||||
#include "MainWindow.h"
|
||||
|
||||
void MainWindow::setupMainWindow( ) {
|
||||
this->setWindowTitle("Crylia Player");
|
||||
this->setWindowIcon(QIcon(":aqua.jpg"));
|
||||
|
||||
setObjectName("MainWindow");
|
||||
setStyleSheet(R"(
|
||||
#MainWindow{
|
||||
background-color: #121212;
|
||||
}
|
||||
)");
|
||||
|
||||
this->setCentralWidget(mainWidget);
|
||||
}
|
||||
|
||||
MainWindow::MainWindow(QWidget* parent)
|
||||
: QMainWindow(parent), mainWidget(new MainWidget(this)) {
|
||||
setupMainWindow( );
|
||||
}
|
||||
|
||||
MainWindow::MainWindow(std::filesystem::path path, QWidget* parent)
|
||||
: QMainWindow(parent), mainWidget(new MainWidget(path, this)) {
|
||||
setupMainWindow( );
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow( ) { }
|
||||
23
src/View/MainWindow.h
Executable file
23
src/View/MainWindow.h
Executable file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QtWidgets>
|
||||
#include <QVBoxLayout>
|
||||
#include <QLayout>
|
||||
#include <QPixmap>
|
||||
#include <filesystem>
|
||||
|
||||
#include "MainWidget.h"
|
||||
|
||||
class MainWindow : public QMainWindow {
|
||||
Q_OBJECT
|
||||
public:
|
||||
MainWindow(QWidget* parent = nullptr);
|
||||
MainWindow(std::filesystem::path path, QWidget* parent = nullptr);
|
||||
~MainWindow( );
|
||||
|
||||
private:
|
||||
MainWidget* mainWidget;
|
||||
|
||||
void setupMainWindow( );
|
||||
};
|
||||
350
src/View/Modules/FloatingControls/FloatingControls.cpp
Executable file
350
src/View/Modules/FloatingControls/FloatingControls.cpp
Executable file
@@ -0,0 +1,350 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "FloatingControls.h"
|
||||
#include <QGraphicsDropShadowEffect>
|
||||
#include <QGraphicsBlurEffect>
|
||||
#include <QLayout>
|
||||
#include <QWidget>
|
||||
#include <QLabel>
|
||||
#include <string>
|
||||
#include <QPixmap>
|
||||
#include <QtSvg>
|
||||
#include <QSvgRenderer>
|
||||
#include <QPainter>
|
||||
#include <QMainWindow>
|
||||
#include <QApplication>
|
||||
|
||||
enum Repeat : short {
|
||||
ALL,
|
||||
CURRENT,
|
||||
NONE
|
||||
};
|
||||
|
||||
static QPushButton* makeSongControlButton(QString name, QSize size = QSize(36, 36), QString color = "#D7D7D7") {
|
||||
QPushButton* button = new QPushButton( );
|
||||
button->setObjectName(name);
|
||||
button->setStyleSheet(R"(
|
||||
QPushButton#)" + name + R"({
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
}
|
||||
)");
|
||||
button->setIcon(RenderSvg(":/icons/" + name + ".svg", 36, 36));
|
||||
button->setIconSize(size);
|
||||
button->setCursor(Qt::PointingHandCursor);
|
||||
QGraphicsColorizeEffect* colorize = new QGraphicsColorizeEffect( );
|
||||
colorize->setColor(QColor(color));
|
||||
colorize->setStrength(1);
|
||||
button->setGraphicsEffect(colorize);
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
FloatingControls::FloatingControls(QWidget* parent, std::filesystem::path path) :
|
||||
QFrame(parent),
|
||||
volume(100),
|
||||
albumArtPath("default.png"),
|
||||
fullscreen(false), shuffle(false),
|
||||
playPause(false),
|
||||
songRepeat(NONE),
|
||||
artist("Artist"),
|
||||
songName("Song"),
|
||||
song(Audio::getInstance( )) {
|
||||
this->setFixedHeight(100);
|
||||
this->setObjectName("main");
|
||||
this->setStyleSheet(R"(
|
||||
QFrame#main{
|
||||
background-color:rgba(40, 40 ,40, 0.3);
|
||||
border: 4px solid #414141;
|
||||
border-radius: 12px;
|
||||
margin: 0px 10px 10px 10px;
|
||||
}
|
||||
)");
|
||||
applyShadow(this);
|
||||
|
||||
/* Main Layout to store the Left Center and right controls */
|
||||
QHBoxLayout* mainLayout = new QHBoxLayout(this);
|
||||
/* Left side Icon, Artist and Song info */
|
||||
QHBoxLayout* leftLayout = new QHBoxLayout( );
|
||||
leftLayout->setSpacing(10);
|
||||
leftLayout->setAlignment(Qt::AlignLeft);
|
||||
|
||||
// Album Art
|
||||
QLabel* albumArt = new QLabel( );
|
||||
albumArt->setObjectName("albumArt");
|
||||
albumArt->setAlignment(Qt::AlignCenter);
|
||||
albumArt->setStyleSheet(R"(
|
||||
QLabel#albumArt{
|
||||
border: 4px solid #414141;
|
||||
border-radius: 8px;
|
||||
}
|
||||
)");
|
||||
//! Change later to the actual album art when the controls are done
|
||||
albumArt->setPixmap(song.GetAlbumCover( ).scaled(QSize(64, 64), Qt::IgnoreAspectRatio));
|
||||
leftLayout->addWidget(albumArt);
|
||||
|
||||
// Artist and Song name layout
|
||||
QVBoxLayout* artistSongLayout = new QVBoxLayout( );
|
||||
QLabel* artist = new QLabel(QString::fromStdString(song.GetArtist( )));
|
||||
artist->setMinimumWidth(50);
|
||||
connect(this, &FloatingControls::artistChanged, artist, &QLabel::setText);
|
||||
artist->setObjectName("artist");
|
||||
artist->setStyleSheet(R"(
|
||||
QLabel#artist{
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #E1E1E1;
|
||||
}
|
||||
)");
|
||||
|
||||
QLabel* songName = new QLabel( );
|
||||
songName->setMinimumWidth(50);
|
||||
QFontMetrics metrics(songName->font( ));
|
||||
songName->setText(metrics.elidedText(QString::fromStdString(song.GetTitle( )), Qt::ElideRight, songName->width( )));
|
||||
|
||||
connect(this, &FloatingControls::songNameChanged, songName, &QLabel::setText);
|
||||
songName->setObjectName("title");
|
||||
songName->setStyleSheet(R"(
|
||||
QLabel#songName{
|
||||
font-size: 14px;
|
||||
color: #D7D7D7;
|
||||
}
|
||||
)");
|
||||
artistSongLayout->addWidget(artist);
|
||||
artistSongLayout->addWidget(songName);
|
||||
leftLayout->addLayout(artistSongLayout);
|
||||
|
||||
/* Center layout to store the song controls and pos bar */
|
||||
QVBoxLayout* centerLayout = new QVBoxLayout( );
|
||||
centerLayout->setAlignment(Qt::AlignCenter);
|
||||
|
||||
mainLayout->setStretchFactor(leftLayout, 1);
|
||||
mainLayout->setStretchFactor(centerLayout, 0.1);
|
||||
|
||||
QHBoxLayout* songControlsLayout = new QHBoxLayout( );
|
||||
songControlsLayout->setAlignment(Qt::AlignCenter | Qt::AlignBottom);
|
||||
|
||||
QString buttonNames[5] = { "shuffle", "prevSong", "play", "nextSong", "songRepeat" };
|
||||
QString col = "#D7D7D7";
|
||||
for (int i = 0; i < 5; i++) {
|
||||
if (buttonNames[i] == "shuffle" || buttonNames[i] == "songRepeat")
|
||||
col = "#CC79AB";
|
||||
else
|
||||
col = "#D7D7D7";
|
||||
QPushButton* pb = makeSongControlButton(buttonNames[i], QSize(36, 36), col);
|
||||
if (buttonNames[i] == "play") {
|
||||
//TODO Change later
|
||||
QObject::connect(pb, &QPushButton::clicked, [pb, this]( ) {
|
||||
if (!song.IsMusicPlaying( )) {
|
||||
song.StartMusic( );
|
||||
pb->setIcon(RenderSvg(":/icons/pause.svg", 36, 36));
|
||||
return;
|
||||
}
|
||||
if (GetPlayPause( )) {
|
||||
song.ResumeMusic( );
|
||||
pb->setIcon(RenderSvg(":/icons/pause.svg", 36, 36));
|
||||
}
|
||||
else {
|
||||
song.PauseMusic( );
|
||||
pb->setIcon(RenderSvg(":/icons/play.svg", 36, 36));
|
||||
}
|
||||
togglePlayPause( );
|
||||
});
|
||||
}
|
||||
songControlsLayout->addWidget(pb);
|
||||
|
||||
}
|
||||
|
||||
|
||||
centerLayout->addLayout(songControlsLayout);
|
||||
|
||||
QHBoxLayout* songScrollerLayout = new QHBoxLayout( );
|
||||
songScrollerLayout->setAlignment(Qt::AlignCenter | Qt::AlignTop);
|
||||
|
||||
// Song timestamp
|
||||
QLabel* songTimestamp = new QLabel("00:00");
|
||||
songTimestamp->setText(
|
||||
QTime(
|
||||
0,
|
||||
song.GetMusicPos( ) / 60,
|
||||
song.GetMusicPos( ) % 60
|
||||
).toString("mm:ss"));
|
||||
songTimestamp->setObjectName("songTimestamp");
|
||||
songTimestamp->setStyleSheet(R"(
|
||||
QLabel#songTimestamp{
|
||||
font-size: 14px;
|
||||
color: #D7D7D7;
|
||||
}
|
||||
)");
|
||||
songTimestamp->setAlignment(Qt::AlignRight);
|
||||
|
||||
// Song duration
|
||||
QLabel* songDuration = new QLabel("00:00");
|
||||
songDuration->setText(
|
||||
QTime(
|
||||
0,
|
||||
song.GetMusicDuration( ) / 60,
|
||||
song.GetMusicDuration( ) % 60
|
||||
).toString("mm:ss"));
|
||||
songDuration->setObjectName("songDuration");
|
||||
songDuration->setStyleSheet(R"(
|
||||
QLabel#songDuration{
|
||||
font-size: 14px;
|
||||
color: #D7D7D7;
|
||||
}
|
||||
)");
|
||||
|
||||
// Song duration slider
|
||||
QSlider* songDurationSlider = new QSlider(Qt::Horizontal);
|
||||
songDurationSlider->setObjectName("songDurationSlider");
|
||||
songDurationSlider->setRange(0, song.GetMusicDuration( ));
|
||||
songDurationSlider->setValue(song.GetMusicPos( ));
|
||||
songDurationSlider->setFixedHeight(28);
|
||||
songDurationSlider->setStyleSheet(R"(
|
||||
QSlider#songDurationSlider::groove:horizontal{
|
||||
border-radius: 4px;
|
||||
height: 8px;
|
||||
background: #414141;
|
||||
}
|
||||
QSlider#songDurationSlider::handle:horizontal{
|
||||
background: #78AB70;
|
||||
border: 4px solid #414141;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
margin: -7px 0;
|
||||
border-radius: 10px;
|
||||
padding: -8px 0;
|
||||
}
|
||||
QSlider#songDurationSlider::sub-page:horizontal{
|
||||
background: #78AB70;
|
||||
border-radius: 4px;
|
||||
height: 8px;
|
||||
}
|
||||
)");
|
||||
songDurationSlider->setCursor(Qt::PointingHandCursor);
|
||||
|
||||
connect(songDurationSlider, &QSlider::sliderReleased, [this, songDurationSlider]( ) {
|
||||
song.SetMusicPos(songDurationSlider->value( ));
|
||||
});
|
||||
|
||||
songScrollerLayout->addWidget(songTimestamp);
|
||||
songScrollerLayout->addWidget(songDurationSlider);
|
||||
songScrollerLayout->addWidget(songDuration);
|
||||
|
||||
QTimer* timer = new QTimer(this);
|
||||
|
||||
connect(timer, &QTimer::timeout, this, [this, songTimestamp, songDurationSlider]( ) {
|
||||
int sec = song.GetMusicPos( );
|
||||
|
||||
songTimestamp->setText(
|
||||
QTime(
|
||||
0,
|
||||
sec / 60,
|
||||
sec % 60
|
||||
).toString("mm:ss"));
|
||||
|
||||
songDurationSlider->setValue(sec);
|
||||
//std::cout << songTimestamp->text( ).toStdString( ) << std::endl;
|
||||
});
|
||||
timer->start(1000);
|
||||
|
||||
centerLayout->addLayout(songScrollerLayout);
|
||||
|
||||
/* Right side layout to store the volume and fullscreen controls */
|
||||
QHBoxLayout* rightLayout = new QHBoxLayout( );
|
||||
rightLayout->setAlignment(Qt::AlignRight);
|
||||
|
||||
//Volume icon
|
||||
QLabel* volumeIcon = new QLabel( );
|
||||
volumeIcon->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
||||
volumeIcon->setObjectName("volumeIcon");
|
||||
volumeIcon->setPixmap(RenderSvg(":icons/volume-high.svg", 36, 36).scaled(QSize(24, 24), Qt::IgnoreAspectRatio));
|
||||
QGraphicsColorizeEffect* colorize = new QGraphicsColorizeEffect( );
|
||||
colorize->setColor(QColor("#78AB70"));
|
||||
colorize->setStrength(1);
|
||||
volumeIcon->setGraphicsEffect(colorize);
|
||||
rightLayout->addWidget(volumeIcon);
|
||||
|
||||
//Volume slider
|
||||
QSlider* VolumeSlider = new QSlider(Qt::Horizontal);
|
||||
VolumeSlider->setObjectName("volumeSlider");
|
||||
VolumeSlider->setRange(0, 128);
|
||||
VolumeSlider->setValue(song.GetVolume( ));
|
||||
VolumeSlider->setFixedHeight(28);
|
||||
VolumeSlider->setStyleSheet(R"(
|
||||
QSlider#volumeSlider::groove:horizontal{
|
||||
border-radius: 4px;
|
||||
height: 8px;
|
||||
background: #414141;
|
||||
}
|
||||
QSlider#volumeSlider::handle:horizontal{
|
||||
background: #78AB70;
|
||||
border: 4px solid #414141;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
margin: -7px 0;
|
||||
border-radius: 10px;
|
||||
padding: -8px 0;
|
||||
}
|
||||
QSlider#volumeSlider::sub-page:horizontal{
|
||||
background: #78AB70;
|
||||
border-radius: 4px;
|
||||
height: 8px;
|
||||
}
|
||||
)");
|
||||
VolumeSlider->setCursor(Qt::PointingHandCursor);
|
||||
|
||||
connect(VolumeSlider, &QSlider::valueChanged, [this, VolumeSlider]( ) {
|
||||
song.SetVolume(VolumeSlider->value( ));
|
||||
});
|
||||
|
||||
rightLayout->addWidget(VolumeSlider);
|
||||
|
||||
//Fullscreen button
|
||||
QPushButton* FullscreenToggle = new QPushButton( );
|
||||
FullscreenToggle->setObjectName("fullscreenToggle");
|
||||
FullscreenToggle->setStyleSheet(R"(
|
||||
QPushButton#fullscreenToggle{
|
||||
background: transparent;
|
||||
border: 4px solid #414141;
|
||||
border-radius: 8px;
|
||||
margin-right: 14px;
|
||||
}
|
||||
)");
|
||||
FullscreenToggle->setFixedSize(50, 36);
|
||||
FullscreenToggle->setCursor(Qt::PointingHandCursor);
|
||||
connect(FullscreenToggle, &QPushButton::clicked, [ ]( ) {
|
||||
QMainWindow* mw = (QMainWindow*)QApplication::activeWindow( );
|
||||
if (mw->isFullScreen( ))
|
||||
mw->showNormal( );
|
||||
else
|
||||
mw->showFullScreen( );
|
||||
});
|
||||
QLabel* FullscreenLabel = new QLabel( );
|
||||
FullscreenLabel->setFixedSize(36, 24);
|
||||
FullscreenLabel->setObjectName("fullscreenLabel");
|
||||
FullscreenLabel->setPixmap(QPixmap(":icons/arrow-expand.svg").scaled(QSize(24, 24), Qt::IgnoreAspectRatio));
|
||||
|
||||
QVBoxLayout* FullscreenLayout = new QVBoxLayout( );
|
||||
FullscreenLayout->setAlignment(Qt::AlignCenter);
|
||||
FullscreenLayout->addWidget(FullscreenLabel);
|
||||
|
||||
QGraphicsColorizeEffect* colorize2 = new QGraphicsColorizeEffect( );
|
||||
colorize2->setColor(QColor("#83BFC8"));
|
||||
colorize2->setStrength(1);
|
||||
FullscreenLabel->setGraphicsEffect(colorize2);
|
||||
FullscreenToggle->setLayout(FullscreenLayout);
|
||||
|
||||
rightLayout->addWidget(FullscreenToggle);
|
||||
|
||||
mainLayout->addLayout(leftLayout, 0);
|
||||
mainLayout->addLayout(centerLayout, 1);
|
||||
mainLayout->addLayout(rightLayout, 0);
|
||||
|
||||
// Some spacing in case the window is small enough to have the items touch
|
||||
mainLayout->setSpacing(10);
|
||||
|
||||
this->setLayout(mainLayout);
|
||||
}
|
||||
|
||||
FloatingControls::~FloatingControls( ) { }
|
||||
87
src/View/Modules/FloatingControls/FloatingControls.h
Executable file
87
src/View/Modules/FloatingControls/FloatingControls.h
Executable file
@@ -0,0 +1,87 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../../core/audio/audio.h"
|
||||
#include "../../Tools/SvgToPixmap.hpp"
|
||||
|
||||
#include <QFrame>
|
||||
#include <QSlider>
|
||||
#include <QPushButton>
|
||||
#include <QObject>
|
||||
#include <filesystem>
|
||||
#include <QStackedLayout>
|
||||
|
||||
enum Repeat : short;
|
||||
|
||||
class FloatingControls : public QFrame {
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QString artist READ getArtist WRITE setArtist NOTIFY artistChanged)
|
||||
Q_PROPERTY(QString songName READ getSongName WRITE setSongName NOTIFY songNameChanged)
|
||||
Q_PROPERTY(int songPos READ getSongPos WRITE setSongPos NOTIFY songPosChanged)
|
||||
public:
|
||||
|
||||
QString getArtist( ) const {
|
||||
return artist;
|
||||
}
|
||||
void setArtist(QString artist) {
|
||||
if (this->artist == artist)
|
||||
return;
|
||||
|
||||
this->artist = artist;
|
||||
emit artistChanged(artist);
|
||||
}
|
||||
|
||||
QString getSongName( ) const {
|
||||
return songName;
|
||||
}
|
||||
void setSongName(QString songName) {
|
||||
if (this->songName == songName)
|
||||
return;
|
||||
|
||||
this->songName = songName;
|
||||
emit songNameChanged(songName);
|
||||
}
|
||||
|
||||
int getSongPos( ) const {
|
||||
return songPos;
|
||||
}
|
||||
void setSongPos(int pos) {
|
||||
if (this->songPos == pos)
|
||||
return;
|
||||
this->songPos = pos;
|
||||
emit songPosChanged(pos);
|
||||
}
|
||||
|
||||
void togglePlayPause( ) {
|
||||
this->playPause = !this->playPause;
|
||||
}
|
||||
|
||||
bool GetPlayPause( ) {
|
||||
return this->playPause;
|
||||
}
|
||||
|
||||
FloatingControls(QWidget* parent = nullptr, std::filesystem::path path = std::filesystem::path( ));
|
||||
~FloatingControls( );
|
||||
|
||||
signals:
|
||||
void artistChanged(QString artist);
|
||||
void songNameChanged(QString songName);
|
||||
void songPosChanged(int songPos);
|
||||
|
||||
private:
|
||||
QString artist;
|
||||
QString songName;
|
||||
|
||||
QString albumArtPath;
|
||||
int volume;
|
||||
bool fullscreen;
|
||||
bool shuffle;
|
||||
bool playPause;
|
||||
Repeat songRepeat;
|
||||
QPixmap albumArt;
|
||||
int songPos;
|
||||
int songLength;
|
||||
|
||||
Audio& song;
|
||||
};
|
||||
32
src/View/Modules/PageNavModule/PageNavModule.cpp
Executable file
32
src/View/Modules/PageNavModule/PageNavModule.cpp
Executable file
@@ -0,0 +1,32 @@
|
||||
#include "PageNavModule.h"
|
||||
|
||||
#include <QWidget>
|
||||
#include <QFrame>
|
||||
|
||||
PageNavModule::PageNavModule(QWidget* parent) :QFrame(parent) {
|
||||
|
||||
this->setStyleSheet(R"(
|
||||
background-color: #282828;
|
||||
border-radius: 12px;
|
||||
)");
|
||||
|
||||
applyShadow(this);
|
||||
|
||||
this->setFixedSize(300, 180);
|
||||
|
||||
QVBoxLayout* layout = new QVBoxLayout(this);
|
||||
|
||||
PageNavigator* home = new PageNavigator("Home", ":icons/home-outline.svg", "#81D4FA");
|
||||
PageNavigator* localFiles = new PageNavigator("Local Files", ":icons/folder-outline.svg", "#FFE082");
|
||||
PageNavigator* playlist = new PageNavigator("Playlist", ":icons/magnify.svg", "#CE93D8");
|
||||
|
||||
layout->addWidget(home);
|
||||
layout->addWidget(localFiles);
|
||||
layout->addWidget(playlist);
|
||||
|
||||
connect(home, &PageNavigator::SelectedChanged, this, &PageNavModule::SelectChanged);
|
||||
connect(localFiles, &PageNavigator::SelectedChanged, this, &PageNavModule::SelectChanged);
|
||||
connect(playlist, &PageNavigator::SelectedChanged, this, &PageNavModule::SelectChanged);
|
||||
}
|
||||
|
||||
PageNavModule::~PageNavModule( ) { }
|
||||
20
src/View/Modules/PageNavModule/PageNavModule.h
Executable file
20
src/View/Modules/PageNavModule/PageNavModule.h
Executable file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include <QVector>
|
||||
#include <QFrame>
|
||||
#include "../../Widgets/PageNavigator/PageNavigator.h"
|
||||
#include "../../Tools/SvgToPixmap.hpp"
|
||||
|
||||
class PageNavModule : public QFrame {
|
||||
Q_OBJECT
|
||||
private:
|
||||
QVector<PageNavigator> pages;
|
||||
|
||||
public:
|
||||
PageNavModule(QWidget* parent = nullptr);
|
||||
~PageNavModule( );
|
||||
|
||||
signals:
|
||||
void SelectChanged(PageNavigator* pn);
|
||||
};
|
||||
17
src/View/Modules/PlaylistNavModule/PlaylistNavModule.cpp
Executable file
17
src/View/Modules/PlaylistNavModule/PlaylistNavModule.cpp
Executable file
@@ -0,0 +1,17 @@
|
||||
#include "PlaylistNavModule.h"
|
||||
|
||||
PlaylistNavModule::PlaylistNavModule(QWidget* parent) : QFrame(parent) {
|
||||
|
||||
this->setStyleSheet(R"(
|
||||
background-color: #282828;
|
||||
border-radius: 12px;
|
||||
)");
|
||||
|
||||
this->setFixedWidth(300);
|
||||
|
||||
QVBoxLayout* mainLayout = new QVBoxLayout(this);
|
||||
mainLayout->addSpacing(10);
|
||||
|
||||
}
|
||||
|
||||
PlaylistNavModule::~PlaylistNavModule( ) { }
|
||||
16
src/View/Modules/PlaylistNavModule/PlaylistNavModule.h
Executable file
16
src/View/Modules/PlaylistNavModule/PlaylistNavModule.h
Executable file
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include <QFrame>
|
||||
#include <QLayout>
|
||||
|
||||
class PlaylistNavModule : public QFrame {
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
|
||||
public:
|
||||
PlaylistNavModule(QWidget* parent);
|
||||
~PlaylistNavModule( );
|
||||
};
|
||||
14
src/View/Pages/Home/HomePage.cpp
Normal file
14
src/View/Pages/Home/HomePage.cpp
Normal file
@@ -0,0 +1,14 @@
|
||||
#include "HomePage.h"
|
||||
|
||||
HomePage::HomePage(QWidget* parent)
|
||||
: QFrame(parent) {
|
||||
|
||||
setStyleSheet(R"(
|
||||
background-color: #28FF28;
|
||||
border-radius: 12px;
|
||||
)");
|
||||
|
||||
applyShadow(this);
|
||||
}
|
||||
|
||||
HomePage::~HomePage( ) { }
|
||||
15
src/View/Pages/Home/HomePage.h
Normal file
15
src/View/Pages/Home/HomePage.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include <QFrame>
|
||||
#include "../../Tools/SvgToPixmap.hpp"
|
||||
|
||||
|
||||
class HomePage : public QFrame {
|
||||
Q_OBJECT
|
||||
private:
|
||||
/* data */
|
||||
public:
|
||||
HomePage(QWidget* parent = nullptr);
|
||||
~HomePage( );
|
||||
};
|
||||
14
src/View/Pages/Playlist/PlaylistPage.cpp
Executable file
14
src/View/Pages/Playlist/PlaylistPage.cpp
Executable file
@@ -0,0 +1,14 @@
|
||||
#include "PlaylistPage.h"
|
||||
|
||||
PlaylistPage::PlaylistPage(QWidget* parent)
|
||||
: QFrame(parent) {
|
||||
|
||||
setStyleSheet(R"(
|
||||
background-color: #2828ff;
|
||||
border-radius: 12px;
|
||||
)");
|
||||
|
||||
applyShadow(this);
|
||||
}
|
||||
|
||||
PlaylistPage::~PlaylistPage( ) { }
|
||||
13
src/View/Pages/Playlist/PlaylistPage.h
Executable file
13
src/View/Pages/Playlist/PlaylistPage.h
Executable file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include <QFrame>
|
||||
#include "../../Tools/SvgToPixmap.hpp"
|
||||
|
||||
class PlaylistPage : public QFrame {
|
||||
Q_OBJECT
|
||||
private:
|
||||
public:
|
||||
PlaylistPage(QWidget* parent = nullptr);
|
||||
~PlaylistPage( );
|
||||
};
|
||||
29
src/View/Tools/SvgToPixmap.hpp
Normal file
29
src/View/Tools/SvgToPixmap.hpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include <QPixmap>
|
||||
#include <QString>
|
||||
#include <QSvgRenderer>
|
||||
#include <QPainter>
|
||||
#include <QGraphicsDropShadowEffect>
|
||||
|
||||
static QPixmap RenderSvg(QString path, int w, int h) {
|
||||
QSvgRenderer renderer(path);
|
||||
QPixmap pixmap(w, h);
|
||||
pixmap.fill(Qt::transparent);
|
||||
QPainter painter(&pixmap);
|
||||
renderer.render(&painter);
|
||||
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void applyShadow(T obj, int blurRadius = 20, int xOffset = 10, int yOffset = 10, QString color = "#000000", int offset = 2) {
|
||||
QGraphicsDropShadowEffect* dropShadow = new QGraphicsDropShadowEffect( );
|
||||
dropShadow->setBlurRadius(blurRadius);
|
||||
dropShadow->setXOffset(xOffset);
|
||||
dropShadow->setYOffset(yOffset);
|
||||
dropShadow->setColor(color);
|
||||
dropShadow->setOffset(offset);
|
||||
obj->setGraphicsEffect(dropShadow);
|
||||
}
|
||||
11
src/View/Widgets/NavigationButton/NavigationButton.cpp
Normal file
11
src/View/Widgets/NavigationButton/NavigationButton.cpp
Normal file
@@ -0,0 +1,11 @@
|
||||
#include "NavigationButton.h"
|
||||
|
||||
NavigationButton::NavigationButton( ) { }
|
||||
|
||||
NavigationButton::~NavigationButton( ) { }
|
||||
|
||||
void setSelected(NavigationButton* newSelected);
|
||||
NavigationButton getSelected( ) { }
|
||||
|
||||
void NavigationButton::select( ) { }
|
||||
void NavigationButton::unselect( ) { }
|
||||
31
src/View/Widgets/NavigationButton/NavigationButton.h
Normal file
31
src/View/Widgets/NavigationButton/NavigationButton.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include <QPushButton>
|
||||
#include <QLabel>
|
||||
#include <QString>
|
||||
|
||||
class NavigationButton : public QPushButton {
|
||||
Q_OBJECT
|
||||
private:
|
||||
QLabel* m_icon;
|
||||
QLabel* m_name;
|
||||
QString* m_colorHex;
|
||||
|
||||
static NavigationButton* m_selected;
|
||||
|
||||
public:
|
||||
static void setSelected(NavigationButton* newSelected);
|
||||
static NavigationButton* getSelected( );
|
||||
|
||||
NavigationButton( );
|
||||
~NavigationButton( );
|
||||
|
||||
signals:
|
||||
void unselected( );
|
||||
void selected( );
|
||||
|
||||
private slots:
|
||||
void select( );
|
||||
void unselect( );
|
||||
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
#include "PagesButton.h"
|
||||
|
||||
PagesButton::PagesButton( ) { }
|
||||
PagesButton::~PagesButton( ) { }
|
||||
11
src/View/Widgets/NavigationButton/PagesButton/PagesButton.h
Normal file
11
src/View/Widgets/NavigationButton/PagesButton/PagesButton.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "../NavigationButton.h"
|
||||
|
||||
class PagesButton : NavigationButton {
|
||||
private:
|
||||
|
||||
public:
|
||||
PagesButton( );
|
||||
~PagesButton( );
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
#include "PlaylistButton.h"
|
||||
|
||||
PlaylistButton::PlaylistButton( ) { }
|
||||
PlaylistButton::~PlaylistButton( ) { }
|
||||
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "../NavigationButton.h"
|
||||
|
||||
class PlaylistButton : NavigationButton {
|
||||
private:
|
||||
|
||||
public:
|
||||
PlaylistButton( );
|
||||
~PlaylistButton( );
|
||||
};
|
||||
88
src/View/Widgets/PageNavigator/PageNavigator.cpp
Normal file
88
src/View/Widgets/PageNavigator/PageNavigator.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
#include "PageNavigator.h"
|
||||
#include "SelectHandler.hpp"
|
||||
#include "../../Tools/SvgToPixmap.hpp"
|
||||
|
||||
class SquareIcon : public QLabel {
|
||||
public:
|
||||
QSize sizeHint( ) const override {
|
||||
QSize hint = QLabel::sizeHint( );
|
||||
int side = qMin(hint.width( ), hint.height( ));
|
||||
return QSize(side, side);
|
||||
}
|
||||
};
|
||||
|
||||
PageNavigator::PageNavigator(QString text, QString icon, QString color, QWidget* parent)
|
||||
:m_text(new QLabel(text)), m_icon(new SquareIcon( )), m_color(color), m_iconPath(icon) {
|
||||
|
||||
|
||||
QSvgRenderer renderer(icon);
|
||||
|
||||
QPixmap pixmap(32, 32);
|
||||
pixmap.fill(Qt::transparent);
|
||||
QPainter painter(&pixmap);
|
||||
renderer.render(&painter, pixmap.rect( ));
|
||||
|
||||
painter.setCompositionMode(QPainter::CompositionMode_SourceIn);
|
||||
painter.fillRect(pixmap.rect( ), color);
|
||||
painter.end( );
|
||||
|
||||
m_icon->setPixmap(pixmap);
|
||||
|
||||
m_icon->setObjectName("icon");
|
||||
|
||||
setObjectName("PageNavigator");
|
||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
setStyleSheet(R"(
|
||||
#PageNavigator{
|
||||
border: 4px solid #414141;
|
||||
border-radius: 6px;
|
||||
color: #E0E0E0;
|
||||
}
|
||||
)");
|
||||
|
||||
QFont font = m_text->font( );
|
||||
font.setPointSize(16);
|
||||
font.setWeight(QFont::Bold);
|
||||
m_text->setFont(font);
|
||||
|
||||
QHBoxLayout* layout = new QHBoxLayout(this);
|
||||
layout->addWidget(m_icon, 0, Qt::AlignLeft);
|
||||
layout->addWidget(m_text, 1, Qt::AlignLeft);
|
||||
|
||||
connect(this, &QPushButton::clicked, [this, parent]( ) {
|
||||
SelectHandler* sh = SelectHandler::GetInstance( );
|
||||
|
||||
sh->setSelected(this);
|
||||
emit SelectedChanged(this);
|
||||
});
|
||||
|
||||
// Little hacky but thats how home is the default
|
||||
if (text == "Home") {
|
||||
SelectHandler* sh = SelectHandler::GetInstance( );
|
||||
|
||||
sh->setSelected(this);
|
||||
emit SelectedChanged(this);
|
||||
}
|
||||
}
|
||||
|
||||
void PageNavigator::unselect( ) {
|
||||
setStyleSheet(R"(
|
||||
#PageNavigator{
|
||||
border: 4px solid #414141;
|
||||
border-radius: 6px;
|
||||
}
|
||||
)");
|
||||
}
|
||||
|
||||
void PageNavigator::select( ) {
|
||||
setStyleSheet(R"(
|
||||
#PageNavigator{
|
||||
border: 4px solid )" + m_color + R"(;
|
||||
border-radius: 6px;
|
||||
}
|
||||
)");
|
||||
}
|
||||
|
||||
QString PageNavigator::GetText( ) {
|
||||
return m_text->text( );
|
||||
}
|
||||
29
src/View/Widgets/PageNavigator/PageNavigator.h
Normal file
29
src/View/Widgets/PageNavigator/PageNavigator.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include <QLabel>
|
||||
#include <QLayout>
|
||||
#include <QFont>
|
||||
#include <QPushButton>
|
||||
#include <QColor>
|
||||
#include <QGraphicsColorizeEffect>
|
||||
|
||||
class PageNavigator :public QPushButton {
|
||||
Q_OBJECT
|
||||
private:
|
||||
QLabel* m_text;
|
||||
QLabel* m_icon;
|
||||
QString m_iconPath;
|
||||
QString m_color;
|
||||
|
||||
public:
|
||||
PageNavigator(QString text, QString icon, QString color, QWidget* parent = nullptr);
|
||||
|
||||
void unselect( );
|
||||
void select( );
|
||||
|
||||
QString GetText( );
|
||||
|
||||
signals:
|
||||
void SelectedChanged(PageNavigator* pn);
|
||||
};
|
||||
53
src/View/Widgets/PageNavigator/SelectHandler.hpp
Normal file
53
src/View/Widgets/PageNavigator/SelectHandler.hpp
Normal file
@@ -0,0 +1,53 @@
|
||||
#pragma once
|
||||
|
||||
#include "PageNavigator.h"
|
||||
|
||||
/*
|
||||
Singleton to handle PageNavigator widget selects
|
||||
*/
|
||||
class SelectHandler {
|
||||
public:
|
||||
static SelectHandler* GetInstance( );
|
||||
|
||||
~SelectHandler( ) { }
|
||||
SelectHandler(const SelectHandler&) = delete;
|
||||
void operator=(const SelectHandler&) = delete;
|
||||
|
||||
void setSelected(PageNavigator* newSelected);
|
||||
|
||||
PageNavigator* getSelected( );
|
||||
|
||||
private:
|
||||
SelectHandler( ) { }
|
||||
|
||||
static SelectHandler* instance;
|
||||
|
||||
PageNavigator* selected = nullptr;
|
||||
};
|
||||
|
||||
SelectHandler* SelectHandler::instance = nullptr;
|
||||
|
||||
SelectHandler* SelectHandler::GetInstance( ) {
|
||||
if (instance == nullptr)
|
||||
instance = new SelectHandler( );
|
||||
return instance;
|
||||
}
|
||||
|
||||
void SelectHandler::setSelected(PageNavigator* newSelected) {
|
||||
if (!newSelected && (newSelected == selected))
|
||||
return;
|
||||
|
||||
if (this->selected == nullptr) {
|
||||
this->selected = newSelected;
|
||||
selected->select( );
|
||||
return;
|
||||
}
|
||||
|
||||
selected->unselect( );
|
||||
newSelected->select( );
|
||||
this->selected = newSelected;
|
||||
}
|
||||
|
||||
PageNavigator* SelectHandler::getSelected( ) {
|
||||
return selected;
|
||||
}
|
||||
Reference in New Issue
Block a user