Put all smart playlist classes in their own namespace

This commit is contained in:
David Sansome 2010-11-18 20:19:33 +00:00
parent d9ed5c91ef
commit 1f267881fe
34 changed files with 380 additions and 287 deletions

View File

@ -129,14 +129,14 @@ set(SOURCES
radio/savedradio.cpp
radio/somafmservice.cpp
smartplaylists/playlistgenerator.cpp
smartplaylists/playlistgeneratorinserter.cpp
smartplaylists/smartplaylistsearch.cpp
smartplaylists/smartplaylistsearchpreview.cpp
smartplaylists/smartplaylistsearchterm.cpp
smartplaylists/smartplaylistsearchtermwidget.cpp
smartplaylists/smartplaylistwizard.cpp
smartplaylists/queryplaylistgenerator.cpp
smartplaylists/generator.cpp
smartplaylists/generatorinserter.cpp
smartplaylists/querygenerator.cpp
smartplaylists/search.cpp
smartplaylists/searchpreview.cpp
smartplaylists/searchterm.cpp
smartplaylists/searchtermwidget.cpp
smartplaylists/wizard.cpp
songinfo/artistinfoview.cpp
songinfo/collapsibleinfoheader.cpp
@ -287,12 +287,12 @@ set(HEADERS
radio/savedradio.h
radio/somafmservice.h
smartplaylists/generator.h
smartplaylists/generatorinserter.h
smartplaylists/generatormimedata.h
smartplaylists/playlistgenerator.h
smartplaylists/playlistgeneratorinserter.h
smartplaylists/smartplaylistsearchpreview.h
smartplaylists/smartplaylistsearchtermwidget.h
smartplaylists/smartplaylistwizard.h
smartplaylists/searchpreview.h
smartplaylists/searchtermwidget.h
smartplaylists/wizard.h
songinfo/artistinfoview.h
songinfo/collapsibleinfoheader.h
@ -374,9 +374,9 @@ set(UI
radio/magnatunedownloaddialog.ui
radio/radioviewcontainer.ui
smartplaylists/smartplaylistsearchpreview.ui
smartplaylists/smartplaylistsearchtermwidget.ui
smartplaylists/smartplaylistwizard.ui
smartplaylists/searchpreview.ui
smartplaylists/searchtermwidget.ui
smartplaylists/wizard.ui
songinfo/lyricsettings.ui

View File

@ -19,7 +19,7 @@
#include "sqlrow.h"
#include "core/database.h"
#include "core/scopedtransaction.h"
#include "smartplaylists/smartplaylistsearch.h"
#include "smartplaylists/search.h"
#include <QDir>
#include <QVariant>
@ -814,7 +814,7 @@ bool LibraryBackend::ExecQuery(LibraryQuery *q) {
return !db_->CheckErrors(q->Exec(db_->Connect(), songs_table_, fts_table_));
}
SongList LibraryBackend::FindSongs(const SmartPlaylistSearch& search) {
SongList LibraryBackend::FindSongs(const smart_playlists::Search& search) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());

View File

@ -27,7 +27,8 @@
#include <boost/shared_ptr.hpp>
class Database;
class SmartPlaylistSearch;
namespace smart_playlists { class Search; }
class LibraryBackendInterface : public QObject {
public:
@ -132,7 +133,7 @@ class LibraryBackend : public LibraryBackendInterface {
void RemoveDirectory(const Directory& dir);
bool ExecQuery(LibraryQuery* q);
SongList FindSongs(const SmartPlaylistSearch& search);
SongList FindSongs(const smart_playlists::Search& search);
void IncrementPlayCountAsync(int id);
void IncrementSkipCountAsync(int id, float progress);

View File

@ -21,9 +21,9 @@
#include "sqlrow.h"
#include "core/database.h"
#include "playlist/songmimedata.h"
#include "smartplaylists/generator.h"
#include "smartplaylists/generatormimedata.h"
#include "smartplaylists/playlistgenerator.h"
#include "smartplaylists/queryplaylistgenerator.h"
#include "smartplaylists/querygenerator.h"
#include "ui/iconloader.h"
#include <QSettings>
@ -33,6 +33,11 @@
#include <boost/bind.hpp>
using smart_playlists::Generator;
using smart_playlists::GeneratorMimeData;
using smart_playlists::GeneratorPtr;
using smart_playlists::QueryGenerator;
const char* LibraryModel::kSmartPlaylistsMimeType = "application/x-clementine-smart-playlist-generator";
const char* LibraryModel::kSmartPlaylistsSettingsGroup = "SerialisedSmartPlaylists";
@ -747,7 +752,7 @@ QMimeData* LibraryModel::mimeData(const QModelIndexList& indexes) const {
// Special case: a smart playlist was dragged
if (IndexToItem(indexes.first())->type == LibraryItem::Type_SmartPlaylist) {
PlaylistGeneratorPtr generator = CreateGenerator(indexes.first());
GeneratorPtr generator = CreateGenerator(indexes.first());
if (!generator)
return NULL;
@ -882,30 +887,33 @@ void LibraryModel::CreateSmartPlaylists() {
s.beginGroup(kSmartPlaylistsSettingsGroup);
s.beginWriteArray("smart");
// These defines really make this section more concise
#define S SmartPlaylistSearch
#define T SmartPlaylistSearchTerm
using smart_playlists::Search;
using smart_playlists::SearchTerm;
int i = 0;
SaveDefaultGenerator(&s, i++, tr("50 random tracks"), S(
S::Type_All, S::TermList(), S::Sort_Random, T::Field_Title, 50));
SaveDefaultGenerator(&s, i++, tr("Ever played"), S(
S::Type_And, S::TermList() << T(T::Field_PlayCount, T::Op_GreaterThan, 0),
S::Sort_Random, T::Field_Title));
SaveDefaultGenerator(&s, i++, tr("Never played"), S(
S::Type_And, S::TermList() << T(T::Field_PlayCount, T::Op_Equals, 0),
S::Sort_Random, T::Field_Title));
SaveDefaultGenerator(&s, i++, tr("Last played"), S(
S::Type_All, S::TermList(), S::Sort_FieldDesc, T::Field_LastPlayed));
SaveDefaultGenerator(&s, i++, tr("Most played"), S(
S::Type_All, S::TermList(), S::Sort_FieldDesc, T::Field_PlayCount));
SaveDefaultGenerator(&s, i++, tr("Favourite tracks"), S(
S::Type_All, S::TermList(), S::Sort_FieldDesc, T::Field_Score));
SaveDefaultGenerator(&s, i++, tr("Newest tracks"), S(
S::Type_All, S::TermList(), S::Sort_FieldDesc, T::Field_DateCreated));
#undef S
#undef T
SaveDefaultGenerator(&s, i++, tr("50 random tracks"), Search(
Search::Type_All, Search::TermList(),
Search::Sort_Random, SearchTerm::Field_Title, 50));
SaveDefaultGenerator(&s, i++, tr("Ever played"), Search(
Search::Type_And, Search::TermList()
<< SearchTerm(SearchTerm::Field_PlayCount, SearchTerm::Op_GreaterThan, 0),
Search::Sort_Random, SearchTerm::Field_Title));
SaveDefaultGenerator(&s, i++, tr("Never played"), Search(
Search::Type_And, Search::TermList()
<< SearchTerm(SearchTerm::Field_PlayCount, SearchTerm::Op_Equals, 0),
Search::Sort_Random, SearchTerm::Field_Title));
SaveDefaultGenerator(&s, i++, tr("Last played"), Search(
Search::Type_All, Search::TermList(),
Search::Sort_FieldDesc, SearchTerm::Field_LastPlayed));
SaveDefaultGenerator(&s, i++, tr("Most played"), Search(
Search::Type_All, Search::TermList(),
Search::Sort_FieldDesc, SearchTerm::Field_PlayCount));
SaveDefaultGenerator(&s, i++, tr("Favourite tracks"), Search(
Search::Type_All, Search::TermList(),
Search::Sort_FieldDesc, SearchTerm::Field_Score));
SaveDefaultGenerator(&s, i++, tr("Newest tracks"), Search(
Search::Type_All, Search::TermList(),
Search::Sort_FieldDesc, SearchTerm::Field_DateCreated));
s.endArray();
s.endGroup();
@ -925,28 +933,28 @@ void LibraryModel::CreateSmartPlaylists() {
}
void LibraryModel::SaveDefaultGenerator(QSettings* s, int i, const QString& name,
const SmartPlaylistSearch& search) const {
boost::shared_ptr<QueryPlaylistGenerator> gen(new QueryPlaylistGenerator);
const smart_playlists::Search& search) const {
boost::shared_ptr<QueryGenerator> gen(new QueryGenerator);
gen->set_name(name);
gen->Load(search);
SaveGenerator(s, i, boost::static_pointer_cast<PlaylistGenerator>(gen));
SaveGenerator(s, i, boost::static_pointer_cast<Generator>(gen));
}
void LibraryModel::SaveGenerator(QSettings* s, int i, PlaylistGeneratorPtr generator) const {
void LibraryModel::SaveGenerator(QSettings* s, int i, GeneratorPtr generator) const {
s->setArrayIndex(i);
s->setValue("name", generator->name());
s->setValue("type", generator->type());
s->setValue("data", generator->Save());
}
PlaylistGeneratorPtr LibraryModel::CreateGenerator(const QModelIndex& index) const {
PlaylistGeneratorPtr ret;
GeneratorPtr LibraryModel::CreateGenerator(const QModelIndex& index) const {
GeneratorPtr ret;
const LibraryItem* item = IndexToItem(index);
if (!item || item->type != LibraryItem::Type_SmartPlaylist)
return ret;
ret = PlaylistGenerator::Create(item->key);
ret = Generator::Create(item->key);
if (!ret)
return ret;

View File

@ -27,13 +27,13 @@
#include "core/simpletreemodel.h"
#include "core/song.h"
#include "engines/engine_fwd.h"
#include "smartplaylists/playlistgenerator_fwd.h"
#include "smartplaylists/generator_fwd.h"
#include <boost/scoped_ptr.hpp>
class LibraryDirectoryModel;
class LibraryBackend;
class SmartPlaylistSearch;
namespace smart_playlists { class Search; }
class QSettings;
@ -102,7 +102,7 @@ class LibraryModel : public SimpleTreeModel<LibraryItem> {
SongList GetChildSongs(const QModelIndex& index) const;
SongList GetChildSongs(const QModelIndexList& indexes) const;
PlaylistGeneratorPtr CreateGenerator(const QModelIndex& index) const;
smart_playlists::GeneratorPtr CreateGenerator(const QModelIndex& index) const;
// QAbstractItemModel
QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
@ -158,8 +158,8 @@ class LibraryModel : public SimpleTreeModel<LibraryItem> {
// Smart playlists are shown in another top-level node
void CreateSmartPlaylists();
void SaveDefaultGenerator(QSettings* s, int i, const QString& name,
const SmartPlaylistSearch& search) const;
void SaveGenerator(QSettings* s, int i, PlaylistGeneratorPtr generator) const;
const smart_playlists::Search& search) const;
void SaveGenerator(QSettings* s, int i, smart_playlists::GeneratorPtr generator) const;
// Helpers for ItemFromQuery and ItemFromSong
LibraryItem* InitItem(GroupBy type, bool signal, LibraryItem* parent,

View File

@ -23,7 +23,7 @@
#include "core/musicstorage.h"
#include "devices/devicemanager.h"
#include "devices/devicestatefiltermodel.h"
#include "smartplaylists/smartplaylistwizard.h"
#include "smartplaylists/wizard.h"
#include "ui/iconloader.h"
#include "ui/organisedialog.h"
#include "ui/organiseerrordialog.h"
@ -35,6 +35,8 @@
#include <QSortFilterProxyModel>
#include <QSettings>
using smart_playlists::Wizard;
const char* LibraryView::kSettingsGroup = "LibraryView";
LibraryItemDelegate::LibraryItemDelegate(QObject *parent)
@ -391,7 +393,7 @@ void LibraryView::CreateSmartPlaylistWizard() {
if (smart_playlist_wizard_)
return;
smart_playlist_wizard_.reset(new SmartPlaylistWizard(library_->backend(), this));
smart_playlist_wizard_.reset(new Wizard(library_->backend(), this));
}
void LibraryView::NewSmartPlaylist() {

View File

@ -27,9 +27,10 @@
class DeviceManager;
class LibraryModel;
class OrganiseDialog;
class SmartPlaylistWizard;
class TaskManager;
namespace smart_playlists { class Wizard; }
class LibraryItemDelegate : public QStyledItemDelegate {
public:
LibraryItemDelegate(QObject* parent);
@ -118,7 +119,7 @@ class LibraryView : public AutoExpandingTreeView {
QAction* delete_smart_playlist_;
boost::scoped_ptr<OrganiseDialog> organise_dialog_;
boost::scoped_ptr<SmartPlaylistWizard> smart_playlist_wizard_;
boost::scoped_ptr<smart_playlists::Wizard> smart_playlist_wizard_;
bool is_in_keyboard_search_;
};

View File

@ -33,8 +33,8 @@
#include "radio/radiomodel.h"
#include "radio/radioplaylistitem.h"
#include "radio/savedradio.h"
#include "smartplaylists/generatorinserter.h"
#include "smartplaylists/generatormimedata.h"
#include "smartplaylists/playlistgeneratorinserter.h"
#include <QtDebug>
#include <QMimeData>
@ -49,6 +49,9 @@
#include <lastfm/ScrobblePoint>
using smart_playlists::GeneratorInserter;
using smart_playlists::GeneratorPtr;
using boost::shared_ptr;
const char* Playlist::kRowsMimetype = "application/x-clementine-playlist-rows";
@ -530,6 +533,8 @@ bool Playlist::dropMimeData(const QMimeData* data, Qt::DropAction action, int ro
if (action == Qt::IgnoreAction)
return false;
using smart_playlists::GeneratorMimeData;
if (const SongMimeData* song_data = qobject_cast<const SongMimeData*>(data)) {
// Dragged from a library
// We want to check if these songs are from the actual local file backend,
@ -592,8 +597,8 @@ void Playlist::InsertUrls(const QList<QUrl> &urls, bool play_now, int pos) {
inserter->Load(this, pos, play_now, urls);
}
void Playlist::InsertSmartPlaylist(PlaylistGeneratorPtr generator, int pos, bool play_now) {
PlaylistGeneratorInserter* inserter = new PlaylistGeneratorInserter(task_manager_, library_, this);
void Playlist::InsertSmartPlaylist(GeneratorPtr generator, int pos, bool play_now) {
GeneratorInserter* inserter = new GeneratorInserter(task_manager_, library_, this);
connect(inserter, SIGNAL(Error(QString)), SIGNAL(LoadTracksError(QString)));
connect(inserter, SIGNAL(PlayRequested(QModelIndex)), SIGNAL(PlayRequested(QModelIndex)));

View File

@ -26,7 +26,7 @@
#include "playlistsequence.h"
#include "core/song.h"
#include "radio/radioitem.h"
#include "smartplaylists/playlistgenerator_fwd.h"
#include "smartplaylists/generator_fwd.h"
class LibraryBackend;
class PlaylistBackend;
@ -151,7 +151,7 @@ class Playlist : public QAbstractListModel {
QModelIndex InsertMagnatuneItems(const SongList& items, int pos = -1);
QModelIndex InsertSongs(const SongList& items, int pos = -1);
QModelIndex InsertRadioStations(const QList<RadioItem*>& items, int pos = -1, bool play_now = false);
void InsertSmartPlaylist(PlaylistGeneratorPtr generator, int pos = -1, bool play_now = false);
void InsertSmartPlaylist(smart_playlists::GeneratorPtr generator, int pos = -1, bool play_now = false);
void InsertUrls(const QList<QUrl>& urls, bool play_now, int pos = -1);
void StopAfter(int row);
void ReloadItems(const QList<int>& rows);

View File

@ -22,11 +22,13 @@
#include "library/librarybackend.h"
#include "library/libraryplaylistitem.h"
#include "playlistparsers/playlistparser.h"
#include "smartplaylists/playlistgenerator.h"
#include "smartplaylists/generator.h"
#include <QFileInfo>
#include <QtDebug>
using smart_playlists::GeneratorPtr;
PlaylistManager::PlaylistManager(TaskManager* task_manager, QObject *parent)
: QObject(parent),
task_manager_(task_manager),
@ -275,7 +277,7 @@ void PlaylistManager::SongsDiscovered(const SongList& songs) {
}
}
void PlaylistManager::PlaySmartPlaylist(PlaylistGeneratorPtr generator, bool as_new, bool clear) {
void PlaylistManager::PlaySmartPlaylist(GeneratorPtr generator, bool as_new, bool clear) {
if (as_new) {
New(generator->name());
}

View File

@ -22,7 +22,7 @@
#include <QObject>
#include "core/song.h"
#include "smartplaylists/playlistgenerator_fwd.h"
#include "smartplaylists/generator_fwd.h"
class LibraryBackend;
class Playlist;
@ -85,7 +85,7 @@ public slots:
void SetActiveStopped();
void SetActiveStreamMetadata(const QUrl& url, const Song& song);
void PlaySmartPlaylist(PlaylistGeneratorPtr generator, bool as_new, bool clear);
void PlaySmartPlaylist(smart_playlists::GeneratorPtr generator, bool as_new, bool clear);
signals:
void PlaylistAdded(int id, const QString& name);

View File

@ -14,24 +14,28 @@
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
*/
#include "queryplaylistgenerator.h"
#include "playlistgenerator.h"
#include "generator.h"
#include "querygenerator.h"
#include <QSettings>
const int PlaylistGenerator::kDefaultLimit = 20;
namespace smart_playlists {
PlaylistGenerator::PlaylistGenerator()
const int Generator::kDefaultLimit = 20;
Generator::Generator()
: QObject(NULL),
backend_(NULL)
{
}
PlaylistGeneratorPtr PlaylistGenerator::Create(const QString& type) {
GeneratorPtr Generator::Create(const QString& type) {
if (type == "Query")
return PlaylistGeneratorPtr(new QueryPlaylistGenerator);
return GeneratorPtr(new QueryGenerator);
qWarning() << "Invalid playlist generator type:" << type;
return PlaylistGeneratorPtr();
return GeneratorPtr();
}
} // namespace

View File

@ -24,15 +24,17 @@
class LibraryBackend;
class PlaylistGenerator : public QObject, public boost::enable_shared_from_this<PlaylistGenerator> {
namespace smart_playlists {
class Generator : public QObject, public boost::enable_shared_from_this<Generator> {
Q_OBJECT
public:
PlaylistGenerator();
virtual ~PlaylistGenerator() {}
Generator();
virtual ~Generator() {}
static const int kDefaultLimit;
static boost::shared_ptr<PlaylistGenerator> Create(const QString& type);
static boost::shared_ptr<Generator> Create(const QString& type);
void set_library(LibraryBackend* backend) { backend_ = backend; }
@ -55,6 +57,8 @@ protected:
QString name_;
};
#include "playlistgenerator_fwd.h"
} // namespace
#include "generator_fwd.h"
#endif // PLAYLISTGENERATOR_H

View File

@ -19,8 +19,12 @@
#include <boost/shared_ptr.hpp>
class PlaylistGenerator;
namespace smart_playlists {
typedef boost::shared_ptr<PlaylistGenerator> PlaylistGeneratorPtr;
class Generator;
typedef boost::shared_ptr<Generator> GeneratorPtr;
} // namespace
#endif // PLAYLISTGENERATOR_FWD_H

View File

@ -14,18 +14,20 @@
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
*/
#include "playlistgenerator.h"
#include "playlistgeneratorinserter.h"
#include "generator.h"
#include "generatorinserter.h"
#include "core/taskmanager.h"
#include "playlist/playlist.h"
#include <QFutureWatcher>
#include <QtConcurrentRun>
namespace smart_playlists {
typedef QFuture<PlaylistItemList> Future;
typedef QFutureWatcher<PlaylistItemList> FutureWatcher;
PlaylistGeneratorInserter::PlaylistGeneratorInserter(
GeneratorInserter::GeneratorInserter(
TaskManager* task_manager, LibraryBackend* library, QObject* parent)
: QObject(parent),
task_manager_(task_manager),
@ -34,12 +36,12 @@ PlaylistGeneratorInserter::PlaylistGeneratorInserter(
{
}
static PlaylistItemList Generate(PlaylistGeneratorPtr generator) {
static PlaylistItemList Generate(GeneratorPtr generator) {
return generator->Generate();
}
void PlaylistGeneratorInserter::Load(
Playlist* destination, int row, bool play_now, PlaylistGeneratorPtr generator) {
void GeneratorInserter::Load(
Playlist* destination, int row, bool play_now, GeneratorPtr generator) {
task_id_ = task_manager_->StartTask(tr("Loading smart playlist"));
destination_ = destination;
@ -55,7 +57,7 @@ void PlaylistGeneratorInserter::Load(
connect(watcher, SIGNAL(finished()), SLOT(Finished()));
}
void PlaylistGeneratorInserter::Finished() {
void GeneratorInserter::Finished() {
FutureWatcher* watcher = static_cast<FutureWatcher*>(sender());
watcher->deleteLater();
@ -69,3 +71,5 @@ void PlaylistGeneratorInserter::Finished() {
deleteLater();
}
} // namespace

View File

@ -17,7 +17,7 @@
#ifndef PLAYLISTGENERATORINSERTER_H
#define PLAYLISTGENERATORINSERTER_H
#include "playlistgenerator_fwd.h"
#include "generator_fwd.h"
#include <QObject>
@ -27,15 +27,17 @@ class TaskManager;
class QModelIndex;
class PlaylistGeneratorInserter : public QObject {
namespace smart_playlists {
class GeneratorInserter : public QObject {
Q_OBJECT
public:
PlaylistGeneratorInserter(TaskManager* task_manager,
LibraryBackend* library, QObject* parent);
GeneratorInserter(TaskManager* task_manager,
LibraryBackend* library, QObject* parent);
void Load(Playlist* destination, int row, bool play_now,
PlaylistGeneratorPtr generator);
GeneratorPtr generator);
signals:
void Error(const QString& message);
@ -54,4 +56,6 @@ private:
bool play_now_;
};
} // namespace
#endif // PLAYLISTGENERATORINSERTER_H

View File

@ -19,15 +19,19 @@
#include <QMimeData>
#include "playlistgenerator_fwd.h"
#include "generator_fwd.h"
namespace smart_playlists {
class GeneratorMimeData : public QMimeData {
Q_OBJECT
public:
GeneratorMimeData(PlaylistGeneratorPtr generator) : generator_(generator) {}
GeneratorMimeData(GeneratorPtr generator) : generator_(generator) {}
PlaylistGeneratorPtr generator_;
GeneratorPtr generator_;
};
} // namespace
#endif // GENERATORMIMEDATA_H

View File

@ -14,26 +14,28 @@
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
*/
#include "queryplaylistgenerator.h"
#include "querygenerator.h"
#include "library/librarybackend.h"
#include "library/libraryplaylistitem.h"
#include <QtDebug>
QueryPlaylistGenerator::QueryPlaylistGenerator()
namespace smart_playlists {
QueryGenerator::QueryGenerator()
{
}
void QueryPlaylistGenerator::Load(const SmartPlaylistSearch& search) {
void QueryGenerator::Load(const Search& search) {
search_ = search;
}
void QueryPlaylistGenerator::Load(const QByteArray& data) {
void QueryGenerator::Load(const QByteArray& data) {
QDataStream s(data);
s >> search_;
}
QByteArray QueryPlaylistGenerator::Save() const {
QByteArray QueryGenerator::Save() const {
QByteArray ret;
QDataStream s(&ret, QIODevice::WriteOnly);
s << search_;
@ -41,7 +43,7 @@ QByteArray QueryPlaylistGenerator::Save() const {
return ret;
}
PlaylistItemList QueryPlaylistGenerator::Generate() {
PlaylistItemList QueryGenerator::Generate() {
SongList songs = backend_->FindSongs(search_);
PlaylistItemList items;
@ -50,3 +52,5 @@ PlaylistItemList QueryPlaylistGenerator::Generate() {
}
return items;
}
} // namespace

View File

@ -17,23 +17,27 @@
#ifndef QUERYPLAYLISTGENERATOR_H
#define QUERYPLAYLISTGENERATOR_H
#include "playlistgenerator.h"
#include "smartplaylistsearch.h"
#include "generator.h"
#include "search.h"
class QueryPlaylistGenerator : public PlaylistGenerator {
namespace smart_playlists {
class QueryGenerator : public Generator {
public:
QueryPlaylistGenerator();
QueryGenerator();
QString type() const { return "Query"; }
void Load(const SmartPlaylistSearch& search);
void Load(const Search& search);
void Load(const QByteArray& data);
QByteArray Save() const;
PlaylistItemList Generate();
private:
SmartPlaylistSearch search_;
Search search_;
};
} // namespace
#endif // QUERYPLAYLISTGENERATOR_H

View File

@ -14,18 +14,20 @@
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
*/
#include "smartplaylistsearch.h"
#include "search.h"
#include "core/song.h"
#include <QStringList>
SmartPlaylistSearch::SmartPlaylistSearch() {
namespace smart_playlists {
Search::Search() {
Reset();
}
SmartPlaylistSearch::SmartPlaylistSearch(
Search::Search(
SearchType type, TermList terms, SortType sort_type,
SmartPlaylistSearchTerm::Field sort_field, int limit)
SearchTerm::Field sort_field, int limit)
: search_type_(type),
terms_(terms),
sort_type_(sort_type),
@ -34,20 +36,20 @@ SmartPlaylistSearch::SmartPlaylistSearch(
{
}
void SmartPlaylistSearch::Reset() {
void Search::Reset() {
search_type_ = Type_And;
terms_.clear();
sort_type_ = Sort_Random;
sort_field_ = SmartPlaylistSearchTerm::Field_Title;
sort_field_ = SearchTerm::Field_Title;
limit_ = -1;
}
QString SmartPlaylistSearch::ToSql(const QString& songs_table) const {
QString Search::ToSql(const QString& songs_table) const {
QString sql = "SELECT ROWID," + Song::kColumnSpec + " FROM " + songs_table;
// Add search terms
QStringList term_sql;
foreach (const SmartPlaylistSearchTerm& term, terms_) {
foreach (const SearchTerm& term, terms_) {
term_sql += term.ToSql();
}
if (!terms_.isEmpty() && search_type_ != Type_All) {
@ -59,7 +61,7 @@ QString SmartPlaylistSearch::ToSql(const QString& songs_table) const {
if (sort_type_ == Sort_Random) {
sql += " ORDER BY random()";
} else {
sql += " ORDER BY " + SmartPlaylistSearchTerm::FieldColumnName(sort_field_)
sql += " ORDER BY " + SearchTerm::FieldColumnName(sort_field_)
+ (sort_type_ == Sort_FieldAsc ? " ASC" : " DESC");
}
@ -71,13 +73,15 @@ QString SmartPlaylistSearch::ToSql(const QString& songs_table) const {
return sql;
}
bool SmartPlaylistSearch::is_valid() const {
bool Search::is_valid() const {
if (search_type_ == Type_All)
return true;
return !terms_.isEmpty();
}
QDataStream& operator <<(QDataStream& s, const SmartPlaylistSearch& search) {
} // namespace
QDataStream& operator <<(QDataStream& s, const smart_playlists::Search& search) {
s << search.terms_;
s << quint8(search.sort_type_);
s << quint8(search.sort_field_);
@ -85,13 +89,13 @@ QDataStream& operator <<(QDataStream& s, const SmartPlaylistSearch& search) {
return s;
}
QDataStream& operator >>(QDataStream& s, SmartPlaylistSearch& search) {
QDataStream& operator >>(QDataStream& s, smart_playlists::Search& search) {
quint8 sort_type, sort_field;
qint32 limit;
s >> search.terms_ >> sort_type >> sort_field >> limit;
search.sort_type_ = SmartPlaylistSearch::SortType(sort_type);
search.sort_field_ = SmartPlaylistSearchTerm::Field(sort_field);
search.sort_type_ = smart_playlists::Search::SortType(sort_type);
search.sort_field_ = smart_playlists::SearchTerm::Field(sort_field);
search.limit_ = limit;
return s;

View File

@ -17,12 +17,14 @@
#ifndef SMARTPLAYLISTSEARCH_H
#define SMARTPLAYLISTSEARCH_H
#include "playlistgenerator.h"
#include "smartplaylistsearchterm.h"
#include "generator.h"
#include "searchterm.h"
class SmartPlaylistSearch {
namespace smart_playlists {
class Search {
public:
typedef QList<SmartPlaylistSearchTerm> TermList;
typedef QList<SearchTerm> TermList;
// These values are persisted, so add to the end of the enum only
enum SearchType {
@ -38,24 +40,26 @@ public:
Sort_FieldDesc,
};
SmartPlaylistSearch();
SmartPlaylistSearch(SearchType type, TermList terms, SortType sort_type,
SmartPlaylistSearchTerm::Field sort_field,
int limit = PlaylistGenerator::kDefaultLimit);
Search();
Search(SearchType type, TermList terms, SortType sort_type,
SearchTerm::Field sort_field,
int limit = Generator::kDefaultLimit);
bool is_valid() const;
SearchType search_type_;
TermList terms_;
SortType sort_type_;
SmartPlaylistSearchTerm::Field sort_field_;
SearchTerm::Field sort_field_;
int limit_;
void Reset();
QString ToSql(const QString& songs_table) const;
};
QDataStream& operator <<(QDataStream& s, const SmartPlaylistSearch& search);
QDataStream& operator >>(QDataStream& s, SmartPlaylistSearch& search);
} // namespace
QDataStream& operator <<(QDataStream& s, const smart_playlists::Search& search);
QDataStream& operator >>(QDataStream& s, smart_playlists::Search& search);
#endif // SMARTPLAYLISTSEARCH_H

View File

@ -14,18 +14,20 @@
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
*/
#include "queryplaylistgenerator.h"
#include "smartplaylistsearchpreview.h"
#include "ui_smartplaylistsearchpreview.h"
#include "querygenerator.h"
#include "searchpreview.h"
#include "ui_searchpreview.h"
#include "playlist/playlist.h"
#include <QFutureWatcher>
#include <QtConcurrentRun>
namespace smart_playlists {
typedef QFuture<PlaylistItemList> Future;
typedef QFutureWatcher<PlaylistItemList> FutureWatcher;
SmartPlaylistSearchPreview::SmartPlaylistSearchPreview(QWidget *parent)
SearchPreview::SearchPreview(QWidget *parent)
: QWidget(parent),
ui_(new Ui_SmartPlaylistSearchPreview),
model_(NULL)
@ -42,11 +44,11 @@ SmartPlaylistSearchPreview::SmartPlaylistSearchPreview(QWidget *parent)
ui_->busy_container->hide();
}
SmartPlaylistSearchPreview::~SmartPlaylistSearchPreview() {
SearchPreview::~SearchPreview() {
delete ui_;
}
void SmartPlaylistSearchPreview::set_library(LibraryBackend* backend) {
void SearchPreview::set_library(LibraryBackend* backend) {
backend_ = backend;
model_ = new Playlist(NULL, NULL, backend_, -1, this);
@ -55,7 +57,7 @@ void SmartPlaylistSearchPreview::set_library(LibraryBackend* backend) {
ui_->tree->SetItemDelegates(backend_);
}
void SmartPlaylistSearchPreview::Update(const SmartPlaylistSearch& search) {
void SearchPreview::Update(const Search& search) {
if (generator_) {
// It's busy generating something already
pending_search_ = search;
@ -65,21 +67,21 @@ void SmartPlaylistSearchPreview::Update(const SmartPlaylistSearch& search) {
RunSearch(search);
}
void SmartPlaylistSearchPreview::RunSearch(const SmartPlaylistSearch& search) {
generator_.reset(new QueryPlaylistGenerator);
void SearchPreview::RunSearch(const Search& search) {
generator_.reset(new QueryGenerator);
generator_->set_library(backend_);
generator_->Load(search);
ui_->busy_container->show();
ui_->count_label->hide();
Future future = QtConcurrent::run(generator_.get(), &QueryPlaylistGenerator::Generate);
Future future = QtConcurrent::run(generator_.get(), &QueryGenerator::Generate);
FutureWatcher* watcher = new FutureWatcher(this);
watcher->setFuture(future);
connect(watcher, SIGNAL(finished()), SLOT(SearchFinished()));
}
void SmartPlaylistSearchPreview::SearchFinished() {
void SearchPreview::SearchFinished() {
FutureWatcher* watcher = static_cast<FutureWatcher*>(sender());
watcher->deleteLater();
generator_.reset();
@ -88,12 +90,12 @@ void SmartPlaylistSearchPreview::SearchFinished() {
// There was another search done while we were running - throw away these
// results and do that one now instead
RunSearch(pending_search_);
pending_search_ = SmartPlaylistSearch();
pending_search_ = Search();
return;
}
PlaylistItemList all_items = watcher->result();
PlaylistItemList displayed_items = all_items.mid(0, PlaylistGenerator::kDefaultLimit);
PlaylistItemList displayed_items = all_items.mid(0, Generator::kDefaultLimit);
model_->Clear();
model_->InsertItems(displayed_items);
@ -108,3 +110,5 @@ void SmartPlaylistSearchPreview::SearchFinished() {
ui_->busy_container->hide();
ui_->count_label->show();
}
} // namespace

View File

@ -17,7 +17,7 @@
#ifndef SMARTPLAYLISTSEARCHPREVIEW_H
#define SMARTPLAYLISTSEARCHPREVIEW_H
#include "smartplaylistsearch.h"
#include "search.h"
#include <QWidget>
@ -25,35 +25,40 @@
class LibraryBackend;
class Playlist;
class QueryPlaylistGenerator;
class Ui_SmartPlaylistSearchPreview;
class SmartPlaylistSearchPreview : public QWidget {
namespace smart_playlists {
class QueryGenerator;
class SearchPreview : public QWidget {
Q_OBJECT
public:
SmartPlaylistSearchPreview(QWidget *parent = 0);
~SmartPlaylistSearchPreview();
SearchPreview(QWidget *parent = 0);
~SearchPreview();
void set_library(LibraryBackend* backend);
void Update(const SmartPlaylistSearch& search);
void Update(const Search& search);
private:
void RunSearch(const SmartPlaylistSearch& search);
void RunSearch(const Search& search);
private slots:
void SearchFinished();
private:
Ui_SmartPlaylistSearchPreview* ui_;
QList<SmartPlaylistSearchTerm::Field> fields_;
QList<SearchTerm::Field> fields_;
LibraryBackend* backend_;
Playlist* model_;
SmartPlaylistSearch pending_search_;
boost::scoped_ptr<QueryPlaylistGenerator> generator_;
Search pending_search_;
boost::scoped_ptr<QueryGenerator> generator_;
};
} // namespace
#endif // SMARTPLAYLISTSEARCHPREVIEW_H

View File

@ -14,16 +14,18 @@
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
*/
#include "smartplaylistsearchterm.h"
#include "searchterm.h"
#include "playlist/playlist.h"
SmartPlaylistSearchTerm::SmartPlaylistSearchTerm()
namespace smart_playlists {
SearchTerm::SearchTerm()
: field_(Field_Title),
operator_(Op_Equals)
{
}
SmartPlaylistSearchTerm::SmartPlaylistSearchTerm(
SearchTerm::SearchTerm(
Field field, Operator op, const QVariant& value)
: field_(field),
operator_(op),
@ -31,7 +33,7 @@ SmartPlaylistSearchTerm::SmartPlaylistSearchTerm(
{
}
QString SmartPlaylistSearchTerm::ToSql() const {
QString SearchTerm::ToSql() const {
const QString col = FieldColumnName(field_);
QString value = value_.toString();
value.replace('\'', "''");
@ -58,7 +60,7 @@ QString SmartPlaylistSearchTerm::ToSql() const {
return QString();
}
bool SmartPlaylistSearchTerm::is_valid() const {
bool SearchTerm::is_valid() const {
switch (TypeOf(field_)) {
case Type_Text: return !value_.toString().isEmpty();
case Type_Date: return value_.toInt() != 0;
@ -69,7 +71,7 @@ bool SmartPlaylistSearchTerm::is_valid() const {
return false;
}
SmartPlaylistSearchTerm::Type SmartPlaylistSearchTerm::TypeOf(Field field) {
SearchTerm::Type SearchTerm::TypeOf(Field field) {
switch (field) {
case Field_Length:
return Type_Time;
@ -99,7 +101,7 @@ SmartPlaylistSearchTerm::Type SmartPlaylistSearchTerm::TypeOf(Field field) {
}
}
OperatorList SmartPlaylistSearchTerm::OperatorsForType(Type type) {
OperatorList SearchTerm::OperatorsForType(Type type) {
switch (type) {
case Type_Text:
return OperatorList() << Op_Contains << Op_NotContains << Op_Equals
@ -109,7 +111,7 @@ OperatorList SmartPlaylistSearchTerm::OperatorsForType(Type type) {
}
}
QString SmartPlaylistSearchTerm::OperatorText(Type type, Operator op) {
QString SearchTerm::OperatorText(Type type, Operator op) {
if (type == Type_Date) {
switch (op) {
case Op_GreaterThan: return QObject::tr("after");
@ -132,7 +134,7 @@ QString SmartPlaylistSearchTerm::OperatorText(Type type, Operator op) {
return QString();
}
QString SmartPlaylistSearchTerm::FieldColumnName(Field field) {
QString SearchTerm::FieldColumnName(Field field) {
switch (field) {
case Field_Length: return "length";
case Field_Track: return "track";
@ -161,7 +163,7 @@ QString SmartPlaylistSearchTerm::FieldColumnName(Field field) {
return QString();
}
QString SmartPlaylistSearchTerm::FieldName(Field field) {
QString SearchTerm::FieldName(Field field) {
switch (field) {
case Field_Length: return Playlist::column_name(Playlist::Column_Length);
case Field_Track: return Playlist::column_name(Playlist::Column_Track);
@ -190,7 +192,7 @@ QString SmartPlaylistSearchTerm::FieldName(Field field) {
return QString();
}
QString SmartPlaylistSearchTerm::FieldSortOrderText(Type type, bool ascending) {
QString SearchTerm::FieldSortOrderText(Type type, bool ascending) {
switch (type) {
case Type_Text: return ascending ? QObject::tr("A-Z") : QObject::tr("Z-A");
case Type_Date: return ascending ? QObject::tr("oldest first") : QObject::tr("newest first");
@ -201,17 +203,19 @@ QString SmartPlaylistSearchTerm::FieldSortOrderText(Type type, bool ascending) {
return QString();
}
QDataStream& operator <<(QDataStream& s, const SmartPlaylistSearchTerm& term) {
} // namespace
QDataStream& operator <<(QDataStream& s, const smart_playlists::SearchTerm& term) {
s << quint8(term.field_);
s << quint8(term.operator_);
s << term.value_;
return s;
}
QDataStream& operator >>(QDataStream& s, SmartPlaylistSearchTerm& term) {
QDataStream& operator >>(QDataStream& s, smart_playlists::SearchTerm& term) {
quint8 field, op;
s >> field >> op >> term.value_;
term.field_ = SmartPlaylistSearchTerm::Field(field);
term.operator_ = SmartPlaylistSearchTerm::Operator(op);
term.field_ = smart_playlists::SearchTerm::Field(field);
term.operator_ = smart_playlists::SearchTerm::Operator(op);
return s;
}

View File

@ -20,7 +20,9 @@
#include <QDataStream>
#include <QVariant>
class SmartPlaylistSearchTerm {
namespace smart_playlists {
class SearchTerm {
public:
// These values are persisted, so add to the end of the enum only
enum Field {
@ -74,8 +76,8 @@ public:
Type_Rating,
};
SmartPlaylistSearchTerm();
SmartPlaylistSearchTerm(Field field, Operator op, const QVariant& value);
SearchTerm();
SearchTerm(Field field, Operator op, const QVariant& value);
Field field_;
Operator operator_;
@ -92,9 +94,11 @@ public:
static QString FieldSortOrderText(Type type, bool ascending);
};
typedef QList<SmartPlaylistSearchTerm::Operator> OperatorList;
typedef QList<SearchTerm::Operator> OperatorList;
QDataStream& operator <<(QDataStream& s, const SmartPlaylistSearchTerm& term);
QDataStream& operator >>(QDataStream& s, SmartPlaylistSearchTerm& term);
} // namespace
QDataStream& operator <<(QDataStream& s, const smart_playlists::SearchTerm& term);
QDataStream& operator >>(QDataStream& s, smart_playlists::SearchTerm& term);
#endif // SMARTPLAYLISTSEARCHTERM_H

View File

@ -14,9 +14,9 @@
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
*/
#include "smartplaylistsearchterm.h"
#include "smartplaylistsearchtermwidget.h"
#include "ui_smartplaylistsearchtermwidget.h"
#include "searchterm.h"
#include "searchtermwidget.h"
#include "ui_searchtermwidget.h"
#include "core/utilities.h"
#include "playlist/playlist.h"
#include "playlist/playlistdelegates.h"
@ -31,9 +31,11 @@
// Exported by QtGui
void qt_blurImage(QPainter *p, QImage &blurImage, qreal radius, bool quality, bool alphaOnly, int transposed = 0);
class SmartPlaylistSearchTermWidget::Overlay : public QWidget {
namespace smart_playlists {
class SearchTermWidget::Overlay : public QWidget {
public:
Overlay(SmartPlaylistSearchTermWidget* parent);
Overlay(SearchTermWidget* parent);
void Grab();
void SetOpacity(float opacity);
float opacity() const { return opacity_; }
@ -46,7 +48,7 @@ protected:
void mouseReleaseEvent(QMouseEvent*);
private:
SmartPlaylistSearchTermWidget* parent_;
SearchTermWidget* parent_;
float opacity_;
QString text_;
@ -54,11 +56,11 @@ private:
QPixmap icon_;
};
const int SmartPlaylistSearchTermWidget::Overlay::kSpacing = 6;
const int SmartPlaylistSearchTermWidget::Overlay::kIconSize = 22;
const int SearchTermWidget::Overlay::kSpacing = 6;
const int SearchTermWidget::Overlay::kIconSize = 22;
SmartPlaylistSearchTermWidget::SmartPlaylistSearchTermWidget(LibraryBackend* library, QWidget* parent)
SearchTermWidget::SearchTermWidget(LibraryBackend* library, QWidget* parent)
: QWidget(parent),
ui_(new Ui_SmartPlaylistSearchTermWidget),
library_(library),
@ -80,8 +82,8 @@ SmartPlaylistSearchTermWidget::SmartPlaylistSearchTermWidget(LibraryBackend* lib
ui_->value_date->setDate(QDate::currentDate());
// Populate the combo boxes
for (int i=0 ; i<SmartPlaylistSearchTerm::FieldCount ; ++i) {
ui_->field->addItem(SmartPlaylistSearchTerm::FieldName(SmartPlaylistSearchTerm::Field(i)));
for (int i=0 ; i<SearchTerm::FieldCount ; ++i) {
ui_->field->addItem(SearchTerm::FieldName(SearchTerm::Field(i)));
ui_->field->setItemData(i, i);
}
ui_->field->model()->sort(0);
@ -101,41 +103,41 @@ SmartPlaylistSearchTermWidget::SmartPlaylistSearchTermWidget(LibraryBackend* lib
setStyleSheet(stylesheet);
}
SmartPlaylistSearchTermWidget::~SmartPlaylistSearchTermWidget() {
SearchTermWidget::~SearchTermWidget() {
delete ui_;
}
void SmartPlaylistSearchTermWidget::FieldChanged(int index) {
SmartPlaylistSearchTerm::Field field = SmartPlaylistSearchTerm::Field(
void SearchTermWidget::FieldChanged(int index) {
SearchTerm::Field field = SearchTerm::Field(
ui_->field->itemData(index).toInt());
SmartPlaylistSearchTerm::Type type = SmartPlaylistSearchTerm::TypeOf(field);
SearchTerm::Type type = SearchTerm::TypeOf(field);
// Populate the operator combo box
ui_->op->clear();
foreach (SmartPlaylistSearchTerm::Operator op, SmartPlaylistSearchTerm::OperatorsForType(type)) {
foreach (SearchTerm::Operator op, SearchTerm::OperatorsForType(type)) {
const int i = ui_->op->count();
ui_->op->addItem(SmartPlaylistSearchTerm::OperatorText(type, op));
ui_->op->addItem(SearchTerm::OperatorText(type, op));
ui_->op->setItemData(i, op);
}
// Show the correct value editor
QWidget* page = NULL;
switch (type) {
case SmartPlaylistSearchTerm::Type_Time: page = ui_->page_time; break;
case SmartPlaylistSearchTerm::Type_Number: page = ui_->page_number; break;
case SmartPlaylistSearchTerm::Type_Date: page = ui_->page_date; break;
case SmartPlaylistSearchTerm::Type_Rating: page = ui_->page_rating; break;
case SmartPlaylistSearchTerm::Type_Text: page = ui_->page_text; break;
case SearchTerm::Type_Time: page = ui_->page_time; break;
case SearchTerm::Type_Number: page = ui_->page_number; break;
case SearchTerm::Type_Date: page = ui_->page_date; break;
case SearchTerm::Type_Rating: page = ui_->page_rating; break;
case SearchTerm::Type_Text: page = ui_->page_text; break;
}
ui_->value_stack->setCurrentWidget(page);
// Maybe set a tag completer
switch (field) {
case SmartPlaylistSearchTerm::Field_Artist:
case SearchTerm::Field_Artist:
new TagCompleter(library_, Playlist::Column_Artist, ui_->value_text);
break;
case SmartPlaylistSearchTerm::Field_Album:
case SearchTerm::Field_Album:
new TagCompleter(library_, Playlist::Column_Album, ui_->value_text);
break;
@ -146,7 +148,7 @@ void SmartPlaylistSearchTermWidget::FieldChanged(int index) {
emit Changed();
}
void SmartPlaylistSearchTermWidget::SetActive(bool active) {
void SearchTermWidget::SetActive(bool active) {
active_ = active;
delete overlay_;
overlay_ = NULL;
@ -156,7 +158,7 @@ void SmartPlaylistSearchTermWidget::SetActive(bool active) {
}
}
void SmartPlaylistSearchTermWidget::enterEvent(QEvent*) {
void SearchTermWidget::enterEvent(QEvent*) {
if (!overlay_)
return;
@ -166,7 +168,7 @@ void SmartPlaylistSearchTermWidget::enterEvent(QEvent*) {
animation_->start();
}
void SmartPlaylistSearchTermWidget::leaveEvent(QEvent*) {
void SearchTermWidget::leaveEvent(QEvent*) {
if (!overlay_)
return;
@ -176,40 +178,40 @@ void SmartPlaylistSearchTermWidget::leaveEvent(QEvent*) {
animation_->start();
}
void SmartPlaylistSearchTermWidget::resizeEvent(QResizeEvent* e) {
void SearchTermWidget::resizeEvent(QResizeEvent* e) {
QWidget::resizeEvent(e);
if (overlay_ && overlay_->isVisible()) {
QTimer::singleShot(0, this, SLOT(Grab()));
}
}
void SmartPlaylistSearchTermWidget::showEvent(QShowEvent* e) {
void SearchTermWidget::showEvent(QShowEvent* e) {
QWidget::showEvent(e);
if (overlay_) {
QTimer::singleShot(0, this, SLOT(Grab()));
}
}
void SmartPlaylistSearchTermWidget::Grab() {
void SearchTermWidget::Grab() {
overlay_->Grab();
}
void SmartPlaylistSearchTermWidget::set_overlay_opacity(float opacity) {
void SearchTermWidget::set_overlay_opacity(float opacity) {
if (overlay_)
overlay_->SetOpacity(opacity);
}
float SmartPlaylistSearchTermWidget::overlay_opacity() const {
float SearchTermWidget::overlay_opacity() const {
return overlay_ ? overlay_->opacity() : 0.0;
}
SmartPlaylistSearchTerm SmartPlaylistSearchTermWidget::Term() const {
SearchTerm SearchTermWidget::Term() const {
const int field = ui_->field->itemData(ui_->field->currentIndex()).toInt();
const int op = ui_->op->itemData(ui_->op->currentIndex()).toInt();
SmartPlaylistSearchTerm ret;
ret.field_ = SmartPlaylistSearchTerm::Field(field);
ret.operator_ = SmartPlaylistSearchTerm::Operator(op);
SearchTerm ret;
ret.field_ = SearchTerm::Field(field);
ret.operator_ = SearchTerm::Operator(op);
// The value depends on the data type
const QWidget* value_page = ui_->value_stack->currentWidget();
@ -230,7 +232,7 @@ SmartPlaylistSearchTerm SmartPlaylistSearchTermWidget::Term() const {
SmartPlaylistSearchTermWidget::Overlay::Overlay(SmartPlaylistSearchTermWidget* parent)
SearchTermWidget::Overlay::Overlay(SearchTermWidget* parent)
: QWidget(parent),
parent_(parent),
opacity_(0.0),
@ -240,12 +242,12 @@ SmartPlaylistSearchTermWidget::Overlay::Overlay(SmartPlaylistSearchTermWidget* p
raise();
}
void SmartPlaylistSearchTermWidget::Overlay::SetOpacity(float opacity) {
void SearchTermWidget::Overlay::SetOpacity(float opacity) {
opacity_ = opacity;
update();
}
void SmartPlaylistSearchTermWidget::Overlay::Grab() {
void SearchTermWidget::Overlay::Grab() {
hide();
// Take a "screenshot" of the window
@ -267,7 +269,7 @@ void SmartPlaylistSearchTermWidget::Overlay::Grab() {
update();
}
void SmartPlaylistSearchTermWidget::Overlay::paintEvent(QPaintEvent*) {
void SearchTermWidget::Overlay::paintEvent(QPaintEvent*) {
QPainter p(this);
// Background
@ -300,6 +302,8 @@ void SmartPlaylistSearchTermWidget::Overlay::paintEvent(QPaintEvent*) {
p.drawText(text, Qt::TextDontClip | Qt::AlignVCenter, text_);
}
void SmartPlaylistSearchTermWidget::Overlay::mouseReleaseEvent(QMouseEvent*) {
void SearchTermWidget::Overlay::mouseReleaseEvent(QMouseEvent*) {
emit parent_->Clicked();
}
} // namespace

View File

@ -17,7 +17,7 @@
#ifndef SMARTPLAYLISTSEARCHTERMWIDGET_H
#define SMARTPLAYLISTSEARCHTERMWIDGET_H
#include "smartplaylistsearchterm.h"
#include "searchterm.h"
#include <QPushButton>
#include <QWidget>
@ -27,22 +27,24 @@ class Ui_SmartPlaylistSearchTermWidget;
class QPropertyAnimation;
class SmartPlaylistSearchTermWidget : public QWidget {
namespace smart_playlists {
class SearchTermWidget : public QWidget {
Q_OBJECT
Q_PROPERTY(float overlay_opacity
READ overlay_opacity
WRITE set_overlay_opacity);
public:
SmartPlaylistSearchTermWidget(LibraryBackend* library, QWidget* parent);
~SmartPlaylistSearchTermWidget();
SearchTermWidget(LibraryBackend* library, QWidget* parent);
~SearchTermWidget();
void SetActive(bool active);
float overlay_opacity() const;
void set_overlay_opacity(float opacity);
SmartPlaylistSearchTerm Term() const;
SearchTerm Term() const;
signals:
void Clicked();
@ -72,4 +74,6 @@ private:
bool active_;
};
} // namespace
#endif // SMARTPLAYLISTSEARCHTERMWIDGET_H

View File

@ -14,35 +14,37 @@
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
*/
#include "smartplaylistsearchpreview.h"
#include "smartplaylistsearchtermwidget.h"
#include "smartplaylistwizard.h"
#include "ui_smartplaylistwizard.h"
#include "playlistgenerator.h"
#include "generator.h"
#include "searchpreview.h"
#include "searchtermwidget.h"
#include "wizard.h"
#include "ui_wizard.h"
SmartPlaylistWizard::SearchPage::SearchPage(QWidget* parent)
namespace smart_playlists {
Wizard::SearchPage::SearchPage(QWidget* parent)
: QWizardPage(parent)
{
}
bool SmartPlaylistWizard::SearchPage::isComplete() const {
bool Wizard::SearchPage::isComplete() const {
if (type_->currentIndex() == 2) // All songs
return true;
foreach (SmartPlaylistSearchTermWidget* widget, terms_) {
foreach (SearchTermWidget* widget, terms_) {
if (!widget->Term().is_valid())
return false;
}
return true;
}
SmartPlaylistWizard::SmartPlaylistWizard(LibraryBackend* library, QWidget* parent)
Wizard::Wizard(LibraryBackend* library, QWidget* parent)
: QWizard(parent),
ui_(new Ui_SmartPlaylistWizard),
library_(library)
{
ui_->setupUi(this);
ui_->limit_value->setValue(PlaylistGenerator::kDefaultLimit);
ui_->limit_value->setValue(Generator::kDefaultLimit);
connect(ui_->search_type, SIGNAL(currentIndexChanged(int)), SLOT(SearchTypeChanged()));
@ -50,7 +52,7 @@ SmartPlaylistWizard::SmartPlaylistWizard(LibraryBackend* library, QWidget* paren
ui_->page_query_search->type_ = ui_->search_type;
// Create the new search term widget
ui_->page_query_search->new_term_ = new SmartPlaylistSearchTermWidget(library_, this);
ui_->page_query_search->new_term_ = new SearchTermWidget(library_, this);
ui_->page_query_search->new_term_->SetActive(false);
connect(ui_->page_query_search->new_term_, SIGNAL(Clicked()), SLOT(AddSearchTerm()));
@ -62,14 +64,14 @@ SmartPlaylistWizard::SmartPlaylistWizard(LibraryBackend* library, QWidget* paren
// Add the preview widget at the bottom of the search terms page
QVBoxLayout* terms_page_layout = static_cast<QVBoxLayout*>(ui_->page_query_search->layout());
terms_page_layout->addStretch();
ui_->page_query_search->preview_ = new SmartPlaylistSearchPreview(this);
ui_->page_query_search->preview_ = new SearchPreview(this);
ui_->page_query_search->preview_->set_library(library_);
terms_page_layout->addWidget(ui_->page_query_search->preview_);
// Add sort field texts
for (int i=0 ; i<SmartPlaylistSearchTerm::FieldCount ; ++i) {
const SmartPlaylistSearchTerm::Field field = SmartPlaylistSearchTerm::Field(i);
const QString field_name = SmartPlaylistSearchTerm::FieldName(field);
for (int i=0 ; i<SearchTerm::FieldCount ; ++i) {
const SearchTerm::Field field = SearchTerm::Field(i);
const QString field_name = SearchTerm::FieldName(field);
ui_->sort_field_value->addItem(field_name);
}
connect(ui_->sort_field_value, SIGNAL(currentIndexChanged(int)), SLOT(UpdateSortOrder()));
@ -84,25 +86,25 @@ SmartPlaylistWizard::SmartPlaylistWizard(LibraryBackend* library, QWidget* paren
ui_->sort_preview->set_library(library_);
}
SmartPlaylistWizard::~SmartPlaylistWizard() {
Wizard::~Wizard() {
delete ui_;
}
void SmartPlaylistWizard::UpdateSortOrder() {
const SmartPlaylistSearchTerm::Field field =
SmartPlaylistSearchTerm::Field(ui_->sort_field_value->currentIndex());
const SmartPlaylistSearchTerm::Type type = SmartPlaylistSearchTerm::TypeOf(field);
const QString asc = SmartPlaylistSearchTerm::FieldSortOrderText(type, true);
const QString desc = SmartPlaylistSearchTerm::FieldSortOrderText(type, false);
void Wizard::UpdateSortOrder() {
const SearchTerm::Field field =
SearchTerm::Field(ui_->sort_field_value->currentIndex());
const SearchTerm::Type type = SearchTerm::TypeOf(field);
const QString asc = SearchTerm::FieldSortOrderText(type, true);
const QString desc = SearchTerm::FieldSortOrderText(type, false);
ui_->sort_order->clear();
ui_->sort_order->addItem(asc);
ui_->sort_order->addItem(desc);
}
void SmartPlaylistWizard::AddSearchTerm() {
SmartPlaylistSearchTermWidget* widget =
new SmartPlaylistSearchTermWidget(library_, this);
void Wizard::AddSearchTerm() {
SearchTermWidget* widget =
new SearchTermWidget(library_, this);
connect(widget, SIGNAL(RemoveClicked()), SLOT(RemoveSearchTerm()));
connect(widget, SIGNAL(Changed()), SLOT(UpdateTermPreview()));
@ -113,9 +115,9 @@ void SmartPlaylistWizard::AddSearchTerm() {
UpdateTermPreview();
}
void SmartPlaylistWizard::RemoveSearchTerm() {
SmartPlaylistSearchTermWidget* widget =
qobject_cast<SmartPlaylistSearchTermWidget*>(sender());
void Wizard::RemoveSearchTerm() {
SearchTermWidget* widget =
qobject_cast<SearchTermWidget*>(sender());
if (!widget)
return;
@ -127,8 +129,8 @@ void SmartPlaylistWizard::RemoveSearchTerm() {
UpdateTermPreview();
}
void SmartPlaylistWizard::UpdateTermPreview() {
SmartPlaylistSearch search = MakeSearch();
void Wizard::UpdateTermPreview() {
Search search = MakeSearch();
emit ui_->page_query_search->completeChanged();
if (!search.is_valid())
return;
@ -139,35 +141,35 @@ void SmartPlaylistWizard::UpdateTermPreview() {
ui_->page_query_search->preview_->Update(search);
}
void SmartPlaylistWizard::UpdateSortPreview() {
SmartPlaylistSearch search = MakeSearch();
void Wizard::UpdateSortPreview() {
Search search = MakeSearch();
if (!search.is_valid())
return;
ui_->sort_preview->Update(search);
}
SmartPlaylistSearch SmartPlaylistWizard::MakeSearch() const {
SmartPlaylistSearch ret;
Search Wizard::MakeSearch() const {
Search ret;
// Search type
ret.search_type_ = SmartPlaylistSearch::SearchType(ui_->search_type->currentIndex());
ret.search_type_ = Search::SearchType(ui_->search_type->currentIndex());
// Search terms
foreach (SmartPlaylistSearchTermWidget* widget, ui_->page_query_search->terms_) {
SmartPlaylistSearchTerm term = widget->Term();
foreach (SearchTermWidget* widget, ui_->page_query_search->terms_) {
SearchTerm term = widget->Term();
if (term.is_valid())
ret.terms_ << term;
}
// Sort order
if (ui_->sort_random->isChecked()) {
ret.sort_type_ = SmartPlaylistSearch::Sort_Random;
ret.sort_type_ = Search::Sort_Random;
} else {
const bool ascending = ui_->sort_order->currentIndex() == 0;
ret.sort_type_ = ascending ? SmartPlaylistSearch::Sort_FieldAsc :
SmartPlaylistSearch::Sort_FieldDesc;
ret.sort_field_ = SmartPlaylistSearchTerm::Field(
ret.sort_type_ = ascending ? Search::Sort_FieldAsc :
Search::Sort_FieldDesc;
ret.sort_field_ = SearchTerm::Field(
ui_->sort_field_value->currentIndex());
}
@ -180,9 +182,11 @@ SmartPlaylistSearch SmartPlaylistWizard::MakeSearch() const {
return ret;
}
void SmartPlaylistWizard::SearchTypeChanged() {
void Wizard::SearchTypeChanged() {
const bool all = ui_->search_type->currentIndex() == 2;
ui_->terms_group->setEnabled(!all);
UpdateTermPreview();
}
} // namespace

View File

@ -17,37 +17,40 @@
#ifndef SMARTPLAYLISTWIZARD_H
#define SMARTPLAYLISTWIZARD_H
#include "smartplaylistsearch.h"
#include "search.h"
#include <QWizard>
class LibraryBackend;
class SmartPlaylistSearchPreview;
class SmartPlaylistSearchTermWidget;
class Ui_SmartPlaylistWizard;
class QComboBox;
class QVBoxLayout;
class SmartPlaylistWizard : public QWizard {
namespace smart_playlists {
class SearchPreview;
class SearchTermWidget;
class Wizard : public QWizard {
Q_OBJECT
public:
SmartPlaylistWizard(LibraryBackend* library, QWidget* parent);
~SmartPlaylistWizard();
Wizard(LibraryBackend* library, QWidget* parent);
~Wizard();
class SearchPage : public QWizardPage {
friend class SmartPlaylistWizard;
friend class Wizard;
public:
SearchPage(QWidget* parent = 0);
bool isComplete() const;
QVBoxLayout* layout_;
QComboBox* type_;
QList<SmartPlaylistSearchTermWidget*> terms_;
SmartPlaylistSearchTermWidget* new_term_;
QList<SearchTermWidget*> terms_;
SearchTermWidget* new_term_;
SmartPlaylistSearchPreview* preview_;
SearchPreview* preview_;
};
private slots:
@ -61,11 +64,13 @@ private slots:
void UpdateSortOrder();
private:
SmartPlaylistSearch MakeSearch() const;
Search MakeSearch() const;
private:
Ui_SmartPlaylistWizard* ui_;
LibraryBackend* library_;
};
} // namespace
#endif // SMARTPLAYLISTWIZARD_H

View File

@ -81,7 +81,7 @@ QLabel {
</item>
</layout>
</widget>
<widget class="SmartPlaylistWizard::SearchPage" name="page_query_search">
<widget class="smart_playlists::Wizard::SearchPage" name="page_query_search">
<property name="styleSheet">
<string notr="true">#termframe {
border: 1px solid grey;
@ -233,22 +233,22 @@ margin-left: 9px;
</widget>
</item>
<item>
<widget class="SmartPlaylistSearchPreview" name="sort_preview" native="true"/>
<widget class="smart_playlists::SearchPreview" name="sort_preview" native="true"/>
</item>
</layout>
</widget>
</widget>
<customwidgets>
<customwidget>
<class>SmartPlaylistSearchPreview</class>
<class>smart_playlists::SearchPreview</class>
<extends>QWidget</extends>
<header>smartplaylists/smartplaylistsearchpreview.h</header>
<header>smartplaylists/searchpreview.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>SmartPlaylistWizard::SearchPage</class>
<class>smart_playlists::Wizard::SearchPage</class>
<extends>QWizardPage</extends>
<header>smartplaylists/smartplaylistwizard.h</header>
<header>smartplaylists/wizard.h</header>
<container>1</container>
</customwidget>
</customwidgets>

View File

@ -653,7 +653,7 @@ void MainWindow::LibrarySongsDoubleClicked(const SongList &songs) {
AddLibrarySongsToPlaylist(autoclear_playlist_, songs);
}
void MainWindow::AddSmartPlaylistToPlaylist(bool clear_first, PlaylistGeneratorPtr gen) {
void MainWindow::AddSmartPlaylistToPlaylist(bool clear_first, smart_playlists::GeneratorPtr gen) {
if (clear_first)
playlists_->ClearCurrent();

View File

@ -198,7 +198,7 @@ class MainWindow : public QMainWindow, public PlatformInterface {
void AddFilesToPlaylist(bool clear_first, const QList<QUrl>& urls);
void AddLibraryItemToPlaylist(bool clear_first, const QModelIndexList& indexes);
void AddLibrarySongsToPlaylist(bool clear_first, const SongList& songs);
void AddSmartPlaylistToPlaylist(bool clear_first, PlaylistGeneratorPtr gen);
void AddSmartPlaylistToPlaylist(bool clear_first, smart_playlists::GeneratorPtr gen);
void AddDeviceSongsToPlaylist(bool clear_first, const SongList& songs);
void AddUrls(bool play_now, const QList<QUrl>& urls);
void ConnectInfoView(SongInfoBase* view);