From b9f7cf78a9649727a0658c00f0ada67c908c8383 Mon Sep 17 00:00:00 2001 From: David Sansome Date: Tue, 23 Nov 2010 23:05:42 +0000 Subject: [PATCH] Make sorting and filtering the list of icecast stations work --- src/radio/icecastbackend.cpp | 56 ++++++++++++++++++++++++------- src/radio/icecastbackend.h | 7 ++-- src/radio/icecastfilterwidget.cpp | 32 +++++++++++++++--- src/radio/icecastfilterwidget.h | 12 ++++++- src/radio/icecastmodel.cpp | 18 ++++++++-- src/radio/icecastmodel.h | 8 +++-- 6 files changed, 106 insertions(+), 27 deletions(-) diff --git a/src/radio/icecastbackend.cpp b/src/radio/icecastbackend.cpp index 70a49a72a..fa5ddb6fd 100644 --- a/src/radio/icecastbackend.cpp +++ b/src/radio/icecastbackend.cpp @@ -33,13 +33,21 @@ void IcecastBackend::Init(boost::shared_ptr db) { db_ = db; } -QStringList IcecastBackend::GetGenresAlphabetical() { +QStringList IcecastBackend::GetGenresAlphabetical(const QString& filter) { QStringList ret; QMutexLocker l(db_->Mutex()); QSqlDatabase db = db_->Connect(); - QSqlQuery q(QString("SELECT DISTINCT genre FROM %1 ORDER BY genre") - .arg(kTableName), db); + QString where = filter.isEmpty() ? "" : "WHERE name LIKE :filter"; + + QString sql = QString("SELECT DISTINCT genre FROM %1 %2 ORDER BY genre") + .arg(kTableName, where); + + QSqlQuery q(sql, db); + if (!filter.isEmpty()) { + q.bindValue(":filter", "%" + filter + "%"); + } + q.exec(); if (db_->CheckErrors(q.lastError())) return ret; @@ -49,15 +57,22 @@ QStringList IcecastBackend::GetGenresAlphabetical() { return ret; } -QStringList IcecastBackend::GetGenresByPopularity() { +QStringList IcecastBackend::GetGenresByPopularity(const QString& filter) { QStringList ret; QMutexLocker l(db_->Mutex()); QSqlDatabase db = db_->Connect(); - QSqlQuery q(QString("SELECT genre, COUNT(*) AS count FROM %1 " - " GROUP BY genre" - " ORDER BY count DESC") - .arg(kTableName), db); + QString where = filter.isEmpty() ? "" : "WHERE name LIKE :filter"; + + QString sql = QString("SELECT genre, COUNT(*) AS count FROM %1 " + " %2" + " GROUP BY genre" + " ORDER BY count DESC").arg(kTableName, where); + QSqlQuery q(sql, db); + if (!filter.isEmpty()) { + q.bindValue(":filter", "%" + filter + "%"); + } + q.exec(); if (db_->CheckErrors(q.lastError())) return ret; @@ -67,21 +82,36 @@ QStringList IcecastBackend::GetGenresByPopularity() { return ret; } -IcecastBackend::StationList IcecastBackend::GetStations(const QString& genre) { +IcecastBackend::StationList IcecastBackend::GetStations(const QString& filter, + const QString& genre) { StationList ret; QMutexLocker l(db_->Mutex()); QSqlDatabase db = db_->Connect(); + QStringList where_clauses; + QStringList bound_items; + + if (!genre.isEmpty()) { + where_clauses << "genre = :genre"; + bound_items << genre; + } + if (!filter.isEmpty()) { + where_clauses << "name LIKE :filter"; + bound_items << "%" + filter + "%"; + } + QString sql = QString("SELECT name, url, mime_type, bitrate, channels," " samplerate, genre" " FROM %1").arg(kTableName); - if (!genre.isEmpty()) { - sql += " WHERE genre = :genre"; + + if (!where_clauses.isEmpty()) { + sql += " WHERE " + where_clauses.join(" AND "); } QSqlQuery q(sql, db); - if (!genre.isEmpty()) { - q.bindValue(":genre", genre); + foreach (const QString& value, bound_items) { + q.addBindValue(value); } + q.exec(); if (db_->CheckErrors(q.lastError())) return ret; diff --git a/src/radio/icecastbackend.h b/src/radio/icecastbackend.h index e95ba0093..7d1ef28d8 100644 --- a/src/radio/icecastbackend.h +++ b/src/radio/icecastbackend.h @@ -51,9 +51,10 @@ public: }; typedef QList StationList; - QStringList GetGenresAlphabetical(); - QStringList GetGenresByPopularity(); - StationList GetStations(const QString& genre = QString()); + QStringList GetGenresAlphabetical(const QString& filter = QString()); + QStringList GetGenresByPopularity(const QString& filter = QString()); + StationList GetStations(const QString& filter = QString(), + const QString& genre = QString()); void ClearAndAddStations(const StationList& stations); diff --git a/src/radio/icecastfilterwidget.cpp b/src/radio/icecastfilterwidget.cpp index 95a140c51..1e4bbfe64 100644 --- a/src/radio/icecastfilterwidget.cpp +++ b/src/radio/icecastfilterwidget.cpp @@ -15,16 +15,19 @@ along with Clementine. If not, see . */ +#include "icecastmodel.h" #include "icecastfilterwidget.h" #include "ui_icecastfilterwidget.h" #include "ui/iconloader.h" #include "widgets/maclineedit.h" #include +#include IcecastFilterWidget::IcecastFilterWidget(QWidget *parent) : QWidget(parent), - ui_(new Ui_IcecastFilterWidget) + ui_(new Ui_IcecastFilterWidget), + sort_mode_mapper_(new QSignalMapper(this)) { ui_->setupUi(this); connect(ui_->clear, SIGNAL(clicked()), SLOT(ClearFilter())); @@ -33,13 +36,19 @@ IcecastFilterWidget::IcecastFilterWidget(QWidget *parent) ui_->clear->setIcon(IconLoader::Load("edit-clear-locationbar-ltr")); ui_->options->setIcon(IconLoader::Load("configure")); - QMenu* options_menu = new QMenu(this); - options_menu->addAction(ui_->action_sort_genre_popularity); - options_menu->addAction(ui_->action_sort_genre_alphabetically); - options_menu->addAction(ui_->action_sort_station); + // Options actions + QActionGroup* group = new QActionGroup(this); + AddAction(group, ui_->action_sort_genre_popularity, IcecastModel::SortMode_GenreByPopularity); + AddAction(group, ui_->action_sort_genre_alphabetically, IcecastModel::SortMode_GenreAlphabetical); + AddAction(group, ui_->action_sort_station, IcecastModel::SortMode_StationAlphabetical); + // Options menu + QMenu* options_menu = new QMenu(this); + options_menu->addActions(group->actions()); ui_->options->setMenu(options_menu); + connect(sort_mode_mapper_, SIGNAL(mapped(int)), SLOT(SortModeChanged(int))); + #ifdef Q_OS_DARWIN delete ui_->filter; MacLineEdit* lineedit = new MacLineEdit(this); @@ -51,15 +60,28 @@ IcecastFilterWidget::IcecastFilterWidget(QWidget *parent) #endif } +void IcecastFilterWidget::AddAction( + QActionGroup* group, QAction* action, IcecastModel::SortMode mode) { + group->addAction(action); + sort_mode_mapper_->setMapping(action, mode); + connect(action, SIGNAL(triggered()), sort_mode_mapper_, SLOT(map())); +} + IcecastFilterWidget::~IcecastFilterWidget() { delete ui_; } void IcecastFilterWidget::SetIcecastModel(IcecastModel* model) { model_ = model; + connect(filter_->object(), SIGNAL(textChanged(QString)), + model_, SLOT(SetFilterText(QString))); } void IcecastFilterWidget::ClearFilter() { filter_->clear(); filter_->setFocus(); } + +void IcecastFilterWidget::SortModeChanged(int mode) { + model_->SetSortMode(IcecastModel::SortMode(mode)); +} diff --git a/src/radio/icecastfilterwidget.h b/src/radio/icecastfilterwidget.h index 4ad871330..32dabd973 100644 --- a/src/radio/icecastfilterwidget.h +++ b/src/radio/icecastfilterwidget.h @@ -18,12 +18,16 @@ #ifndef ICECASTFILTERWIDGET_H #define ICECASTFILTERWIDGET_H +#include "icecastmodel.h" + #include -class IcecastModel; class LineEditInterface; class Ui_IcecastFilterWidget; +class QActionGroup; +class QSignalMapper; + class IcecastFilterWidget : public QWidget { Q_OBJECT @@ -35,11 +39,17 @@ public: private slots: void ClearFilter(); + void SortModeChanged(int mode); + +private: + void AddAction(QActionGroup* group, QAction* action, IcecastModel::SortMode mode); private: Ui_IcecastFilterWidget* ui_; IcecastModel* model_; + QSignalMapper* sort_mode_mapper_; + LineEditInterface* filter_; }; diff --git a/src/radio/icecastmodel.cpp b/src/radio/icecastmodel.cpp index 5e8695eb2..db31e64d4 100644 --- a/src/radio/icecastmodel.cpp +++ b/src/radio/icecastmodel.cpp @@ -45,6 +45,8 @@ void IcecastModel::Reset() { root_->lazy_loaded = false; LazyPopulate(root_); + + reset(); } void IcecastModel::LazyPopulate(IcecastItem* parent) { @@ -63,11 +65,11 @@ void IcecastModel::LazyPopulate(IcecastItem* parent) { case IcecastItem::Type_Root: switch (sort_mode_) { case SortMode_GenreAlphabetical: - AddGenres(backend_->GetGenresAlphabetical()); + AddGenres(backend_->GetGenresAlphabetical(filter_)); break; case SortMode_GenreByPopularity: - AddGenres(backend_->GetGenresByPopularity()); + AddGenres(backend_->GetGenresByPopularity(filter_)); break; case SortMode_StationAlphabetical: @@ -79,7 +81,7 @@ void IcecastModel::LazyPopulate(IcecastItem* parent) { } void IcecastModel::PopulateGenre(IcecastItem* parent, const QString& genre) { - IcecastBackend::StationList stations = backend_->GetStations(genre); + IcecastBackend::StationList stations = backend_->GetStations(filter_, genre); foreach (const IcecastBackend::Station& station, stations) { IcecastItem* item = new IcecastItem(IcecastItem::Type_Station, parent); item->display_text = station.name; @@ -116,3 +118,13 @@ QVariant IcecastModel::data(const IcecastItem* item, int role) const { } return QVariant(); } + +void IcecastModel::SetFilterText(const QString& filter) { + filter_ = filter; + Reset(); +} + +void IcecastModel::SetSortMode(SortMode mode) { + sort_mode_ = mode; + Reset(); +} diff --git a/src/radio/icecastmodel.h b/src/radio/icecastmodel.h index be31cc7fd..f86f9072d 100644 --- a/src/radio/icecastmodel.h +++ b/src/radio/icecastmodel.h @@ -34,8 +34,8 @@ public: // These values get saved in QSettings - don't change them enum SortMode { - SortMode_GenreAlphabetical = 0, - SortMode_GenreByPopularity = 1, + SortMode_GenreByPopularity = 0, + SortMode_GenreAlphabetical = 1, SortMode_StationAlphabetical = 2, }; @@ -52,6 +52,9 @@ public slots: void Init(); void Reset(); + void SetFilterText(const QString& filter); + void SetSortMode(SortMode mode); + protected: void LazyPopulate(IcecastItem* parent); @@ -63,6 +66,7 @@ private: private: IcecastBackend* backend_; + QString filter_; SortMode sort_mode_; QIcon genre_icon_;