3 import com.nokia.meego 1.0
5 import 'config.js' as Config
12 return controller.translate(x)
15 function n_(x, y, z) {
16 return controller.ntranslate(x, y, z)
19 property alias podcastModel: podcastList.model
20 property alias episodeModel: episodeList.model
21 property alias currentEpisode: mediaPlayer.episode
22 property variant currentPodcast: undefined
23 property bool hasPodcasts: podcastList.hasItems
24 property alias currentFilterText: episodeList.currentFilterText
26 property bool playing: mediaPlayer.playing
27 property bool canGoBack: (closeButton.isRequired || mediaPlayer.visible) && !progressIndicator.opacity
28 property bool hasPlayButton: nowPlayingThrobber.shouldAppear && !progressIndicator.opacity
29 property bool hasSearchButton: searchButton.visible && !mediaPlayer.visible && !progressIndicator.opacity
30 property bool hasFilterButton: state == 'episodes' && !mediaPlayer.visible
33 if (nowPlayingThrobber.opened) {
34 nowPlayingThrobber.opened = false
40 function showFilterDialog() {
41 episodeList.showFilterDialog()
44 function clickPlayButton() {
45 nowPlayingThrobber.clicked()
48 function clickSearchButton() {
49 searchButton.clicked()
53 console.log(event.key)
54 if (event.key == Qt.Key_Escape) {
57 if (event.key == Qt.Key_F && event.modifiers & Qt.ControlModifier) {
58 searchButton.clicked()
65 property bool useEmptyBackground: !podcastList.hasItems
67 anchors.topMargin: useEmptyBackground?-35:0
68 fillMode: useEmptyBackground?Image.Tile:Image.Stretch
70 if (useEmptyBackground) {
71 '/usr/share/themes/blanco/meegotouch/images/backgrounds/meegotouch-empty-application-background-black-portrait.png'
73 'artwork/background-harmattan.png'
79 function enqueueEpisode(episode) {
80 if (currentEpisode === undefined) {
81 togglePlayback(episode);
83 mediaPlayer.enqueueEpisode(episode);
87 function removeQueuedEpisodesForPodcast(podcast) {
88 mediaPlayer.removeQueuedEpisodesForPodcast(podcast);
91 function removeQueuedEpisode(episode) {
92 mediaPlayer.removeQueuedEpisode(episode);
95 function togglePlayback(episode) {
96 if (episode !== undefined && episode.qfiletype == 'video') {
97 controller.playVideo(episode)
99 mediaPlayer.togglePlayback(episode)
103 function openShowNotes(episode) {
104 showNotes.episode = episode
105 main.state = 'shownotes'
108 function openContextMenu(items) {
109 hrmtnContextMenu.items = items
110 hrmtnContextMenu.open()
113 function startProgress(text) {
114 progressIndicator.text = text
115 progressIndicator.opacity = 1
118 function endProgress() {
119 progressIndicator.opacity = 0
131 anchors.leftMargin: 100
139 script: episodeList.resetSelection()
151 anchors.leftMargin: -100
156 anchors.leftMargin: main.width
162 target: listContainer
168 anchors.leftMargin: 0
176 anchors.topMargin: titleBar.height
185 controller.podcastSelected(podcast)
186 main.currentPodcast = podcast
188 onPodcastContextMenu: controller.podcastContextMenu(podcast)
189 onSubscribe: contextMenu.showSubscribe()
191 Behavior on opacity { NumberAnimation { duration: Config.slowTransition } }
192 Behavior on anchors.leftMargin { NumberAnimation { duration: Config.slowTransition } }
202 onEpisodeContextMenu: controller.episodeContextMenu(episode)
204 Behavior on opacity { NumberAnimation { duration: Config.slowTransition } }
205 Behavior on anchors.leftMargin { NumberAnimation { duration: Config.slowTransition } }
208 Behavior on opacity { NumberAnimation { duration: Config.slowTransition } }
209 Behavior on scale { NumberAnimation { duration: Config.fadeTransition } }
218 bottom: parent.bottom
222 Behavior on opacity { NumberAnimation { duration: Config.slowTransition } }
223 Behavior on anchors.leftMargin { NumberAnimation { duration: Config.slowTransition } }
227 id: overlayInteractionBlockWall
229 anchors.topMargin: (nowPlayingThrobber.opened || messageDialog.opacity > 0 || inputDialog.opacity > 0 || progressIndicator.opacity > 0)?0:titleBar.height
230 z: (contextMenu.state != 'opened')?2:0
232 opacity: (nowPlayingThrobber.opened || contextMenu.state == 'opened' || messageDialog.opacity || inputDialog.opacity || progressIndicator.opacity)?1:0
233 Behavior on opacity { NumberAnimation { duration: Config.slowTransition } }
238 if (contextMenu.state == 'opened') {
240 } else if (progressIndicator.opacity) {
242 } else if (inputDialog.opacity) {
244 } else if (messageDialog.opacity) {
245 messageDialog.opacity = 0
247 nowPlayingThrobber.opened = false
260 source: 'artwork/mask.png'
267 z: (contextMenu.state == 'opened')?2:0
268 tab: 'artwork/back-tab.png'
269 icon: 'artwork/back.png'
271 anchors.bottom: parent.bottom
272 anchors.left: parent.left
273 onClicked: closeButton.clicked()
274 opened: !(!Config.hasCloseButton && closeButton.isRequired)
280 property bool shouldAppear: ((contextMenu.state != 'opened') && (mediaPlayer.episode !== undefined))
282 id: nowPlayingThrobber
284 anchors.bottom: parent.bottom
285 anchors.right: parent.right
286 opacity: shouldAppear
288 caption: (mediaPlayer.episode!=undefined)?mediaPlayer.episode.qtitle:''
291 onClicked: { opened = !opened }
296 visible: nowPlayingThrobber.opened
300 anchors.top: parent.bottom
301 anchors.left: parent.left
302 anchors.right: parent.right
303 anchors.topMargin: nowPlayingThrobber.opened?-(height+(parent.height-height)/2):0
305 Behavior on anchors.topMargin { PropertyAnimation { duration: Config.quickTransition; easing.type: Easing.OutCirc } }
310 property variant items: []
314 model: hrmtnContextMenu.items
317 text: modelData.caption
319 hrmtnContextMenu.close()
320 controller.contextMenuResponse(index)
335 bottom: parent.bottom
338 onClose: contextMenu.state = 'closed'
339 onResponse: controller.contextMenuResponse(index)
343 Behavior on opacity { NumberAnimation { duration: Config.fadeTransition } }
354 anchors.right: main.right
365 anchors.right: main.left
368 script: controller.contextMenuClosed()
373 transitions: Transition {
374 AnchorAnimation { duration: Config.slowTransition }
380 visible: podcastList.hasItems
381 height: visible?taskSwitcher.height*.8:0
382 anchors.left: parent.left
383 anchors.right: parent.right
384 anchors.top: parent.top
386 //anchors.topMargin: mediaPlayer.fullscreen?-height:0
387 //opacity: mediaPlayer.fullscreen?0:1
389 Behavior on opacity { PropertyAnimation { } }
390 Behavior on anchors.topMargin { PropertyAnimation { } }
398 // clicks should not fall through!
405 visible: contextMenu.state != 'opened' && Config.hasTaskSwitcher
406 anchors.left: parent.left
407 anchors.top: parent.top
408 width: Config.switcherWidth
409 height: Config.headerHeight
413 onClicked: controller.switcher()
418 verticalCenter: parent.verticalCenter
420 leftMargin: (parent.width * .8 - width) / 2
422 source: 'artwork/switch.png'
428 anchors.verticalCenter: parent.verticalCenter
429 anchors.left: taskSwitcher.visible?taskSwitcher.right:taskSwitcher.left
430 anchors.leftMargin: (contextMenu.state == 'opened')?(Config.largeSpacing):(Config.hasTaskSwitcher?0:Config.largeSpacing)
431 anchors.right: searchButton.visible?searchButton.left:searchButton.right
432 wrapMode: Text.NoWrap
434 text: (contextMenu.state == 'opened')?(contextMenu.subscribeMode?_('Add a new podcast'):_('Context menu')):((main.state == 'episodes' || main.state == 'shownotes')?(controller.episodeListTitle + ' (' + episodeList.count + ')'):"gPodder")
436 font.pixelSize: parent.height * .5
442 property: 'windowTitle'
443 value: titleBarText.text
448 anchors.right: closeButton.visible?closeButton.left:closeButton.right
450 source: 'artwork/subscriptions.png'
452 onClicked: contextMenu.showSubscribe()
454 visible: (contextMenu.state == 'closed' && main.state == 'podcasts')
460 anchors.right: parent.right
461 property bool isRequired: main.state != 'podcasts' || contextMenu.state != 'closed'
462 visible: extraCloseButton.opened && (Config.hasCloseButton || isRequired)
464 source: (main.state == 'podcasts' && contextMenu.state == 'closed')?'artwork/close.png':'artwork/back.png'
468 if (contextMenu.state == 'opened') {
469 contextMenu.state = 'closed'
470 } else if (main.state == 'podcasts') {
473 } else if (main.state == 'episodes') {
474 main.state = 'podcasts'
475 main.currentPodcast = undefined
476 } else if (main.state == 'shownotes') {
477 main.state = 'episodes'
483 function showMessage(message) {
484 messageDialogText.text = message
485 messageDialog.opacity = 1
494 Behavior on opacity { PropertyAnimation { } }
497 id: messageDialogText
498 anchors.centerIn: parent
505 function showInputDialog(message, value, accept, reject, textInput) {
506 inputDialogText.text = message
507 inputDialogField.text = value
508 inputDialogAccept.text = accept
509 inputDialogReject.text = reject
510 inputDialogField.visible = textInput
522 acceptButtonText: inputDialogAccept.text
523 rejectButtonText: inputDialogReject.text
525 message: inputDialogText.text
527 onAccepted: inputDialog.accept()
528 onRejected: inputDialog.close()
534 acceptButtonText: inputDialogAccept.text
535 rejectButtonText: inputDialogReject.text
542 onClicked: console.log('caught')
547 anchors.margins: Config.smallSpacing
548 spacing: Config.smallSpacing
557 anchors.margins: Config.smallSpacing
573 actionName: inputDialogAccept.text
578 onAccepted: inputDialog.accept()
579 onRejected: inputDialog.close()
590 controller.inputDialogResponse(true, inputDialogField.text,
591 inputDialogField.visible)
597 controller.inputDialogResponse(false, inputDialogField.text,
598 inputDialogField.visible)
602 id: inputDialogReject
603 width: parent.width / 2
604 onClicked: inputDialog.close()
608 id: inputDialogAccept
609 width: parent.width / 2
610 onClicked: inputDialog.accept()
615 id: progressIndicator
616 property string text: '...'
617 anchors.centerIn: parent
619 spacing: Config.largeSpacing * 2
622 Behavior on opacity { NumberAnimation { duration: Config.slowTransition } }
626 anchors.horizontalCenter: parent.horizontalCenter
630 anchors.horizontalCenter: parent.horizontalCenter
631 running: parent.opacity > 0