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

View File

@ -51,9 +51,10 @@ public:
};
typedef QList<Station> 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);

View File

@ -15,16 +15,19 @@
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
*/
#include "icecastmodel.h"
#include "icecastfilterwidget.h"
#include "ui_icecastfilterwidget.h"
#include "ui/iconloader.h"
#include "widgets/maclineedit.h"
#include <QMenu>
#include <QSignalMapper>
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));
}

View File

@ -18,12 +18,16 @@
#ifndef ICECASTFILTERWIDGET_H
#define ICECASTFILTERWIDGET_H
#include "icecastmodel.h"
#include <QWidget>
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_;
};

View File

@ -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();
}

View File

@ -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_;