Make searching more responsive on large libraries (Jamendo)
This commit is contained in:
parent
af234763f2
commit
dd937fb06d
@ -23,20 +23,26 @@
|
|||||||
#include "ui/settingsdialog.h"
|
#include "ui/settingsdialog.h"
|
||||||
#include "widgets/maclineedit.h"
|
#include "widgets/maclineedit.h"
|
||||||
|
|
||||||
|
#include <QActionGroup>
|
||||||
#include <QKeyEvent>
|
#include <QKeyEvent>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QActionGroup>
|
|
||||||
#include <QSignalMapper>
|
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
|
#include <QSignalMapper>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
LibraryFilterWidget::LibraryFilterWidget(QWidget *parent)
|
LibraryFilterWidget::LibraryFilterWidget(QWidget *parent)
|
||||||
: QWidget(parent),
|
: QWidget(parent),
|
||||||
ui_(new Ui_LibraryFilterWidget),
|
ui_(new Ui_LibraryFilterWidget),
|
||||||
model_(NULL),
|
model_(NULL),
|
||||||
group_by_dialog_(new GroupByDialog)
|
group_by_dialog_(new GroupByDialog),
|
||||||
|
filter_delay_(new QTimer(this))
|
||||||
{
|
{
|
||||||
ui_->setupUi(this);
|
ui_->setupUi(this);
|
||||||
connect(ui_->filter, SIGNAL(returnPressed()), SIGNAL(ReturnPressed()));
|
connect(ui_->filter, SIGNAL(returnPressed()), SIGNAL(ReturnPressed()));
|
||||||
|
connect(filter_delay_, SIGNAL(timeout()), SLOT(FilterDelayTimeout()));
|
||||||
|
|
||||||
|
filter_delay_->setInterval(kFilterDelay);
|
||||||
|
filter_delay_->setSingleShot(true);
|
||||||
|
|
||||||
// Icons
|
// Icons
|
||||||
ui_->clear->setIcon(IconLoader::Load("edit-clear-locationbar-ltr"));
|
ui_->clear->setIcon(IconLoader::Load("edit-clear-locationbar-ltr"));
|
||||||
@ -114,6 +120,8 @@ LibraryFilterWidget::LibraryFilterWidget(QWidget *parent)
|
|||||||
#else
|
#else
|
||||||
filter_ = ui_->filter;
|
filter_ = ui_->filter;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
connect(filter_->object(), SIGNAL(textChanged(QString)), SLOT(FilterTextChanged(QString)));
|
||||||
}
|
}
|
||||||
|
|
||||||
LibraryFilterWidget::~LibraryFilterWidget() {
|
LibraryFilterWidget::~LibraryFilterWidget() {
|
||||||
@ -125,7 +133,6 @@ void LibraryFilterWidget::SetLibraryModel(LibraryModel *model) {
|
|||||||
disconnect(model_, 0, this, 0);
|
disconnect(model_, 0, this, 0);
|
||||||
disconnect(model_, 0, group_by_dialog_.get(), 0);
|
disconnect(model_, 0, group_by_dialog_.get(), 0);
|
||||||
disconnect(group_by_dialog_.get(), 0, model_, 0);
|
disconnect(group_by_dialog_.get(), 0, model_, 0);
|
||||||
disconnect(filter_->object(), 0, model_, 0);
|
|
||||||
disconnect(filter_age_mapper_, 0, model_, 0);
|
disconnect(filter_age_mapper_, 0, model_, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,7 +145,6 @@ void LibraryFilterWidget::SetLibraryModel(LibraryModel *model) {
|
|||||||
SLOT(GroupingChanged(LibraryModel::Grouping)));
|
SLOT(GroupingChanged(LibraryModel::Grouping)));
|
||||||
connect(group_by_dialog_.get(), SIGNAL(Accepted(LibraryModel::Grouping)),
|
connect(group_by_dialog_.get(), SIGNAL(Accepted(LibraryModel::Grouping)),
|
||||||
model_, SLOT(SetGroupBy(LibraryModel::Grouping)));
|
model_, SLOT(SetGroupBy(LibraryModel::Grouping)));
|
||||||
connect(filter_->object(), SIGNAL(textChanged(QString)), model_, SLOT(SetFilterText(QString)));
|
|
||||||
connect(filter_age_mapper_, SIGNAL(mapped(int)), model_, SLOT(SetFilterAge(int)));
|
connect(filter_age_mapper_, SIGNAL(mapped(int)), model_, SLOT(SetFilterAge(int)));
|
||||||
|
|
||||||
// Load settings
|
// Load settings
|
||||||
@ -226,3 +232,20 @@ void LibraryFilterWidget::keyReleaseEvent(QKeyEvent* e) {
|
|||||||
|
|
||||||
QWidget::keyReleaseEvent(e);
|
QWidget::keyReleaseEvent(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LibraryFilterWidget::FilterTextChanged(const QString& text) {
|
||||||
|
// Searching with one or two characters can be very expensive on the database
|
||||||
|
// even with FTS, so if there are a large number of songs in the database
|
||||||
|
// introduce a small delay before actually filtering the model, so if the
|
||||||
|
// user is typing the first few characters of something it will be quicker.
|
||||||
|
if (!text.isEmpty() && text.length() < 3 && model_->total_song_count() >= 100000) {
|
||||||
|
filter_delay_->start();
|
||||||
|
} else {
|
||||||
|
filter_delay_->stop();
|
||||||
|
model_->SetFilterText(text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LibraryFilterWidget::FilterDelayTimeout() {
|
||||||
|
model_->SetFilterText(filter_->text());
|
||||||
|
}
|
||||||
|
@ -40,6 +40,8 @@ class LibraryFilterWidget : public QWidget {
|
|||||||
LibraryFilterWidget(QWidget* parent = 0);
|
LibraryFilterWidget(QWidget* parent = 0);
|
||||||
~LibraryFilterWidget();
|
~LibraryFilterWidget();
|
||||||
|
|
||||||
|
static const int kFilterDelay = 500; // msec
|
||||||
|
|
||||||
void SetFilterHint(const QString& hint);
|
void SetFilterHint(const QString& hint);
|
||||||
void SetAgeFilterEnabled(bool enabled);
|
void SetAgeFilterEnabled(bool enabled);
|
||||||
void SetGroupByEnabled(bool enabled);
|
void SetGroupByEnabled(bool enabled);
|
||||||
@ -64,6 +66,9 @@ class LibraryFilterWidget : public QWidget {
|
|||||||
void GroupByClicked(QAction* action);
|
void GroupByClicked(QAction* action);
|
||||||
void ClearFilter();
|
void ClearFilter();
|
||||||
|
|
||||||
|
void FilterTextChanged(const QString& text);
|
||||||
|
void FilterDelayTimeout();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui_LibraryFilterWidget* ui_;
|
Ui_LibraryFilterWidget* ui_;
|
||||||
LibraryModel* model_;
|
LibraryModel* model_;
|
||||||
@ -77,6 +82,8 @@ class LibraryFilterWidget : public QWidget {
|
|||||||
QActionGroup* group_by_group_;
|
QActionGroup* group_by_group_;
|
||||||
QSignalMapper* filter_age_mapper_;
|
QSignalMapper* filter_age_mapper_;
|
||||||
|
|
||||||
|
QTimer* filter_delay_;
|
||||||
|
|
||||||
QString settings_group_;
|
QString settings_group_;
|
||||||
|
|
||||||
LineEditInterface* filter_;
|
LineEditInterface* filter_;
|
||||||
|
@ -55,6 +55,7 @@ LibraryModel::LibraryModel(LibraryBackend* backend, QObject* parent)
|
|||||||
dir_model_(new LibraryDirectoryModel(backend, this)),
|
dir_model_(new LibraryDirectoryModel(backend, this)),
|
||||||
show_smart_playlists_(false),
|
show_smart_playlists_(false),
|
||||||
show_various_artists_(true),
|
show_various_artists_(true),
|
||||||
|
total_song_count_(0),
|
||||||
artist_icon_(":/icons/22x22/x-clementine-artist.png"),
|
artist_icon_(":/icons/22x22/x-clementine-artist.png"),
|
||||||
album_icon_(":/icons/22x22/x-clementine-album.png"),
|
album_icon_(":/icons/22x22/x-clementine-album.png"),
|
||||||
no_cover_icon_(":nocover.png"),
|
no_cover_icon_(":nocover.png"),
|
||||||
@ -77,7 +78,7 @@ void LibraryModel::Init() {
|
|||||||
connect(backend_, SIGNAL(SongsDeleted(SongList)), SLOT(SongsDeleted(SongList)));
|
connect(backend_, SIGNAL(SongsDeleted(SongList)), SLOT(SongsDeleted(SongList)));
|
||||||
connect(backend_, SIGNAL(SongsStatisticsChanged(SongList)), SLOT(SongsStatisticsChanged(SongList)));
|
connect(backend_, SIGNAL(SongsStatisticsChanged(SongList)), SLOT(SongsStatisticsChanged(SongList)));
|
||||||
connect(backend_, SIGNAL(DatabaseReset()), SLOT(Reset()));
|
connect(backend_, SIGNAL(DatabaseReset()), SLOT(Reset()));
|
||||||
connect(backend_, SIGNAL(TotalSongCountUpdated(int)), SIGNAL(TotalSongCountUpdated(int)));
|
connect(backend_, SIGNAL(TotalSongCountUpdated(int)), SLOT(TotalSongCountUpdatedSlot(int)));
|
||||||
|
|
||||||
backend_->UpdateTotalSongCountAsync();
|
backend_->UpdateTotalSongCountAsync();
|
||||||
|
|
||||||
@ -1107,3 +1108,8 @@ GeneratorPtr LibraryModel::CreateGenerator(const QModelIndex& index) const {
|
|||||||
ret->Load(item->smart_playlist_data);
|
ret->Load(item->smart_playlist_data);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LibraryModel::TotalSongCountUpdatedSlot(int count) {
|
||||||
|
total_song_count_ = count;
|
||||||
|
emit TotalSongCountUpdated(count);
|
||||||
|
}
|
||||||
|
@ -112,6 +112,9 @@ class LibraryModel : public SimpleTreeModel<LibraryItem> {
|
|||||||
SongList GetChildSongs(const QModelIndex& index) const;
|
SongList GetChildSongs(const QModelIndex& index) const;
|
||||||
SongList GetChildSongs(const QModelIndexList& indexes) const;
|
SongList GetChildSongs(const QModelIndexList& indexes) const;
|
||||||
|
|
||||||
|
// Might be accurate
|
||||||
|
int total_song_count() const { return total_song_count_; }
|
||||||
|
|
||||||
// Smart playlists
|
// Smart playlists
|
||||||
smart_playlists::GeneratorPtr CreateGenerator(const QModelIndex& index) const;
|
smart_playlists::GeneratorPtr CreateGenerator(const QModelIndex& index) const;
|
||||||
void AddGenerator(smart_playlists::GeneratorPtr gen);
|
void AddGenerator(smart_playlists::GeneratorPtr gen);
|
||||||
@ -146,6 +149,7 @@ class LibraryModel : public SimpleTreeModel<LibraryItem> {
|
|||||||
void SongsDiscovered(const SongList& songs);
|
void SongsDiscovered(const SongList& songs);
|
||||||
void SongsDeleted(const SongList& songs);
|
void SongsDeleted(const SongList& songs);
|
||||||
void SongsStatisticsChanged(const SongList& songs);
|
void SongsStatisticsChanged(const SongList& songs);
|
||||||
|
void TotalSongCountUpdatedSlot(int count);
|
||||||
|
|
||||||
// Called after ResetAsync
|
// Called after ResetAsync
|
||||||
void ResetAsyncQueryFinished();
|
void ResetAsyncQueryFinished();
|
||||||
@ -215,6 +219,8 @@ class LibraryModel : public SimpleTreeModel<LibraryItem> {
|
|||||||
DefaultGenerators default_smart_playlists_;
|
DefaultGenerators default_smart_playlists_;
|
||||||
bool show_various_artists_;
|
bool show_various_artists_;
|
||||||
|
|
||||||
|
int total_song_count_;
|
||||||
|
|
||||||
QueryOptions query_options_;
|
QueryOptions query_options_;
|
||||||
Grouping group_by_;
|
Grouping group_by_;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user