Skip to content

Commit

Permalink
QML UI: Implement multi-episode selection (bug 1594)
Browse files Browse the repository at this point in the history
Multi-episode actions: Play, Delete, Download
  • Loading branch information
thp committed Apr 29, 2012
1 parent 8805b0d commit 581a954
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 10 deletions.
62 changes: 62 additions & 0 deletions share/gpodder/ui/qml/Main.qml
Expand Up @@ -45,6 +45,13 @@ Image {
nowPlayingThrobber.clicked()
}

function showMultiEpisodesSheet(label, action) {
multiEpisodesSheet.acceptButtonText = label;
multiEpisodesSheet.action = action;
multiEpisodesList.selected = [];
multiEpisodesSheet.open();
}

function clickSearchButton() {
searchButton.clicked()
}
Expand Down Expand Up @@ -528,6 +535,61 @@ Image {
onRejected: inputDialog.close()
}

Sheet {
id: multiEpisodesSheet
property string action: 'delete'
acceptButtonText: _('Delete')

rejectButtonText: _('Cancel')

visualParent: rootWindow

onAccepted: {
controller.multiEpisodeAction(multiEpisodesList.selected, action);
}

content: Item {
anchors.fill: parent
ListView {
id: multiEpisodesList
property variant selected: []

anchors.fill: parent
anchors.bottomMargin: Config.largeSpacing
model: episodeList.model

delegate: EpisodeItem {
inSelection: multiEpisodesList.selected.indexOf(index) !== -1
onSelected: {
var newSelection = [];
var found = false;

for (var i=0; i<multiEpisodesList.selected.length; i++) {
var value = multiEpisodesList.selected[i];
if (value === index) {
found = true;
} else {
newSelection.push(value);
}
}

if (!found) {
if (multiEpisodesSheet.action === 'delete' && item.qarchive) {
// cannot delete archived episodes
} else {
newSelection.push(index);
}
}

multiEpisodesList.selected = newSelection;
}
}
}

ScrollDecorator { flickableItem: multiEpisodesList }
}
}

Sheet {
id: inputSheet

Expand Down
56 changes: 46 additions & 10 deletions share/gpodder/ui/qml/main_default.qml
Expand Up @@ -44,15 +44,15 @@ PageStackWindow {
ToolIcon {
id: toolMenu
onClicked: {
/*if (mainObject.currentPodcast !== undefined) {
controller.podcastContextMenu(mainObject.currentPodcast)
} else {*/
hrmtnMainViewMenu.open()
//}
if (mainObject.state === 'episodes') {
hrmtnEpisodesMenu.open();
} else {
hrmtnMainViewMenu.open();
}
}
anchors.right: parent.right
iconId: "toolbar-view-menu"
visible: (!toolBack.visible && mainObject.state == 'podcasts') //|| (mainObject.currentPodcast !== undefined && mainObject.state == 'episodes')
visible: (!toolBack.visible && mainObject.state == 'podcasts') || (mainObject.currentPodcast !== undefined && mainObject.state == 'episodes')
}

ToolIcon {
Expand Down Expand Up @@ -98,6 +98,10 @@ PageStackWindow {
id: hrmtnMainViewMenu

MenuLayout {
MenuItem {
text: _('Now playing')
onClicked: nowPlayingMenuItem.clicked()
}
MenuItem {
text: _('Settings')
onClicked: {
Expand All @@ -107,18 +111,50 @@ PageStackWindow {
}
}
MenuItem {
text: _('About gPodder')
onClicked: {
hrmtnMainViewMenu.close()
pageStack.push(aboutBox)
}
}
}
}

ContextMenu {
id: hrmtnEpisodesMenu

MenuLayout {
MenuItem {
id: nowPlayingMenuItem
text: _('Now playing')
onClicked: {
if (mainObject.hasPlayButton) {
hrmtnMainViewMenu.close();
mainObject.clickPlayButton();
} else {
mainObject.showMessage(_('Playlist empty'));
}
}
}
MenuItem {
text: _('Download episodes')
onClicked: {
mainObject.showMultiEpisodesSheet(_('Download'), 'download');
hrmtnMainViewMenu.close()
mainObject.clickPlayButton()
}
visible: mainObject.hasPlayButton
}
MenuItem {
text: _('About gPodder')
text: _('Playback episodes')
onClicked: {
mainObject.showMultiEpisodesSheet(_('Play'), 'play');
hrmtnMainViewMenu.close()
}
}
MenuItem {
text: _('Delete episodes')
onClicked: {
mainObject.showMultiEpisodesSheet(_('Delete'), 'delete');
hrmtnMainViewMenu.close()
pageStack.push(aboutBox)
}
}
}
Expand Down
37 changes: 37 additions & 0 deletions src/gpodder/qmlui/__init__.py
Expand Up @@ -131,6 +131,40 @@ def getEpisodeListTitle(self):
def getEpisodeListFilterNames(self):
return [caption for caption, eql in EPISODE_LIST_FILTERS]

@Slot('QVariant', str)
def multiEpisodeAction(self, selected, action):
if not selected:
return

count = len(selected)
episodes = map(self.root.episode_model.get_object_by_index, selected)

def delete():
for episode in episodes:
if not episode.qarchive:
episode.delete_episode()
self.update_subset_stats()
self.root.mygpo_client.on_delete(episodes)
self.root.mygpo_client.flush()
for episode in episodes:
self.root.on_episode_deleted(episode)
self.root.episode_model.sort()

if action == 'delete':
msg = N_('Delete %(count)d episode?', 'Delete %(count)d episodes?', count) % {'count':count}
self.confirm_action(msg, _('Delete'), delete)
elif action == 'download':
for episode in episodes:
if episode.qdownloaded:
print ' XXX already downloaded'
continue
episode.qdownload(self.root.config, self.update_subset_stats)
self.root.mygpo_client.on_download(episodes)
self.root.mygpo_client.flush()
elif action == 'play':
for episode in episodes:
self.root.enqueue_episode(episode)

@Slot(str, result=str)
def translate(self, x):
return _(x)
Expand Down Expand Up @@ -652,6 +686,9 @@ def get_objects(self):
def get_object(self, index):
return self._filtered[index.row()]

def get_object_by_index(self, index):
return self._filtered[index]

@Slot(result=int)
def getFilter(self):
return self._filter
Expand Down

0 comments on commit 581a954

Please sign in to comment.