From c3ca038af7766f201e5ccfb621befd9fd8388654 Mon Sep 17 00:00:00 2001 From: Bart De Vries Date: Thu, 27 Jul 2023 09:24:03 +0000 Subject: [PATCH] Implement backend to allow Feed list sort and search The current list of things to sort on (ascending and descending), includes: - unplayed episodes - new episodes - favorite episodes - title (alphabetical) For the first three categories, the value of the sort quantity will be shown in the upper right corner of the delegate. BUG: 471012 CCBUG: 459885 --- src/CMakeLists.txt | 2 + src/datamanager.cpp | 22 ----- src/datamanager.h | 2 - src/feed.cpp | 43 +++++++++- src/feed.h | 4 + src/models/feedsmodel.cpp | 36 +++++---- src/models/feedsmodel.h | 5 ++ src/models/feedsproxymodel.cpp | 142 +++++++++++++++++++++++++++++++-- src/models/feedsproxymodel.h | 36 +++++++++ src/qml/FeedListDelegate.qml | 7 +- src/qml/FeedListPage.qml | 84 +++++++++++++++++-- src/qml/SearchBar.qml | 20 +++-- src/qml/main.qml | 2 + 13 files changed, 340 insertions(+), 65 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5910d57c..485f943d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -267,6 +267,8 @@ if(ANDROID) view-sort view-sort-descending view-sort-ascending + view-sort-descending-name + view-sort-ascending-name ) else() target_link_libraries(kasts PRIVATE Qt::Widgets) diff --git a/src/datamanager.cpp b/src/datamanager.cpp index 438c05b7..e1e4accb 100644 --- a/src/datamanager.cpp +++ b/src/datamanager.cpp @@ -196,28 +196,6 @@ int DataManager::entryCount(const Feed *feed) const return m_entrymap[feed->url()].count(); } -int DataManager::newEntryCount(const Feed *feed) const -{ - QSqlQuery query; - query.prepare(QStringLiteral("SELECT COUNT (id) FROM Entries where feed=:feed AND new=1;")); - query.bindValue(QStringLiteral(":feed"), feed->url()); - Database::instance().execute(query); - if (!query.next()) - return -1; - return query.value(0).toInt(); -} - -int DataManager::favoriteEntryCount(const Feed *feed) const -{ - QSqlQuery query; - query.prepare(QStringLiteral("SELECT COUNT (id) FROM Entries where feed=:feed AND favorite=1;")); - query.bindValue(QStringLiteral(":feed"), feed->url()); - Database::instance().execute(query); - if (!query.next()) - return -1; - return query.value(0).toInt(); -} - void DataManager::removeFeed(Feed *feed) { QList feeds; diff --git a/src/datamanager.h b/src/datamanager.h index b48503d4..47e7ee84 100644 --- a/src/datamanager.h +++ b/src/datamanager.h @@ -37,8 +37,6 @@ public: QStringList getIdList(const Feed *feed) const; int entryCount(const int feed_index) const; int entryCount(const Feed *feed) const; - int newEntryCount(const Feed *feed) const; - int favoriteEntryCount(const Feed *feed) const; Q_INVOKABLE void addFeed(const QString &url); void addFeed(const QString &url, const bool fetch); void addFeeds(const QStringList &urls); diff --git a/src/feed.cpp b/src/feed.cpp index ef113966..d0145c9c 100644 --- a/src/feed.cpp +++ b/src/feed.cpp @@ -44,6 +44,8 @@ Feed::Feed(const QString &feedurl) updateAuthors(); updateUnreadEntryCountFromDB(); + updateNewEntryCountFromDB(); + updateFavoriteEntryCountFromDB(); connect(&Fetcher::instance(), &Fetcher::feedUpdateStatusChanged, this, [this](const QString &url, bool status) { if (url == m_url) { @@ -54,11 +56,26 @@ Feed::Feed(const QString &feedurl) if (url == m_url) { Q_EMIT entryCountChanged(); updateUnreadEntryCountFromDB(); + Q_EMIT DataManager::instance().unreadEntryCountChanged(m_url); Q_EMIT unreadEntryCountChanged(); + Q_EMIT DataManager::instance().newEntryCountChanged(m_url); + Q_EMIT newEntryCountChanged(); setErrorId(0); setErrorString(QLatin1String("")); } }); + connect(&DataManager::instance(), &DataManager::newEntryCountChanged, this, [this](const QString &url) { + if (url == m_url) { + updateNewEntryCountFromDB(); + Q_EMIT newEntryCountChanged(); + } + }); + connect(&DataManager::instance(), &DataManager::favoriteEntryCountChanged, this, [this](const QString &url) { + if (url == m_url) { + updateFavoriteEntryCountFromDB(); + Q_EMIT favoriteEntryCountChanged(); + } + }); connect(&Fetcher::instance(), &Fetcher::error, this, @@ -141,6 +158,28 @@ void Feed::updateUnreadEntryCountFromDB() m_unreadEntryCount = query.value(0).toInt(); } +void Feed::updateNewEntryCountFromDB() +{ + QSqlQuery query; + query.prepare(QStringLiteral("SELECT COUNT (id) FROM Entries where feed=:feed AND new=1;")); + query.bindValue(QStringLiteral(":feed"), m_url); + Database::instance().execute(query); + if (!query.next()) + m_newEntryCount = -1; + m_newEntryCount = query.value(0).toInt(); +} + +void Feed::updateFavoriteEntryCountFromDB() +{ + QSqlQuery query; + query.prepare(QStringLiteral("SELECT COUNT (id) FROM Entries where feed=:feed AND favorite=1;")); + query.bindValue(QStringLiteral(":feed"), m_url); + Database::instance().execute(query); + if (!query.next()) + m_favoriteEntryCount = -1; + m_favoriteEntryCount = query.value(0).toInt(); +} + QString Feed::url() const { return m_url; @@ -218,12 +257,12 @@ int Feed::unreadEntryCount() const int Feed::newEntryCount() const { - return DataManager::instance().newEntryCount(this); + return m_newEntryCount; } int Feed::favoriteEntryCount() const { - return DataManager::instance().favoriteEntryCount(this); + return m_favoriteEntryCount; } bool Feed::refreshing() const diff --git a/src/feed.h b/src/feed.h index fce31564..df535536 100644 --- a/src/feed.h +++ b/src/feed.h @@ -111,6 +111,8 @@ Q_SIGNALS: private: void updateUnreadEntryCountFromDB(); + void updateNewEntryCountFromDB(); + void updateFavoriteEntryCountFromDB(); QString m_url; QString m_name; @@ -127,6 +129,8 @@ private: int m_errorId; QString m_errorString; int m_unreadEntryCount = -1; + int m_newEntryCount = -1; + int m_favoriteEntryCount = -1; EntriesProxyModel *m_entries; diff --git a/src/models/feedsmodel.cpp b/src/models/feedsmodel.cpp index 9e189e4e..6852e614 100644 --- a/src/models/feedsmodel.cpp +++ b/src/models/feedsmodel.cpp @@ -28,22 +28,10 @@ FeedsModel::FeedsModel(QObject *parent) beginRemoveRows(QModelIndex(), index, index); endRemoveRows(); }); - connect(&DataManager::instance(), &DataManager::unreadEntryCountChanged, this, [=](const QString &url) { - for (int i = 0; i < rowCount(QModelIndex()); i++) { - if (data(index(i, 0), UrlRole).toString() == url) { - Q_EMIT dataChanged(index(i, 0), index(i, 0)); - return; - } - } - }); - connect(&Fetcher::instance(), &Fetcher::feedDetailsUpdated, this, [=](const QString &url) { - for (int i = 0; i < rowCount(QModelIndex()); i++) { - if (data(index(i, 0), UrlRole).toString() == url) { - Q_EMIT dataChanged(index(i, 0), index(i, 0)); - return; - } - } - }); + connect(&DataManager::instance(), &DataManager::unreadEntryCountChanged, this, &FeedsModel::triggerFeedUpdate); + connect(&DataManager::instance(), &DataManager::newEntryCountChanged, this, &FeedsModel::triggerFeedUpdate); + connect(&DataManager::instance(), &DataManager::favoriteEntryCountChanged, this, &FeedsModel::triggerFeedUpdate); + connect(&Fetcher::instance(), &Fetcher::feedDetailsUpdated, this, &FeedsModel::triggerFeedUpdate); } QHash FeedsModel::roleNames() const @@ -53,6 +41,8 @@ QHash FeedsModel::roleNames() const {UrlRole, "url"}, {TitleRole, "title"}, {UnreadCountRole, "unreadCount"}, + {NewCountRole, "newCount"}, + {FavoriteCountRole, "favoriteCount"}, }; } @@ -74,7 +64,21 @@ QVariant FeedsModel::data(const QModelIndex &index, int role) const return QVariant::fromValue(DataManager::instance().getFeed(index.row())->name()); case UnreadCountRole: return QVariant::fromValue(DataManager::instance().getFeed(index.row())->unreadEntryCount()); + case NewCountRole: + return QVariant::fromValue(DataManager::instance().getFeed(index.row())->newEntryCount()); + case FavoriteCountRole: + return QVariant::fromValue(DataManager::instance().getFeed(index.row())->favoriteEntryCount()); default: return QVariant(); } } + +void FeedsModel::triggerFeedUpdate(const QString &url) +{ + for (int i = 0; i < rowCount(QModelIndex()); i++) { + if (data(index(i, 0), UrlRole).toString() == url) { + Q_EMIT dataChanged(index(i, 0), index(i, 0)); + return; + } + } +} diff --git a/src/models/feedsmodel.h b/src/models/feedsmodel.h index 5ded58c1..f8bbe3cb 100644 --- a/src/models/feedsmodel.h +++ b/src/models/feedsmodel.h @@ -24,6 +24,8 @@ public: UrlRole, TitleRole, UnreadCountRole, + NewCountRole, + FavoriteCountRole, }; Q_ENUM(Roles) @@ -31,4 +33,7 @@ public: QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; QHash roleNames() const override; int rowCount(const QModelIndex &parent) const override; + +private: + void triggerFeedUpdate(const QString &url); }; diff --git a/src/models/feedsproxymodel.cpp b/src/models/feedsproxymodel.cpp index 4c1a36e0..cc3f7638 100644 --- a/src/models/feedsproxymodel.cpp +++ b/src/models/feedsproxymodel.cpp @@ -6,26 +6,154 @@ #include "models/feedsproxymodel.h" +#include + +#include + FeedsProxyModel::FeedsProxyModel(QObject *parent) : QSortFilterProxyModel(parent) { m_feedsModel = new FeedsModel(this); setSourceModel(m_feedsModel); setDynamicSortFilter(true); - sort(0, Qt::AscendingOrder); + sort(0); } bool FeedsProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const { QString leftTitle = sourceModel()->data(left, FeedsModel::TitleRole).toString(); QString rightTitle = sourceModel()->data(right, FeedsModel::TitleRole).toString(); - int leftUnreadCount = sourceModel()->data(left, FeedsModel::UnreadCountRole).toInt(); - int rightUnreadCount = sourceModel()->data(right, FeedsModel::UnreadCountRole).toInt(); - if (leftUnreadCount == rightUnreadCount) { - return QString::localeAwareCompare(leftTitle, rightTitle) < 0; - } else { - return leftUnreadCount > rightUnreadCount; + if (m_currentSort == SortType::UnreadDescending || m_currentSort == SortType::UnreadAscending) { + int leftUnreadCount = sourceModel()->data(left, FeedsModel::UnreadCountRole).toInt(); + int rightUnreadCount = sourceModel()->data(right, FeedsModel::UnreadCountRole).toInt(); + + if (leftUnreadCount != rightUnreadCount) { + if (m_currentSort == SortType::UnreadDescending) { + return leftUnreadCount > rightUnreadCount; + } else { + return leftUnreadCount < rightUnreadCount; + } + } + } else if (m_currentSort == SortType::NewDescending || m_currentSort == SortType::NewAscending) { + int leftNewCount = sourceModel()->data(left, FeedsModel::NewCountRole).toInt(); + int rightNewCount = sourceModel()->data(right, FeedsModel::NewCountRole).toInt(); + + if (leftNewCount != rightNewCount) { + if (m_currentSort == SortType::NewDescending) { + return leftNewCount > rightNewCount; + } else { + return leftNewCount < rightNewCount; + } + } + } else if (m_currentSort == SortType::FavoriteDescending || m_currentSort == SortType::FavoriteAscending) { + int leftFavoriteCount = sourceModel()->data(left, FeedsModel::FavoriteCountRole).toInt(); + int rightFavoriteCount = sourceModel()->data(right, FeedsModel::FavoriteCountRole).toInt(); + + if (leftFavoriteCount != rightFavoriteCount) { + if (m_currentSort == SortType::FavoriteDescending) { + return leftFavoriteCount > rightFavoriteCount; + } else { + return leftFavoriteCount < rightFavoriteCount; + } + } + } else if (m_currentSort == SortType::TitleDescending) { + return QString::localeAwareCompare(leftTitle, rightTitle) > 0; + } + + // In case there is a "tie" always use ascending alphabetical ordering + return QString::localeAwareCompare(leftTitle, rightTitle) < 0; +} + +bool FeedsProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const +{ + QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent); + + bool found = m_searchFilter.isEmpty(); + if (!m_searchFilter.isEmpty()) { + if (sourceModel()->data(index, FeedsModel::Roles::TitleRole).value().contains(m_searchFilter, Qt::CaseInsensitive)) { + found |= true; + } + } + + return found; +} + +QString FeedsProxyModel::searchFilter() const +{ + return m_searchFilter; +} + +FeedsProxyModel::SortType FeedsProxyModel::sortType() const +{ + return m_currentSort; +} + +void FeedsProxyModel::setSearchFilter(const QString &searchString) +{ + if (searchString != m_searchFilter) { + beginResetModel(); + m_searchFilter = searchString; + endResetModel(); + + Q_EMIT searchFilterChanged(); + } +} + +void FeedsProxyModel::setSortType(SortType type) +{ + if (type != m_currentSort) { + m_currentSort = type; + + // HACK: get the list re-sorted with a custom lessThan implementation + sort(-1); + sort(0); + + Q_EMIT sortTypeChanged(); + } +} + +QString FeedsProxyModel::getSortName(SortType type) const +{ + switch (type) { + case SortType::UnreadDescending: + return i18nc("@label:chooser Sort podcasts by decreasing number of unplayed episodes", "Unplayed count: descending"); + case SortType::UnreadAscending: + return i18nc("@label:chooser Sort podcasts by increasing number of unplayed episodes", "Unplayed count: ascending"); + case SortType::NewDescending: + return i18nc("@label:chooser Sort podcasts by decreasing number of new episodes", "New count: descending"); + case SortType::NewAscending: + return i18nc("@label:chooser Sort podcasts by increasing number of new episodes", "New count: ascending"); + case SortType::FavoriteDescending: + return i18nc("@label:chooser Sort podcasts by decreasing number of favorites", "Favorite count: descending"); + case SortType::FavoriteAscending: + return i18nc("@label:chooser Sort podcasts by increasing number of favorites", "Favorite count: ascending"); + case SortType::TitleAscending: + return i18nc("@label:chooser Sort podcasts titles alphabetically", "Podcast title: A → Z"); + case SortType::TitleDescending: + return i18nc("@label:chooser Sort podcasts titles in reverse alphabetical order", "Podcast title: Z → A"); + default: + return QString(); + } +} + +QString FeedsProxyModel::getSortIconName(SortType type) const +{ + switch (type) { + case SortType::UnreadDescending: + case SortType::NewDescending: + case SortType::FavoriteDescending: + return QStringLiteral("view-sort-descending"); + case SortType::UnreadAscending: + case SortType::NewAscending: + case SortType::FavoriteAscending: + return QStringLiteral("view-sort-ascending"); + case SortType::TitleDescending: + return QStringLiteral("view-sort-descending-name"); + case SortType::TitleAscending: + return QStringLiteral("view-sort-ascending-name"); + default: + return QString(); } } diff --git a/src/models/feedsproxymodel.h b/src/models/feedsproxymodel.h index 4200a074..4c20bd79 100644 --- a/src/models/feedsproxymodel.h +++ b/src/models/feedsproxymodel.h @@ -7,7 +7,9 @@ #pragma once #include +#include #include +#include #include "models/feedsmodel.h" @@ -18,12 +20,46 @@ class FeedsProxyModel : public QSortFilterProxyModel Q_OBJECT public: + enum SortType { + UnreadDescending, + UnreadAscending, + NewDescending, + NewAscending, + FavoriteDescending, + FavoriteAscending, + TitleAscending, + TitleDescending, + }; + Q_ENUM(SortType) + + Q_PROPERTY(QString searchFilter READ searchFilter WRITE setSearchFilter NOTIFY searchFilterChanged) + Q_PROPERTY(SortType sortType READ sortType WRITE setSortType NOTIFY sortTypeChanged) + explicit FeedsProxyModel(QObject *parent = nullptr); bool lessThan(const QModelIndex &left, const QModelIndex &right) const override; + bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; + + QString searchFilter() const; + SortType sortType() const; + + void setSearchFilter(const QString &searchString); + void setSortType(SortType type); + + Q_INVOKABLE QString getSortName(SortType type) const; + Q_INVOKABLE QString getSortIconName(SortType type) const; Q_INVOKABLE QItemSelection createSelection(int rowa, int rowb); +Q_SIGNALS: + void searchFilterChanged(); + void sortTypeChanged(); + private: FeedsModel *m_feedsModel; + + QString m_searchFilter; + SortType m_currentSort = SortType::UnreadDescending; }; + +Q_DECLARE_METATYPE(FeedsProxyModel::SortType) diff --git a/src/qml/FeedListDelegate.qml b/src/qml/FeedListDelegate.qml index 55061103..5bcebca0 100644 --- a/src/qml/FeedListDelegate.qml +++ b/src/qml/FeedListDelegate.qml @@ -18,6 +18,7 @@ import org.kde.kasts 1.0 Controls.ItemDelegate { id: feedDelegate + property var countProperty: (kastsMainWindow.feedSorting === FeedsProxyModel.UnreadDescending || kastsMainWindow.feedSorting === FeedsProxyModel.UnreadAscending) ? feed.unreadEntryCount : ((kastsMainWindow.feedSorting === FeedsProxyModel.NewDescending || kastsMainWindow.feedSorting === FeedsProxyModel.NewAscending) ? feed.newEntryCount : ((kastsMainWindow.feedSorting === FeedsProxyModel.FavoriteDescending || kastsMainWindow.feedSorting === FeedsProxyModel.FavoriteAscending) ? feed.favoriteEntryCount : 0)) property int cardSize: 0 property int cardMargin: 0 property int borderWidth: 1 @@ -170,7 +171,7 @@ Controls.ItemDelegate { Rectangle { id: countRectangle - visible: feed.unreadEntryCount > 0 + visible: countProperty > 0 anchors.top: img.top anchors.right: img.right width: actionsButton.width @@ -181,10 +182,10 @@ Controls.ItemDelegate { Controls.Label { id: countLabel - visible: feed.unreadEntryCount > 0 + visible: countProperty > 0 anchors.centerIn: countRectangle anchors.margins: Kirigami.Units.smallSpacing - text: feed.unreadEntryCount + text: countProperty font.bold: true color: Kirigami.Theme.highlightedTextColor } diff --git a/src/qml/FeedListPage.qml b/src/qml/FeedListPage.qml index ec5199a0..890d5b81 100644 --- a/src/qml/FeedListPage.qml +++ b/src/qml/FeedListPage.qml @@ -57,6 +57,62 @@ Kirigami.ScrollablePage { addSheet.open() } }, + Kirigami.Action { + id: sortActionRoot + icon.name: "view-sort" + text: i18nc("@action:intoolbar Open menu with options to sort subscriptions", "Sort") + + tooltip: i18nc("@info:tooltip", "Select how to sort subscriptions") + + property Controls.ActionGroup sortGroup: Controls.ActionGroup { } + + property Instantiator repeater: Instantiator { + model: ListModel { + id: sortModel + // have to use script because i18n doesn't work within ListElement + Component.onCompleted: { + if (sortActionRoot.visible) { + var sortList = [FeedsProxyModel.UnreadDescending, + FeedsProxyModel.UnreadAscending, + FeedsProxyModel.NewDescending, + FeedsProxyModel.NewAscending, + FeedsProxyModel.FavoriteDescending, + FeedsProxyModel.FavoriteAscending, + FeedsProxyModel.TitleAscending, + FeedsProxyModel.TitleDescending] + for (var i in sortList) { + sortModel.append({"name": feedsModel.getSortName(sortList[i]), + "iconName": feedsModel.getSortIconName(sortList[i]), + "sortType": sortList[i]}); + } + } + } + } + + Kirigami.Action { + visible: sortActionRoot.visible + icon.name: model.iconName + text: model.name + checkable: true + checked: kastsMainWindow.feedSorting === model.sortType + Controls.ActionGroup.group: sortActionRoot.sortGroup + + onTriggered: { + kastsMainWindow.feedSorting = model.sortType; + } + } + + onObjectAdded: (index, object) => { + sortActionRoot.children.push(object); + } + } + }, + Kirigami.Action { + id: searchActionButton + icon.name: "search" + text: i18nc("@action:intoolbar", "Search") + checkable: true + }, Kirigami.Action { id: importAction text: i18nc("@action:intoolbar", "Import Podcasts…") @@ -83,6 +139,19 @@ Kirigami.ScrollablePage { // TODO: KF6 replace contextualActions with actions contextualActions: pageActions + header: Loader { + anchors.right: parent.right + anchors.left: parent.left + + active: searchActionButton.checked + visible: active + sourceComponent: SearchBar { + proxyModel: feedsModel + parentKey: searchActionButton + showSearchFilters: false + } + } + AddFeedSheet { id: addSheet } @@ -114,9 +183,9 @@ Kirigami.ScrollablePage { visible: feedList.count === 0 width: Kirigami.Units.gridUnit * 20 anchors.centerIn: parent - type: Kirigami.PlaceholderMessage.Actionable - text: i18nc("@info Placeholder message for empty podcast list", "No podcasts added yet") - explanation: i18nc("@info:tipoftheday", "Get started by adding podcasts:") + type: feedsModel.searchFilter === "" ? Kirigami.PlaceholderMessage.Actionable : Kirigami.PlaceholderMessage.Informational + text: feedsModel.searchFilter === "" ? i18nc("@info Placeholder message for empty podcast list", "No podcasts added yet") : i18nc("@info Placeholder message for podcast list when no podcast matches the search criteria", "No podcasts found") + explanation: feedsModel.searchFilter === "" ? i18nc("@info:tipoftheday", "Get started by adding podcasts:") : null readonly property int buttonSize: Math.max(discoverButton.implicitWidth, addButton.implicitWidth, importButton.implicitWidth, syncButton.implicitWidth) @@ -124,6 +193,7 @@ Kirigami.ScrollablePage { // to give them more descriptive names Controls.Button { id: discoverButton + visible: feedsModel.searchFilter === "" Layout.preferredWidth: placeholderMessage.buttonSize Layout.alignment: Qt.AlignHCenter Layout.topMargin: Kirigami.Units.gridUnit @@ -136,6 +206,7 @@ Kirigami.ScrollablePage { Controls.Button { id: addButton + visible: feedsModel.searchFilter === "" Layout.preferredWidth: placeholderMessage.buttonSize Layout.alignment: Qt.AlignHCenter action: addAction @@ -143,6 +214,7 @@ Kirigami.ScrollablePage { Controls.Button { id: importButton + visible: feedsModel.searchFilter === "" Layout.preferredWidth: placeholderMessage.buttonSize Layout.alignment: Qt.AlignHCenter action: importAction @@ -150,6 +222,7 @@ Kirigami.ScrollablePage { Controls.Button { id: syncButton + visible: feedsModel.searchFilter === "" Layout.preferredWidth: placeholderMessage.buttonSize Layout.alignment: Qt.AlignHCenter action: Kirigami.Action { @@ -184,6 +257,7 @@ Kirigami.ScrollablePage { model: FeedsProxyModel { id: feedsModel + sortType: kastsMainWindow.feedSorting } delegate: FeedListDelegate { @@ -207,9 +281,9 @@ Kirigami.ScrollablePage { Connections { target: feedList.model function onModelAboutToBeReset() { - selectionForContextMenu = []; + feedList.selectionForContextMenu = []; feedList.selectionModel.clear(); - feedList.selectionModel.setCurrentIndex(model.index(0, 0), ItemSelectionModel.Current); // Only set current item; don't select it + feedList.selectionModel.setCurrentIndex(feedList.model.index(0, 0), ItemSelectionModel.Current); // Only set current item; don't select it currentIndex = 0; } } diff --git a/src/qml/SearchBar.qml b/src/qml/SearchBar.qml index 5ee60233..7a2e5722 100644 --- a/src/qml/SearchBar.qml +++ b/src/qml/SearchBar.qml @@ -16,6 +16,7 @@ Controls.Control { required property var proxyModel required property var parentKey + property bool showSearchFilters: true leftPadding: Kirigami.Units.largeSpacing + Kirigami.Units.smallSpacing rightPadding: Kirigami.Units.largeSpacing @@ -46,6 +47,8 @@ Controls.Control { Kirigami.Action { id: searchSettingsButton + visible: showSearchFilters + enabled: visible icon.name: "settings-configure" text: i18nc("@action:intoolbar", "Advanced Search Options") @@ -68,7 +71,6 @@ Controls.Control { } Keys.onEscapePressed: { - proxyModel.filterType = AbstractEpisodeProxyModel.NoFilter; proxyModel.searchFilter = ""; parentKey.checked = false; event.accepted = true; @@ -88,13 +90,15 @@ Controls.Control { function reload() { clear(); - var searchList = [AbstractEpisodeProxyModel.TitleFlag, - AbstractEpisodeProxyModel.ContentFlag, - AbstractEpisodeProxyModel.FeedNameFlag] - for (var i in searchList) { - searchSettingsModel.append({"name": proxyModel.getSearchFlagName(searchList[i]), - "searchFlag": searchList[i], - "checked": proxyModel.searchFlags & searchList[i]}); + if (showSearchFilters) { + var searchList = [AbstractEpisodeProxyModel.TitleFlag, + AbstractEpisodeProxyModel.ContentFlag, + AbstractEpisodeProxyModel.FeedNameFlag] + for (var i in searchList) { + searchSettingsModel.append({"name": proxyModel.getSearchFlagName(searchList[i]), + "searchFlag": searchList[i], + "checked": proxyModel.searchFlags & searchList[i]}); + } } } diff --git a/src/qml/main.qml b/src/qml/main.qml index 596fbd5b..4a0ee84b 100644 --- a/src/qml/main.qml +++ b/src/qml/main.qml @@ -43,6 +43,7 @@ Kirigami.ApplicationWindow { } property var lastFeed: "" property string currentPage: "" + property int feedSorting: FeedsProxyModel.UnreadDescending property bool isWidescreen: kastsMainWindow.width > kastsMainWindow.height @@ -85,6 +86,7 @@ Kirigami.ApplicationWindow { property var desktopHeight property int headerSize: Kirigami.Units.gridUnit * 5 property alias lastOpenedPage: kastsMainWindow.currentPage + property alias feedSorting: kastsMainWindow.feedSorting } function saveWindowLayout() {