Use C++11 enum class
This commit is contained in:
@@ -43,13 +43,13 @@ class PlaylistGenerator : public QObject, public std::enable_shared_from_this<Pl
|
||||
static const int kDefaultDynamicHistory;
|
||||
static const int kDefaultDynamicFuture;
|
||||
|
||||
enum Type {
|
||||
Type_None = 0,
|
||||
Type_Query = 1
|
||||
enum class Type {
|
||||
None = 0,
|
||||
Query = 1
|
||||
};
|
||||
|
||||
// Creates a new PlaylistGenerator of the given type
|
||||
static std::shared_ptr<PlaylistGenerator> Create(const Type type = Type_Query);
|
||||
static std::shared_ptr<PlaylistGenerator> Create(const Type type = Type::Query);
|
||||
|
||||
// Should be called before Load on a new PlaylistGenerator
|
||||
void set_collection(CollectionBackend *backend) { backend_ = backend; }
|
||||
@@ -68,7 +68,7 @@ class PlaylistGenerator : public QObject, public std::enable_shared_from_this<Pl
|
||||
|
||||
// Creates and returns a playlist
|
||||
// Called from non-UI thread.
|
||||
virtual PlaylistItemList Generate() = 0;
|
||||
virtual PlaylistItemPtrList Generate() = 0;
|
||||
|
||||
// If the generator can be used as a dynamic playlist then GenerateMore should return the next tracks in the sequence.
|
||||
// The subclass should remember the last GetDynamicHistory() + GetDynamicFuture() tracks,
|
||||
@@ -76,9 +76,9 @@ class PlaylistGenerator : public QObject, public std::enable_shared_from_this<Pl
|
||||
virtual bool is_dynamic() const { return false; }
|
||||
virtual void set_dynamic(const bool dynamic) { Q_UNUSED(dynamic); }
|
||||
// Called from non-UI thread.
|
||||
virtual PlaylistItemList GenerateMore(int count) {
|
||||
virtual PlaylistItemPtrList GenerateMore(int count) {
|
||||
Q_UNUSED(count);
|
||||
return PlaylistItemList();
|
||||
return PlaylistItemPtrList();
|
||||
}
|
||||
|
||||
virtual int GetDynamicHistory() { return kDefaultDynamicHistory; }
|
||||
|
||||
@@ -46,7 +46,7 @@ PlaylistGeneratorInserter::PlaylistGeneratorInserter(TaskManager *task_manager,
|
||||
enqueue_next_(false),
|
||||
is_dynamic_(false) {}
|
||||
|
||||
PlaylistItemList PlaylistGeneratorInserter::Generate(PlaylistGeneratorPtr generator, int dynamic_count) {
|
||||
PlaylistItemPtrList PlaylistGeneratorInserter::Generate(PlaylistGeneratorPtr generator, int dynamic_count) {
|
||||
|
||||
if (dynamic_count > 0) {
|
||||
return generator->GenerateMore(dynamic_count);
|
||||
@@ -70,17 +70,17 @@ void PlaylistGeneratorInserter::Load(Playlist *destination, const int row, const
|
||||
|
||||
QObject::connect(generator.get(), &PlaylistGenerator::Error, this, &PlaylistGeneratorInserter::Error);
|
||||
|
||||
QFuture<PlaylistItemList> future = QtConcurrent::run(PlaylistGeneratorInserter::Generate, generator, dynamic_count);
|
||||
QFutureWatcher<PlaylistItemList> *watcher = new QFutureWatcher<PlaylistItemList>();
|
||||
QObject::connect(watcher, &QFutureWatcher<PlaylistItemList>::finished, this, &PlaylistGeneratorInserter::Finished);
|
||||
QFuture<PlaylistItemPtrList> future = QtConcurrent::run(PlaylistGeneratorInserter::Generate, generator, dynamic_count);
|
||||
QFutureWatcher<PlaylistItemPtrList> *watcher = new QFutureWatcher<PlaylistItemPtrList>();
|
||||
QObject::connect(watcher, &QFutureWatcher<PlaylistItemPtrList>::finished, this, &PlaylistGeneratorInserter::Finished);
|
||||
watcher->setFuture(future);
|
||||
|
||||
}
|
||||
|
||||
void PlaylistGeneratorInserter::Finished() {
|
||||
|
||||
QFutureWatcher<PlaylistItemList> *watcher = static_cast<QFutureWatcher<PlaylistItemList>*>(sender());
|
||||
PlaylistItemList items = watcher->result();
|
||||
QFutureWatcher<PlaylistItemPtrList> *watcher = static_cast<QFutureWatcher<PlaylistItemPtrList>*>(sender());
|
||||
PlaylistItemPtrList items = watcher->result();
|
||||
watcher->deleteLater();
|
||||
|
||||
if (items.isEmpty()) {
|
||||
|
||||
@@ -44,7 +44,7 @@ class PlaylistGeneratorInserter : public QObject {
|
||||
void Load(Playlist *destination, const int row, const bool play_now, const bool enqueue, const bool enqueue_next, PlaylistGeneratorPtr generator, const int dynamic_count = 0);
|
||||
|
||||
private:
|
||||
static PlaylistItemList Generate(PlaylistGeneratorPtr generator, const int dynamic_count);
|
||||
static PlaylistItemPtrList Generate(PlaylistGeneratorPtr generator, const int dynamic_count);
|
||||
|
||||
signals:
|
||||
void Error(QString message);
|
||||
|
||||
@@ -67,7 +67,7 @@ QByteArray PlaylistQueryGenerator::Save() const {
|
||||
|
||||
}
|
||||
|
||||
PlaylistItemList PlaylistQueryGenerator::Generate() {
|
||||
PlaylistItemPtrList PlaylistQueryGenerator::Generate() {
|
||||
|
||||
previous_ids_.clear();
|
||||
current_pos_ = 0;
|
||||
@@ -75,7 +75,7 @@ PlaylistItemList PlaylistQueryGenerator::Generate() {
|
||||
|
||||
}
|
||||
|
||||
PlaylistItemList PlaylistQueryGenerator::GenerateMore(const int count) {
|
||||
PlaylistItemPtrList PlaylistQueryGenerator::GenerateMore(const int count) {
|
||||
|
||||
SmartPlaylistSearch search_copy = search_;
|
||||
search_copy.id_not_in_ = previous_ids_;
|
||||
@@ -83,13 +83,13 @@ PlaylistItemList PlaylistQueryGenerator::GenerateMore(const int count) {
|
||||
search_copy.limit_ = count;
|
||||
}
|
||||
|
||||
if (search_copy.sort_type_ != SmartPlaylistSearch::Sort_Random) {
|
||||
if (search_copy.sort_type_ != SmartPlaylistSearch::SortType::Random) {
|
||||
search_copy.first_item_ = current_pos_;
|
||||
current_pos_ += search_copy.limit_;
|
||||
}
|
||||
|
||||
SongList songs = backend_->SmartPlaylistsFindSongs(search_copy);
|
||||
PlaylistItemList items;
|
||||
PlaylistItemPtrList items;
|
||||
items.reserve(songs.count());
|
||||
for (const Song &song : songs) {
|
||||
items << PlaylistItem::NewFromSong(song);
|
||||
|
||||
@@ -37,14 +37,14 @@ class PlaylistQueryGenerator : public PlaylistGenerator {
|
||||
explicit PlaylistQueryGenerator(QObject *parent = nullptr);
|
||||
explicit PlaylistQueryGenerator(const QString &name, const SmartPlaylistSearch &search, const bool dynamic = false, QObject *parent = nullptr);
|
||||
|
||||
Type type() const override { return Type_Query; }
|
||||
Type type() const override { return Type::Query; }
|
||||
|
||||
void Load(const SmartPlaylistSearch &search);
|
||||
void Load(const QByteArray &data) override;
|
||||
QByteArray Save() const override;
|
||||
|
||||
PlaylistItemList Generate() override;
|
||||
PlaylistItemList GenerateMore(const int count) override;
|
||||
PlaylistItemPtrList Generate() override;
|
||||
PlaylistItemPtrList GenerateMore(const int count) override;
|
||||
bool is_dynamic() const override { return dynamic_; }
|
||||
void set_dynamic(bool dynamic) override { dynamic_ = dynamic; }
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@ int SmartPlaylistQueryWizardPlugin::CreatePages(QWizard *wizard, int finish_page
|
||||
terms_page_layout->addWidget(search_page_->preview_);
|
||||
|
||||
// Add sort field texts
|
||||
for (int i = 0; i < SmartPlaylistSearchTerm::FieldCount; ++i) {
|
||||
for (int i = 0; i < static_cast<int>(SmartPlaylistSearchTerm::Field::FieldCount); ++i) {
|
||||
const SmartPlaylistSearchTerm::Field field = static_cast<SmartPlaylistSearchTerm::Field>(i);
|
||||
const QString field_name = SmartPlaylistSearchTerm::FieldName(field);
|
||||
sort_ui_->field_value->addItem(field_name);
|
||||
@@ -172,7 +172,7 @@ void SmartPlaylistQueryWizardPlugin::SetGenerator(PlaylistGeneratorPtr g) {
|
||||
SmartPlaylistSearch search = gen->search();
|
||||
|
||||
// Search type
|
||||
search_page_->ui_->type->setCurrentIndex(search.search_type_);
|
||||
search_page_->ui_->type->setCurrentIndex(static_cast<int>(search.search_type_));
|
||||
|
||||
// Search terms
|
||||
qDeleteAll(search_page_->terms_);
|
||||
@@ -184,13 +184,13 @@ void SmartPlaylistQueryWizardPlugin::SetGenerator(PlaylistGeneratorPtr g) {
|
||||
}
|
||||
|
||||
// Sort order
|
||||
if (search.sort_type_ == SmartPlaylistSearch::Sort_Random) {
|
||||
if (search.sort_type_ == SmartPlaylistSearch::SortType::Random) {
|
||||
sort_ui_->random->setChecked(true);
|
||||
}
|
||||
else {
|
||||
sort_ui_->field->setChecked(true);
|
||||
sort_ui_->order->setCurrentIndex(search.sort_type_ == SmartPlaylistSearch::Sort_FieldAsc ? 0 : 1);
|
||||
sort_ui_->field_value->setCurrentIndex(search.sort_field_);
|
||||
sort_ui_->order->setCurrentIndex(search.sort_type_ == SmartPlaylistSearch::SortType::FieldAsc ? 0 : 1);
|
||||
sort_ui_->field_value->setCurrentIndex(static_cast<int>(search.sort_field_));
|
||||
}
|
||||
|
||||
// Limit
|
||||
@@ -292,11 +292,11 @@ SmartPlaylistSearch SmartPlaylistQueryWizardPlugin::MakeSearch() const {
|
||||
|
||||
// Sort order
|
||||
if (sort_ui_->random->isChecked()) {
|
||||
ret.sort_type_ = SmartPlaylistSearch::Sort_Random;
|
||||
ret.sort_type_ = SmartPlaylistSearch::SortType::Random;
|
||||
}
|
||||
else {
|
||||
const bool ascending = sort_ui_->order->currentIndex() == 0;
|
||||
ret.sort_type_ = ascending ? SmartPlaylistSearch::Sort_FieldAsc : SmartPlaylistSearch::Sort_FieldDesc;
|
||||
ret.sort_type_ = ascending ? SmartPlaylistSearch::SortType::FieldAsc : SmartPlaylistSearch::SortType::FieldDesc;
|
||||
ret.sort_field_ = static_cast<SmartPlaylistSearchTerm::Field>(sort_ui_->field_value->currentIndex());
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ class SmartPlaylistQueryWizardPlugin : public SmartPlaylistWizardPlugin {
|
||||
explicit SmartPlaylistQueryWizardPlugin(Application *app, CollectionBackend *collection, QObject *parent);
|
||||
~SmartPlaylistQueryWizardPlugin() override;
|
||||
|
||||
PlaylistGenerator::Type type() const override { return PlaylistGenerator::Type_Query; }
|
||||
PlaylistGenerator::Type type() const override { return PlaylistGenerator::Type::Query; }
|
||||
QString name() const override;
|
||||
QString description() const override;
|
||||
bool is_dynamic() const override { return true; }
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
#include "smartplaylistsearch.h"
|
||||
|
||||
SmartPlaylistSearch::SmartPlaylistSearch() : search_type_(Type_And), sort_type_(Sort_Random), sort_field_(SmartPlaylistSearchTerm::Field_Title), limit_(-1), first_item_(0) { Reset(); }
|
||||
SmartPlaylistSearch::SmartPlaylistSearch() : search_type_(SearchType::And), sort_type_(SortType::Random), sort_field_(SmartPlaylistSearchTerm::Field::Title), limit_(-1), first_item_(0) { Reset(); }
|
||||
|
||||
SmartPlaylistSearch::SmartPlaylistSearch(const SearchType type, const TermList &terms, const SortType sort_type, const SmartPlaylistSearchTerm::Field sort_field, const int limit)
|
||||
: search_type_(type),
|
||||
@@ -40,10 +40,10 @@ SmartPlaylistSearch::SmartPlaylistSearch(const SearchType type, const TermList &
|
||||
|
||||
void SmartPlaylistSearch::Reset() {
|
||||
|
||||
search_type_ = Type_And;
|
||||
search_type_ = SearchType::And;
|
||||
terms_.clear();
|
||||
sort_type_ = Sort_Random;
|
||||
sort_field_ = SmartPlaylistSearchTerm::Field_Title;
|
||||
sort_type_ = SortType::Random;
|
||||
sort_field_ = SmartPlaylistSearchTerm::Field::Title;
|
||||
limit_ = -1;
|
||||
first_item_ = 0;
|
||||
|
||||
@@ -61,8 +61,8 @@ QString SmartPlaylistSearch::ToSql(const QString &songs_table) const {
|
||||
term_where_clauses << term.ToSql();
|
||||
}
|
||||
|
||||
if (!terms_.isEmpty() && search_type_ != Type_All) {
|
||||
QString boolean_op = search_type_ == Type_And ? " AND " : " OR ";
|
||||
if (!terms_.isEmpty() && search_type_ != SearchType::All) {
|
||||
QString boolean_op = search_type_ == SearchType::And ? " AND " : " OR ";
|
||||
where_clauses << "(" + term_where_clauses.join(boolean_op) + ")";
|
||||
}
|
||||
|
||||
@@ -84,11 +84,11 @@ QString SmartPlaylistSearch::ToSql(const QString &songs_table) const {
|
||||
}
|
||||
|
||||
// Add sort by
|
||||
if (sort_type_ == Sort_Random) {
|
||||
if (sort_type_ == SortType::Random) {
|
||||
sql += " ORDER BY random()";
|
||||
}
|
||||
else {
|
||||
sql += " ORDER BY " + SmartPlaylistSearchTerm::FieldColumnName(sort_field_) + (sort_type_ == Sort_FieldAsc ? " ASC" : " DESC");
|
||||
sql += " ORDER BY " + SmartPlaylistSearchTerm::FieldColumnName(sort_field_) + (sort_type_ == SortType::FieldAsc ? " ASC" : " DESC");
|
||||
}
|
||||
|
||||
// Add limit
|
||||
@@ -106,7 +106,7 @@ QString SmartPlaylistSearch::ToSql(const QString &songs_table) const {
|
||||
|
||||
bool SmartPlaylistSearch::is_valid() const {
|
||||
|
||||
if (search_type_ == Type_All) return true;
|
||||
if (search_type_ == SearchType::All) return true;
|
||||
return !terms_.isEmpty();
|
||||
|
||||
}
|
||||
|
||||
@@ -36,10 +36,18 @@ class SmartPlaylistSearch {
|
||||
using TermList = QList<SmartPlaylistSearchTerm>;
|
||||
|
||||
// These values are persisted, so add to the end of the enum only
|
||||
enum SearchType { Type_And = 0, Type_Or, Type_All, };
|
||||
enum class SearchType {
|
||||
And = 0,
|
||||
Or,
|
||||
All
|
||||
};
|
||||
|
||||
// These values are persisted, so add to the end of the enum only
|
||||
enum SortType { Sort_Random = 0, Sort_FieldAsc, Sort_FieldDesc, };
|
||||
enum class SortType {
|
||||
Random = 0,
|
||||
FieldAsc,
|
||||
FieldDesc
|
||||
};
|
||||
|
||||
explicit SmartPlaylistSearch();
|
||||
explicit SmartPlaylistSearch(const SearchType type, const TermList &terms, const SortType sort_type, const SmartPlaylistSearchTerm::Field sort_field, const int limit = PlaylistGenerator::kDefaultLimit);
|
||||
|
||||
@@ -105,7 +105,7 @@ void SmartPlaylistSearchPreview::showEvent(QShowEvent *e) {
|
||||
}
|
||||
|
||||
namespace {
|
||||
PlaylistItemList DoRunSearch(PlaylistGeneratorPtr gen) { return gen->Generate(); }
|
||||
PlaylistItemPtrList DoRunSearch(PlaylistGeneratorPtr gen) { return gen->Generate(); }
|
||||
} // namespace
|
||||
|
||||
void SmartPlaylistSearchPreview::RunSearch(const SmartPlaylistSearch &search) {
|
||||
@@ -116,17 +116,17 @@ void SmartPlaylistSearchPreview::RunSearch(const SmartPlaylistSearch &search) {
|
||||
|
||||
ui_->busy_container->show();
|
||||
ui_->count_label->hide();
|
||||
QFuture<PlaylistItemList> future = QtConcurrent::run(DoRunSearch, generator_);
|
||||
QFutureWatcher<PlaylistItemList> *watcher = new QFutureWatcher<PlaylistItemList>();
|
||||
QObject::connect(watcher, &QFutureWatcher<PlaylistItemList>::finished, this, &SmartPlaylistSearchPreview::SearchFinished);
|
||||
QFuture<PlaylistItemPtrList> future = QtConcurrent::run(DoRunSearch, generator_);
|
||||
QFutureWatcher<PlaylistItemPtrList> *watcher = new QFutureWatcher<PlaylistItemPtrList>();
|
||||
QObject::connect(watcher, &QFutureWatcher<PlaylistItemPtrList>::finished, this, &SmartPlaylistSearchPreview::SearchFinished);
|
||||
watcher->setFuture(future);
|
||||
|
||||
}
|
||||
|
||||
void SmartPlaylistSearchPreview::SearchFinished() {
|
||||
|
||||
QFutureWatcher<PlaylistItemList> *watcher = static_cast<QFutureWatcher<PlaylistItemList>*>(sender());
|
||||
PlaylistItemList all_items = watcher->result();
|
||||
QFutureWatcher<PlaylistItemPtrList> *watcher = static_cast<QFutureWatcher<PlaylistItemPtrList>*>(sender());
|
||||
PlaylistItemPtrList all_items = watcher->result();
|
||||
watcher->deleteLater();
|
||||
|
||||
last_search_ = std::dynamic_pointer_cast<PlaylistQueryGenerator>(generator_)->search();
|
||||
@@ -140,7 +140,7 @@ void SmartPlaylistSearchPreview::SearchFinished() {
|
||||
return;
|
||||
}
|
||||
|
||||
PlaylistItemList displayed_items = all_items.mid(0, PlaylistGenerator::kDefaultLimit);
|
||||
PlaylistItemPtrList displayed_items = all_items.mid(0, PlaylistGenerator::kDefaultLimit);
|
||||
|
||||
model_->Clear();
|
||||
model_->InsertItems(displayed_items);
|
||||
|
||||
@@ -29,21 +29,21 @@
|
||||
#include "smartplaylistsearchterm.h"
|
||||
#include "playlist/playlist.h"
|
||||
|
||||
SmartPlaylistSearchTerm::SmartPlaylistSearchTerm() : field_(Field_Title), operator_(Op_Equals), date_(Date_Hour) {}
|
||||
SmartPlaylistSearchTerm::SmartPlaylistSearchTerm() : field_(Field::Title), operator_(Operator::Equals), datetype_(DateType::Hour) {}
|
||||
|
||||
SmartPlaylistSearchTerm::SmartPlaylistSearchTerm(Field field, Operator op, const QVariant &value)
|
||||
: field_(field), operator_(op), value_(value), date_(Date_Hour) {}
|
||||
: field_(field), operator_(op), value_(value), datetype_(DateType::Hour) {}
|
||||
|
||||
QString SmartPlaylistSearchTerm::ToSql() const {
|
||||
|
||||
QString col = FieldColumnName(field_);
|
||||
QString date = DateName(date_, true);
|
||||
QString date = DateName(datetype_, true);
|
||||
QString value = value_.toString();
|
||||
value.replace('\'', "''");
|
||||
|
||||
if (field_ == Field_Filetype) {
|
||||
if (field_ == Field::Filetype) {
|
||||
Song::FileType filetype = Song::FiletypeByExtension(value);
|
||||
if (filetype == Song::FileType_Unknown) {
|
||||
if (filetype == Song::FileType::Unknown) {
|
||||
filetype = Song::FiletypeByDescription(value);
|
||||
}
|
||||
value = QString::number(static_cast<int>(filetype));
|
||||
@@ -51,15 +51,15 @@ QString SmartPlaylistSearchTerm::ToSql() const {
|
||||
|
||||
QString second_value;
|
||||
|
||||
bool special_date_query = (operator_ == SmartPlaylistSearchTerm::Op_NumericDate ||
|
||||
operator_ == SmartPlaylistSearchTerm::Op_NumericDateNot ||
|
||||
operator_ == SmartPlaylistSearchTerm::Op_RelativeDate);
|
||||
bool special_date_query = (operator_ == Operator::NumericDate ||
|
||||
operator_ == Operator::NumericDateNot ||
|
||||
operator_ == Operator::RelativeDate);
|
||||
|
||||
// Floating point problems...
|
||||
// Theoretically 0.0 == 0 stars, 0.1 == 0.5 star, 0.2 == 1 star etc.
|
||||
// but in reality we need to consider anything from [0.05, 0.15) range to be 0.5 star etc.
|
||||
// To make this simple, I transform the ranges to integeres and then operate on ints: [0.0, 0.05) -> 0, [0.05, 0.15) -> 1 etc.
|
||||
if (TypeOf(field_) == Type_Date) {
|
||||
if (TypeOf(field_) == Type::Date) {
|
||||
if (!special_date_query) {
|
||||
// We have the exact date
|
||||
// The calendar widget specifies no time so ditch the possible time part
|
||||
@@ -80,75 +80,75 @@ QString SmartPlaylistSearchTerm::ToSql() const {
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (TypeOf(field_) == Type_Time) {
|
||||
else if (TypeOf(field_) == Type::Time) {
|
||||
// Convert seconds to nanoseconds
|
||||
value = "CAST (" + value + " *1000000000 AS INTEGER)";
|
||||
}
|
||||
|
||||
// File paths need some extra processing since they are stored as encoded urls in the database.
|
||||
if (field_ == Field_Filepath) {
|
||||
if (operator_ == Op_StartsWith || operator_ == Op_Equals) {
|
||||
if (field_ == Field::Filepath) {
|
||||
if (operator_ == Operator::StartsWith || operator_ == Operator::Equals) {
|
||||
value = QUrl::fromLocalFile(value).toEncoded();
|
||||
}
|
||||
else {
|
||||
value = QUrl(value).toEncoded();
|
||||
}
|
||||
}
|
||||
else if (TypeOf(field_) == Type_Rating) {
|
||||
else if (TypeOf(field_) == Type::Rating) {
|
||||
col = "CAST ((" + col + " + 0.05) * 10 AS INTEGER)";
|
||||
value = "CAST ((" + value + " + 0.05) * 10 AS INTEGER)";
|
||||
}
|
||||
|
||||
switch (operator_) {
|
||||
case Op_Contains:
|
||||
case Operator::Contains:
|
||||
return col + " LIKE '%" + value + "%'";
|
||||
case Op_NotContains:
|
||||
case Operator::NotContains:
|
||||
return col + " NOT LIKE '%" + value + "%'";
|
||||
case Op_StartsWith:
|
||||
case Operator::StartsWith:
|
||||
return col + " LIKE '" + value + "%'";
|
||||
case Op_EndsWith:
|
||||
case Operator::EndsWith:
|
||||
return col + " LIKE '%" + value + "'";
|
||||
case Op_Equals:
|
||||
if (TypeOf(field_) == Type_Text) {
|
||||
case Operator::Equals:
|
||||
if (TypeOf(field_) == Type::Text) {
|
||||
return col + " LIKE '" + value + "'";
|
||||
}
|
||||
else if (TypeOf(field_) == Type_Date || TypeOf(field_) == Type_Time || TypeOf(field_) == Type_Rating) {
|
||||
else if (TypeOf(field_) == Type::Date || TypeOf(field_) == Type::Time || TypeOf(field_) == Type::Rating) {
|
||||
return col + " = " + value;
|
||||
}
|
||||
else {
|
||||
return col + " = '" + value + "'";
|
||||
}
|
||||
case Op_GreaterThan:
|
||||
if (TypeOf(field_) == Type_Date || TypeOf(field_) == Type_Time || TypeOf(field_) == Type_Rating) {
|
||||
case Operator::GreaterThan:
|
||||
if (TypeOf(field_) == Type::Date || TypeOf(field_) == Type::Time || TypeOf(field_) == Type::Rating) {
|
||||
return col + " > " + value;
|
||||
}
|
||||
else {
|
||||
return col + " > '" + value + "'";
|
||||
}
|
||||
case Op_LessThan:
|
||||
if (TypeOf(field_) == Type_Date || TypeOf(field_) == Type_Time || TypeOf(field_) == Type_Rating) {
|
||||
case Operator::LessThan:
|
||||
if (TypeOf(field_) == Type::Date || TypeOf(field_) == Type::Time || TypeOf(field_) == Type::Rating) {
|
||||
return col + " < " + value;
|
||||
}
|
||||
else {
|
||||
return col + " < '" + value + "'";
|
||||
}
|
||||
case Op_NumericDate:
|
||||
case Operator::NumericDate:
|
||||
return col + " > " + "DATETIME('now', '-" + value + " " + date + "', 'localtime')";
|
||||
case Op_NumericDateNot:
|
||||
case Operator::NumericDateNot:
|
||||
return col + " < " + "DATETIME('now', '-" + value + " " + date + "', 'localtime')";
|
||||
case Op_RelativeDate:
|
||||
case Operator::RelativeDate:
|
||||
// Consider the time range before the first date but after the second one
|
||||
return "(" + col + " < " + "DATETIME('now', '-" + value + " " + date + "', 'localtime') AND " + col + " > " + "DATETIME('now', '-" + second_value + " " + date + "', 'localtime'))";
|
||||
case Op_NotEquals:
|
||||
if (TypeOf(field_) == Type_Text) {
|
||||
case Operator::NotEquals:
|
||||
if (TypeOf(field_) == Type::Text) {
|
||||
return col + " <> '" + value + "'";
|
||||
}
|
||||
else {
|
||||
return col + " <> " + value;
|
||||
}
|
||||
case Op_Empty:
|
||||
case Operator::Empty:
|
||||
return col + " = ''";
|
||||
case Op_NotEmpty:
|
||||
case Operator::NotEmpty:
|
||||
return col + " <> ''";
|
||||
}
|
||||
|
||||
@@ -158,30 +158,30 @@ QString SmartPlaylistSearchTerm::ToSql() const {
|
||||
bool SmartPlaylistSearchTerm::is_valid() const {
|
||||
|
||||
// We can accept also a zero value in these cases
|
||||
if (operator_ == SmartPlaylistSearchTerm::Op_NumericDate) {
|
||||
if (operator_ == Operator::NumericDate) {
|
||||
return value_.toInt() >= 0;
|
||||
}
|
||||
else if (operator_ == SmartPlaylistSearchTerm::Op_RelativeDate) {
|
||||
else if (operator_ == Operator::RelativeDate) {
|
||||
return (value_.toInt() >= 0 && value_.toInt() < second_value_.toInt());
|
||||
}
|
||||
|
||||
switch (TypeOf(field_)) {
|
||||
case Type_Text:
|
||||
if (operator_ == SmartPlaylistSearchTerm::Op_Empty || operator_ == SmartPlaylistSearchTerm::Op_NotEmpty) {
|
||||
case Type::Text:
|
||||
if (operator_ == Operator::Empty || operator_ == Operator::NotEmpty) {
|
||||
return true;
|
||||
}
|
||||
// Empty fields should be possible.
|
||||
// All values for Type_Text should be valid.
|
||||
// All values for Type::Text should be valid.
|
||||
return !value_.toString().isEmpty();
|
||||
case Type_Date:
|
||||
case Type::Date:
|
||||
return value_.toInt() != 0;
|
||||
case Type_Number:
|
||||
case Type::Number:
|
||||
return value_.toInt() >= 0;
|
||||
case Type_Time:
|
||||
case Type::Time:
|
||||
return true;
|
||||
case Type_Rating:
|
||||
case Type::Rating:
|
||||
return value_.toFloat() >= 0.0;
|
||||
case Type_Invalid:
|
||||
case Type::Invalid:
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
@@ -189,78 +189,80 @@ bool SmartPlaylistSearchTerm::is_valid() const {
|
||||
}
|
||||
|
||||
bool SmartPlaylistSearchTerm::operator==(const SmartPlaylistSearchTerm &other) const {
|
||||
return field_ == other.field_ && operator_ == other.operator_ &&
|
||||
value_ == other.value_ && date_ == other.date_ &&
|
||||
return field_ == other.field_ &&
|
||||
operator_ == other.operator_ &&
|
||||
value_ == other.value_ &&
|
||||
datetype_ == other.datetype_ &&
|
||||
second_value_ == other.second_value_;
|
||||
}
|
||||
|
||||
SmartPlaylistSearchTerm::Type SmartPlaylistSearchTerm::TypeOf(const Field field) {
|
||||
|
||||
switch (field) {
|
||||
case Field_Length:
|
||||
return Type_Time;
|
||||
case Field::Length:
|
||||
return Type::Time;
|
||||
|
||||
case Field_Track:
|
||||
case Field_Disc:
|
||||
case Field_Year:
|
||||
case Field_OriginalYear:
|
||||
case Field_Filesize:
|
||||
case Field_PlayCount:
|
||||
case Field_SkipCount:
|
||||
case Field_Samplerate:
|
||||
case Field_Bitdepth:
|
||||
case Field_Bitrate:
|
||||
return Type_Number;
|
||||
case Field::Track:
|
||||
case Field::Disc:
|
||||
case Field::Year:
|
||||
case Field::OriginalYear:
|
||||
case Field::Filesize:
|
||||
case Field::PlayCount:
|
||||
case Field::SkipCount:
|
||||
case Field::Samplerate:
|
||||
case Field::Bitdepth:
|
||||
case Field::Bitrate:
|
||||
return Type::Number;
|
||||
|
||||
case Field_LastPlayed:
|
||||
case Field_DateCreated:
|
||||
case Field_DateModified:
|
||||
return Type_Date;
|
||||
case Field::LastPlayed:
|
||||
case Field::DateCreated:
|
||||
case Field::DateModified:
|
||||
return Type::Date;
|
||||
|
||||
case Field_Rating:
|
||||
return Type_Rating;
|
||||
case Field::Rating:
|
||||
return Type::Rating;
|
||||
|
||||
default:
|
||||
return Type_Text;
|
||||
return Type::Text;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
OperatorList SmartPlaylistSearchTerm::OperatorsForType(const Type type) {
|
||||
SmartPlaylistSearchTerm::OperatorList SmartPlaylistSearchTerm::OperatorsForType(const Type type) {
|
||||
|
||||
switch (type) {
|
||||
case Type_Text:
|
||||
return OperatorList() << Op_Contains << Op_NotContains << Op_Equals
|
||||
<< Op_NotEquals << Op_Empty << Op_NotEmpty
|
||||
<< Op_StartsWith << Op_EndsWith;
|
||||
case Type_Date:
|
||||
return OperatorList() << Op_Equals << Op_NotEquals << Op_GreaterThan
|
||||
<< Op_LessThan << Op_NumericDate
|
||||
<< Op_NumericDateNot << Op_RelativeDate;
|
||||
case Type::Text:
|
||||
return OperatorList() << Operator::Contains << Operator::NotContains << Operator::Equals
|
||||
<< Operator::NotEquals << Operator::Empty << Operator::NotEmpty
|
||||
<< Operator::StartsWith << Operator::EndsWith;
|
||||
case Type::Date:
|
||||
return OperatorList() << Operator::Equals << Operator::NotEquals << Operator::GreaterThan
|
||||
<< Operator::LessThan << Operator::NumericDate
|
||||
<< Operator::NumericDateNot << Operator::RelativeDate;
|
||||
default:
|
||||
return OperatorList() << Op_Equals << Op_NotEquals << Op_GreaterThan
|
||||
<< Op_LessThan;
|
||||
return OperatorList() << Operator::Equals << Operator::NotEquals << Operator::GreaterThan
|
||||
<< Operator::LessThan;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
QString SmartPlaylistSearchTerm::OperatorText(const Type type, const Operator op) {
|
||||
|
||||
if (type == Type_Date) {
|
||||
if (type == Type::Date) {
|
||||
switch (op) {
|
||||
case Op_GreaterThan:
|
||||
case Operator::GreaterThan:
|
||||
return QObject::tr("after");
|
||||
case Op_LessThan:
|
||||
case Operator::LessThan:
|
||||
return QObject::tr("before");
|
||||
case Op_Equals:
|
||||
case Operator::Equals:
|
||||
return QObject::tr("on");
|
||||
case Op_NotEquals:
|
||||
case Operator::NotEquals:
|
||||
return QObject::tr("not on");
|
||||
case Op_NumericDate:
|
||||
case Operator::NumericDate:
|
||||
return QObject::tr("in the last");
|
||||
case Op_NumericDateNot:
|
||||
case Operator::NumericDateNot:
|
||||
return QObject::tr("not in the last");
|
||||
case Op_RelativeDate:
|
||||
case Operator::RelativeDate:
|
||||
return QObject::tr("between");
|
||||
default:
|
||||
return QString();
|
||||
@@ -268,25 +270,25 @@ QString SmartPlaylistSearchTerm::OperatorText(const Type type, const Operator op
|
||||
}
|
||||
|
||||
switch (op) {
|
||||
case Op_Contains:
|
||||
case Operator::Contains:
|
||||
return QObject::tr("contains");
|
||||
case Op_NotContains:
|
||||
case Operator::NotContains:
|
||||
return QObject::tr("does not contain");
|
||||
case Op_StartsWith:
|
||||
case Operator::StartsWith:
|
||||
return QObject::tr("starts with");
|
||||
case Op_EndsWith:
|
||||
case Operator::EndsWith:
|
||||
return QObject::tr("ends with");
|
||||
case Op_GreaterThan:
|
||||
case Operator::GreaterThan:
|
||||
return QObject::tr("greater than");
|
||||
case Op_LessThan:
|
||||
case Operator::LessThan:
|
||||
return QObject::tr("less than");
|
||||
case Op_Equals:
|
||||
case Operator::Equals:
|
||||
return QObject::tr("equals");
|
||||
case Op_NotEquals:
|
||||
case Operator::NotEquals:
|
||||
return QObject::tr("not equals");
|
||||
case Op_Empty:
|
||||
case Operator::Empty:
|
||||
return QObject::tr("empty");
|
||||
case Op_NotEmpty:
|
||||
case Operator::NotEmpty:
|
||||
return QObject::tr("not empty");
|
||||
default:
|
||||
return QString();
|
||||
@@ -299,59 +301,59 @@ QString SmartPlaylistSearchTerm::OperatorText(const Type type, const Operator op
|
||||
QString SmartPlaylistSearchTerm::FieldColumnName(const Field field) {
|
||||
|
||||
switch (field) {
|
||||
case Field_AlbumArtist:
|
||||
case Field::AlbumArtist:
|
||||
return "albumartist";
|
||||
case Field_Artist:
|
||||
case Field::Artist:
|
||||
return "artist";
|
||||
case Field_Album:
|
||||
case Field::Album:
|
||||
return "album";
|
||||
case Field_Title:
|
||||
case Field::Title:
|
||||
return "title";
|
||||
case Field_Track:
|
||||
case Field::Track:
|
||||
return "track";
|
||||
case Field_Disc:
|
||||
case Field::Disc:
|
||||
return "disc";
|
||||
case Field_Year:
|
||||
case Field::Year:
|
||||
return "year";
|
||||
case Field_OriginalYear:
|
||||
case Field::OriginalYear:
|
||||
return "originalyear";
|
||||
case Field_Genre:
|
||||
case Field::Genre:
|
||||
return "genre";
|
||||
case Field_Composer:
|
||||
case Field::Composer:
|
||||
return "composer";
|
||||
case Field_Performer:
|
||||
case Field::Performer:
|
||||
return "performer";
|
||||
case Field_Grouping:
|
||||
case Field::Grouping:
|
||||
return "grouping";
|
||||
case Field_Comment:
|
||||
case Field::Comment:
|
||||
return "comment";
|
||||
case Field_Length:
|
||||
case Field::Length:
|
||||
return "length";
|
||||
case Field_Filepath:
|
||||
case Field::Filepath:
|
||||
return "url";
|
||||
case Field_Filetype:
|
||||
case Field::Filetype:
|
||||
return "filetype";
|
||||
case Field_Filesize:
|
||||
case Field::Filesize:
|
||||
return "filesize";
|
||||
case Field_DateCreated:
|
||||
case Field::DateCreated:
|
||||
return "ctime";
|
||||
case Field_DateModified:
|
||||
case Field::DateModified:
|
||||
return "mtime";
|
||||
case Field_PlayCount:
|
||||
case Field::PlayCount:
|
||||
return "playcount";
|
||||
case Field_SkipCount:
|
||||
case Field::SkipCount:
|
||||
return "skipcount";
|
||||
case Field_LastPlayed:
|
||||
case Field::LastPlayed:
|
||||
return "lastplayed";
|
||||
case Field_Rating:
|
||||
case Field::Rating:
|
||||
return "rating";
|
||||
case Field_Samplerate:
|
||||
case Field::Samplerate:
|
||||
return "samplerate";
|
||||
case Field_Bitdepth:
|
||||
case Field::Bitdepth:
|
||||
return "bitdepth";
|
||||
case Field_Bitrate:
|
||||
case Field::Bitrate:
|
||||
return "bitrate";
|
||||
case FieldCount:
|
||||
case Field::FieldCount:
|
||||
Q_ASSERT(0);
|
||||
}
|
||||
return QString();
|
||||
@@ -361,59 +363,59 @@ QString SmartPlaylistSearchTerm::FieldColumnName(const Field field) {
|
||||
QString SmartPlaylistSearchTerm::FieldName(const Field field) {
|
||||
|
||||
switch (field) {
|
||||
case Field_AlbumArtist:
|
||||
case Field::AlbumArtist:
|
||||
return Playlist::column_name(Playlist::Column_AlbumArtist);
|
||||
case Field_Artist:
|
||||
case Field::Artist:
|
||||
return Playlist::column_name(Playlist::Column_Artist);
|
||||
case Field_Album:
|
||||
case Field::Album:
|
||||
return Playlist::column_name(Playlist::Column_Album);
|
||||
case Field_Title:
|
||||
case Field::Title:
|
||||
return Playlist::column_name(Playlist::Column_Title);
|
||||
case Field_Track:
|
||||
case Field::Track:
|
||||
return Playlist::column_name(Playlist::Column_Track);
|
||||
case Field_Disc:
|
||||
case Field::Disc:
|
||||
return Playlist::column_name(Playlist::Column_Disc);
|
||||
case Field_Year:
|
||||
case Field::Year:
|
||||
return Playlist::column_name(Playlist::Column_Year);
|
||||
case Field_OriginalYear:
|
||||
case Field::OriginalYear:
|
||||
return Playlist::column_name(Playlist::Column_OriginalYear);
|
||||
case Field_Genre:
|
||||
case Field::Genre:
|
||||
return Playlist::column_name(Playlist::Column_Genre);
|
||||
case Field_Composer:
|
||||
case Field::Composer:
|
||||
return Playlist::column_name(Playlist::Column_Composer);
|
||||
case Field_Performer:
|
||||
case Field::Performer:
|
||||
return Playlist::column_name(Playlist::Column_Performer);
|
||||
case Field_Grouping:
|
||||
case Field::Grouping:
|
||||
return Playlist::column_name(Playlist::Column_Grouping);
|
||||
case Field_Comment:
|
||||
case Field::Comment:
|
||||
return QObject::tr("Comment");
|
||||
case Field_Length:
|
||||
case Field::Length:
|
||||
return Playlist::column_name(Playlist::Column_Length);
|
||||
case Field_Filepath:
|
||||
case Field::Filepath:
|
||||
return Playlist::column_name(Playlist::Column_Filename);
|
||||
case Field_Filetype:
|
||||
case Field::Filetype:
|
||||
return Playlist::column_name(Playlist::Column_Filetype);
|
||||
case Field_Filesize:
|
||||
case Field::Filesize:
|
||||
return Playlist::column_name(Playlist::Column_Filesize);
|
||||
case Field_DateCreated:
|
||||
case Field::DateCreated:
|
||||
return Playlist::column_name(Playlist::Column_DateCreated);
|
||||
case Field_DateModified:
|
||||
case Field::DateModified:
|
||||
return Playlist::column_name(Playlist::Column_DateModified);
|
||||
case Field_PlayCount:
|
||||
case Field::PlayCount:
|
||||
return Playlist::column_name(Playlist::Column_PlayCount);
|
||||
case Field_SkipCount:
|
||||
case Field::SkipCount:
|
||||
return Playlist::column_name(Playlist::Column_SkipCount);
|
||||
case Field_LastPlayed:
|
||||
case Field::LastPlayed:
|
||||
return Playlist::column_name(Playlist::Column_LastPlayed);
|
||||
case Field_Rating:
|
||||
case Field::Rating:
|
||||
return Playlist::column_name(Playlist::Column_Rating);
|
||||
case Field_Samplerate:
|
||||
case Field::Samplerate:
|
||||
return Playlist::column_name(Playlist::Column_Samplerate);
|
||||
case Field_Bitdepth:
|
||||
case Field::Bitdepth:
|
||||
return Playlist::column_name(Playlist::Column_Bitdepth);
|
||||
case Field_Bitrate:
|
||||
case Field::Bitrate:
|
||||
return Playlist::column_name(Playlist::Column_Bitrate);
|
||||
case FieldCount:
|
||||
case Field::FieldCount:
|
||||
Q_ASSERT(0);
|
||||
}
|
||||
return QString();
|
||||
@@ -423,35 +425,35 @@ QString SmartPlaylistSearchTerm::FieldName(const Field field) {
|
||||
QString SmartPlaylistSearchTerm::FieldSortOrderText(const Type type, const bool ascending) {
|
||||
|
||||
switch (type) {
|
||||
case Type_Text:
|
||||
case Type::Text:
|
||||
return ascending ? QObject::tr("A-Z") : QObject::tr("Z-A");
|
||||
case Type_Date:
|
||||
case Type::Date:
|
||||
return ascending ? QObject::tr("oldest first") : QObject::tr("newest first");
|
||||
case Type_Time:
|
||||
case Type::Time:
|
||||
return ascending ? QObject::tr("shortest first") : QObject::tr("longest first");
|
||||
case Type_Number:
|
||||
case Type_Rating:
|
||||
case Type::Number:
|
||||
case Type::Rating:
|
||||
return ascending ? QObject::tr("smallest first") : QObject::tr("biggest first");
|
||||
case Type_Invalid:
|
||||
case Type::Invalid:
|
||||
return QString();
|
||||
}
|
||||
return QString();
|
||||
|
||||
}
|
||||
|
||||
QString SmartPlaylistSearchTerm::DateName(const DateType date, const bool forQuery) {
|
||||
QString SmartPlaylistSearchTerm::DateName(const DateType datetype, const bool forQuery) {
|
||||
|
||||
// If forQuery is true, untranslated keywords are returned
|
||||
switch (date) {
|
||||
case Date_Hour:
|
||||
switch (datetype) {
|
||||
case DateType::Hour:
|
||||
return (forQuery ? "hours" : QObject::tr("Hours"));
|
||||
case Date_Day:
|
||||
case DateType::Day:
|
||||
return (forQuery ? "days" : QObject::tr("Days"));
|
||||
case Date_Week:
|
||||
case DateType::Week:
|
||||
return (forQuery ? "weeks" : QObject::tr("Weeks"));
|
||||
case Date_Month:
|
||||
case DateType::Month:
|
||||
return (forQuery ? "months" : QObject::tr("Months"));
|
||||
case Date_Year:
|
||||
case DateType::Year:
|
||||
return (forQuery ? "years" : QObject::tr("Years"));
|
||||
}
|
||||
return QString();
|
||||
@@ -464,7 +466,7 @@ QDataStream &operator<<(QDataStream &s, const SmartPlaylistSearchTerm &term) {
|
||||
s << static_cast<quint8>(term.operator_);
|
||||
s << term.value_;
|
||||
s << term.second_value_;
|
||||
s << static_cast<quint8>(term.date_);
|
||||
s << static_cast<quint8>(term.datetype_);
|
||||
return s;
|
||||
|
||||
}
|
||||
@@ -475,7 +477,7 @@ QDataStream &operator>>(QDataStream &s, SmartPlaylistSearchTerm &term) {
|
||||
s >> field >> op >> term.value_ >> term.second_value_ >> date;
|
||||
term.field_ = static_cast<SmartPlaylistSearchTerm::Field>(field);
|
||||
term.operator_ = static_cast<SmartPlaylistSearchTerm::Operator>(op);
|
||||
term.date_ = static_cast<SmartPlaylistSearchTerm::DateType>(date);
|
||||
term.datetype_ = static_cast<SmartPlaylistSearchTerm::DateType>(date);
|
||||
return s;
|
||||
|
||||
}
|
||||
|
||||
@@ -31,82 +31,83 @@
|
||||
class SmartPlaylistSearchTerm {
|
||||
public:
|
||||
// These values are persisted, so add to the end of the enum only
|
||||
enum Field {
|
||||
Field_AlbumArtist = 0,
|
||||
Field_Artist,
|
||||
Field_Album,
|
||||
Field_Title,
|
||||
Field_Track,
|
||||
Field_Disc,
|
||||
Field_Year,
|
||||
Field_OriginalYear,
|
||||
Field_Genre,
|
||||
Field_Composer,
|
||||
Field_Performer,
|
||||
Field_Grouping,
|
||||
Field_Comment,
|
||||
Field_Length,
|
||||
Field_Filepath,
|
||||
Field_Filetype,
|
||||
Field_Filesize,
|
||||
Field_DateCreated,
|
||||
Field_DateModified,
|
||||
Field_PlayCount,
|
||||
Field_SkipCount,
|
||||
Field_LastPlayed,
|
||||
Field_Rating,
|
||||
Field_Samplerate,
|
||||
Field_Bitdepth,
|
||||
Field_Bitrate,
|
||||
enum class Field {
|
||||
AlbumArtist = 0,
|
||||
Artist,
|
||||
Album,
|
||||
Title,
|
||||
Track,
|
||||
Disc,
|
||||
Year,
|
||||
OriginalYear,
|
||||
Genre,
|
||||
Composer,
|
||||
Performer,
|
||||
Grouping,
|
||||
Comment,
|
||||
Length,
|
||||
Filepath,
|
||||
Filetype,
|
||||
Filesize,
|
||||
DateCreated,
|
||||
DateModified,
|
||||
PlayCount,
|
||||
SkipCount,
|
||||
LastPlayed,
|
||||
Rating,
|
||||
Samplerate,
|
||||
Bitdepth,
|
||||
Bitrate,
|
||||
FieldCount
|
||||
};
|
||||
|
||||
// These values are persisted, so add to the end of the enum only
|
||||
enum Operator {
|
||||
enum class Operator {
|
||||
// For text
|
||||
Op_Contains = 0,
|
||||
Op_NotContains = 1,
|
||||
Op_StartsWith = 2,
|
||||
Op_EndsWith = 3,
|
||||
Contains = 0,
|
||||
NotContains = 1,
|
||||
StartsWith = 2,
|
||||
EndsWith = 3,
|
||||
|
||||
// For numbers
|
||||
Op_GreaterThan = 4,
|
||||
Op_LessThan = 5,
|
||||
GreaterThan = 4,
|
||||
LessThan = 5,
|
||||
|
||||
// For everything
|
||||
Op_Equals = 6,
|
||||
Op_NotEquals = 9,
|
||||
Equals = 6,
|
||||
NotEquals = 9,
|
||||
|
||||
// For numeric dates (e.g. in the last X days)
|
||||
Op_NumericDate = 7,
|
||||
NumericDate = 7,
|
||||
// For relative dates
|
||||
Op_RelativeDate = 8,
|
||||
RelativeDate = 8,
|
||||
|
||||
// For numeric dates (e.g. not in the last X days)
|
||||
Op_NumericDateNot = 10,
|
||||
NumericDateNot = 10,
|
||||
|
||||
Op_Empty = 11,
|
||||
Op_NotEmpty = 12,
|
||||
Empty = 11,
|
||||
NotEmpty = 12,
|
||||
|
||||
// Next value = 13
|
||||
};
|
||||
using OperatorList = QList<Operator>;
|
||||
|
||||
enum Type {
|
||||
Type_Text,
|
||||
Type_Date,
|
||||
Type_Time,
|
||||
Type_Number,
|
||||
Type_Rating,
|
||||
Type_Invalid
|
||||
enum class Type {
|
||||
Text,
|
||||
Date,
|
||||
Time,
|
||||
Number,
|
||||
Rating,
|
||||
Invalid
|
||||
};
|
||||
|
||||
// These values are persisted, so add to the end of the enum only
|
||||
enum DateType {
|
||||
Date_Hour = 0,
|
||||
Date_Day,
|
||||
Date_Week,
|
||||
Date_Month,
|
||||
Date_Year
|
||||
enum class DateType {
|
||||
Hour = 0,
|
||||
Day,
|
||||
Week,
|
||||
Month,
|
||||
Year
|
||||
};
|
||||
|
||||
explicit SmartPlaylistSearchTerm();
|
||||
@@ -115,7 +116,7 @@ class SmartPlaylistSearchTerm {
|
||||
Field field_;
|
||||
Operator operator_;
|
||||
QVariant value_;
|
||||
DateType date_;
|
||||
DateType datetype_;
|
||||
// For relative dates, we need a second parameter, might be useful somewhere else
|
||||
QVariant second_value_;
|
||||
|
||||
@@ -130,13 +131,14 @@ class SmartPlaylistSearchTerm {
|
||||
static QString FieldName(const Field field);
|
||||
static QString FieldColumnName(const Field field);
|
||||
static QString FieldSortOrderText(const Type type, const bool ascending);
|
||||
static QString DateName(const DateType date, const bool forQuery);
|
||||
static QString DateName(const DateType datetype, const bool forQuery);
|
||||
|
||||
};
|
||||
|
||||
using OperatorList = QList<SmartPlaylistSearchTerm::Operator>;
|
||||
|
||||
QDataStream &operator<<(QDataStream &s, const SmartPlaylistSearchTerm &term);
|
||||
QDataStream &operator>>(QDataStream &s, SmartPlaylistSearchTerm &term);
|
||||
|
||||
Q_DECLARE_METATYPE(SmartPlaylistSearchTerm::Operator)
|
||||
Q_DECLARE_METATYPE(SmartPlaylistSearchTerm::OperatorList)
|
||||
|
||||
#endif // SMARTPLAYLISTSEARCHTERM_H
|
||||
|
||||
@@ -81,7 +81,7 @@ SmartPlaylistSearchTermWidget::SmartPlaylistSearchTermWidget(CollectionBackend *
|
||||
animation_(new QPropertyAnimation(this, "overlay_opacity", this)),
|
||||
active_(true),
|
||||
initialized_(false),
|
||||
current_field_type_(SmartPlaylistSearchTerm::Type_Invalid) {
|
||||
current_field_type_(SmartPlaylistSearchTerm::Type::Invalid) {
|
||||
|
||||
ui_->setupUi(this);
|
||||
|
||||
@@ -103,7 +103,7 @@ SmartPlaylistSearchTermWidget::SmartPlaylistSearchTermWidget(CollectionBackend *
|
||||
ui_->value_date->setDate(QDate::currentDate());
|
||||
|
||||
// Populate the combo boxes
|
||||
for (int i = 0; i < SmartPlaylistSearchTerm::FieldCount; ++i) {
|
||||
for (int i = 0; i < static_cast<int>(SmartPlaylistSearchTerm::Field::FieldCount); ++i) {
|
||||
ui_->field->addItem(SmartPlaylistSearchTerm::FieldName(static_cast<SmartPlaylistSearchTerm::Field>(i)));
|
||||
ui_->field->setItemData(i, i);
|
||||
}
|
||||
@@ -149,7 +149,7 @@ void SmartPlaylistSearchTermWidget::FieldChanged(int index) {
|
||||
for (SmartPlaylistSearchTerm::Operator op : SmartPlaylistSearchTerm::OperatorsForType(type)) {
|
||||
const int i = ui_->op->count();
|
||||
ui_->op->addItem(SmartPlaylistSearchTerm::OperatorText(type, op));
|
||||
ui_->op->setItemData(i, op);
|
||||
ui_->op->setItemData(i, QVariant::fromValue(op));
|
||||
}
|
||||
current_field_type_ = type;
|
||||
}
|
||||
@@ -158,27 +158,27 @@ void SmartPlaylistSearchTermWidget::FieldChanged(int index) {
|
||||
QWidget *page = nullptr;
|
||||
SmartPlaylistSearchTerm::Operator op = static_cast<SmartPlaylistSearchTerm::Operator>(ui_->op->itemData(ui_->op->currentIndex()).toInt());
|
||||
switch (type) {
|
||||
case SmartPlaylistSearchTerm::Type_Time:
|
||||
case SmartPlaylistSearchTerm::Type::Time:
|
||||
page = ui_->page_time;
|
||||
break;
|
||||
case SmartPlaylistSearchTerm::Type_Number:
|
||||
case SmartPlaylistSearchTerm::Type::Number:
|
||||
page = ui_->page_number;
|
||||
break;
|
||||
case SmartPlaylistSearchTerm::Type_Date:
|
||||
case SmartPlaylistSearchTerm::Type::Date:
|
||||
page = ui_->page_date;
|
||||
break;
|
||||
case SmartPlaylistSearchTerm::Type_Text:
|
||||
if (op == SmartPlaylistSearchTerm::Op_Empty || op == SmartPlaylistSearchTerm::Op_NotEmpty) {
|
||||
case SmartPlaylistSearchTerm::Type::Text:
|
||||
if (op == SmartPlaylistSearchTerm::Operator::Empty || op == SmartPlaylistSearchTerm::Operator::NotEmpty) {
|
||||
page = ui_->page_empty;
|
||||
}
|
||||
else {
|
||||
page = ui_->page_text;
|
||||
}
|
||||
break;
|
||||
case SmartPlaylistSearchTerm::Type_Rating:
|
||||
case SmartPlaylistSearchTerm::Type::Rating:
|
||||
page = ui_->page_rating;
|
||||
break;
|
||||
case SmartPlaylistSearchTerm::Type_Invalid:
|
||||
case SmartPlaylistSearchTerm::Type::Invalid:
|
||||
page = nullptr;
|
||||
break;
|
||||
}
|
||||
@@ -186,11 +186,11 @@ void SmartPlaylistSearchTermWidget::FieldChanged(int index) {
|
||||
|
||||
// Maybe set a tag completer
|
||||
switch (field) {
|
||||
case SmartPlaylistSearchTerm::Field_Artist:
|
||||
case SmartPlaylistSearchTerm::Field::Artist:
|
||||
new TagCompleter(collection_, Playlist::Column_Artist, ui_->value_text);
|
||||
break;
|
||||
|
||||
case SmartPlaylistSearchTerm::Field_Album:
|
||||
case SmartPlaylistSearchTerm::Field::Album:
|
||||
new TagCompleter(collection_, Playlist::Column_Album, ui_->value_text);
|
||||
break;
|
||||
|
||||
@@ -214,7 +214,7 @@ void SmartPlaylistSearchTermWidget::OpChanged(int idx) {
|
||||
// We need to change the page only in the following case
|
||||
if ((ui_->value_stack->currentWidget() == ui_->page_text) || (ui_->value_stack->currentWidget() == ui_->page_empty)) {
|
||||
QWidget *page = nullptr;
|
||||
if (op == SmartPlaylistSearchTerm::Op_Empty || op == SmartPlaylistSearchTerm::Op_NotEmpty) {
|
||||
if (op == SmartPlaylistSearchTerm::Operator::Empty || op == SmartPlaylistSearchTerm::Operator::NotEmpty) {
|
||||
page = ui_->page_empty;
|
||||
}
|
||||
else {
|
||||
@@ -228,10 +228,10 @@ void SmartPlaylistSearchTermWidget::OpChanged(int idx) {
|
||||
(ui_->value_stack->currentWidget() == ui_->page_date_relative)
|
||||
) {
|
||||
QWidget *page = nullptr;
|
||||
if (op == SmartPlaylistSearchTerm::Op_NumericDate || op == SmartPlaylistSearchTerm::Op_NumericDateNot) {
|
||||
if (op == SmartPlaylistSearchTerm::Operator::NumericDate || op == SmartPlaylistSearchTerm::Operator::NumericDateNot) {
|
||||
page = ui_->page_date_numeric;
|
||||
}
|
||||
else if (op == SmartPlaylistSearchTerm::Op_RelativeDate) {
|
||||
else if (op == SmartPlaylistSearchTerm::Operator::RelativeDate) {
|
||||
page = ui_->page_date_relative;
|
||||
}
|
||||
else {
|
||||
@@ -317,12 +317,12 @@ float SmartPlaylistSearchTermWidget::overlay_opacity() const {
|
||||
|
||||
void SmartPlaylistSearchTermWidget::SetTerm(const SmartPlaylistSearchTerm &term) {
|
||||
|
||||
ui_->field->setCurrentIndex(ui_->field->findData(term.field_));
|
||||
ui_->op->setCurrentIndex(ui_->op->findData(term.operator_));
|
||||
ui_->field->setCurrentIndex(ui_->field->findData(static_cast<int>(term.field_)));
|
||||
ui_->op->setCurrentIndex(ui_->op->findData(static_cast<int>(term.operator_)));
|
||||
|
||||
// The value depends on the data type
|
||||
switch (SmartPlaylistSearchTerm::TypeOf(term.field_)) {
|
||||
case SmartPlaylistSearchTerm::Type_Text:
|
||||
case SmartPlaylistSearchTerm::Type::Text:
|
||||
if (ui_->value_stack->currentWidget() == ui_->page_empty) {
|
||||
ui_->value_text->setText("");
|
||||
}
|
||||
@@ -331,34 +331,34 @@ void SmartPlaylistSearchTermWidget::SetTerm(const SmartPlaylistSearchTerm &term)
|
||||
}
|
||||
break;
|
||||
|
||||
case SmartPlaylistSearchTerm::Type_Number:
|
||||
case SmartPlaylistSearchTerm::Type::Number:
|
||||
ui_->value_number->setValue(term.value_.toInt());
|
||||
break;
|
||||
|
||||
case SmartPlaylistSearchTerm::Type_Date:
|
||||
case SmartPlaylistSearchTerm::Type::Date:
|
||||
if (ui_->value_stack->currentWidget() == ui_->page_date_numeric) {
|
||||
ui_->value_date_numeric->setValue(term.value_.toInt());
|
||||
ui_->date_type->setCurrentIndex(term.date_);
|
||||
ui_->date_type->setCurrentIndex(static_cast<int>(term.datetype_));
|
||||
}
|
||||
else if (ui_->value_stack->currentWidget() == ui_->page_date_relative) {
|
||||
ui_->value_date_numeric1->setValue(term.value_.toInt());
|
||||
ui_->value_date_numeric2->setValue(term.second_value_.toInt());
|
||||
ui_->date_type_relative->setCurrentIndex(term.date_);
|
||||
ui_->date_type_relative->setCurrentIndex(static_cast<int>(term.datetype_));
|
||||
}
|
||||
else if (ui_->value_stack->currentWidget() == ui_->page_date) {
|
||||
ui_->value_date->setDateTime(QDateTime::fromSecsSinceEpoch(term.value_.toInt()));
|
||||
}
|
||||
break;
|
||||
|
||||
case SmartPlaylistSearchTerm::Type_Time:
|
||||
case SmartPlaylistSearchTerm::Type::Time:
|
||||
ui_->value_time->setTime(QTime(0, 0).addSecs(term.value_.toInt()));
|
||||
break;
|
||||
|
||||
case SmartPlaylistSearchTerm::Type_Rating:
|
||||
case SmartPlaylistSearchTerm::Type::Rating:
|
||||
ui_->value_rating->set_rating(term.value_.toFloat());
|
||||
break;
|
||||
|
||||
case SmartPlaylistSearchTerm::Type_Invalid:
|
||||
case SmartPlaylistSearchTerm::Type::Invalid:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -391,11 +391,11 @@ SmartPlaylistSearchTerm SmartPlaylistSearchTermWidget::Term() const {
|
||||
ret.value_ = QTime(0, 0).secsTo(ui_->value_time->time());
|
||||
}
|
||||
else if (value_page == ui_->page_date_numeric) {
|
||||
ret.date_ = static_cast<SmartPlaylistSearchTerm::DateType>(ui_->date_type->currentIndex());
|
||||
ret.datetype_ = static_cast<SmartPlaylistSearchTerm::DateType>(ui_->date_type->currentIndex());
|
||||
ret.value_ = ui_->value_date_numeric->value();
|
||||
}
|
||||
else if (value_page == ui_->page_date_relative) {
|
||||
ret.date_ = static_cast<SmartPlaylistSearchTerm::DateType>(ui_->date_type_relative->currentIndex());
|
||||
ret.datetype_ = static_cast<SmartPlaylistSearchTerm::DateType>(ui_->date_type_relative->currentIndex());
|
||||
ret.value_ = ui_->value_date_numeric1->value();
|
||||
ret.second_value_ = ui_->value_date_numeric2->value();
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ class SmartPlaylistsItem : public SimpleTreeItem<SmartPlaylistsItem> {
|
||||
public:
|
||||
enum Type {
|
||||
Type_Root,
|
||||
Type_SmartPlaylist,
|
||||
Type_SmartPlaylist
|
||||
};
|
||||
|
||||
SmartPlaylistsItem(SimpleTreeModel<SmartPlaylistsItem> *_model) : SimpleTreeItem<SmartPlaylistsItem>(Type_Root, _model) {}
|
||||
@@ -44,4 +44,6 @@ class SmartPlaylistsItem : public SimpleTreeItem<SmartPlaylistsItem> {
|
||||
Q_DISABLE_COPY(SmartPlaylistsItem)
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(SmartPlaylistsItem::Type)
|
||||
|
||||
#endif // SMARTPLAYLISTSITEM_H
|
||||
|
||||
@@ -64,57 +64,57 @@ void SmartPlaylistsModel::Init() {
|
||||
<< PlaylistGeneratorPtr(
|
||||
new PlaylistQueryGenerator(
|
||||
QT_TRANSLATE_NOOP("SmartPlaylists", "Newest tracks"),
|
||||
SmartPlaylistSearch(SmartPlaylistSearch::Type_All, SmartPlaylistSearch::TermList(),
|
||||
SmartPlaylistSearch::Sort_FieldDesc,
|
||||
SmartPlaylistSearchTerm::Field_DateCreated)
|
||||
SmartPlaylistSearch(SmartPlaylistSearch::SearchType::All, SmartPlaylistSearch::TermList(),
|
||||
SmartPlaylistSearch::SortType::FieldDesc,
|
||||
SmartPlaylistSearchTerm::Field::DateCreated)
|
||||
)
|
||||
)
|
||||
<< PlaylistGeneratorPtr(new PlaylistQueryGenerator(
|
||||
QT_TRANSLATE_NOOP("SmartPlaylists", "50 random tracks"),
|
||||
SmartPlaylistSearch(SmartPlaylistSearch::Type_All, SmartPlaylistSearch::TermList(), SmartPlaylistSearch::Sort_Random, SmartPlaylistSearchTerm::Field_Title, 50)
|
||||
SmartPlaylistSearch(SmartPlaylistSearch::SearchType::All, SmartPlaylistSearch::TermList(), SmartPlaylistSearch::SortType::Random, SmartPlaylistSearchTerm::Field::Title, 50)
|
||||
)
|
||||
)
|
||||
<< PlaylistGeneratorPtr(
|
||||
new PlaylistQueryGenerator(
|
||||
QT_TRANSLATE_NOOP("SmartPlaylists", "Ever played"),
|
||||
SmartPlaylistSearch(SmartPlaylistSearch::Type_And, SmartPlaylistSearch::TermList() << SmartPlaylistSearchTerm( SmartPlaylistSearchTerm::Field_PlayCount, SmartPlaylistSearchTerm::Op_GreaterThan, 0), SmartPlaylistSearch::Sort_Random, SmartPlaylistSearchTerm::Field_Title)
|
||||
SmartPlaylistSearch(SmartPlaylistSearch::SearchType::And, SmartPlaylistSearch::TermList() << SmartPlaylistSearchTerm( SmartPlaylistSearchTerm::Field::PlayCount, SmartPlaylistSearchTerm::Operator::GreaterThan, 0), SmartPlaylistSearch::SortType::Random, SmartPlaylistSearchTerm::Field::Title)
|
||||
)
|
||||
)
|
||||
<< PlaylistGeneratorPtr(
|
||||
new PlaylistQueryGenerator(
|
||||
QT_TRANSLATE_NOOP("SmartPlaylists", "Never played"),
|
||||
SmartPlaylistSearch(SmartPlaylistSearch::Type_And, SmartPlaylistSearch::TermList() << SmartPlaylistSearchTerm(SmartPlaylistSearchTerm::Field_PlayCount, SmartPlaylistSearchTerm::Op_Equals, 0), SmartPlaylistSearch::Sort_Random, SmartPlaylistSearchTerm::Field_Title)
|
||||
SmartPlaylistSearch(SmartPlaylistSearch::SearchType::And, SmartPlaylistSearch::TermList() << SmartPlaylistSearchTerm(SmartPlaylistSearchTerm::Field::PlayCount, SmartPlaylistSearchTerm::Operator::Equals, 0), SmartPlaylistSearch::SortType::Random, SmartPlaylistSearchTerm::Field::Title)
|
||||
)
|
||||
)
|
||||
<< PlaylistGeneratorPtr(
|
||||
new PlaylistQueryGenerator(
|
||||
QT_TRANSLATE_NOOP("SmartPlaylists", "Last played"),
|
||||
SmartPlaylistSearch(SmartPlaylistSearch::Type_All, SmartPlaylistSearch::TermList(), SmartPlaylistSearch::Sort_FieldDesc, SmartPlaylistSearchTerm::Field_LastPlayed)
|
||||
SmartPlaylistSearch(SmartPlaylistSearch::SearchType::All, SmartPlaylistSearch::TermList(), SmartPlaylistSearch::SortType::FieldDesc, SmartPlaylistSearchTerm::Field::LastPlayed)
|
||||
)
|
||||
)
|
||||
<< PlaylistGeneratorPtr(
|
||||
new PlaylistQueryGenerator(
|
||||
QT_TRANSLATE_NOOP("SmartPlaylists", "Most played"),
|
||||
SmartPlaylistSearch(SmartPlaylistSearch::Type_All, SmartPlaylistSearch::TermList(), SmartPlaylistSearch::Sort_FieldDesc, SmartPlaylistSearchTerm::Field_PlayCount)
|
||||
SmartPlaylistSearch(SmartPlaylistSearch::SearchType::All, SmartPlaylistSearch::TermList(), SmartPlaylistSearch::SortType::FieldDesc, SmartPlaylistSearchTerm::Field::PlayCount)
|
||||
)
|
||||
)
|
||||
<< PlaylistGeneratorPtr(
|
||||
new PlaylistQueryGenerator(
|
||||
QT_TRANSLATE_NOOP("SmartPlaylists", "Favourite tracks"),
|
||||
SmartPlaylistSearch(SmartPlaylistSearch::Type_All, SmartPlaylistSearch::TermList(), SmartPlaylistSearch::Sort_FieldDesc, SmartPlaylistSearchTerm::Field_Rating)
|
||||
SmartPlaylistSearch(SmartPlaylistSearch::SearchType::All, SmartPlaylistSearch::TermList(), SmartPlaylistSearch::SortType::FieldDesc, SmartPlaylistSearchTerm::Field::Rating)
|
||||
)
|
||||
)
|
||||
<< PlaylistGeneratorPtr(
|
||||
new PlaylistQueryGenerator(
|
||||
QT_TRANSLATE_NOOP("Library", "Least favourite tracks"),
|
||||
SmartPlaylistSearch(SmartPlaylistSearch::Type_Or, SmartPlaylistSearch::TermList()
|
||||
<< SmartPlaylistSearchTerm(SmartPlaylistSearchTerm::Field_Rating, SmartPlaylistSearchTerm::Op_LessThan, 0.5)
|
||||
<< SmartPlaylistSearchTerm(SmartPlaylistSearchTerm::Field_SkipCount, SmartPlaylistSearchTerm::Op_GreaterThan, 4), SmartPlaylistSearch::Sort_FieldDesc, SmartPlaylistSearchTerm::Field_SkipCount)
|
||||
SmartPlaylistSearch(SmartPlaylistSearch::SearchType::Or, SmartPlaylistSearch::TermList()
|
||||
<< SmartPlaylistSearchTerm(SmartPlaylistSearchTerm::Field::Rating, SmartPlaylistSearchTerm::Operator::LessThan, 0.5)
|
||||
<< SmartPlaylistSearchTerm(SmartPlaylistSearchTerm::Field::SkipCount, SmartPlaylistSearchTerm::Operator::GreaterThan, 4), SmartPlaylistSearch::SortType::FieldDesc, SmartPlaylistSearchTerm::Field::SkipCount)
|
||||
)
|
||||
)
|
||||
)
|
||||
<< (SmartPlaylistsModel::GeneratorList() << PlaylistGeneratorPtr(new PlaylistQueryGenerator(QT_TRANSLATE_NOOP("SmartPlaylists", "All tracks"), SmartPlaylistSearch(SmartPlaylistSearch::Type_All, SmartPlaylistSearch::TermList(), SmartPlaylistSearch::Sort_FieldAsc, SmartPlaylistSearchTerm::Field_Artist, -1))))
|
||||
<< (SmartPlaylistsModel::GeneratorList() << PlaylistGeneratorPtr(new PlaylistQueryGenerator( QT_TRANSLATE_NOOP("SmartPlaylists", "Dynamic random mix"), SmartPlaylistSearch(SmartPlaylistSearch::Type_All, SmartPlaylistSearch::TermList(), SmartPlaylistSearch::Sort_Random, SmartPlaylistSearchTerm::Field_Title), true)));
|
||||
<< (SmartPlaylistsModel::GeneratorList() << PlaylistGeneratorPtr(new PlaylistQueryGenerator(QT_TRANSLATE_NOOP("SmartPlaylists", "All tracks"), SmartPlaylistSearch(SmartPlaylistSearch::SearchType::All, SmartPlaylistSearch::TermList(), SmartPlaylistSearch::SortType::FieldAsc, SmartPlaylistSearchTerm::Field::Artist, -1))))
|
||||
<< (SmartPlaylistsModel::GeneratorList() << PlaylistGeneratorPtr(new PlaylistQueryGenerator( QT_TRANSLATE_NOOP("SmartPlaylists", "Dynamic random mix"), SmartPlaylistSearch(SmartPlaylistSearch::SearchType::All, SmartPlaylistSearch::TermList(), SmartPlaylistSearch::SortType::Random, SmartPlaylistSearchTerm::Field::Title), true)));
|
||||
|
||||
QSettings s;
|
||||
s.beginGroup(kSettingsGroup);
|
||||
@@ -232,7 +232,7 @@ void SmartPlaylistsModel::DeleteGenerator(const QModelIndex &idx) {
|
||||
for (SmartPlaylistsItem *item : root_->children) {
|
||||
s.setArrayIndex(i++);
|
||||
s.setValue("name", item->display_text);
|
||||
s.setValue("type", item->smart_playlist_type);
|
||||
s.setValue("type", QVariant::fromValue(item->smart_playlist_type));
|
||||
s.setValue("data", item->smart_playlist_data);
|
||||
}
|
||||
s.endArray();
|
||||
@@ -244,7 +244,7 @@ void SmartPlaylistsModel::SaveGenerator(QSettings *s, const int i, PlaylistGener
|
||||
|
||||
s->setArrayIndex(i);
|
||||
s->setValue("name", generator->name());
|
||||
s->setValue("type", generator->type());
|
||||
s->setValue("type", QVariant::fromValue(generator->type()));
|
||||
s->setValue("data", generator->Save());
|
||||
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ void SmartPlaylistWizard::SetGenerator(PlaylistGeneratorPtr gen) {
|
||||
}
|
||||
|
||||
if (type_index_ == -1) {
|
||||
qLog(Error) << "Plugin was not found for generator type" << gen->type();
|
||||
qLog(Error) << "Plugin was not found for generator type" << static_cast<int>(gen->type());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user