Implement Filter actions in GUI

This commit is contained in:
Bart De Vries 2021-07-02 16:41:09 +02:00
parent 531c6a2483
commit 86d1476687
5 changed files with 120 additions and 10 deletions

View File

@ -136,6 +136,7 @@ if(ANDROID)
list-add
list-remove
view-refresh
view-filter
kasts
mail-sent
globe

View File

@ -28,9 +28,10 @@ public:
QHash<int, QByteArray> roleNames() const override;
int rowCount(const QModelIndex &parent) const override;
private:
public Q_SLOTS:
void updateInternalState();
private:
QStringList m_entryIds;
QVector<bool> m_read;
QVector<bool> m_new;

View File

@ -6,6 +6,8 @@
#include "models/episodeproxymodel.h"
#include <KLocalizedString>
EpisodeProxyModel::EpisodeProxyModel()
: QSortFilterProxyModel(nullptr)
{
@ -46,6 +48,37 @@ EpisodeProxyModel::FilterType EpisodeProxyModel::filterType() const
void EpisodeProxyModel::setFilterType(FilterType type)
{
m_currentFilter = type;
Q_EMIT filterTypeChanged(m_currentFilter);
if (type != m_currentFilter) {
beginResetModel();
// TODO: Connect to signals to capture new and read updates in case those
// filters are active. Also disconnect from signals if the filters are
// removed
m_currentFilter = type;
m_episodeModel->updateInternalState();
endResetModel();
Q_EMIT filterTypeChanged();
}
}
QString EpisodeProxyModel::filterName() const
{
return getFilterName(m_currentFilter);
}
QString EpisodeProxyModel::getFilterName(FilterType type) const
{
switch (type) {
case NoFilter:
return i18n("No Filter");
case ReadFilter:
return i18n("Played Episodes");
case NotReadFilter:
return i18n("Unplayed Episodes");
case NewFilter:
return i18n("Episodes marked as \"New\"");
case NotNewFilter:
return i18n("Episodes not marked as \"New\"");
default:
return QString();
}
}

View File

@ -25,6 +25,7 @@ public:
Q_ENUM(FilterType)
Q_PROPERTY(FilterType filterType READ filterType WRITE setFilterType NOTIFY filterTypeChanged)
Q_PROPERTY(QString filterName READ filterName NOTIFY filterTypeChanged)
explicit EpisodeProxyModel();
~EpisodeProxyModel();
@ -32,10 +33,13 @@ public:
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
FilterType filterType() const;
QString filterName() const;
void setFilterType(FilterType type);
Q_INVOKABLE QString getFilterName(FilterType type) const;
Q_SIGNALS:
void filterTypeChanged(FilterType filter);
void filterTypeChanged();
private:
EpisodeModel *m_episodeModel;

View File

@ -25,13 +25,84 @@ Kirigami.ScrollablePage {
}
}
actions {
main: Kirigami.Action {
iconName: "view-refresh"
text: i18n("Refresh All Podcasts")
onTriggered: refreshing = true
visible: !Kirigami.Settings.isMobile || episodeList.count === 0
actions.main: Kirigami.Action {
iconName: "view-filter"
text: i18n("Filter")
onTriggered: filterTypeOverlay.open();
}
actions.left: Kirigami.Action {
iconName: "view-refresh"
text: i18n("Refresh All Podcasts")
onTriggered: refreshing = true
visible: !Kirigami.Settings.isMobile || (episodeList.count === 0 && episodeProxyModel.filterType == EpisodeProxyModel.NoFilter)
}
Kirigami.OverlaySheet {
id: filterTypeOverlay
header: Kirigami.Heading {
text: i18n("Select Filter")
}
ListView {
// TODO: fix automatic width
implicitWidth: Kirigami.Units.gridUnit * 12
clip: true
model: ListModel {
id: filterModel
// have to use script because i18n doesn't work within ListElement
Component.onCompleted: {
var filterList = [EpisodeProxyModel.NoFilter,
EpisodeProxyModel.ReadFilter,
EpisodeProxyModel.NotReadFilter,
EpisodeProxyModel.NewFilter,
EpisodeProxyModel.NotNewFilter]
for (var i in filterList) {
filterModel.append({"name": episodeProxyModel.getFilterName(filterList[i]),
"filterType": filterList[i]});
}
}
}
delegate: Kirigami.BasicListItem {
id: swipeDelegate
highlighted: filterType === episodeProxyModel.filterType
text: name
onClicked: {
episodeProxyModel.filterType = filterType;
filterTypeOverlay.close();
}
}
}
}
Kirigami.InlineMessage {
z: 2
anchors {
horizontalCenter: parent.horizontalCenter
bottom: parent.bottom
bottomMargin: (Kirigami.Settings.isMobile ? Kirigami.Units.largeSpacing * 9 : Kirigami.Units.largeSpacing * 2) + (errorNotification.visible ? errorNotification.height : 0)
}
type: Kirigami.MessageType.Information
visible: episodeProxyModel.filterType != EpisodeProxyModel.NoFilter
TextMetrics {
id: textMetrics
text: i18n("Filter Active: ") + episodeProxyModel.filterName
}
text: textMetrics.text
width: Math.min(textMetrics.width + 2 * Kirigami.Units.largeSpacing + 10 * Kirigami.Units.gridUnit, parent.width)
actions: [
Kirigami.Action {
id: resetButton
icon.name: "edit-delete-remove"
text: i18n("Reset")
onTriggered: {
episodeProxyModel.filterType = EpisodeProxyModel.NoFilter;
}
}
]
}
Kirigami.PlaceholderMessage {