Compare commits

...
Author SHA1 Message Date
Jonah Brüchert c1341fad05 Also use optimized search models for mobile search history 2023-08-07 20:22:04 +02:00
Théophile Gilgien 0b1a8105d4 Small cleanup 2023-08-07 15:58:30 +02:00
Theophile Gilgien 5b1f3c7120 remove filterText
It isn't needed anymore, in the two places where it was still used, it
can be replaced by Library.searches.filter.
2023-08-07 14:41:00 +02:00
Jonah Brüchert 9c11b75658 Filter search history in the database
Allows to easily limit the default number of history entries.
Previously, limiting the number of sql results would not have worked,
since the filter was being applied on top of them.
2023-08-07 02:00:16 +02:00
Jonah Brüchert 3bce344e0c Improve performance of search popup with new local search model 2023-08-07 01:59:34 +02:00
5 changed files with 77 additions and 30 deletions

No files matched your search

+4 -9
View File
@@ -38,11 +38,10 @@ Kirigami.ScrollablePage {
Repeater {
id: recentsRepeater
Layout.fillWidth: true
model: SortFilterModel {
filterRole: PlaybackHistoryModel.Title
filterRegularExpression: searchLoader.filterExpression
sourceModel: Library.playbackHistory
model: LocalSearchModel {
searchQuery: searchLoader.text
}
delegate: Kirigami.DelegateRecycler {
Layout.alignment: Qt.AlignTop
sourceComponent: searchAlbum
@@ -61,10 +60,7 @@ Kirigami.ScrollablePage {
Repeater {
Layout.fillHeight: true
Layout.fillWidth: true
model: SortFilterModel {
sourceModel: Library.searches
filterRegularExpression: searchLoader.filterExpression
}
model: Library.searches
delegate: Kirigami.AbstractListItem {
implicitHeight: Kirigami.Units.gridUnit * 2
@@ -98,5 +94,4 @@ Kirigami.ScrollablePage {
}
}
}
}
+7 -16
View File
@@ -13,7 +13,6 @@ import org.kde.ytmusic 1.0
Item {
function forceFocus(){searchField.forceActiveFocus()}
function accepted(){searchField.accepted()}
property alias filterExpression: searchField.filterExpression
property alias text: searchField.text
id: root
@@ -25,21 +24,17 @@ Item {
readOnly: true
}
Kirigami.SearchField {
property var filterExpression: new RegExp(`.*${filterText}.*`, "i")
property string filterText: ""
id: searchField
autoAccept: false
width: root.width
selectByMouse: true
onFocusChanged: {
filterText = text
if (wideScreen && focus)
popup.open()
}
onTextEdited: {
filterText = text
Library.searches.filter = text
if(completionList.count === 0) {
//no matching search -> message should display
Library.temporarySearch = ""
@@ -202,7 +197,7 @@ Item {
from: searchField.height
duration: 200
to: completionList
? (searchField.filterText && recentsRepeater.count > 0 //can't use recentsRepeater.visible directly, because it always returns false at this stage
? (Library.searches.filter && recentsRepeater.count > 0 //can't use recentsRepeater.visible directly, because it always returns false at this stage
? (Math.min(fieldContainer.height+ (completionList.count) * (completionList.delegateHeight + completionList.delegatePadding) + Kirigami.Separator.implicitHeight + recentsRepeater.implicitHeight, Kirigami.Units.gridUnit * 20))+2*(popup.shadowSize+popup.expansion)
: (completionList.count === 0
?(Math.min(fieldContainer.height+ noMatchingSearchLabel.height + 2*noMatchingSearchLabel.Layout.margins, Kirigami.Units.gridUnit * 20))+2*(popup.shadowSize+popup.expansion)
@@ -314,13 +309,12 @@ Item {
Layout.fillWidth: true
visible: searchField.filterText && recentsRepeater.count > 0 //if changed, adjust playOpenHeight
visible: Library.searches.filter && recentsRepeater.count > 0 //if changed, adjust playOpenHeight
model: SortFilterModel {
filterRole: PlaybackHistoryModel.Title
filterRegularExpression: searchField.filterExpression
sourceModel: Library.playbackHistory
model: LocalSearchModel {
searchQuery: Library.searches.filter
}
delegate: searchAlbum
}
Kirigami.Separator {
@@ -355,10 +349,7 @@ Item {
property int empiricDelegateHeight: recentsRepeater.visible ? (mainScrollView.contentHeight - recentsRepeater.height) / count : (mainScrollView.contentHeight + mainScrollViewLayout.spacing) / (count)
id: completionList
model: SortFilterModel {
sourceModel: Library.searches
filterRegularExpression: searchField.filterExpression
}
model: Library.searches
function isSelectedDelegateVisible() {
if(!recentsRepeater.visible) {
+39 -3
View File
@@ -27,7 +27,7 @@ Library::Library(QObject *parent)
}()))
{
m_database->runMigrations(":/migrations/");
m_searches = new SearchHistoryModel(m_database->getResults<SingleValue<QString>>("select distinct (search_query) from searches order by search_id desc"), this);
m_searches = new SearchHistoryModel(this);
refreshFavourites();
refreshPlaybackHistory();
@@ -175,6 +175,11 @@ PlaybackHistoryModel::PlaybackHistoryModel(QFuture<std::vector<PlayedSong>> &&so
});
}
PlaybackHistoryModel::PlaybackHistoryModel(QObject *parent)
: QAbstractListModel(parent)
{
}
QHash<int, QByteArray> PlaybackHistoryModel::roleNames() const {
return {
{Roles::VideoId, "videoId"},
@@ -283,9 +288,25 @@ bool FavouriteWatcher::isFavourite() const {
return m_isFavourite;
}
SearchHistoryModel::SearchHistoryModel(QFuture<std::vector<SingleValue<QString>>> &&historyFuture, QObject *parent)
: QAbstractListModel(parent)
SearchHistoryModel::SearchHistoryModel(Library *library)
: QAbstractListModel(library)
{
auto historyFuture = library->database()
.getResults<SingleValue<QString>>("select distinct (search_query) from searches order by search_id desc limit 20");
connect(this, &SearchHistoryModel::filterChanged, this, [library, this]() {
auto future = library->database()
.getResults<SingleValue<QString>>("select distinct (search_query) from searches "
"where search_query like '%" % m_filter % "%'"
"order by search_id desc limit 20");
QCoro::connect(std::move(future), this, [this](auto history) {
beginResetModel();
m_history = history;
endResetModel();
});
});
QCoro::connect(std::move(historyFuture), this, [this](const auto history) {
beginResetModel();
m_history = history;
@@ -402,3 +423,18 @@ void WasPlayedWatcher::update(std::optional<SingleValue<bool> > result)
Q_EMIT wasPlayedChanged();
}
}
LocalSearchModel::LocalSearchModel(QObject *parent) : PlaybackHistoryModel(parent)
{
connect(this, &LocalSearchModel::searchQueryChanged, this, [this]() {
auto resultFuture = Library::instance().database()
.getResults<PlayedSong>("select * from played_songs natural join songs "
"where title like '%" % m_searchQuery % "%' "
"order by plays desc limit 10");
QCoro::connect(std::move(resultFuture), this, [this](auto results) {
beginResetModel();
m_playedSongs = results;
endResetModel();
});
});
}
+26 -2
View File
@@ -84,21 +84,42 @@ public:
Q_ENUM(Roles);
PlaybackHistoryModel(QFuture<std::vector<PlayedSong>> &&songs, QObject *parent = nullptr);
PlaybackHistoryModel(QObject *parent = nullptr);
QHash<int, QByteArray> roleNames() const override;
int rowCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role) const override;
std::vector<PlayedSong> getPlayedSong() const;
private:
protected:
std::vector<PlayedSong> m_playedSongs;
};
///
/// Provides a list of recently played songs matching a search query.
///
class LocalSearchModel : public PlaybackHistoryModel {
Q_OBJECT
Q_PROPERTY(QString searchQuery MEMBER m_searchQuery NOTIFY searchQueryChanged)
Q_SIGNAL void searchQueryChanged();
public:
LocalSearchModel(QObject *parent = nullptr);
QString m_searchQuery;
};
class Library;
class SearchHistoryModel : public QAbstractListModel {
Q_OBJECT
Q_PROPERTY(QString filter MEMBER m_filter NOTIFY filterChanged)
public:
SearchHistoryModel(QFuture<std::vector<SingleValue<QString>>> &&historyFuture, QObject *parent = nullptr);
SearchHistoryModel(Library *library);
int rowCount(const QModelIndex &parent) const override;
void removeSearch(const QString &search);
QVariant data(const QModelIndex &index, int role) const override;
@@ -106,10 +127,13 @@ public:
const QString & temporarySearch() const;
void setTemporarySearch(QString const& text);
Q_SIGNAL void filterChanged();
private:
size_t getRow(QString const &search) const;
std::vector<SingleValue<QString>> m_history;
QString m_temporarySearch;
QString m_filter;
};
class Library : public QObject
+1
View File
@@ -91,6 +91,7 @@ Q_DECL_EXPORT int main(int argc, char *argv[])
qmlRegisterUncreatableType<PlaybackHistoryModel>(URI, 1, 0, "PlaybackHistoryModel","");
qmlRegisterType<QSortFilterProxyModel>(URI, 1, 0, "SortFilterModel");
qmlRegisterType<Blur>(URI, 1, 0, "Blur");
qmlRegisterType<LocalSearchModel>(URI, 1, 0, "LocalSearchModel");
qmlRegisterType<LocalPlaylistModel>(URI, 1, 0, "LocalPlaylistModel");
qmlRegisterType<LocalPlaylistsModel>(URI, 1, 0, "LocalPlaylistsModel");
qmlRegisterType<PlaylistImporter>(URI, 1, 0, "PlaylistImporter");