Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

QML UI: Basic episode list filters (bug 1527)

This still needs some work (i.e. the list might
need refreshing after a download has finished
or an episode has been played/marked as old).
  • Loading branch information...
commit 83a541837f445e03547b0eeb88f6810a38ba6273 1 parent 17bd235
@thp thp authored
View
48 data/ui/qml/EpisodeList.qml
@@ -7,20 +7,41 @@ import 'config.js' as Config
Item {
id: episodeList
+ property string currentFilterText
property alias model: listView.model
property alias moving: listView.moving
+ property alias count: listView.count
signal episodeContextMenu(variant episode)
+ function showFilterDialog() {
+ filterDialog.open();
+ }
+
function resetSelection() {
listView.openedIndex = -1
}
+ Text {
+ anchors.centerIn: parent
+ color: 'white'
+ font.pixelSize: 30
+ horizontalAlignment: Text.AlignHCenter
+ text: '<big>' + _('No episodes') + '</big>' + '<br><small>' + _('Touch to change filter') + '</small>'
+ visible: !listView.visible
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: episodeList.showFilterDialog()
+ }
+ }
+
ListView {
id: listView
anchors.fill: parent
property int openedIndex: -1
+ visible: count > 0
delegate: Item {
id: listItem
@@ -91,5 +112,32 @@ Item {
ScrollDecorator {
flickableItem: listView
}
+
+ SelectionDialog {
+ id: filterDialog
+ titleText: _('Show episodes')
+
+ function resetSelection() {
+ selectedIndex = 0;
+ accepted();
+ }
+
+ onAccepted: {
+ episodeList.currentFilterText = model.get(selectedIndex).name;
+ episodeList.model.setFilter(selectedIndex);
+ }
+
+ model: ListModel {}
+
+ Component.onCompleted: {
+ var filters = controller.getEpisodeListFilterNames();
+
+ for (var index in filters) {
+ model.append({name: filters[index]});
+ }
+
+ resetSelection();
+ }
+ }
}
View
8 data/ui/qml/Main.qml
@@ -21,12 +21,14 @@ Image {
property alias currentEpisode: mediaPlayer.episode
property variant currentPodcast: undefined
property bool hasPodcasts: podcastList.hasItems
+ property alias currentFilterText: episodeList.currentFilterText
property bool playing: mediaPlayer.playing
property bool canGoBack: (closeButton.isRequired || mediaPlayer.visible) && !progressIndicator.opacity && !myGpoSheetVisible
property bool hasPlayButton: nowPlayingThrobber.shouldAppear && !progressIndicator.opacity && !myGpoSheetVisible
property bool hasSearchButton: searchButton.visible && !mediaPlayer.visible && !progressIndicator.opacity && !myGpoSheetVisible
property bool myGpoSheetVisible: false
+ property bool hasFilterButton: state == 'episodes' && !mediaPlayer.visible
function openMyGpo() {
myGpoEnableSwitch.checked = controller.myGpoEnabled
@@ -45,6 +47,10 @@ Image {
}
}
+ function showFilterDialog() {
+ episodeList.showFilterDialog()
+ }
+
function clickPlayButton() {
nowPlayingThrobber.clicked()
}
@@ -407,7 +413,7 @@ Image {
anchors.right: searchButton.visible?searchButton.left:searchButton.right
wrapMode: Text.NoWrap
clip: true
- text: (contextMenu.state == 'opened')?(contextMenu.subscribeMode?_('Add a new podcast'):_('Context menu')):((main.state == 'episodes' || main.state == 'shownotes')?controller.episodeListTitle:"gPodder")
+ text: (contextMenu.state == 'opened')?(contextMenu.subscribeMode?_('Add a new podcast'):_('Context menu')):((main.state == 'episodes' || main.state == 'shownotes')?(controller.episodeListTitle + ' (' + episodeList.count + ')'):"gPodder")
color: 'white'
font.pixelSize: parent.height * .5
font.bold: false
View
13 data/ui/qml/main_harmattan.qml
@@ -66,6 +66,19 @@ PageStackWindow {
//anchors.right: toolPlay.visible?toolPlay.left:toolPlay.right
}
+ ToolButton {
+ id: toolFilter
+ visible: mainObject.hasFilterButton
+ onClicked: mainObject.showFilterDialog()
+ anchors.centerIn: parent
+
+ Label {
+ color: 'white'
+ text: mainObject.currentFilterText
+ anchors.centerIn: parent
+ }
+ }
+
ToolIcon {
id: toolPlay
iconId: "icon-m-toolbar-content-audio-white"
View
2  src/gpodder/model.py
@@ -709,7 +709,7 @@ def is_finished(self):
current position is greater than 99 percent of the
total time or inside the last 10 seconds of a track.
"""
- return self.current_position > 0 and \
+ return self.current_position > 0 and self.total_time > 0 and \
(self.current_position + 10 >= self.total_time or \
self.current_position >= self.total_time*.99)
View
52 src/gpodder/qmlui/__init__.py
@@ -39,6 +39,7 @@
from gpodder import core
from gpodder import util
from gpodder import my
+from gpodder import query
from gpodder.model import Model
@@ -49,6 +50,19 @@
import logging
logger = logging.getLogger("qmlui")
+
+EPISODE_LIST_FILTERS = [
+ # (UI label, EQL expression)
+ (_('All'), None),
+ (_('Hide deleted'), 'not deleted'),
+ (_('New'), 'new or downloading'),
+ (_('Downloaded'), 'downloaded or downloading'),
+ (_('Deleted'), 'deleted'),
+ (_('Finished'), 'finished'),
+ (_('Archived'), 'downloaded and archive'),
+ (_('Videos'), 'video'),
+]
+
class Controller(QObject):
def __init__(self, root):
QObject.__init__(self)
@@ -83,6 +97,10 @@ def getEpisodeListTitle(self):
episodeListTitle = Property(unicode, getEpisodeListTitle, \
setEpisodeListTitle, notify=episodeListTitleChanged)
+ @Slot(result='QStringList')
+ def getEpisodeListFilterNames(self):
+ return [caption for caption, eql in EPISODE_LIST_FILTERS]
+
@Slot(str, result=str)
def translate(self, x):
return _(x)
@@ -528,7 +546,7 @@ def get_object(self, index):
return self._objects[index.row()]
def rowCount(self, parent=QModelIndex()):
- return len(self._objects)
+ return len(self.get_objects())
def data(self, index, role):
if index.isValid():
@@ -553,6 +571,36 @@ def sort(self):
self._objects = sorted(self._objects, key=model.QPodcast.sort_key)
self.reset()
+class gPodderEpisodeListModel(gPodderListModel):
+ def __init__(self):
+ gPodderListModel.__init__(self)
+ self._filter = 0
+ self._filtered = []
+
+ def sort(self):
+ caption, eql = EPISODE_LIST_FILTERS[self._filter]
+
+ if eql is None:
+ self._filtered = self._objects
+ else:
+ eql = query.EQL(eql)
+ match = lambda episode: eql.match(episode._episode)
+ self._filtered = filter(match, self._objects)
+
+ self.reset()
+
+ def get_objects(self):
+ return self._filtered
+
+ def get_object(self, index):
+ return self._filtered[index.row()]
+
+ @Slot(int)
+ def setFilter(self, filter_index):
+ self._filter = filter_index
+ self.sort()
+
+
def QML(filename):
for folder in gpodder.ui_folders:
filename = os.path.join(folder, filename)
@@ -605,7 +653,7 @@ def __init__(self, args, gpodder_core):
self.controller = Controller(self)
self.media_buttons_handler = helper.MediaButtonsHandler()
self.podcast_model = gPodderPodcastListModel()
- self.episode_model = gPodderListModel()
+ self.episode_model = gPodderEpisodeListModel()
self.last_episode = None
# A dictionary of episodes that are currently active
View
2  src/gpodder/query.py
@@ -56,6 +56,8 @@ def __getitem__(self, k):
return episode.state == gpodder.STATE_DELETED
elif k == 'played':
return not episode.is_new
+ elif k == 'downloading':
+ return episode.downloading
elif k == 'archive':
return episode.archive
elif k in ('finished', 'fin'):

0 comments on commit 83a5418

Please sign in to comment.
Something went wrong with that request. Please try again.