Make sorting and filtering the list of icecast stations work

This commit is contained in:
David Sansome 2010-11-23 23:05:42 +00:00
parent 8d23c8b3ee
commit b9f7cf78a9
6 changed files with 106 additions and 27 deletions

View File

@ -33,13 +33,21 @@ void IcecastBackend::Init(boost::shared_ptr<Database> db) {
db_ = db; db_ = db;
} }
QStringList IcecastBackend::GetGenresAlphabetical() { QStringList IcecastBackend::GetGenresAlphabetical(const QString& filter) {
QStringList ret; QStringList ret;
QMutexLocker l(db_->Mutex()); QMutexLocker l(db_->Mutex());
QSqlDatabase db = db_->Connect(); QSqlDatabase db = db_->Connect();
QSqlQuery q(QString("SELECT DISTINCT genre FROM %1 ORDER BY genre") QString where = filter.isEmpty() ? "" : "WHERE name LIKE :filter";
.arg(kTableName), db);
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(); q.exec();
if (db_->CheckErrors(q.lastError())) return ret; if (db_->CheckErrors(q.lastError())) return ret;
@ -49,15 +57,22 @@ QStringList IcecastBackend::GetGenresAlphabetical() {
return ret; return ret;
} }
QStringList IcecastBackend::GetGenresByPopularity() { QStringList IcecastBackend::GetGenresByPopularity(const QString& filter) {
QStringList ret; QStringList ret;
QMutexLocker l(db_->Mutex()); QMutexLocker l(db_->Mutex());
QSqlDatabase db = db_->Connect(); QSqlDatabase db = db_->Connect();
QSqlQuery q(QString("SELECT genre, COUNT(*) AS count FROM %1 " QString where = filter.isEmpty() ? "" : "WHERE name LIKE :filter";
" GROUP BY genre"
" ORDER BY count DESC") QString sql = QString("SELECT genre, COUNT(*) AS count FROM %1 "
.arg(kTableName), db); " %2"
" GROUP BY genre"
" ORDER BY count DESC").arg(kTableName, where);
QSqlQuery q(sql, db);
if (!filter.isEmpty()) {
q.bindValue(":filter", "%" + filter + "%");
}
q.exec(); q.exec();
if (db_->CheckErrors(q.lastError())) return ret; if (db_->CheckErrors(q.lastError())) return ret;
@ -67,21 +82,36 @@ QStringList IcecastBackend::GetGenresByPopularity() {
return ret; return ret;
} }
IcecastBackend::StationList IcecastBackend::GetStations(const QString& genre) { IcecastBackend::StationList IcecastBackend::GetStations(const QString& filter,
const QString& genre) {
StationList ret; StationList ret;
QMutexLocker l(db_->Mutex()); QMutexLocker l(db_->Mutex());
QSqlDatabase db = db_->Connect(); 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," QString sql = QString("SELECT name, url, mime_type, bitrate, channels,"
" samplerate, genre" " samplerate, genre"
" FROM %1").arg(kTableName); " 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); QSqlQuery q(sql, db);
if (!genre.isEmpty()) { foreach (const QString& value, bound_items) {
q.bindValue(":genre", genre); q.addBindValue(value);
} }
q.exec(); q.exec();
if (db_->CheckErrors(q.lastError())) return ret; if (db_->CheckErrors(q.lastError())) return ret;

View File

@ -51,9 +51,10 @@ public:
}; };
typedef QList<Station> StationList; typedef QList<Station> StationList;
QStringList GetGenresAlphabetical(); QStringList GetGenresAlphabetical(const QString& filter = QString());
QStringList GetGenresByPopularity(); QStringList GetGenresByPopularity(const QString& filter = QString());
StationList GetStations(const QString& genre = QString()); StationList GetStations(const QString& filter = QString(),
const QString& genre = QString());
void ClearAndAddStations(const StationList& stations); void ClearAndAddStations(const StationList& stations);

View File

@ -15,16 +15,19 @@
along with Clementine. If not, see <http://www.gnu.org/licenses/>. along with Clementine. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "icecastmodel.h"
#include "icecastfilterwidget.h" #include "icecastfilterwidget.h"
#include "ui_icecastfilterwidget.h" #include "ui_icecastfilterwidget.h"
#include "ui/iconloader.h" #include "ui/iconloader.h"
#include "widgets/maclineedit.h" #include "widgets/maclineedit.h"
#include <QMenu> #include <QMenu>
#include <QSignalMapper>
IcecastFilterWidget::IcecastFilterWidget(QWidget *parent) IcecastFilterWidget::IcecastFilterWidget(QWidget *parent)
: QWidget(parent), : QWidget(parent),
ui_(new Ui_IcecastFilterWidget) ui_(new Ui_IcecastFilterWidget),
sort_mode_mapper_(new QSignalMapper(this))
{ {
ui_->setupUi(this); ui_->setupUi(this);
connect(ui_->clear, SIGNAL(clicked()), SLOT(ClearFilter())); 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_->clear->setIcon(IconLoader::Load("edit-clear-locationbar-ltr"));
ui_->options->setIcon(IconLoader::Load("configure")); ui_->options->setIcon(IconLoader::Load("configure"));
QMenu* options_menu = new QMenu(this); // Options actions
options_menu->addAction(ui_->action_sort_genre_popularity); QActionGroup* group = new QActionGroup(this);
options_menu->addAction(ui_->action_sort_genre_alphabetically); AddAction(group, ui_->action_sort_genre_popularity, IcecastModel::SortMode_GenreByPopularity);
options_menu->addAction(ui_->action_sort_station); 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); ui_->options->setMenu(options_menu);
connect(sort_mode_mapper_, SIGNAL(mapped(int)), SLOT(SortModeChanged(int)));
#ifdef Q_OS_DARWIN #ifdef Q_OS_DARWIN
delete ui_->filter; delete ui_->filter;
MacLineEdit* lineedit = new MacLineEdit(this); MacLineEdit* lineedit = new MacLineEdit(this);
@ -51,15 +60,28 @@ IcecastFilterWidget::IcecastFilterWidget(QWidget *parent)
#endif #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() { IcecastFilterWidget::~IcecastFilterWidget() {
delete ui_; delete ui_;
} }
void IcecastFilterWidget::SetIcecastModel(IcecastModel* model) { void IcecastFilterWidget::SetIcecastModel(IcecastModel* model) {
model_ = model; model_ = model;
connect(filter_->object(), SIGNAL(textChanged(QString)),
model_, SLOT(SetFilterText(QString)));
} }
void IcecastFilterWidget::ClearFilter() { void IcecastFilterWidget::ClearFilter() {
filter_->clear(); filter_->clear();
filter_->setFocus(); filter_->setFocus();
} }
void IcecastFilterWidget::SortModeChanged(int mode) {
model_->SetSortMode(IcecastModel::SortMode(mode));
}

View File

@ -18,12 +18,16 @@
#ifndef ICECASTFILTERWIDGET_H #ifndef ICECASTFILTERWIDGET_H
#define ICECASTFILTERWIDGET_H #define ICECASTFILTERWIDGET_H
#include "icecastmodel.h"
#include <QWidget> #include <QWidget>
class IcecastModel;
class LineEditInterface; class LineEditInterface;
class Ui_IcecastFilterWidget; class Ui_IcecastFilterWidget;
class QActionGroup;
class QSignalMapper;
class IcecastFilterWidget : public QWidget { class IcecastFilterWidget : public QWidget {
Q_OBJECT Q_OBJECT
@ -35,11 +39,17 @@ public:
private slots: private slots:
void ClearFilter(); void ClearFilter();
void SortModeChanged(int mode);
private:
void AddAction(QActionGroup* group, QAction* action, IcecastModel::SortMode mode);
private: private:
Ui_IcecastFilterWidget* ui_; Ui_IcecastFilterWidget* ui_;
IcecastModel* model_; IcecastModel* model_;
QSignalMapper* sort_mode_mapper_;
LineEditInterface* filter_; LineEditInterface* filter_;
}; };

View File

@ -45,6 +45,8 @@ void IcecastModel::Reset() {
root_->lazy_loaded = false; root_->lazy_loaded = false;
LazyPopulate(root_); LazyPopulate(root_);
reset();
} }
void IcecastModel::LazyPopulate(IcecastItem* parent) { void IcecastModel::LazyPopulate(IcecastItem* parent) {
@ -63,11 +65,11 @@ void IcecastModel::LazyPopulate(IcecastItem* parent) {
case IcecastItem::Type_Root: case IcecastItem::Type_Root:
switch (sort_mode_) { switch (sort_mode_) {
case SortMode_GenreAlphabetical: case SortMode_GenreAlphabetical:
AddGenres(backend_->GetGenresAlphabetical()); AddGenres(backend_->GetGenresAlphabetical(filter_));
break; break;
case SortMode_GenreByPopularity: case SortMode_GenreByPopularity:
AddGenres(backend_->GetGenresByPopularity()); AddGenres(backend_->GetGenresByPopularity(filter_));
break; break;
case SortMode_StationAlphabetical: case SortMode_StationAlphabetical:
@ -79,7 +81,7 @@ void IcecastModel::LazyPopulate(IcecastItem* parent) {
} }
void IcecastModel::PopulateGenre(IcecastItem* parent, const QString& genre) { 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) { foreach (const IcecastBackend::Station& station, stations) {
IcecastItem* item = new IcecastItem(IcecastItem::Type_Station, parent); IcecastItem* item = new IcecastItem(IcecastItem::Type_Station, parent);
item->display_text = station.name; item->display_text = station.name;
@ -116,3 +118,13 @@ QVariant IcecastModel::data(const IcecastItem* item, int role) const {
} }
return QVariant(); return QVariant();
} }
void IcecastModel::SetFilterText(const QString& filter) {
filter_ = filter;
Reset();
}
void IcecastModel::SetSortMode(SortMode mode) {
sort_mode_ = mode;
Reset();
}

View File

@ -34,8 +34,8 @@ public:
// These values get saved in QSettings - don't change them // These values get saved in QSettings - don't change them
enum SortMode { enum SortMode {
SortMode_GenreAlphabetical = 0, SortMode_GenreByPopularity = 0,
SortMode_GenreByPopularity = 1, SortMode_GenreAlphabetical = 1,
SortMode_StationAlphabetical = 2, SortMode_StationAlphabetical = 2,
}; };
@ -52,6 +52,9 @@ public slots:
void Init(); void Init();
void Reset(); void Reset();
void SetFilterText(const QString& filter);
void SetSortMode(SortMode mode);
protected: protected:
void LazyPopulate(IcecastItem* parent); void LazyPopulate(IcecastItem* parent);
@ -63,6 +66,7 @@ private:
private: private:
IcecastBackend* backend_; IcecastBackend* backend_;
QString filter_;
SortMode sort_mode_; SortMode sort_mode_;
QIcon genre_icon_; QIcon genre_icon_;