Refer to playlists by ID rather than index in the tabbar, so they can be moved around

This commit is contained in:
David Sansome 2010-05-21 10:29:17 +00:00
parent a274f8cbfc
commit 119c6fbd6e
7 changed files with 150 additions and 68 deletions

View File

@ -233,7 +233,7 @@ void Player::PlayPause() {
case Engine::Empty:
case Engine::Idle: {
playlists_->SetActivePlaylist(playlists_->current_index());
playlists_->SetActivePlaylist(playlists_->current_id());
if (playlists_->active()->rowCount() == 0)
break;

View File

@ -78,7 +78,7 @@ void PlaylistContainer::ClearFilter() {
void PlaylistContainer::SetManager(PlaylistManager *manager) {
manager_ = manager;
connect(ui_->tab_bar, SIGNAL(currentChanged(int)),
connect(ui_->tab_bar, SIGNAL(CurrentIdChanged(int)),
manager, SLOT(SetCurrentPlaylist(int)));
connect(ui_->tab_bar, SIGNAL(Rename(int,QString)),
manager, SLOT(Rename(int,QString)));
@ -103,8 +103,8 @@ void PlaylistContainer::SetViewModel(Playlist* playlist) {
playlist->IgnoreSorting(false);
// Ensure that tab is current
if (ui_->tab_bar->currentIndex() != manager_->current_index())
ui_->tab_bar->setCurrentIndex(manager_->current_index());
if (ui_->tab_bar->current_id() != manager_->current_id())
ui_->tab_bar->set_current_id(manager_->current_id());
// Sort out the undo/redo actions
delete undo_;
@ -142,25 +142,26 @@ void PlaylistContainer::UpdateActiveIcon(const QIcon& icon) {
// Set our icon
if (!icon.isNull())
ui_->tab_bar->setTabIcon(manager_->active_index(), icon);
ui_->tab_bar->set_icon_by_id(manager_->active_id(), icon);
}
void PlaylistContainer::PlaylistAdded(int index, const QString &name) {
ui_->tab_bar->insertTab(index, name);
void PlaylistContainer::PlaylistAdded(int id, const QString &name) {
int index = ui_->tab_bar->count();
ui_->tab_bar->InsertTab(id, index, name);
// Are we startup up, should we select this tab?
if (starting_up_ && settings_.value("current_playlist", 0).toInt() == index) {
if (starting_up_ && settings_.value("current_playlist", 0).toInt() == id) {
starting_up_ = false;
ui_->tab_bar->setCurrentIndex(index);
ui_->tab_bar->set_current_id(id);
}
}
void PlaylistContainer::PlaylistRemoved(int index) {
ui_->tab_bar->removeTab(index);
void PlaylistContainer::PlaylistRemoved(int id) {
ui_->tab_bar->RemoveTab(id);
}
void PlaylistContainer::PlaylistRenamed(int index, const QString &new_name) {
ui_->tab_bar->setTabText(index, new_name);
void PlaylistContainer::PlaylistRenamed(int id, const QString &new_name) {
ui_->tab_bar->set_text_by_id(id, new_name);
}
void PlaylistContainer::NewPlaylist() {
@ -185,5 +186,5 @@ void PlaylistContainer::Save() {
if (starting_up_)
return;
settings_.setValue("current_playlist", ui_->tab_bar->currentIndex());
settings_.setValue("current_playlist", ui_->tab_bar->current_id());
}

View File

@ -28,6 +28,12 @@ PlaylistManager::PlaylistManager(QObject *parent)
{
}
PlaylistManager::~PlaylistManager() {
foreach (const Data& data, playlists_.values()) {
delete data.p;
}
}
void PlaylistManager::Init(LibraryBackend* library_backend,
PlaylistBackend* playlist_backend,
PlaylistSequence* sequence) {
@ -52,16 +58,15 @@ Playlist* PlaylistManager::AddPlaylist(int id, const QString& name) {
connect(ret, SIGNAL(PlaylistChanged()), SIGNAL(PlaylistChanged()));
connect(ret, SIGNAL(EditingFinished(QModelIndex)), SIGNAL(EditingFinished(QModelIndex)));
playlists_ << Data(ret, name);
playlists_[id] = Data(ret, name);
int index = playlists_.count() - 1;
emit PlaylistAdded(index, name);
emit PlaylistAdded(id, name);
if (current_ == -1) {
SetCurrentPlaylist(index);
SetCurrentPlaylist(id);
}
if (active_ == -1) {
SetActivePlaylist(index);
SetActivePlaylist(id);
}
return ret;
@ -74,60 +79,64 @@ void PlaylistManager::New(const QString& name) {
qFatal("Couldn't create playlist");
AddPlaylist(id, name);
SetCurrentPlaylist(playlists_.count() - 1);
SetCurrentPlaylist(id);
}
void PlaylistManager::Load(const QString& filename) {
}
void PlaylistManager::Save(int index, const QString& filename) {
Q_ASSERT(index >= 0 && index < playlists_.count());
void PlaylistManager::Save(int id, const QString& filename) {
Q_ASSERT(playlists_.contains(id));
}
void PlaylistManager::Rename(int index, const QString& new_name) {
Q_ASSERT(index >= 0 && index < playlists_.count());
void PlaylistManager::Rename(int id, const QString& new_name) {
Q_ASSERT(playlists_.contains(id));
playlist_backend_->RenamePlaylist(playlist(index)->id(), new_name);
playlists_[index].name = new_name;
playlist_backend_->RenamePlaylist(id, new_name);
playlists_[id].name = new_name;
emit PlaylistRenamed(index, new_name);
emit PlaylistRenamed(id, new_name);
}
void PlaylistManager::Remove(int index) {
Q_ASSERT(index >= 0 && index < playlists_.count());
void PlaylistManager::Remove(int id) {
Q_ASSERT(playlists_.contains(id));
// Won't allow removing the last playlist
if (playlists_.count() <= 1)
return;
playlist_backend_->RemovePlaylist(playlist(index)->id());
playlist_backend_->RemovePlaylist(id);
if (index == active_)
SetActivePlaylist(qMax(0, index-1));
if (index == current_)
SetCurrentPlaylist(qMax(0, index-1));
playlists_.takeAt(index);
int next_id = playlists_.constBegin()->p->id();
emit PlaylistRemoved(index);
if (id == active_)
SetActivePlaylist(next_id);
if (id == current_)
SetCurrentPlaylist(next_id);
Data data = playlists_.take(id);
delete data.p;
emit PlaylistRemoved(id);
}
void PlaylistManager::SetCurrentPlaylist(int index) {
Q_ASSERT(index >= 0 && index < playlists_.count());
current_ = index;
void PlaylistManager::SetCurrentPlaylist(int id) {
Q_ASSERT(playlists_.contains(id));
current_ = id;
emit CurrentChanged(current());
}
void PlaylistManager::SetActivePlaylist(int index) {
Q_ASSERT(index >= 0 && index < playlists_.count());
void PlaylistManager::SetActivePlaylist(int id) {
Q_ASSERT(playlists_.contains(id));
// Kinda a hack: unset the current item from the old active playlist before
// setting the new one
if (active_ != -1)
active()->set_current_index(-1);
active_ = index;
emit ActiveChanged(current());
active_ = id;
emit ActiveChanged(active());
}
void PlaylistManager::ClearCurrent() {

View File

@ -18,6 +18,7 @@
#define PLAYLISTMANAGER_H
#include <QObject>
#include <QMap>
class LibraryBackend;
class Playlist;
@ -33,13 +34,14 @@ class PlaylistManager : public QObject {
public:
PlaylistManager(QObject *parent = 0);
~PlaylistManager();
int current_index() const { return current_; }
int active_index() const { return active_; }
int current_id() const { return current_; }
int active_id() const { return active_; }
Playlist* playlist(int index) const { return playlists_[index].p; }
Playlist* current() const { return playlist(current_index()); }
Playlist* active() const { return playlist(active_index()); }
Playlist* playlist(int id) const { return playlists_[id].p; }
Playlist* current() const { return playlist(current_id()); }
Playlist* active() const { return playlist(active_id()); }
QString name(int index) const { return playlists_[index].name; }
@ -53,12 +55,13 @@ public:
public slots:
void New(const QString& name);
void Load(const QString& filename);
void Save(int index, const QString& filename);
void Rename(int index, const QString& new_name);
void Remove(int index);
void Save(int id, const QString& filename);
void Rename(int id, const QString& new_name);
void Remove(int id);
void SetCurrentPlaylist(int index);
void SetActivePlaylist(int index);
void SetCurrentPlaylist(int id);
void SetActivePlaylist(int id);
void SetActiveToCurrent() { SetActivePlaylist(current_id()); }
// Convenience slots that defer to either current() or active()
void ClearCurrent();
@ -69,9 +72,9 @@ public slots:
void SetActiveStreamMetadata(const QUrl& url, const Song& song);
signals:
void PlaylistAdded(int index, const QString& name);
void PlaylistRemoved(int index);
void PlaylistRenamed(int index, const QString& new_name);
void PlaylistAdded(int id, const QString& name);
void PlaylistRemoved(int id);
void PlaylistRenamed(int id, const QString& new_name);
void CurrentChanged(Playlist* new_playlist);
void ActiveChanged(Playlist* new_playlist);
@ -85,7 +88,7 @@ private:
private:
struct Data {
Data(Playlist* _p, const QString& _name) : p(_p), name(_name) {}
Data(Playlist* _p = NULL, const QString& _name = QString()) : p(_p), name(_name) {}
Playlist* p;
QString name;
};
@ -94,7 +97,9 @@ private:
LibraryBackend* library_backend_;
PlaylistSequence* sequence_;
QList<Data> playlists_;
// key = id
QMap<int, Data> playlists_;
int current_;
int active_;
};

View File

@ -24,11 +24,14 @@
PlaylistTabBar::PlaylistTabBar(QWidget *parent)
: QTabBar(parent),
menu_(new QMenu(this)),
menu_index_(-1)
menu_index_(-1),
suppress_current_changed_(false)
{
rename_ = menu_->addAction(IconLoader::Load("edit-rename"), tr("Rename playlist"), this, SLOT(Rename()));
remove_ = menu_->addAction(IconLoader::Load("list-remove"), tr("Remove playlist"), this, SLOT(Remove()));
menu_->addSeparator();
connect(this, SIGNAL(currentChanged(int)), this, SLOT(CurrentIndexChanged(int)));
}
void PlaylistTabBar::SetActions(
@ -67,3 +70,50 @@ void PlaylistTabBar::Remove() {
emit Remove(menu_index_);
}
int PlaylistTabBar::current_id() const {
if (currentIndex() == -1)
return -1;
return tabData(currentIndex()).toInt();
}
int PlaylistTabBar::index_of(int id) const {
for (int i=0 ; i<count() ; ++i) {
if (tabData(i).toInt() == id) {
return i;
}
}
return -1;
}
void PlaylistTabBar::set_current_id(int id) {
setCurrentIndex(index_of(id));
}
void PlaylistTabBar::set_icon_by_id(int id, const QIcon &icon) {
setTabIcon(index_of(id), icon);
}
void PlaylistTabBar::RemoveTab(int id) {
removeTab(index_of(id));
}
void PlaylistTabBar::set_text_by_id(int id, const QString &text) {
setTabText(index_of(id), text);
}
void PlaylistTabBar::CurrentIndexChanged(int index) {
if (!suppress_current_changed_)
emit CurrentIdChanged(tabData(index).toInt());
}
void PlaylistTabBar::InsertTab(int id, int index, const QString& text) {
suppress_current_changed_ = true;
insertTab(index, text);
setTabData(index, id);
suppress_current_changed_ = false;
if (currentIndex() == index)
emit CurrentIdChanged(id);
}

View File

@ -30,11 +30,26 @@ public:
void SetActions(QAction* new_playlist, QAction* save_playlist,
QAction* load_playlist);
// We use IDs to refer to tabs so the tabs can be moved around (and their
// indexes change).
int index_of(int id) const;
int current_id() const;
// Utility functions that use IDs rather than indexes
void set_current_id(int id);
void set_icon_by_id(int id, const QIcon& icon);
void set_text_by_id(int id, const QString& text);
void RemoveTab(int id);
void InsertTab(int id, int index, const QString& text);
signals:
void Rename(int index, const QString& name);
void Remove(int index);
void CurrentIdChanged(int id);
void Rename(int id, const QString& name);
void Remove(int id);
private slots:
void CurrentIndexChanged(int index);
void Rename();
void Remove();
@ -46,6 +61,8 @@ private:
int menu_index_;
QAction* rename_;
QAction* remove_;
bool suppress_current_changed_;
};
#endif // PLAYLISTTABBAR_H

View File

@ -479,7 +479,7 @@ void MainWindow::AddFilesToPlaylist(bool clear_first, const QList<QUrl>& urls) {
QModelIndex playlist_index = playlists_->current()->InsertPaths(urls);
if (playlist_index.isValid() && player_->GetState() != Engine::Playing) {
playlists_->SetActivePlaylist(playlists_->current_index());
playlists_->SetActiveToCurrent();
player_->PlayAt(playlist_index.row(), Engine::First, true);
}
}
@ -570,7 +570,7 @@ void MainWindow::PlayIndex(const QModelIndex& index) {
if (!index.isValid())
return;
playlists_->SetActivePlaylist(playlists_->current_index());
playlists_->SetActiveToCurrent();
player_->PlayAt(index.row(), Engine::Manual, true);
}
@ -598,7 +598,7 @@ void MainWindow::AddLibraryItemToPlaylist(bool clear_first, const QModelIndex& i
library_->model()->GetChildSongs(idx));
if (first_song.isValid() && player_->GetState() != Engine::Playing) {
playlists_->SetActivePlaylist(playlists_->current_index());
playlists_->SetActiveToCurrent();
player_->PlayAt(first_song.row(), Engine::First, true);
}
}
@ -716,7 +716,7 @@ void MainWindow::RadioDoubleClick(const QModelIndex& index) {
QModelIndex first_song = playlists_->current()->index(0, 0);
if (first_song.isValid() && player_->GetState() != Engine::Playing) {
playlists_->SetActivePlaylist(playlists_->current_index());
playlists_->SetActiveToCurrent();
player_->PlayAt(first_song.row(), Engine::First, true);
}
}
@ -726,7 +726,7 @@ void MainWindow::InsertRadioItem(RadioItem* item) {
QList<RadioItem*>() << item);
if (first_song.isValid() && player_->GetState() != Engine::Playing) {
playlists_->SetActivePlaylist(playlists_->current_index());
playlists_->SetActiveToCurrent();
player_->PlayAt(first_song.row(), Engine::First, true);
}
}
@ -735,7 +735,7 @@ void MainWindow::InsertRadioItems(const PlaylistItemList& items) {
QModelIndex first_song = playlists_->current()->InsertItems(items);
if (first_song.isValid() && player_->GetState() != Engine::Playing) {
playlists_->SetActivePlaylist(playlists_->current_index());
playlists_->SetActiveToCurrent();
player_->PlayAt(first_song.row(), Engine::First, true);
}
}
@ -808,7 +808,7 @@ void MainWindow::PlaylistPlay() {
if (playlists_->current()->current_index() == playlist_menu_index_.row()) {
player_->PlayPause();
} else {
playlists_->SetActivePlaylist(playlists_->current_index());
playlists_->SetActiveToCurrent();
player_->PlayAt(playlist_menu_index_.row(), Engine::Manual, true);
}
}