diff --git a/data/data.qrc b/data/data.qrc
index 129f6f24f..1c68d5d89 100644
--- a/data/data.qrc
+++ b/data/data.qrc
@@ -345,6 +345,7 @@
schema/schema-43.sql
schema/schema-44.sql
schema/schema-45.sql
+ schema/schema-46.sql
schema/schema-4.sql
schema/schema-5.sql
schema/schema-6.sql
diff --git a/data/schema/schema-46.sql b/data/schema/schema-46.sql
new file mode 100644
index 000000000..8b92896bb
--- /dev/null
+++ b/data/schema/schema-46.sql
@@ -0,0 +1,3 @@
+ALTER TABLE playlists ADD COLUMN is_favorite INTEGER NOT NULL DEFAULT 0;
+
+UPDATE schema_version SET version=46;
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 7fc5e7511..8090222a4 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -362,6 +362,7 @@ set(SOURCES
widgets/equalizerslider.cpp
widgets/errordialog.cpp
widgets/fancytabwidget.cpp
+ widgets/favoritewidget.cpp
widgets/fileview.cpp
widgets/fileviewlist.cpp
widgets/forcescrollperpixel.cpp
@@ -631,6 +632,7 @@ set(HEADERS
widgets/equalizerslider.h
widgets/errordialog.h
widgets/fancytabwidget.h
+ widgets/favoritewidget.h
widgets/fileview.h
widgets/fileviewlist.h
widgets/freespacebar.h
diff --git a/src/core/database.cpp b/src/core/database.cpp
index 2ea105b9a..e0755befa 100644
--- a/src/core/database.cpp
+++ b/src/core/database.cpp
@@ -37,7 +37,7 @@
#include
const char* Database::kDatabaseFilename = "clementine.db";
-const int Database::kSchemaVersion = 45;
+const int Database::kSchemaVersion = 46;
const char* Database::kMagicAllSongsTables = "%allsongstables";
int Database::sNextConnectionId = 1;
diff --git a/src/playlist/playlist.cpp b/src/playlist/playlist.cpp
index 2747357bb..ea07cca42 100644
--- a/src/playlist/playlist.cpp
+++ b/src/playlist/playlist.cpp
@@ -98,6 +98,7 @@ Playlist::Playlist(PlaylistBackend* backend,
LibraryBackend* library,
int id,
const QString& special_type,
+ bool favorite,
QObject *parent)
: QAbstractListModel(parent),
is_loading_(false),
@@ -107,6 +108,7 @@ Playlist::Playlist(PlaylistBackend* backend,
task_manager_(task_manager),
library_(library),
id_(id),
+ favorite_(favorite),
current_is_paused_(false),
current_virtual_index_(-1),
is_shuffled_(false),
diff --git a/src/playlist/playlist.h b/src/playlist/playlist.h
index 449ef3a80..8a24ce7f8 100644
--- a/src/playlist/playlist.h
+++ b/src/playlist/playlist.h
@@ -80,6 +80,7 @@ class Playlist : public QAbstractListModel {
LibraryBackend* library,
int id,
const QString& special_type = QString(),
+ bool favorite = false,
QObject* parent = 0);
~Playlist();
@@ -175,6 +176,8 @@ class Playlist : public QAbstractListModel {
int id() const { return id_; }
const QString& ui_path() const { return ui_path_; }
void set_ui_path(const QString& path) { ui_path_ = path; }
+ bool is_favorite() const { return favorite_; }
+ void set_favorite(bool favorite) { favorite_ = favorite; }
int current_row() const;
int last_played_row() const;
@@ -364,6 +367,7 @@ class Playlist : public QAbstractListModel {
LibraryBackend* library_;
int id_;
QString ui_path_;
+ bool favorite_;
PlaylistItemList items_;
QList virtual_items_; // Contains the indices into items_ in the order
diff --git a/src/playlist/playlistbackend.cpp b/src/playlist/playlistbackend.cpp
index de2a7c9d2..7311361b5 100644
--- a/src/playlist/playlistbackend.cpp
+++ b/src/playlist/playlistbackend.cpp
@@ -49,26 +49,35 @@ PlaylistBackend::PlaylistBackend(Application* app, QObject* parent)
}
PlaylistBackend::PlaylistList PlaylistBackend::GetAllOpenPlaylists() {
- return GetPlaylists(true);
+ return GetPlaylists(GetPlaylists_OpenInUi);
}
-PlaylistBackend::PlaylistList PlaylistBackend::GetAllPlaylists() {
- return GetPlaylists(false);
+PlaylistBackend::PlaylistList PlaylistBackend::GetAllFavoritePlaylists() {
+ return GetPlaylists(GetPlaylists_Favorite);
}
-PlaylistBackend::PlaylistList PlaylistBackend::GetPlaylists(bool open_in_ui) {
+PlaylistBackend::PlaylistList PlaylistBackend::GetPlaylists(GetPlaylistsFlags flags) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
PlaylistList ret;
- const QString open_in_ui_condition = open_in_ui ? "WHERE ui_order != -1" : "";
+ QString condition;
+ if (flags & GetPlaylists_OpenInUi) {
+ condition += "WHERE ui_order != -1";
+ }
+ if (flags == GetPlaylists_All) {
+ condition += " AND ";
+ }
+ if (flags & GetPlaylists_Favorite) {
+ condition += "WHERE is_favorite != 0";
+ }
QSqlQuery q("SELECT ROWID, name, last_played, dynamic_playlist_type,"
" dynamic_playlist_data, dynamic_playlist_backend,"
- " special_type, ui_path"
+ " special_type, ui_path, is_favorite"
" FROM playlists"
- " " + open_in_ui_condition +
+ " " + condition +
" ORDER BY ui_order", db);
q.exec();
if (db_->CheckErrors(q))
@@ -84,6 +93,7 @@ PlaylistBackend::PlaylistList PlaylistBackend::GetPlaylists(bool open_in_ui) {
p.dynamic_backend = q.value(5).toString();
p.special_type = q.value(6).toString();
p.ui_path = q.value(7).toString();
+ p.favorite = q.value(8).toBool();
ret << p;
}
@@ -96,7 +106,7 @@ PlaylistBackend::Playlist PlaylistBackend::GetPlaylist(int id) {
QSqlQuery q("SELECT ROWID, name, last_played, dynamic_playlist_type,"
" dynamic_playlist_data, dynamic_playlist_backend,"
- " special_type"
+ " special_type, ui_path, is_favorite"
" FROM playlists"
" WHERE ROWID=:id", db);
q.bindValue(":id", id);
@@ -114,6 +124,8 @@ PlaylistBackend::Playlist PlaylistBackend::GetPlaylist(int id) {
p.dynamic_data = q.value(4).toByteArray();
p.dynamic_backend = q.value(5).toString();
p.special_type = q.value(6).toString();
+ p.ui_path = q.value(7).toString();
+ p.favorite = q.value(8).toBool();
return p;
}
@@ -331,6 +343,17 @@ void PlaylistBackend::RenamePlaylist(int id, const QString &new_name) {
db_->CheckErrors(q);
}
+void PlaylistBackend::FavoritePlaylist(int id, bool is_favorite) {
+ QMutexLocker l(db_->Mutex());
+ QSqlDatabase db(db_->Connect());
+ QSqlQuery q("UPDATE playlists SET is_favorite=:is_favorite WHERE ROWID=:id", db);
+ q.bindValue(":is_favorite", is_favorite ? 1 : 0);
+ q.bindValue(":id", id);
+
+ q.exec();
+ db_->CheckErrors(q);
+}
+
void PlaylistBackend::SetPlaylistOrder(const QList& ids) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
diff --git a/src/playlist/playlistbackend.h b/src/playlist/playlistbackend.h
index 44587f4fe..38b192920 100644
--- a/src/playlist/playlistbackend.h
+++ b/src/playlist/playlistbackend.h
@@ -39,12 +39,14 @@ class PlaylistBackend : public QObject {
struct Playlist {
Playlist()
: id(-1),
+ favorite(false),
last_played(0) {
}
int id;
QString name;
QString ui_path;
+ bool favorite;
int last_played;
QString dynamic_type;
QString dynamic_backend;
@@ -60,7 +62,7 @@ class PlaylistBackend : public QObject {
static const int kSongTableJoins;
PlaylistList GetAllOpenPlaylists();
- PlaylistList GetAllPlaylists();
+ PlaylistList GetAllFavoritePlaylists();
PlaylistBackend::Playlist GetPlaylist(int id);
PlaylistItemFuture GetPlaylistItems(int playlist);
@@ -71,6 +73,7 @@ class PlaylistBackend : public QObject {
void SavePlaylistAsync(int playlist, const PlaylistItemList& items,
int last_played, smart_playlists::GeneratorPtr dynamic);
void RenamePlaylist(int id, const QString& new_name);
+ void FavoritePlaylist(int id, bool is_favorite);
void RemovePlaylist(int id);
public slots:
@@ -86,7 +89,12 @@ class PlaylistBackend : public QObject {
PlaylistItemPtr NewSongFromQuery(const SqlRow& row, boost::shared_ptr state);
PlaylistItemPtr RestoreCueData(PlaylistItemPtr item, boost::shared_ptr state);
- PlaylistList GetPlaylists(bool open_in_ui);
+ enum GetPlaylistsFlags {
+ GetPlaylists_OpenInUi = 1,
+ GetPlaylists_Favorite = 2,
+ GetPlaylists_All = GetPlaylists_OpenInUi | GetPlaylists_Favorite
+ };
+ PlaylistList GetPlaylists(GetPlaylistsFlags flags);
Application* app_;
Database* db_;
diff --git a/src/playlist/playlistcontainer.cpp b/src/playlist/playlistcontainer.cpp
index 94688db3b..96520915a 100644
--- a/src/playlist/playlistcontainer.cpp
+++ b/src/playlist/playlistcontainer.cpp
@@ -108,6 +108,10 @@ void PlaylistContainer::SetActions(QAction* new_playlist,
QAction* save_playlist,
QAction* next_playlist,
QAction* previous_playlist) {
+ ui_->create_new->setDefaultAction(new_playlist);
+ ui_->save->setDefaultAction(save_playlist);
+ ui_->load->setDefaultAction(load_playlist);
+
ui_->tab_bar->SetActions(new_playlist, load_playlist);
connect(new_playlist, SIGNAL(triggered()), SLOT(NewPlaylist()));
@@ -127,13 +131,16 @@ void PlaylistContainer::SetManager(PlaylistManager *manager) {
manager, SLOT(Rename(int,QString)));
connect(ui_->tab_bar, SIGNAL(Close(int)),
manager, SLOT(Close(int)));
+ connect(ui_->tab_bar, SIGNAL(PlaylistFavorited(int, bool)),
+ manager, SLOT(Favorite(int, bool)));
+
connect(ui_->tab_bar, SIGNAL(PlaylistOrderChanged(QList)),
manager, SLOT(ChangePlaylistOrder(QList)));
connect(manager, SIGNAL(CurrentChanged(Playlist*)),
SLOT(SetViewModel(Playlist*)));
- connect(manager, SIGNAL(PlaylistAdded(int,QString)),
- SLOT(PlaylistAdded(int,QString)));
+ connect(manager, SIGNAL(PlaylistAdded(int,QString,bool)),
+ SLOT(PlaylistAdded(int,QString,bool)));
connect(manager, SIGNAL(PlaylistClosed(int)),
SLOT(PlaylistClosed(int)));
connect(manager, SIGNAL(PlaylistRenamed(int,QString)),
@@ -232,9 +239,9 @@ void PlaylistContainer::UpdateActiveIcon(const QIcon& icon) {
ui_->tab_bar->set_icon_by_id(manager_->active_id(), icon);
}
-void PlaylistContainer::PlaylistAdded(int id, const QString &name) {
+void PlaylistContainer::PlaylistAdded(int id, const QString &name, bool favorite) {
const int index = ui_->tab_bar->count();
- ui_->tab_bar->InsertTab(id, index, name);
+ ui_->tab_bar->InsertTab(id, index, name, favorite);
// Are we startup up, should we select this tab?
if (starting_up_ && settings_.value("current_playlist", 1).toInt() == id) {
diff --git a/src/playlist/playlistcontainer.h b/src/playlist/playlistcontainer.h
index c771824e0..24412fac5 100644
--- a/src/playlist/playlistcontainer.h
+++ b/src/playlist/playlistcontainer.h
@@ -70,7 +70,7 @@ private slots:
void GoToPreviousPlaylistTab();
void SetViewModel(Playlist* playlist);
- void PlaylistAdded(int id, const QString& name);
+ void PlaylistAdded(int id, const QString& name, bool favorite);
void PlaylistClosed(int id);
void PlaylistRenamed(int id, const QString& new_name);
diff --git a/src/playlist/playlistcontainer.ui b/src/playlist/playlistcontainer.ui
index 232a4be83..7956a5b13 100644
--- a/src/playlist/playlistcontainer.ui
+++ b/src/playlist/playlistcontainer.ui
@@ -39,6 +39,45 @@
0
+ -
+
+
+
+ 16
+ 16
+
+
+
+ true
+
+
+
+ -
+
+
+
+ 16
+ 16
+
+
+
+ true
+
+
+
+ -
+
+
+
+ 16
+ 16
+
+
+
+ true
+
+
+
-
diff --git a/src/playlist/playlistlistcontainer.cpp b/src/playlist/playlistlistcontainer.cpp
index db2229bec..ce8e6a21f 100644
--- a/src/playlist/playlistlistcontainer.cpp
+++ b/src/playlist/playlistlistcontainer.cpp
@@ -138,10 +138,10 @@ void PlaylistListContainer::SetApplication(Application* app) {
PlaylistManager* manager = app_->playlist_manager();
Player* player = app_->player();
- connect(manager, SIGNAL(PlaylistAdded(int,QString)),
- SLOT(PlaylistAdded(int,QString)));
- connect(manager, SIGNAL(PlaylistDeleted(int)),
- SLOT(PlaylistDeleted(int)));
+ connect(manager, SIGNAL(PlaylistAdded(int,QString,bool)),
+ SLOT(AddPlaylist(int,QString,bool)));
+ connect(manager, SIGNAL(PlaylistFavorited(int,bool)),
+ SLOT(PlaylistFavoriteStateChanged(int,bool)));
connect(manager, SIGNAL(PlaylistRenamed(int,QString)),
SLOT(PlaylistRenamed(int,QString)));
connect(manager, SIGNAL(CurrentChanged(Playlist*)),
@@ -158,7 +158,7 @@ void PlaylistListContainer::SetApplication(Application* app) {
// Get all playlists, even ones that are hidden in the UI.
foreach (const PlaylistBackend::Playlist& p,
- app->playlist_backend()->GetAllPlaylists()) {
+ app->playlist_backend()->GetAllFavoritePlaylists()) {
QStandardItem* playlist_item = model_->NewPlaylist(p.name, p.id);
QStandardItem* parent_folder = model_->FolderByPath(p.ui_path);
parent_folder->appendRow(playlist_item);
@@ -190,7 +190,11 @@ void PlaylistListContainer::NewFolderClicked() {
model_->invisibleRootItem()->appendRow(model_->NewFolder(name));
}
-void PlaylistListContainer::PlaylistAdded(int id, const QString& name) {
+void PlaylistListContainer::AddPlaylist(int id, const QString& name, bool favorite) {
+ if (!favorite) {
+ return;
+ }
+
if (model_->PlaylistById(id)) {
// We know about this playlist already - it was probably one of the open
// ones that was loaded on startup.
@@ -213,7 +217,7 @@ void PlaylistListContainer::PlaylistRenamed(int id, const QString& new_name) {
item->setText(new_name);
}
-void PlaylistListContainer::PlaylistDeleted(int id) {
+void PlaylistListContainer::RemovePlaylist(int id) {
QStandardItem* item = model_->PlaylistById(id);
if (item) {
QStandardItem* parent = item->parent();
@@ -224,6 +228,15 @@ void PlaylistListContainer::PlaylistDeleted(int id) {
}
}
+void PlaylistListContainer::PlaylistFavoriteStateChanged(int id, bool favorite) {
+ if (favorite) {
+ const QString& name = app_->playlist_manager()->GetPlaylistName(id);
+ AddPlaylist(id, name, favorite);
+ } else {
+ RemovePlaylist(id);
+ }
+}
+
void PlaylistListContainer::ActiveChanged(Playlist* new_playlist) {
const int new_id = new_playlist->id();
@@ -254,6 +267,7 @@ void PlaylistListContainer::CurrentChanged(Playlist* new_playlist) {
void PlaylistListContainer::PlaylistPathChanged(int id, const QString& new_path) {
// Update the path in the database
app_->playlist_backend()->SetPlaylistUiPath(id, new_path);
+ app_->playlist_manager()->playlist(id)->set_ui_path(new_path);
}
void PlaylistListContainer::ViewIndexSelected(const QModelIndex& proxy_index) {
@@ -289,11 +303,11 @@ void PlaylistListContainer::DeleteClicked() {
}
}
- // Make sure the user really wants to delete all these playlists.
+ // Make sure the user really wants to unfavorite all these playlists.
if (ids.count() > 1) {
const int button =
- QMessageBox::question(this, tr("Delete playlists"),
- tr("You are about to delete %1 playlists, are you sure?").arg(ids.count()),
+ QMessageBox::question(this, tr("Remove playlists"),
+ tr("You are about to remove %1 playlists from your favorites, are you sure?").arg(ids.count()),
QMessageBox::Yes, QMessageBox::Cancel);
if (button != QMessageBox::Yes) {
@@ -301,9 +315,9 @@ void PlaylistListContainer::DeleteClicked() {
}
}
- // Delete the playlists
+ // Unfavorite the playlists
foreach (int id, ids) {
- app_->playlist_manager()->Delete(id);
+ app_->playlist_manager()->Favorite(id, false);
}
// Delete the top-level folders.
diff --git a/src/playlist/playlistlistcontainer.h b/src/playlist/playlistlistcontainer.h
index eed63ce32..7baddac61 100644
--- a/src/playlist/playlistlistcontainer.h
+++ b/src/playlist/playlistlistcontainer.h
@@ -56,9 +56,11 @@ private slots:
void PlaylistPathChanged(int id, const QString& new_path);
// From the PlaylistManager
- void PlaylistAdded(int id, const QString& name);
void PlaylistRenamed(int id, const QString& new_name);
- void PlaylistDeleted(int id);
+ // Add playlist if favorite == true
+ void AddPlaylist(int id, const QString& name, bool favorite);
+ void RemovePlaylist(int id);
+ void PlaylistFavoriteStateChanged(int id, bool favorite);
void CurrentChanged(Playlist* new_playlist);
void ActiveChanged(Playlist* new_playlist);
diff --git a/src/playlist/playlistmanager.cpp b/src/playlist/playlistmanager.cpp
index 97c5f6670..4442c1bb0 100644
--- a/src/playlist/playlistmanager.cpp
+++ b/src/playlist/playlistmanager.cpp
@@ -71,7 +71,7 @@ void PlaylistManager::Init(LibraryBackend* library_backend,
connect(library_backend_, SIGNAL(SongsRatingChanged(SongList)), SLOT(SongsDiscovered(SongList)));
foreach (const PlaylistBackend::Playlist& p, playlist_backend->GetAllOpenPlaylists()) {
- AddPlaylist(p.id, p.name, p.special_type, p.ui_path);
+ AddPlaylist(p.id, p.name, p.special_type, p.ui_path, p.favorite);
}
// If no playlist exists then make a new one
@@ -98,9 +98,10 @@ QItemSelection PlaylistManager::selection(int id) const {
Playlist* PlaylistManager::AddPlaylist(int id, const QString& name,
const QString& special_type,
- const QString& ui_path) {
+ const QString& ui_path,
+ bool favorite) {
Playlist* ret = new Playlist(playlist_backend_, app_->task_manager(),
- library_backend_, id, special_type);
+ library_backend_, id, special_type, favorite);
ret->set_sequence(sequence_);
ret->set_ui_path(ui_path);
@@ -115,7 +116,7 @@ Playlist* PlaylistManager::AddPlaylist(int id, const QString& name,
playlists_[id] = Data(ret, name);
- emit PlaylistAdded(id, name);
+ emit PlaylistAdded(id, name, favorite);
if (current_ == -1) {
SetCurrentPlaylist(id);
@@ -137,7 +138,7 @@ void PlaylistManager::New(const QString& name, const SongList& songs,
if (id == -1)
qFatal("Couldn't create playlist");
- Playlist* playlist = AddPlaylist(id, name, special_type, QString());
+ Playlist* playlist = AddPlaylist(id, name, special_type, QString(), false);
playlist->InsertSongsOrLibraryItems(songs);
SetCurrentPlaylist(id);
@@ -192,6 +193,12 @@ void PlaylistManager::Rename(int id, const QString& new_name) {
emit PlaylistRenamed(id, new_name);
}
+void PlaylistManager::Favorite(int id, bool favorite) {
+ playlist_backend_->FavoritePlaylist(id, favorite);
+ playlists_[id].p->set_favorite(favorite);
+ emit PlaylistFavorited(id, favorite);
+}
+
bool PlaylistManager::Close(int id) {
// Won't allow removing the last playlist
if (playlists_.count() <= 1 || !playlists_.contains(id))
@@ -213,9 +220,15 @@ bool PlaylistManager::Close(int id) {
SetCurrentPlaylist(next_id);
Data data = playlists_.take(id);
+ emit PlaylistClosed(id);
+
+ if (!data.p->is_favorite()) {
+ // TODO: should we warn the user this action cannot be undone?
+ playlist_backend_->RemovePlaylist(id);
+ emit PlaylistDeleted(id);
+ }
delete data.p;
- emit PlaylistClosed(id);
return true;
}
@@ -439,7 +452,7 @@ void PlaylistManager::Open(int id) {
return;
}
- AddPlaylist(p.id, p.name, p.special_type, p.ui_path);
+ AddPlaylist(p.id, p.name, p.special_type, p.ui_path, p.favorite);
}
void PlaylistManager::SetCurrentOrOpen(int id) {
diff --git a/src/playlist/playlistmanager.h b/src/playlist/playlistmanager.h
index 99c125b9b..ed07c397e 100644
--- a/src/playlist/playlistmanager.h
+++ b/src/playlist/playlistmanager.h
@@ -108,10 +108,11 @@ public slots:
signals:
void PlaylistManagerInitialized();
- void PlaylistAdded(int id, const QString& name);
+ void PlaylistAdded(int id, const QString& name, bool favorite);
void PlaylistDeleted(int id);
void PlaylistClosed(int id);
void PlaylistRenamed(int id, const QString& new_name);
+ void PlaylistFavorited(int id, bool favorite);
void CurrentChanged(Playlist* new_playlist);
void ActiveChanged(Playlist* new_playlist);
@@ -176,6 +177,7 @@ public slots:
void Load(const QString& filename);
void Save(int id, const QString& filename);
void Rename(int id, const QString& new_name);
+ void Favorite(int id, bool favorite);
void Delete(int id);
bool Close(int id);
void Open(int id);
@@ -217,7 +219,7 @@ private slots:
private:
Playlist* AddPlaylist(int id, const QString& name, const QString& special_type,
- const QString& ui_path);
+ const QString& ui_path, bool favorite);
private:
struct Data {
diff --git a/src/playlist/playlisttabbar.cpp b/src/playlist/playlisttabbar.cpp
index 65c4c3b8e..5adf1a842 100644
--- a/src/playlist/playlisttabbar.cpp
+++ b/src/playlist/playlisttabbar.cpp
@@ -24,11 +24,13 @@
#include "internet/internetmimedata.h"
#include "ui/iconloader.h"
#include "widgets/renametablineedit.h"
+#include "widgets/favoritewidget.h"
#include
+#include
#include
#include
-#include
+#include
#include
PlaylistTabBar::PlaylistTabBar(QWidget *parent)
@@ -69,6 +71,8 @@ void PlaylistTabBar::SetActions(
void PlaylistTabBar::SetManager(PlaylistManager *manager) {
manager_ = manager;
+ connect(manager_, SIGNAL(PlaylistFavorited(int, bool)),
+ SLOT(PlaylistFavoritedSlot(int, bool)));
}
void PlaylistTabBar::contextMenuEvent(QContextMenuEvent* e) {
@@ -223,11 +227,14 @@ void PlaylistTabBar::CurrentIndexChanged(int index) {
emit CurrentIdChanged(tabData(index).toInt());
}
-void PlaylistTabBar::InsertTab(int id, int index, const QString& text) {
+void PlaylistTabBar::InsertTab(int id, int index, const QString& text, bool favorite) {
suppress_current_changed_ = true;
insertTab(index, text);
setTabData(index, id);
setTabToolTip(index, text);
+ FavoriteWidget* widget = new FavoriteWidget(index, favorite);
+ connect(widget, SIGNAL(FavoriteStateChanged(int, bool)), SLOT(TabFavorited(int, bool)));
+ setTabButton(index, QTabBar::LeftSide, widget);
suppress_current_changed_ = false;
if (currentIndex() == index)
@@ -245,6 +252,10 @@ void PlaylistTabBar::TabMoved() {
emit PlaylistOrderChanged(ids);
}
+void PlaylistTabBar::TabFavorited(int index, bool favorite) {
+ emit PlaylistFavorited(tabData(index).toInt(), favorite);
+}
+
void PlaylistTabBar::dragEnterEvent(QDragEnterEvent* e) {
if (e->mimeData()->hasUrls() ||
e->mimeData()->hasFormat(Playlist::kRowsMimetype) ||
@@ -322,3 +333,11 @@ bool PlaylistTabBar::event(QEvent* e) {
return QTabBar::event(e);
}
}
+
+void PlaylistTabBar::PlaylistFavoritedSlot(int id, bool favorite) {
+ const int index = index_of(id);
+ FavoriteWidget* favorite_widget = qobject_cast(tabButton(index, QTabBar::LeftSide));
+ if (favorite_widget) {
+ favorite_widget->SetFavorite(favorite);
+ }
+}
diff --git a/src/playlist/playlisttabbar.h b/src/playlist/playlisttabbar.h
index 656df7837..2b92d31ca 100644
--- a/src/playlist/playlisttabbar.h
+++ b/src/playlist/playlisttabbar.h
@@ -50,7 +50,7 @@ public:
void set_text_by_id(int id, const QString& text);
void RemoveTab(int id);
- void InsertTab(int id, int index, const QString& text);
+ void InsertTab(int id, int index, const QString& text, bool favorite);
signals:
void CurrentIdChanged(int id);
@@ -58,6 +58,7 @@ signals:
void Close(int id);
void Save(int id);
void PlaylistOrderChanged(const QList& ids);
+ void PlaylistFavorited(int id, bool favorite);
protected:
void contextMenuEvent(QContextMenuEvent* e);
@@ -77,6 +78,10 @@ private slots:
void HideEditor();
void Close();
void CloseFromTabIndex(int index);
+ void TabFavorited(int index, bool favorite);
+ // Used when playlist's favorite flag isn't changed from the favorite widget
+ // (e.g. from the playlistlistcontainer): will update the favorite widget
+ void PlaylistFavoritedSlot(int id, bool favorite);
void TabMoved();
void Save();
diff --git a/src/smartplaylists/searchpreview.cpp b/src/smartplaylists/searchpreview.cpp
index d084c0400..08c6065f0 100644
--- a/src/smartplaylists/searchpreview.cpp
+++ b/src/smartplaylists/searchpreview.cpp
@@ -56,7 +56,7 @@ void SearchPreview::set_application(Application* app) {
void SearchPreview::set_library(LibraryBackend* backend) {
backend_ = backend;
- model_ = new Playlist(NULL, NULL, backend_, -1, QString(), this);
+ model_ = new Playlist(NULL, NULL, backend_, -1, QString(), false, this);
ui_->tree->setModel(model_);
ui_->tree->SetPlaylist(model_);
ui_->tree->SetItemDelegates(backend_);
diff --git a/src/widgets/favoritewidget.cpp b/src/widgets/favoritewidget.cpp
new file mode 100644
index 000000000..2063e0cca
--- /dev/null
+++ b/src/widgets/favoritewidget.cpp
@@ -0,0 +1,67 @@
+/* This file is part of Clementine.
+ Copyright 2013, David Sansome
+
+ Clementine is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Clementine is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Clementine. If not, see .
+*/
+
+#include "favoritewidget.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#include "core/logging.h"
+
+const int FavoriteWidget::kStarSize = 15;
+
+FavoriteWidget::FavoriteWidget(int tab_index, bool favorite, QWidget* parent)
+ : QWidget(parent),
+ tab_index_(tab_index),
+ favorite_(favorite),
+ on_(":/star-on.png"),
+ off_(":/star-off.png"),
+ rect_(0, 0, kStarSize, kStarSize)
+{
+}
+
+void FavoriteWidget::SetFavorite(bool favorite) {
+ if (favorite_ != favorite) {
+ favorite_ = favorite;
+ update();
+ emit FavoriteStateChanged(tab_index_, favorite_);
+ }
+}
+
+QSize FavoriteWidget::sizeHint() const {
+ const int frame_width = 1 + style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
+ return QSize(kStarSize + frame_width*2, kStarSize + frame_width*2);
+}
+
+void FavoriteWidget::paintEvent(QPaintEvent* e) {
+ QStylePainter p(this);
+
+ if (favorite_) {
+ p.drawPixmap(rect_, on_);
+ } else {
+ p.drawPixmap(rect_, off_);
+ }
+}
+
+void FavoriteWidget::mousePressEvent(QMouseEvent* e) {
+ favorite_ = !favorite_;
+ update();
+ emit FavoriteStateChanged(tab_index_, favorite_);
+}
diff --git a/src/widgets/favoritewidget.h b/src/widgets/favoritewidget.h
new file mode 100644
index 000000000..f12905db8
--- /dev/null
+++ b/src/widgets/favoritewidget.h
@@ -0,0 +1,51 @@
+/* This file is part of Clementine.
+ Copyright 2013, David Sansome
+
+ Clementine is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Clementine is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Clementine. If not, see .
+*/
+
+#include
+
+class QPaintEvent;
+class QMouseEvent;
+
+class FavoriteWidget : public QWidget {
+ Q_OBJECT
+
+ public:
+ FavoriteWidget(int tab_id, bool favorite = false, QWidget *parent = 0);
+
+ // Change the value if different from the current one and then update display
+ // and emit FavoriteStateChanged signal
+ void SetFavorite(bool favorite);
+
+ QSize sizeHint() const;
+
+ signals:
+ void FavoriteStateChanged(int, bool);
+
+ protected:
+ void paintEvent(QPaintEvent* e);
+ void mousePressEvent(QMouseEvent* e);
+
+ private:
+ static const int kStarSize;
+
+ // The tab's id this widget belongs to
+ int tab_index_;
+ bool favorite_;
+ QPixmap on_;
+ QPixmap off_;
+ QRect rect_;
+};