Skip to content

Commit

Permalink
QML UI: Basic episode list filters (bug 1527)
Browse files Browse the repository at this point in the history
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
thp committed Jan 14, 2012
1 parent 17bd235 commit 83a5418
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 4 deletions.
48 changes: 48 additions & 0 deletions data/ui/qml/EpisodeList.qml
Expand Up @@ -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
Expand Down Expand Up @@ -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();
}
}
}

8 changes: 7 additions & 1 deletion data/ui/qml/Main.qml
Expand Up @@ -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
Expand All @@ -45,6 +47,10 @@ Image {
}
}

function showFilterDialog() {
episodeList.showFilterDialog()
}

function clickPlayButton() {
nowPlayingThrobber.clicked()
}
Expand Down Expand Up @@ -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
Expand Down
13 changes: 13 additions & 0 deletions data/ui/qml/main_harmattan.qml
Expand Up @@ -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"
Expand Down
2 changes: 1 addition & 1 deletion src/gpodder/model.py
Expand Up @@ -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)

Expand Down
52 changes: 50 additions & 2 deletions src/gpodder/qmlui/__init__.py
Expand Up @@ -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

Expand All @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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():
Expand All @@ -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)
Expand Down Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions src/gpodder/query.py
Expand Up @@ -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'):
Expand Down

0 comments on commit 83a5418

Please sign in to comment.