diff options
author | Arno <arno@disconnect.de> | 2017-02-25 18:45:49 +0100 |
---|---|---|
committer | Arno <arno@disconnect.de> | 2017-02-25 18:45:49 +0100 |
commit | a169ca87cbe7b3ebe6f9ef24335f65ca64791116 (patch) | |
tree | da37dd590ac329bb36229702017cd76daf4b12a3 | |
parent | ffa50a24296688d1c6e9f4de2315bbd494f86cf6 (diff) | |
download | BeetPlayer-a169ca87cbe7b3ebe6f9ef24335f65ca64791116.tar.gz BeetPlayer-a169ca87cbe7b3ebe6f9ef24335f65ca64791116.tar.bz2 BeetPlayer-a169ca87cbe7b3ebe6f9ef24335f65ca64791116.zip |
Implement filtering
Well, as it turns out, QSortFilterProxyModel isn't the weapon of choice
for this. Implement it by creating a separate model which is populated
by SQL-Queries.
-rw-r--r-- | beetplayerproxy.cpp | 43 | ||||
-rw-r--r-- | beetplayerproxy.h | 4 | ||||
-rw-r--r-- | playerwidget.cpp | 98 | ||||
-rw-r--r-- | playerwidget.h | 9 |
4 files changed, 133 insertions, 21 deletions
diff --git a/beetplayerproxy.cpp b/beetplayerproxy.cpp index 115bd3a..574713f 100644 --- a/beetplayerproxy.cpp +++ b/beetplayerproxy.cpp @@ -7,13 +7,50 @@ BeetPlayerProxy::BeetPlayerProxy(QObject *parent) : QSortFilterProxyModel(parent } bool BeetPlayerProxy::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const{ + if(filterRegExp().isEmpty()){ + return true; + } QRegExp filter = filterRegExp(); QModelIndex curIdx = sourceModel()->index(source_row, 0, source_parent); - while(curIdx.isValid()){ - if(curIdx.data().toString().contains(filter)){ + return recurseChildren(curIdx); +} + +bool BeetPlayerProxy::recurseChildren(QModelIndex parent) const{ + static bool retval = false; + if(parent.data().toString().contains(filterRegExp())){ + qDebug() << "found:" << parent.data(); + retval = true; + }else{ + retval = false; + } + for(int i = 0; i < sourceModel()->rowCount(parent); ++i){ + QModelIndex cur = sourceModel()->index(i, 0, parent); + //qDebug() << cur.data(); + if(cur.data().toString().contains(filterRegExp())){ + retval = true; + } + if(sourceModel()->hasChildren(cur)){ + recurseChildren(cur); + } + } + return retval; +} + +bool BeetPlayerProxy::hasValidChild(QModelIndex parent) const{ + QModelIndex curIdx = parent; + if(curIdx.isValid()){ + if(curIdx.data().toString().contains(filterRegExp())){ + qDebug() << "found:" << curIdx.data(); return true; } - curIdx = curIdx.parent(); + qDebug() << parent.data() << sourceModel()->rowCount(curIdx); + for(int i = 0; i < sourceModel()->rowCount(curIdx); ++i){ + curIdx = sourceModel()->index(i, 0, curIdx); + //qDebug() << "in for:" << curIdx.data() << i; + if(sourceModel()->hasChildren(curIdx)){ + hasValidChild(curIdx); + } + } } return false; } diff --git a/beetplayerproxy.h b/beetplayerproxy.h index b50b972..69907ae 100644 --- a/beetplayerproxy.h +++ b/beetplayerproxy.h @@ -10,6 +10,10 @@ class BeetPlayerProxy : public QSortFilterProxyModel { protected: virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const; + + private: + bool hasValidChild(QModelIndex parent) const; + bool recurseChildren(QModelIndex parent) const; }; #endif // BEETPLAYERPROXY_H diff --git a/playerwidget.cpp b/playerwidget.cpp index 5df9951..237f0f0 100644 --- a/playerwidget.cpp +++ b/playerwidget.cpp @@ -24,9 +24,8 @@ void PlayerWidget::setupGui(){ //THE view mView = new QTreeView; mViewModel = new QStandardItemModel; - mViewProxy = new BeetPlayerProxy; - mViewProxy->setSourceModel(mViewModel); - mView->setModel(mViewProxy); + mView->setModel(mViewModel); + mSearchModel = new QStandardItemModel; //filter QGroupBox *filterGB = new QGroupBox(tr("Filter")); @@ -101,22 +100,21 @@ void PlayerWidget::setupGui(){ populate(); } -void PlayerWidget::populate(){ - //prepare Queries +void PlayerWidget::populateByArtist(QStandardItem *parent, const QString &filter){ QSqlDatabase db = QSqlDatabase::database("beetplayerdb"); + QStandardItem *root = parent; QSqlQuery artistsQ(db); - artistsQ.prepare("SELECT iartists_id, tartists_name FROM artists ORDER BY tartists_name ASC"); + if(!filter.isEmpty()){ + artistsQ.prepare("SELECT iartists_id, tartists_name FROM artists WHERE tartists_name ~ :f ORDER BY tartists_name ASC"); + artistsQ.bindValue(":f", filter); + }else{ + artistsQ.prepare("SELECT iartists_id, tartists_name FROM artists ORDER BY tartists_name ASC"); + } QSqlQuery albumQ(db); albumQ.prepare("SELECT DISTINCT(songs.ialbums_id), talbum_name, siyear FROM songs, albums WHERE songs.iartists_id = :artistid AND songs.ialbums_id = albums.ialbums_id ORDER BY siyear ASC"); QSqlQuery songQ(db); songQ.prepare("SELECT sipos, ttitle, tfullpath, igenres_id FROM songs WHERE ialbums_id = :alid AND iartists_id = :arid ORDER BY sipos ASC"); - //reset view+model - mView->setSortingEnabled(false); - mViewModel->clear(); - mViewModel->setHorizontalHeaderLabels(QStringList() << tr("Name")); - QStandardItem *root = mViewModel->invisibleRootItem(); - //read data artistsQ.exec(); while(artistsQ.next()){ @@ -155,11 +153,81 @@ void PlayerWidget::populate(){ } } +void PlayerWidget::populateBySong(QStandardItem *parent, const QString &filter){ + QSqlDatabase db = QSqlDatabase::database("beetplayerdb"); + QStandardItem *root = parent; + QSqlQuery songQ = QSqlQuery(db); + songQ.prepare("SELECT sipos, ttitle, tfullpath, igenres_id, artists.tartists_name FROM songs, artists WHERE ttitle ~ :f AND songs.iartists_id = artists.iartists_id ORDER BY ttitle ASC"); + songQ.bindValue(":f", filter); + songQ.exec(); + while(songQ.next()){ + QStandardItem *curSong = new QStandardItem; + curSong->setFont(QFont("courier")); + QString songText = QString(tr("%1 %2 (%3)")).arg(QString("🅢")).arg(songQ.value(1).toString()).arg(songQ.value(4).toString()); + curSong->setText(songText); + curSong->setData(songQ.value(0), IdRole); + curSong->setData(songQ.value(2), FullPathRole); + curSong->setData(songQ.value(3), GenreRole); + root->appendRow(curSong); + } +} + +void PlayerWidget::populateByGenre(QStandardItem *parent, const QString &filter){ + QSqlDatabase db = QSqlDatabase::database("beetplayerdb"); + QStandardItem *root = parent; + QSqlQuery genreQ(db); + genreQ.prepare("SELECT igenres_id, tgenres_name FROM genres WHERE tgenres_name ~ :f"); + genreQ.bindValue(":f", filter); + genreQ.exec(); + while(genreQ.next()){ + QStandardItem *curGenre = new QStandardItem; + curGenre->setFont(QFont("courier")); + QString genreText = QString(tr("%1 %2")).arg(QString("🅖")).arg(genreQ.value(1).toString()); + curGenre->setText(genreText); + curGenre->setData(Genre, TypeRole); + curGenre->setData(genreQ.value(0), IdRole); + root->appendRow(curGenre); + QSqlQuery songQ = QSqlQuery(db); + songQ.prepare("SELECT sipos, ttitle, tfullpath, igenres_id, artists.tartists_name FROM songs, artists WHERE igenres_id = :id AND songs.iartists_id = artists.iartists_id ORDER BY ttitle ASC"); + songQ.bindValue(":id", genreQ.value(0)); + songQ.exec(); + while(songQ.next()){ + QStandardItem *curSong = new QStandardItem; + curSong->setFont(QFont("courier")); + QString songText = QString(tr("%1 %2 (%3)")).arg(QChar(0x266C)).arg(songQ.value(1).toString()).arg(songQ.value(4).toString()); + curSong->setText(songText); + curSong->setData(Song, TypeRole); + curSong->setData(songQ.value(0), IdRole); + curSong->setData(songQ.value(2), FullPathRole); + curSong->setData(songQ.value(3), GenreRole); + curGenre->appendRow(curSong); + } + } +} + +void PlayerWidget::populate(){ + mView->setModel(mViewModel); + mViewModel->clear(); + mViewModel->setHorizontalHeaderLabels(QStringList() << tr("Name")); + QStandardItem *root = mViewModel->invisibleRootItem(); + populateByArtist(root, QString()); +} + void PlayerWidget::doFilter(){ - mViewProxy->setFilterRegExp(QRegExp(mFilter->text())); + QString filter = mFilter->text(); + if(filter.isEmpty()){ + mView->setModel(mViewModel); + } + mSearchModel->clear(); + mSearchModel->setHorizontalHeaderLabels(QStringList() << tr("Name")); + mView->setModel(mSearchModel); + QStandardItem *root = mSearchModel->invisibleRootItem(); + populateByArtist(root, filter); + populateByGenre(root, filter); + populateBySong(root, filter); } void PlayerWidget::clearFilter(){ - mFilter->setText(QString()); - doFilter(); + mFilter->clear(); + mView->setModel(mViewModel); } diff --git a/playerwidget.h b/playerwidget.h index c9206cd..5a6ff95 100644 --- a/playerwidget.h +++ b/playerwidget.h @@ -5,7 +5,7 @@ class QTreeView; class QStandardItemModel; -class QSortFilterProxyModel; +class QStandardItem; class QLineEdit; class QLabel; class QSlider; @@ -16,7 +16,7 @@ class BeetPlayerProxy; class PlayerWidget : public QWidget { Q_OBJECT public: - enum ItemType { Artist, Album, Song }; + enum ItemType { Artist, Album, Song, Genre }; enum CustomRoles { TypeRole = Qt::UserRole + 1, IdRole = Qt::UserRole + 2, FullPathRole = Qt::UserRole + 3, GenreRole = Qt::UserRole + 4 }; explicit PlayerWidget(QWidget *parent = 0); @@ -27,11 +27,14 @@ class PlayerWidget : public QWidget { private: void setupGui(); + void populateByArtist(QStandardItem *parent, const QString &filter); + void populateBySong(QStandardItem *parent, const QString &filter); + void populateByGenre(QStandardItem *parent, const QString &filter); QLineEdit *mFilter; QMediaPlayer *mPlayer; QTreeView *mView; QStandardItemModel *mViewModel; - BeetPlayerProxy *mViewProxy; + QStandardItemModel *mSearchModel; QLabel *mNowPlayingL; QSlider *mSlider; QTextEdit *mCurrentTE; |