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_; +};