Shuffle and repeat buttons now work.

Fixes issue #20
This commit is contained in:
David Sansome 2010-03-08 17:55:40 +00:00
parent d15fffc802
commit 85d5e398da
4 changed files with 150 additions and 18 deletions

View File

@ -689,7 +689,8 @@ void MainWindow::SetCurrentPlaylist(PlaylistView* pCurrent){
current_playlist_view_ = pCurrent ;
current_playlist_ = qobject_cast< Playlist* >( pCurrent->model() );
player_->SetCurrentPlaylist(current_playlist_);
current_playlist_->set_shuffle_repeat_widget(shuffle_repeat_widget_);
// connects !! :)
@ -709,6 +710,9 @@ void MainWindow::SetCurrentPlaylist(PlaylistView* pCurrent){
connect(player_, SIGNAL(Stopped()), current_playlist_view_, SLOT(StopGlowing()));
connect(radio_model_, SIGNAL(StreamMetadataFound(QUrl,Song)), current_playlist_, SLOT(SetStreamMetadata(QUrl,Song)));
connect(shuffle_repeat_widget_, SIGNAL(ShuffleModeChanged(ShuffleRepeatWidget::ShuffleMode)),
current_playlist_, SLOT(ShuffleModeChanged(ShuffleRepeatWidget::ShuffleMode)));
}
void MainWindow::CurrentTabChanged(int index ){

View File

@ -14,6 +14,7 @@
#include <QDirIterator>
#include <boost/bind.hpp>
#include <algorithm>
#include <lastfm/ScrobblePoint>
@ -23,11 +24,14 @@ const char* Playlist::kSettingsGroup = "Playlist";
Playlist::Playlist(QObject *parent) :
QAbstractListModel(parent),
current_is_paused_(false),
current_virtual_index_(-1),
is_shuffled_(false),
scrobble_point_(-1),
has_scrobbled_(false),
ignore_sorting_(false),
title_(""),
index_(-1)
index_(-1),
shuffle_repeat_widget_(NULL)
{
}
@ -111,14 +115,68 @@ int Playlist::current_index() const {
return current_item_.isValid() ? current_item_.row() : -1;
}
void Playlist::ShuffleModeChanged(ShuffleRepeatWidget::ShuffleMode mode) {
is_shuffled_ = (mode != ShuffleRepeatWidget::Shuffle_Off);
ReshuffleIndices();
}
int Playlist::NextVirtualIndex(int i) const {
ShuffleRepeatWidget::RepeatMode repeat_mode = shuffle_repeat_widget_->repeat_mode();
ShuffleRepeatWidget::ShuffleMode shuffle_mode = shuffle_repeat_widget_->shuffle_mode();
bool album_only = repeat_mode == ShuffleRepeatWidget::Repeat_Album ||
shuffle_mode == ShuffleRepeatWidget::Shuffle_Album;
// This one's easy - if we have to repeat the current track then just return i
if (repeat_mode == ShuffleRepeatWidget::Repeat_Track)
return i;
// If we're not bothered about whether a song is on the same album then
// return the next virtual index, whatever it is.
if (!album_only)
return i+1;
// We need to advance i until we get something else on the same album
Song last_song = current_item_metadata();
for (int j=i+1 ; j<virtual_items_.count(); ++j) {
Song this_song = item_at(virtual_items_[j])->Metadata();
if ((last_song.is_compilation() && this_song.is_compilation() ||
last_song.artist() == this_song.artist()) &&
last_song.album() == this_song.album()) {
return j; // Found one
}
}
// Couldn't find one - return past the end of the list
return virtual_items_.count();
}
int Playlist::next_index() const {
int i = current_index() + 1;
if (i >= items_.count())
return -1;
// Did we want to stop after this track?
if (stop_after_.isValid() && current_index() == stop_after_.row())
return -1;
return i;
int next_virtual_index = NextVirtualIndex(current_virtual_index_);
if (next_virtual_index >= virtual_items_.count()) {
// We've gone off the end of the playlist.
switch (shuffle_repeat_widget_->repeat_mode()) {
case ShuffleRepeatWidget::Repeat_Off:
return -1;
case ShuffleRepeatWidget::Repeat_Track:
next_virtual_index = current_virtual_index_;
break;
default:
next_virtual_index = NextVirtualIndex(-1);
break;
}
}
// Still off the end? Then just give up
if (next_virtual_index >= virtual_items_.count())
return -1;
return virtual_items_[next_virtual_index];
}
int Playlist::previous_index() const {
@ -142,6 +200,23 @@ void Playlist::set_current_index(int i) {
emit CurrentSongChanged(current_item_metadata());
}
// Update the virtual index
if (i == -1)
current_virtual_index_ = -1;
else if (is_shuffled_ && current_virtual_index_ == -1) {
// This is the first thing we're playing so we want to make sure the array
// is shuffled
ReshuffleIndices();
// Bring the one we've been asked to play to the start of the list
virtual_items_.takeAt(virtual_items_.indexOf(i));
virtual_items_.prepend(i);
current_virtual_index_ = 0;
} else if (is_shuffled_)
current_virtual_index_ = virtual_items_.indexOf(i);
else
current_virtual_index_ = i;
UpdateScrobblePoint();
}
@ -275,14 +350,14 @@ QModelIndex Playlist::InsertItems(const QList<PlaylistItem*>& items, int after)
const int end = start + items.count() - 1;
beginInsertRows(QModelIndex(), start, end);
for (int i=start ; i<=end ; ++i) {
items_.insert(i, items[i - start]);
virtual_items_ << virtual_items_.count();
}
endInsertRows();
// Save();
ReshuffleIndices();
return index(start, 0);
}
@ -428,6 +503,7 @@ void Playlist::SaveR() const {
void Playlist::RestoreR() {
qDeleteAll(items_);
items_.clear();
virtual_items_.clear();
QSettings s;
s.beginGroup(kSettingsGroup);
@ -444,6 +520,7 @@ void Playlist::RestoreR() {
item->Restore(s);
items_ << item;
virtual_items_ << virtual_items_.count();
}
s.endArray();
s.endGroup();
@ -460,6 +537,20 @@ bool Playlist::removeRows(int row, int count, const QModelIndex& parent) {
endRemoveRows();
QList<int>::iterator it = virtual_items_.begin();
int i = 0;
while (it != virtual_items_.end()) {
if (*it >= items_.count()) {
if (i >= current_virtual_index_)
current_virtual_index_ --;
it = virtual_items_.erase(it);
} else {
++it;
}
++i;
}
// Save();
return true;
}
@ -582,3 +673,22 @@ void Playlist::Shuffle() {
// Save();
}
void Playlist::ReshuffleIndices() {
if (!is_shuffled_) {
std::sort(virtual_items_.begin(), virtual_items_.end());
if (current_index() != -1)
current_virtual_index_ = virtual_items_.indexOf(current_index());
} else {
QList<int>::iterator begin = virtual_items_.begin();
if (current_virtual_index_ != -1)
std::advance(begin, current_virtual_index_ + 1);
std::random_shuffle(begin, virtual_items_.end());
}
}
void Playlist::set_shuffle_repeat_widget(ShuffleRepeatWidget* w) {
shuffle_repeat_widget_ = w;
ShuffleModeChanged(w->shuffle_mode());
}

View File

@ -7,6 +7,7 @@
#include "playlistitem.h"
#include "song.h"
#include "radioitem.h"
#include "shufflerepeatwidget.h"
class RadioService;
@ -72,7 +73,10 @@ class Playlist : public QAbstractListModel {
void SetTitle(const QString& title) { title_ = title; }
void SetPlaylistIndex( int ipos ) { index_ = ipos ; }
int GetPlaylistIndex() const { return index_ ; }
int GetPlaylistIndex() const { return index_ ; }
void set_shuffle_repeat_widget(ShuffleRepeatWidget* w);
ShuffleRepeatWidget* shuffle_repeat_widget() const { return shuffle_repeat_widget_; }
// Scrobbling
int scrobble_point() const { return scrobble_point_; }
@ -114,12 +118,16 @@ class Playlist : public QAbstractListModel {
void Clear();
void Shuffle();
void ShuffleModeChanged(ShuffleRepeatWidget::ShuffleMode mode);
signals:
void CurrentSongChanged(const Song& metadata);
private:
void SetCurrentIsPaused(bool paused);
void UpdateScrobblePoint();
void ReshuffleIndices();
int NextVirtualIndex(int i) const;
// Persistence
void SaveR() const;
@ -127,10 +135,14 @@ class Playlist : public QAbstractListModel {
private:
QList<PlaylistItem*> items_;
QList<int> virtual_items_; // Contains the indices into items_ in the order
// that they will be played.
bool is_shuffled_;
QPersistentModelIndex current_item_;
QPersistentModelIndex stop_after_;
bool current_is_paused_;
int current_virtual_index_;
int scrobble_point_;
bool has_scrobbled_;
@ -138,7 +150,9 @@ class Playlist : public QAbstractListModel {
// Hack to stop QTreeView::setModel sorting the playlist
bool ignore_sorting_;
QString title_;
int index_ ;
int index_ ;
ShuffleRepeatWidget* shuffle_repeat_widget_;
};
#endif // PLAYLIST_H

View File

@ -3,10 +3,10 @@
#include <QWidget>
class QMenu;
#include "ui_shufflerepeatwidget.h"
class QMenu;
class ShuffleRepeatWidget : public QWidget {
Q_OBJECT
@ -27,21 +27,25 @@ class ShuffleRepeatWidget : public QWidget {
static const char* kSettingsGroup;
void Load();
void Save();
RepeatMode repeat_mode() const { return repeat_mode_; }
ShuffleMode shuffle_mode() const { return shuffle_mode_; }
public slots:
void SetRepeatMode(RepeatMode mode);
void SetShuffleMode(ShuffleMode mode);
void SetRepeatMode(ShuffleRepeatWidget::RepeatMode mode);
void SetShuffleMode(ShuffleRepeatWidget::ShuffleMode mode);
signals:
void RepeatModeChanged(RepeatMode mode);
void ShuffleModeChanged(ShuffleMode mode);
void RepeatModeChanged(ShuffleRepeatWidget::RepeatMode mode);
void ShuffleModeChanged(ShuffleRepeatWidget::ShuffleMode mode);
private slots:
void RepeatActionTriggered(QAction*);
void ShuffleActionTriggered(QAction*);
private:
void Load();
void Save();
private:
Ui::ShuffleRepeatWidget ui_;