#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "playerwidget.h" #include "beetview.h" #include "indexerdialog.h" #include "globals.h" PlayerWidget::PlayerWidget(QWidget *parent) : QWidget(parent){ setupGui(); createActions(); } void PlayerWidget::setupGui(){ //the Player mPlayer = new QMediaPlayer(this); connect(mPlayer, SIGNAL(positionChanged(qint64)), this, SLOT(setPosition(qint64))); connect(mPlayer, SIGNAL(durationChanged(qint64)), this, SLOT(setDuration(qint64))); connect(mPlayer, SIGNAL(stateChanged(QMediaPlayer::State)), this, SLOT(continuePlaying(QMediaPlayer::State))); //THE view mView = new BeetView; mViewModel = new QStandardItemModel; mView->setModel(mViewModel); mSearchModel = new QStandardItemModel; mView->setSelectionMode(QAbstractItemView::ExtendedSelection); currentModel = mViewModel; QToolBar *viewTB = new QToolBar; QActionGroup *viewAG = new QActionGroup(this); viewAG->setExclusive(true); QAction *viewByArtistA = new QAction(QIcon(":/artist.png"), tr("View by artist"), this); viewByArtistA->setCheckable(true); viewAG->addAction(viewByArtistA); connect(viewByArtistA, SIGNAL(triggered()), this, SLOT(doPopulateByArtist())); QAction *viewByAlbumA = new QAction(QIcon(":/album.png"), tr("View by album"), this); viewByAlbumA->setCheckable(true); viewAG->addAction(viewByAlbumA); connect(viewByAlbumA, SIGNAL(triggered()), this, SLOT(doPopulateByAlbum())); QAction *viewBySongA = new QAction(QIcon(":/song.png"), tr("View by song"), this); viewBySongA->setCheckable(true); viewAG->addAction(viewBySongA); connect(viewBySongA, SIGNAL(triggered()), this, SLOT(doPopulateBySong())); QAction *viewByGenreA = new QAction(QIcon(":/genre.png"), tr("View by genre"), this); viewByGenreA->setCheckable(true); viewAG->addAction(viewByGenreA); connect(viewByGenreA, SIGNAL(triggered()), this, SLOT(doPopulateByGenre())); viewTB->addActions(viewAG->actions()); //filter QGroupBox *filterGB = new QGroupBox(tr("Search")); mSearch = new QLineEdit; connect(mSearch, SIGNAL(returnPressed()), this, SLOT(doFilter())); QToolBar *searchTB = new QToolBar; QAction *clearSearchA = new QAction(QIcon(":/clean_tampon.png"), tr("Clear search"), this); connect(clearSearchA, SIGNAL(triggered()), this, SLOT(clearFilter())); searchTB->addAction(clearSearchA); QAction *doSearchA = new QAction(QIcon(":/stomp.png"), tr("Go searching!"), this); connect(doSearchA, SIGNAL(triggered()), this, SLOT(doFilter())); searchTB->addAction(doSearchA); QHBoxLayout *filterLayout = new QHBoxLayout; filterLayout->addWidget(mSearch); filterLayout->addWidget(searchTB); filterGB->setLayout(filterLayout); //left widget QWidget *leftWidget = new QWidget; QVBoxLayout *leftWidgetL = new QVBoxLayout; leftWidgetL->addWidget(filterGB); leftWidgetL->addWidget(mView); QHBoxLayout *selViewL = new QHBoxLayout; selViewL->addWidget(new QLabel(tr("View by:"))); selViewL->addStretch(); selViewL->addWidget(viewTB); selViewL->addStretch(); leftWidgetL->addLayout(selViewL); leftWidget->setLayout(leftWidgetL); //now playing label mNowPlayingL = new QLabel; mNowPlayingL->setAlignment(Qt::AlignCenter); mNowPlayingL->setFont(QFont("courier new", 20, QFont::Bold)); mNowPlayingL->setText(tr("(none)")); //song slider QLabel *l1 = new QLabel(tr("Song")); mSongSlider = new QSlider; mSongSlider->setOrientation(Qt::Horizontal); connect(mSongSlider, SIGNAL(sliderMoved(int)), this, SLOT(slide(int))); mPos = new QLabel(tr("00:00")); mPos->setFont(QFont("courier")); QHBoxLayout *songSliderL = new QHBoxLayout; songSliderL->addWidget(l1); songSliderL->addWidget(mSongSlider); songSliderL->addWidget(mPos); //current info QGroupBox *currentInfoGB = new QGroupBox(tr("Current")); mCurrentTE = new QTextEdit; mCurrentTE->setFont(QFont("courier")); QVBoxLayout *currentInfoL = new QVBoxLayout; currentInfoL->addWidget(mCurrentTE); currentInfoGB->setLayout(currentInfoL); //volume slider QLabel *l2 = new QLabel(tr("Volume")); mVolumeSlider = new QSlider; mVolumeSlider->setOrientation(Qt::Horizontal); mVolumeSlider->setMinimum(0); mVolumeSlider->setMaximum(100); mVolumePos = new QLabel(tr("000 %")); mVolumePos->setFont(QFont("courier")); connect(mVolumeSlider, SIGNAL(valueChanged(int)), mPlayer, SLOT(setVolume(int))); connect(mVolumeSlider, SIGNAL(valueChanged(int)), this, SLOT(volumeChanged(int))); mVolumeSlider->setValue(33); QHBoxLayout *volumeL = new QHBoxLayout; volumeL->addWidget(l2); volumeL->addWidget(mVolumeSlider); volumeL->addWidget(mVolumePos); //center widget QWidget *centerWidget = new QWidget; QVBoxLayout *centerWidgetL = new QVBoxLayout; mToolBar = new QToolBar; centerWidgetL->addWidget(mToolBar); centerWidgetL->addWidget(mNowPlayingL); centerWidgetL->addLayout(songSliderL); centerWidgetL->addWidget(currentInfoGB); centerWidgetL->addLayout(volumeL); centerWidget->setLayout(centerWidgetL); //playlist mPlayListModel = new QStandardItemModel; mPlayListModel->setHorizontalHeaderLabels(QStringList() << "Title"); mPlayListView = new BeetView; mPlayListView->setModel(mPlayListModel); mPlayListView->setRootIsDecorated(false); mPlayListView->setSelectionMode(QAbstractItemView::ExtendedSelection); connect(mPlayListView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(playCurrent(QModelIndex))); QGroupBox *playListGB = new QGroupBox(tr("Playlist")); QVBoxLayout *playListL = new QVBoxLayout; playListL->addWidget(mPlayListView); playListGB->setLayout(playListL); //right widget QWidget *rightWidget = new QWidget; QVBoxLayout *rightWidgetL = new QVBoxLayout; rightWidgetL->addWidget(playListGB); rightWidget->setLayout(rightWidgetL); //put it all together QSplitter *splitter = new QSplitter; splitter->addWidget(leftWidget); splitter->addWidget(centerWidget); splitter->addWidget(rightWidget); QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->addWidget(splitter); setLayout(mainLayout); viewByArtistA->trigger(); } void PlayerWidget::createActions(){ QActionGroup *playAG = new QActionGroup(this); playAG->setExclusive(true); mPlayA = new QAction(QIcon(":/play.png"), tr("Play"), this); mPlayA->setCheckable(true); playAG->addAction(mPlayA); connect(mPlayA, SIGNAL(triggered()), mPlayer, SLOT(play())); QAction *pauseA = new QAction(QIcon(":/pause.png"), tr("Pause"), this); pauseA->setCheckable(true); playAG->addAction(pauseA); connect(pauseA, SIGNAL(triggered()), mPlayer, SLOT(pause())); mStopA = new QAction(QIcon(":/stop.png"), tr("Stop"), this); mStopA->setCheckable(true); playAG->addAction(mStopA); mStopA->trigger(); connect(mStopA, SIGNAL(triggered()), mPlayer, SLOT(stop())); QAction *previousA = new QAction(QIcon(":/previous.png"), tr("Previous"), this); connect(previousA, SIGNAL(triggered()), this, SLOT(previous())); QAction *nextA = new QAction(QIcon(":/next.png"), tr("Next"), this); connect(nextA, SIGNAL(triggered()), this, SLOT(next())); QAction *addToPlayListA = new QAction(QIcon(":/belly_right.png"), tr("Add to playlist"), this); connect(addToPlayListA, SIGNAL(triggered()), this, SLOT(addToPlayList())); QAction *removeFromPlayListA = new QAction(QIcon(":/belly_left.png"), tr("Remove from playlist"), this); connect(removeFromPlayListA, SIGNAL(triggered()), this, SLOT(removeFromPlayList())); QAction *clearPlayListA = new QAction(QIcon(":/delete.png"), tr("Clear Playlist"), this); connect(clearPlayListA, SIGNAL(triggered()), this, SLOT(clearPlayList())); QAction *refreshA = new QAction(QIcon(":/refresh.png"), tr("Refresh..."), this); connect(refreshA, SIGNAL(triggered()), this, SLOT(reindex())); QAction *shufflePlayistA = new QAction(QIcon(":/shuffle.png"), tr("Shuffle playlist"), this); connect(shufflePlayistA, SIGNAL(triggered()), this, SLOT(shufflePlayList())); QAction *randomPlayA = new QAction(QIcon(":/dice.png"), tr("Play random"), this); connect(randomPlayA, SIGNAL(triggered()), this, SLOT(randomPlay())); QAction *muteA = new QAction(QIcon(":/mute.png"), tr("Mute"), this); muteA->setCheckable(true); connect(muteA, SIGNAL(triggered(bool)), this, SLOT(mute(bool))); QAction *configA = Globals::instance()->action(Globals::ConfigAction); mView->addAction(addToPlayListA); mView->addAction(randomPlayA); mPlayListView->addAction(removeFromPlayListA); mPlayListView->addAction(shufflePlayistA); mPlayListView->addAction(clearPlayListA); QWidget* spacer1 = new QWidget(); spacer1->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); mToolBar->addWidget(spacer1); mToolBar->addAction(mPlayA); mToolBar->addAction(pauseA); mToolBar->addAction(mStopA); mToolBar->addSeparator(); mToolBar->addAction(previousA); mToolBar->addAction(nextA); mToolBar->addSeparator(); mToolBar->addAction(addToPlayListA); mToolBar->addAction(removeFromPlayListA); mToolBar->addAction(clearPlayListA); mToolBar->addAction(shufflePlayistA); mToolBar->addAction(randomPlayA); mToolBar->addSeparator(); mToolBar->addAction(refreshA); mToolBar->addSeparator(); mToolBar->addAction(muteA); mToolBar->addSeparator(); mToolBar->addAction(configA); QWidget* spacer2 = new QWidget(); spacer2->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); mToolBar->addWidget(spacer2); } void PlayerWidget::populateByArtist(QStandardItem *parent, const QString &filter){ QSqlDatabase db = QSqlDatabase::database("beetplayerdb"); QStandardItem *root = parent; QSqlQuery artistsQ(db); if(!filter.isEmpty()){ artistsQ.prepare("SELECT iartists_id, tartists_name FROM artists WHERE tartists_name ~ :f ORDER BY tartists_name ASC"); artistsQ.bindValue(":f", filter); }else{ artistsQ.prepare("SELECT iartists_id, tartists_name FROM artists ORDER BY tartists_name ASC"); } QSqlQuery albumQ(db); albumQ.prepare("SELECT DISTINCT(songs.ialbums_id), talbum_name, siyear FROM songs, albums WHERE songs.iartists_id = :artistid AND songs.ialbums_id = albums.ialbums_id ORDER BY siyear ASC"); QSqlQuery songQ(db); songQ.prepare("SELECT sipos, ttitle, tfullpath, igenres_id FROM songs WHERE ialbums_id = :alid AND iartists_id = :arid ORDER BY sipos ASC"); QIcon songIcon(":/song.png"); QIcon albumIcon(":/album.png"); QIcon artistIcon(":/artist.png"); //read data artistsQ.exec(); while(artistsQ.next()){ QStandardItem *curArtist = new QStandardItem; curArtist->setEditable(false); curArtist->setFont(QFont("courier")); curArtist->setText(artistsQ.value(1).toString()); curArtist->setIcon(artistIcon); curArtist->setData(Artist, TypeRole); curArtist->setData(artistsQ.value(0).toInt(), IdRole); root->appendRow(curArtist); albumQ.bindValue(":artistid", artistsQ.value(0)); albumQ.exec(); while(albumQ.next()){ QStandardItem *curAlbum = new QStandardItem; curAlbum->setEditable(false); curAlbum->setFont(QFont("courier")); QString albumText = QString(tr("%1 - %2")).arg(QString::number(albumQ.value(2).toInt())).arg(albumQ.value(1).toString()); curAlbum->setText(albumText); curAlbum->setIcon(albumIcon); curAlbum->setData(Album, TypeRole); curAlbum->setData(albumQ.value(0), IdRole); curArtist->appendRow(curAlbum); songQ.bindValue(":alid", albumQ.value(0)); songQ.bindValue(":arid", artistsQ.value(0)); songQ.exec(); while(songQ.next()){ QStandardItem *curSong = new QStandardItem; curSong->setEditable(false); curSong->setFont(QFont("courier")); QString songText = QString(tr("%1 - %2")).arg(songQ.value(0).toInt(), 3, 10, QChar('0')).arg(songQ.value(1).toString()); curSong->setText(songText); curSong->setIcon(songIcon); curSong->setData(Song, TypeRole); curSong->setData(songQ.value(0), IdRole); curSong->setData(songQ.value(2), FullPathRole); curSong->setData(songQ.value(3), GenreRole); curSong->setData(artistsQ.value(1), ArtistRole); curSong->setData(songQ.value(1), TitleRole); curSong->setData(albumQ.value(1), AlbumRole); curAlbum->appendRow(curSong); } } } } void PlayerWidget::populateByAlbum(QStandardItem *parent, const QVariant &filter, int type){ QSqlDatabase db = QSqlDatabase::database("beetplayerdb"); QIcon albumIcon(":/album.png"); QIcon songIcon(":/song.png"); QSqlQuery albumQ(db); if(type == EmptyType){ albumQ.prepare("SELECT DISTINCT(ialbums_id), talbum_name, siyear FROM albums ORDER BY talbum_name"); }else if(type == FilterType){ albumQ.prepare("SELECT DISTINCT(songs.ialbums_id), talbum_name, siyear FROM songs, albums WHERE talbum_name ~ :album AND songs.ialbums_id = albums.ialbums_id ORDER BY siyear ASC"); albumQ.bindValue(":album", filter); } albumQ.exec(); while(albumQ.next()){ QHash artistcount; QStandardItem *curAlbum = new QStandardItem; curAlbum->setEditable(false); curAlbum->setFont(QFont("courier")); curAlbum->setIcon(albumIcon); curAlbum->setData(Album, TypeRole); curAlbum->setData(albumQ.value(0), IdRole); parent->appendRow(curAlbum); QSqlQuery songQ = QSqlQuery(db); songQ.prepare("SELECT sipos, ttitle, tfullpath, igenres_id, artists.tartists_name, albums.talbum_name FROM songs, artists, albums WHERE albums.ialbums_id = :id AND songs.iartists_id = artists.iartists_id and songs.ialbums_id = albums.ialbums_id ORDER BY sipos"); songQ.bindValue(":id", albumQ.value(0)); songQ.exec(); while(songQ.next()){ QStandardItem *curSong = new QStandardItem; curSong->setEditable(false); curSong->setFont(QFont("courier")); QString songText = QString(tr("%1 - %2 - %3")).arg(songQ.value(0).toInt(), 3, 10, QChar('0')).arg(songQ.value(1).toString()).arg(songQ.value(4).toString()); curSong->setText(songText); curSong->setIcon(songIcon); curSong->setData(Song, TypeRole); curSong->setData(songQ.value(0), IdRole); curSong->setData(songQ.value(2), FullPathRole); curSong->setData(songQ.value(3), GenreRole); curSong->setData(songQ.value(4), ArtistRole); ++artistcount[songQ.value(4).toString()]; curSong->setData(songQ.value(1), TitleRole); curSong->setData(songQ.value(5), AlbumRole); curAlbum->appendRow(curSong); } QString albumText; if(artistcount.keys().count() > 1){ albumText = QString(tr("%1 - VA - (%2)")).arg(albumQ.value(1).toString()).arg(QString::number(albumQ.value(2).toInt())); }else{ albumText = QString(tr("%1 - %2 - (%3)")).arg(albumQ.value(1).toString()).arg(artistcount.keys().first()). arg(QString::number(albumQ.value(2).toInt())); } curAlbum->setText(albumText); } } void PlayerWidget::populateBySong(QStandardItem *parent, const QVariant &filter, int type){ QSqlDatabase db = QSqlDatabase::database("beetplayerdb"); QStandardItem *root = parent; QIcon songIcon(":/song.png"); QSqlQuery songQ = QSqlQuery(db); if(type == EmptyType){ songQ.prepare("SELECT sipos, ttitle, tfullpath, igenres_id, artists.tartists_name, albums.talbum_name FROM songs, artists, albums WHERE songs.iartists_id = artists.iartists_id and songs.ialbums_id = albums.ialbums_id ORDER BY ttitle ASC"); }else if(type == FilterType){ songQ.prepare("SELECT sipos, ttitle, tfullpath, igenres_id, artists.tartists_name, albums.talbum_name FROM songs, artists, albums WHERE ttitle ~ :f AND songs.iartists_id = artists.iartists_id and songs.ialbums_id = albums.ialbums_id ORDER BY ttitle ASC"); songQ.bindValue(":f", filter); }else if(type == IdType){ songQ.prepare("SELECT sipos, ttitle, tfullpath, igenres_id, artists.tartists_name, albums.talbum_name FROM songs, artists, albums WHERE albums.ialbums_id = :id AND songs.iartists_id = artists.iartists_id and songs.ialbums_id = albums.ialbums_id ORDER BY sipos"); songQ.bindValue(":id", filter); } songQ.exec(); while(songQ.next()){ QStandardItem *curSong = new QStandardItem; curSong->setEditable(false); curSong->setFont(QFont("courier")); QString songText; if(type == IdType){ songText = QString(tr("%1 - %2")).arg(songQ.value(0).toInt(), 3, 10, QChar('0')).arg(songQ.value(1).toString()); }else{ songText = QString(tr("%1 (%2)")).arg(songQ.value(1).toString()).arg(songQ.value(4).toString()); } curSong->setText(songText); curSong->setIcon(songIcon); curSong->setData(Song, TypeRole); curSong->setData(songQ.value(0), IdRole); curSong->setData(songQ.value(2), FullPathRole); curSong->setData(songQ.value(3), GenreRole); curSong->setData(songQ.value(4), ArtistRole); curSong->setData(songQ.value(1), TitleRole); curSong->setData(songQ.value(5), AlbumRole); root->appendRow(curSong); } } void PlayerWidget::populateByGenre(QStandardItem *parent, const QString &filter){ QSqlDatabase db = QSqlDatabase::database("beetplayerdb"); QStandardItem *root = parent; QIcon songIcon(":/song.png"); QIcon genreIcon(":/genre.png"); QSqlQuery genreQ(db); if(filter.isEmpty()){ genreQ.prepare("SELECT igenres_id, tgenres_name FROM genres ORDER BY tgenres_name"); }else{ genreQ.prepare("SELECT igenres_id, tgenres_name FROM genres WHERE tgenres_name ~ :f"); genreQ.bindValue(":f", filter); } genreQ.exec(); while(genreQ.next()){ QStandardItem *curGenre = new QStandardItem; curGenre->setEditable(false); curGenre->setFont(QFont("courier")); curGenre->setText(genreQ.value(1).toString()); curGenre->setIcon(genreIcon); curGenre->setData(Genre, TypeRole); curGenre->setData(genreQ.value(0), IdRole); root->appendRow(curGenre); QSqlQuery songQ = QSqlQuery(db); songQ.prepare("SELECT sipos, ttitle, tfullpath, igenres_id, artists.tartists_name, albums.talbum_name FROM songs, artists, albums WHERE igenres_id = :id AND songs.iartists_id = artists.iartists_id AND songs.ialbums_id = albums.ialbums_id ORDER BY ttitle ASC"); songQ.bindValue(":id", genreQ.value(0)); songQ.exec(); while(songQ.next()){ QStandardItem *curSong = new QStandardItem; curSong->setEditable(false); curSong->setFont(QFont("courier")); QString songText = QString(tr("%1 (%2)")).arg(songQ.value(1).toString()).arg(songQ.value(4).toString()); curSong->setText(songText); curSong->setIcon(songIcon); curSong->setData(Song, TypeRole); curSong->setData(songQ.value(0), IdRole); curSong->setData(songQ.value(2), FullPathRole); curSong->setData(songQ.value(3), GenreRole); curSong->setData(songQ.value(4), ArtistRole); curSong->setData(songQ.value(1), TitleRole); curSong->setData(songQ.value(5), AlbumRole); curGenre->appendRow(curSong); } } } void PlayerWidget::recurse(const QModelIndex &parent){ for(int i = 0; i < currentModel->rowCount(parent); ++i){ QModelIndex cur = currentModel->index(i, 0, parent); int type = cur.data(TypeRole).toInt(); if(type == Song){ addSong(cur); }else{ recurse(cur); } } } void PlayerWidget::addSong(const QModelIndex &idx){ QStandardItem *root = mPlayListModel->invisibleRootItem(); QString title = idx.data(TitleRole).toString(); QString artist = idx.data(ArtistRole).toString(); QString album = idx.data(AlbumRole).toString(); QString display = QString(tr("%1 - %2 - %3")).arg(artist).arg(title).arg(album); QStandardItem *item = new QStandardItem; item->setEditable(false); item->setFont(QFont("courier")); item->setText(display); item->setIcon(QIcon(":/song.png")); item->setData(idx.data(FullPathRole), FullPathRole); root->appendRow(item); } void PlayerWidget::doPopulateByArtist(){ qApp->setOverrideCursor(Qt::BusyCursor); mView->setModel(mViewModel); mViewModel->clear(); mViewModel->setHorizontalHeaderLabels(QStringList() << tr("Artist name")); QStandardItem *root = mViewModel->invisibleRootItem(); populateByArtist(root, QString()); qApp->restoreOverrideCursor(); } void PlayerWidget::doPopulateByAlbum(){ qApp->setOverrideCursor(Qt::BusyCursor); mView->setModel(mViewModel); mViewModel->clear(); mViewModel->setHorizontalHeaderLabels(QStringList() << tr("Album name")); QStandardItem *root = mViewModel->invisibleRootItem(); populateByAlbum(root, QString(), EmptyType); qApp->restoreOverrideCursor(); } void PlayerWidget::doPopulateByGenre(){ qApp->setOverrideCursor(Qt::BusyCursor); mView->setModel(mViewModel); mViewModel->clear(); mViewModel->setHorizontalHeaderLabels(QStringList() << tr("Genre name")); QStandardItem *root = mViewModel->invisibleRootItem(); populateByGenre(root, QString()); qApp->restoreOverrideCursor(); } void PlayerWidget::doPopulateBySong(){ qApp->setOverrideCursor(Qt::BusyCursor); mView->setModel(mViewModel); mViewModel->clear(); mViewModel->setHorizontalHeaderLabels(QStringList() << tr("Genre name")); QStandardItem *root = mViewModel->invisibleRootItem(); populateBySong(root, QString(), EmptyType); qApp->restoreOverrideCursor(); } void PlayerWidget::doFilter(){ QString filter = mSearch->text(); if(filter.isEmpty()){ mView->setModel(mViewModel); return; } qApp->setOverrideCursor(Qt::BusyCursor); mSearchModel->clear(); mSearchModel->setHorizontalHeaderLabels(QStringList() << tr("Name")); mView->setModel(mSearchModel); currentModel = mSearchModel; QStandardItem *root = mSearchModel->invisibleRootItem(); populateByArtist(root, filter); populateByGenre(root, filter); populateBySong(root, filter, FilterType); qApp->restoreOverrideCursor(); } void PlayerWidget::clearFilter(){ mSearch->clear(); mView->setModel(mViewModel); currentModel = mViewModel; } void PlayerWidget::reindex(){ IndexerDialog dlg(this); dlg.exec(); } void PlayerWidget::addToPlayList(){ QModelIndexList sel = mView->selectionModel()->selectedRows(); if(sel.isEmpty()){ return; } foreach(QModelIndex i, sel){ int type = i.data(TypeRole).toInt(); if(type == Song){ addSong(i); }else{ recurse(i); } } } void PlayerWidget::removeFromPlayList(){ QModelIndexList sel = mPlayListView->selectionModel()->selectedRows(); QList persistent; foreach(QModelIndex i, sel){ persistent << QPersistentModelIndex(i); } foreach(QPersistentModelIndex i, persistent){ mPlayListModel->removeRow(i.row()); } } void PlayerWidget::clearPlayList(){ mPlayListModel->clear(); mPlayListModel->setHorizontalHeaderLabels(QStringList() << "Title"); } void PlayerWidget::shufflePlayList(){ QVector items; for(int i = 0; i < mPlayListModel->rowCount(); ++i){ QStandardItem *cur = mPlayListModel->item(i, 0)->clone(); items << cur; } std::random_shuffle(items.begin(), items.end()); mPlayListModel->clear(); mPlayListModel->setHorizontalHeaderLabels(QStringList() << "Title"); QStandardItem *root = mPlayListModel->invisibleRootItem(); foreach(QStandardItem *i, items){ root->appendRow(i); } } void PlayerWidget::randomPlay(){ mPlayListModel->clear(); mPlayListModel->setHorizontalHeaderLabels(QStringList() << "Title"); QStandardItem *root = mPlayListModel->invisibleRootItem(); QIcon songIcon(":/song.png"); QSqlDatabase db = QSqlDatabase::database("beetplayerdb"); QSqlQuery randomQ(db); randomQ.prepare("SELECT sipos, ttitle, tfullpath, igenres_id, artists.tartists_name, albums.talbum_name FROM songs, artists, albums WHERE songs.iartists_id = artists.iartists_id AND songs.ialbums_id = albums.ialbums_id ORDER BY random() LIMIT 1000"); randomQ.exec(); while(randomQ.next()){ QString display = QString(tr("%1 - %2 - %3")).arg(randomQ.value(4).toString()).arg(randomQ.value(1).toString()).arg(randomQ.value(5).toString()); QStandardItem *item = new QStandardItem; item->setEditable(false); item->setFont(QFont("courier")); item->setText(display); item->setIcon(songIcon); item->setData(randomQ.value(2), FullPathRole); root->appendRow(item); } } void PlayerWidget::playCurrent(const QModelIndex &index){ mStopA->trigger(); QString fullPath = index.data(FullPathRole).toString(); play(fullPath); } void PlayerWidget::play(const QString &fullPath){ mPlayer->setMedia(QUrl::fromLocalFile(fullPath)); mCurrentTE->clear(); TagLib::FileRef file(QString(fullPath).toUtf8()); QString artist = QString::fromStdWString(file.tag()->artist().toWString()); QString album = QString::fromStdWString(file.tag()->album().toWString()); QString title = QString::fromStdWString(file.tag()->title().toWString()); QString genre = QString::fromStdWString(file.tag()->genre().toWString()); quint16 track = file.tag()->track(); quint16 year = file.tag()->year(); mNowPlayingL->setText(title); mCurrentTE->append(QString("%1 %2").arg(tr("Artist:"), -20).arg(artist)); mCurrentTE->append(QString("%1 %2").arg(tr("Album:"), -20).arg(album)); mCurrentTE->append(QString("%1 %2").arg(tr("Title:"), -20).arg(title)); mCurrentTE->append(QString("%1 %2").arg(tr("Genre:"), -20).arg(genre)); mCurrentTE->append(QString("%1 %2").arg(tr("Track:"), -20).arg(track, 3, 10, QChar('0'))); mCurrentTE->append(QString("%1 %2").arg(tr("Year:"), -20).arg(year, 4, 10)); mPlayA->trigger(); } void PlayerWidget::volumeChanged(int volume){ QString s = QString("%1 %").arg(volume, 3, 10, QChar('0')); mVolumePos->setText(s); } void PlayerWidget::mute(bool triggered){ mPlayer->setMuted(triggered); } void PlayerWidget::next(){ advance(1); } void PlayerWidget::previous(){ advance(-1); } void PlayerWidget::advance(int numSongs){ mStopA->trigger(); QModelIndexList sel = mPlayListView->selectionModel()->selectedRows(); if(sel.isEmpty()){ QStandardItem *root = mPlayListModel->invisibleRootItem(); if(root->rowCount() > 0){ QModelIndex first = mPlayListModel->index(0, 0); mPlayListView->selectionModel()->setCurrentIndex(first, QItemSelectionModel::ClearAndSelect); QString fp = first.data(FullPathRole).toString(); play(fp); return; } return; } QModelIndex cur = sel.first(); QModelIndex nextIdx = mPlayListModel->index(cur.row() + numSongs, 0); if(nextIdx.isValid()){ mPlayListView->selectionModel()->setCurrentIndex(nextIdx, QItemSelectionModel::ClearAndSelect); cur = nextIdx; QString fp = cur.data(FullPathRole).toString(); play(fp); } } void PlayerWidget::slide(int value){ qint64 newValue = value * 1000; mPlayer->setPosition(newValue); } void PlayerWidget::setPosition(qint64 pos){ int curPos = pos / 1000; mSongSlider->setValue(curPos); int minutes = curPos / 60; int seconds = curPos % 60; QString posString = QString("%1:%2").arg(minutes, 2, 10, QChar('0')).arg(seconds, 2, 10, QChar('0')); mPos->setText(posString); } void PlayerWidget::setDuration(qint64 dur){ mDurSecs = dur / 1000; mSongSlider->setMinimum(0); mSongSlider->setMaximum(mDurSecs); int minutes = mDurSecs / 60; int seconds = mDurSecs % 60; mCurrentTE->append(QString("%1 %2:%3").arg(tr("Length:"), -20).arg(minutes, 2, 10, QChar('0')).arg(seconds, 2, 10, QChar('0'))); } void PlayerWidget::continuePlaying(QMediaPlayer::State state){ if(mPlayA->isChecked() && state == QMediaPlayer::StoppedState){ next(); } }