Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c1341fad05 | ||
|
|
0b1a8105d4 | ||
|
|
5b1f3c7120 | ||
|
|
9c11b75658 | ||
|
|
3bce344e0c |
No files matched your search
@@ -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 {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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");
|
||||
|
||||
Reference in new issue
Block a user