Make sorting and filtering the list of icecast stations work
This commit is contained in:
parent
8d23c8b3ee
commit
b9f7cf78a9
@ -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";
|
||||||
|
|
||||||
|
QString sql = QString("SELECT genre, COUNT(*) AS count FROM %1 "
|
||||||
|
" %2"
|
||||||
" GROUP BY genre"
|
" GROUP BY genre"
|
||||||
" ORDER BY count DESC")
|
" ORDER BY count DESC").arg(kTableName, where);
|
||||||
.arg(kTableName), db);
|
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;
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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));
|
||||||
|
}
|
||||||
|
@ -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_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
}
|
||||||
|
@ -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_;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user