diff --git a/touch/Dialog.qml b/touch/Dialog.qml index e5208e6..a13eff3 100644 --- a/touch/Dialog.qml +++ b/touch/Dialog.qml @@ -26,9 +26,13 @@ Rectangle { id: page color: Constants.colors.dialogBackground + Component.onCompleted: pgst.dialogsVisible = pgst.dialogsVisible + 1; + Component.onDestruction: pgst.dialogsVisible = pgst.dialogsVisible - 1; + default property alias children: contents.children property bool isDialog: true property int contentHeight: -1 + property bool fullWidth: false function closePage() { stacking.startFadeOut(); @@ -49,7 +53,7 @@ Rectangle { Rectangle { id: contents property int border: parent.width * 0.1 - width: parent.width - 2 * border + width: parent.fullWidth ? parent.width : (parent.width - 2 * border) property int maxHeight: parent.height - 4 * border height: ((page.contentHeight > 0 && page.contentHeight < maxHeight) ? page.contentHeight : maxHeight) * parent.opacity anchors.centerIn: parent diff --git a/touch/Dragging.qml b/touch/Dragging.qml index 12df2b0..ed9f72d 100644 --- a/touch/Dragging.qml +++ b/touch/Dragging.qml @@ -24,16 +24,14 @@ MouseArea { id: dragging property Item stacking - property bool hasPull: false property bool canClose: true - signal pulled anchors.fill: parent drag { target: parent axis: Drag.XAxis - minimumX: dragging.hasPull ? (-parent.width/4) : 0 + minimumX: 0 maximumX: canClose ? parent.width : 0 filterChildren: true } @@ -46,10 +44,7 @@ MouseArea { if (pressed) { dragging.stacking.stopAllAnimations(); } else { - if (hasPull && parent.x < -parent.width / 4 + 10) { - pulled(); - parent.x = -parent.width / 4; - } else if (parent.x > parent.width / 3) { + if (parent.x > parent.width / 3) { dragging.stacking.startFadeOut(); } else { dragging.stacking.fadeInAgain(); diff --git a/touch/EpisodeQueryControl.qml b/touch/EpisodeQueryControl.qml index 63a2399..6392d7a 100644 --- a/touch/EpisodeQueryControl.qml +++ b/touch/EpisodeQueryControl.qml @@ -25,6 +25,7 @@ Item { property var model property string title + property string currentFilter: model.filters[model.currentFilterIndex].label function showSelectionDialog() { pgst.loadPage('SelectionDialog.qml', { diff --git a/touch/EpisodeQueryPage.qml b/touch/EpisodeQueryPage.qml index 1e97dba..34c5c1c 100644 --- a/touch/EpisodeQueryPage.qml +++ b/touch/EpisodeQueryPage.qml @@ -48,7 +48,7 @@ SlidePage { id: episodeList property int selectedIndex: -1 title: 'Episodes' - headerHasIcon: true + headerIcon: Icons.magnifying_glass headerIconText: 'Filter' onHeaderIconClicked: queryControl.showSelectionDialog(); diff --git a/touch/EpisodesPage.qml b/touch/EpisodesPage.qml index 32524d7..f4e0ddb 100644 --- a/touch/EpisodesPage.qml +++ b/touch/EpisodesPage.qml @@ -28,8 +28,6 @@ import 'icons/icons.js' as Icons SlidePage { id: episodesPage - hasPull: true - property int podcast_id property string title @@ -48,52 +46,40 @@ SlidePage { title: 'Select filter' } - PullMenu { - PullMenuItem { - text: 'Now Playing' - icon: Icons.play - color: Constants.colors.playback - onClicked: { - pgst.loadPage('PlayerPage.qml'); - episodesPage.unPull(); - } - } - - PullMenuItem { - text: 'Mark all as old' - icon: Icons.eye - color: Constants.colors.text - onClicked: { - py.call('main.mark_episodes_as_old', [episodesPage.podcast_id]); - episodesPage.unPull(); - } - } - - PullMenuItem { - text: 'Unsubscribe' - icon: Icons.trash - color: Constants.colors.destructive - onClicked: { - episodesPage.unPull(); - - var ctx = { py: py, id: episodesPage.podcast_id, page: episodesPage }; - pgst.showConfirmation('Unsubscribe', Icons.trash, function () { - ctx.py.call('main.unsubscribe', [ctx.id]); - ctx.page.closePage(); - }); - } - } - } - PListView { id: episodeList property int selectedIndex: -1 title: episodesPage.title model: GPodderEpisodeListModel { id: episodeListModel } - headerHasIcon: true - headerIconText: 'Filter' - onHeaderIconClicked: queryControl.showSelectionDialog(); + headerIcon: Icons.cog + headerIconText: 'Settings' + onHeaderIconClicked: { + pgst.showSelection([ + { + label: 'Filter list (' + queryControl.currentFilter + ')', + callback: function () { + queryControl.showSelectionDialog(); + } + }, + { + label: 'Mark episodes as old', + callback: function () { + py.call('main.mark_episodes_as_old', [episodesPage.podcast_id]); + }, + }, + { + label: 'Unsubscribe', + callback: function () { + var ctx = { py: py, id: episodesPage.podcast_id, page: episodesPage }; + pgst.showConfirmation('Unsubscribe', Icons.trash, function () { + ctx.py.call('main.unsubscribe', [ctx.id]); + ctx.page.closePage(); + }); + }, + }, + ]); + } PPlaceholder { text: 'No episodes' diff --git a/touch/Main.qml b/touch/Main.qml index 7135804..748dece 100644 --- a/touch/Main.qml +++ b/touch/Main.qml @@ -21,6 +21,9 @@ import QtQuick 2.0 import 'common' +import 'common/constants.js' as Constants +import 'icons/icons.js' as Icons + Item { id: pgst @@ -30,6 +33,7 @@ Item { GPodderPodcastListModel { id: podcastListModel } property real scalef: width / 480 + property int dialogsVisible: 0 anchors.fill: parent @@ -60,6 +64,23 @@ Item { }); } + function showSelection(items, title, selectedIndex) { + loadPage('SelectionDialog.qml', { + title: title, + callback: function (index, item) { + items[index].callback(); + }, + items: function() { + var result = []; + for (var i in items) { + result.push(items[i].label); + } + return result; + }(), + selectedIndex: selectedIndex, + }); + } + function loadPage(filename, properties) { if (pgst.loadPageInProgress) { console.log('ignoring loadPage request while load in progress'); @@ -85,6 +106,30 @@ Item { visible: !py.ready } + IconMenuItem { + id: throbber + + z: 100 + + anchors { + right: parent.right + bottom: parent.bottom + bottomMargin: 30 * pgst.scalef + } + + text: 'Now Playing' + color: Constants.colors.playback + icon: Icons.play + + transparent: false + enabled: opacity + + opacity: player.episode != 0 && !pgst.dialogsVisible + Behavior on opacity { PropertyAnimation { duration: 200 } } + + onClicked: loadPage('PlayerPage.qml'); + } + StartPage { id: startPage visible: py.ready diff --git a/touch/PListView.qml b/touch/PListView.qml index 0947f19..06c84ed 100644 --- a/touch/PListView.qml +++ b/touch/PListView.qml @@ -27,7 +27,7 @@ ListView { property string title property real pushPhase: 0 - property bool headerHasIcon: false + property string headerIcon property string headerIconText signal headerIconClicked() @@ -35,8 +35,9 @@ ListView { boundsBehavior: Flickable.StopAtBounds header: SlidePageHeader { + id: header title: pListView.title - hasIcon: pListView.headerHasIcon + icon: pListView.headerIcon iconText: pListView.headerIconText onIconClicked: pListView.headerIconClicked() } diff --git a/touch/PlayerPage.qml b/touch/PlayerPage.qml index 852c269..a1870fe 100644 --- a/touch/PlayerPage.qml +++ b/touch/PlayerPage.qml @@ -24,9 +24,12 @@ import 'common/util.js' as Util import 'common/constants.js' as Constants import 'icons/icons.js' as Icons -SlidePage { +Dialog { id: playerPage + contentHeight: flickable.contentHeight + fullWidth: true + Flickable { id: flickable anchors.fill: parent @@ -38,7 +41,7 @@ SlidePage { Column { id: column - width: playerPage.width + width: flickable.width spacing: 10 * pgst.scalef SlidePageHeader { @@ -79,7 +82,7 @@ SlidePage { PSlider { id: slider - width: playerPage.width + width: flickable.width value: player.position min: 0 max: player.duration diff --git a/touch/PodcastsPage.qml b/touch/PodcastsPage.qml index edcc9c1..b085d3a 100644 --- a/touch/PodcastsPage.qml +++ b/touch/PodcastsPage.qml @@ -27,38 +27,6 @@ import 'common/constants.js' as Constants SlidePage { id: podcastsPage - hasPull: true - - PullMenu { - PullMenuItem { - text: 'Now Playing' - color: Constants.colors.playback - icon: Icons.play - onClicked: { - pgst.loadPage('PlayerPage.qml'); - podcastsPage.unPull(); - } - } - - PullMenuItem { - text: 'Refresh feeds' - icon: Icons.loop_alt2 - onClicked: { - podcastsPage.unPull(); - py.call('main.check_for_episodes'); - } - } - - PullMenuItem { - text: 'Subscribe' - icon: Icons.plus - color: Constants.colors.download - onClicked: { - pgst.loadPage('Subscribe.qml'); - podcastsPage.unPull(); - } - } - } PListView { id: podcastList @@ -67,6 +35,25 @@ SlidePage { section.property: 'section' section.delegate: SectionHeader { text: section } + headerIcon: Icons.cog + headerIconText: 'Settings' + onHeaderIconClicked: { + pgst.showSelection([ + { + label: 'Check for new episodes', + callback: function () { + py.call('main.check_for_episodes'); + } + }, + { + label: 'Add new podcast', + callback: function () { + pgst.loadPage('Subscribe.qml'); + }, + }, + ]); + } + PPlaceholder { text: 'No podcasts' visible: podcastList.count === 0 diff --git a/touch/PullMenu.qml b/touch/PullMenu.qml deleted file mode 100644 index e130c6b..0000000 --- a/touch/PullMenu.qml +++ /dev/null @@ -1,38 +0,0 @@ - -/** - * - * gPodder QML UI Reference Implementation - * Copyright (c) 2013, Thomas Perl - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - * - */ - -import QtQuick 2.0 - -import 'common/constants.js' as Constants - -MouseArea { - id: pullMenu - default property alias items: pullMenuColumn.children - - width: parent.width / 4 - height: parent.height - anchors.top: parent.top - anchors.left: parent.right - - Column { - id: pullMenuColumn - anchors.fill: parent - } -} diff --git a/touch/PullMenuItem.qml b/touch/PullMenuItem.qml deleted file mode 100644 index 5b3238b..0000000 --- a/touch/PullMenuItem.qml +++ /dev/null @@ -1,33 +0,0 @@ - -/** - * - * gPodder QML UI Reference Implementation - * Copyright (c) 2013, Thomas Perl - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - * - */ - -import QtQuick 2.0 - -import 'common/constants.js' as Constants - -IconMenuItem { - id: pullMenuItem - size: 80 - - width: parent.width - height: width - - anchors.horizontalCenter: parent.horizontalCenter -} diff --git a/touch/SelectionDialog.qml b/touch/SelectionDialog.qml index 3f66119..e4e1a37 100644 --- a/touch/SelectionDialog.qml +++ b/touch/SelectionDialog.qml @@ -26,7 +26,7 @@ import 'icons/icons.js' as Icons Dialog { id: selectionDialog - property string title: 'Dialog' + property string title: '' property var callback: undefined property var items: ([]) property var selectedIndex: -1 @@ -45,6 +45,7 @@ Dialog { SlidePageHeader { id: header + visible: title != '' color: Constants.colors.highlight title: selectionDialog.title } diff --git a/touch/SlidePage.qml b/touch/SlidePage.qml index c16dc5f..186c654 100644 --- a/touch/SlidePage.qml +++ b/touch/SlidePage.qml @@ -27,15 +27,9 @@ Rectangle { color: Constants.colors.page default property alias children: dragging.children - property alias hasPull: dragging.hasPull property alias canClose: dragging.canClose - property real pullPhase: (x >= 0) ? 0 : (-x / (width / 4)) property bool isDialog: false - function unPull() { - stacking.fadeInAgain(); - } - function closePage() { stacking.startFadeOut(); } @@ -52,19 +46,6 @@ Rectangle { stacking: stacking } - Rectangle { - color: Constants.colors.page - anchors.fill: parent - - opacity: page.pullPhase * 0.9 - - MouseArea { - enabled: parent.opacity > 0 - anchors.fill: parent - onClicked: page.unPull(); - } - } - Image { anchors { right: parent.left diff --git a/touch/SlidePageHeader.qml b/touch/SlidePageHeader.qml index a3d6c92..e1d51b2 100644 --- a/touch/SlidePageHeader.qml +++ b/touch/SlidePageHeader.qml @@ -28,8 +28,8 @@ Item { property alias title: label.text property alias color: label.color - property alias hasIcon: icon.visible property alias iconText: icon.text + property alias icon: icon.icon signal iconClicked() width: parent.width @@ -38,11 +38,11 @@ Item { IconMenuItem { id: icon - visible: false + visible: icon != '' && icon != undefined enabled: visible text: 'Search' - icon: Icons.magnifying_glass + icon: '' color: label.color anchors { @@ -56,7 +56,7 @@ Item { PLabel { id: label anchors { - left: icon.right + left: icon.visible ? icon.right : parent.left right: parent.right rightMargin: 20 * pgst.scalef leftMargin: 20 * pgst.scalef diff --git a/touch/StartPage.qml b/touch/StartPage.qml index 5b22f0f..2902627 100644 --- a/touch/StartPage.qml +++ b/touch/StartPage.qml @@ -27,19 +27,6 @@ import 'common/util.js' as Util SlidePage { id: startPage canClose: false - hasPull: true - - PullMenu { - PullMenuItem { - text: 'Now Playing' - color: Constants.colors.playback - icon: Icons.play - onClicked: { - pgst.loadPage('PlayerPage.qml'); - startPage.unPull(); - } - } - } function update_stats() { py.call('main.get_stats', [], function (result) { diff --git a/touch/Subscribe.qml b/touch/Subscribe.qml index 30c1339..1c99829 100644 --- a/touch/Subscribe.qml +++ b/touch/Subscribe.qml @@ -22,15 +22,14 @@ import QtQuick 2.0 import 'common/constants.js' as Constants -SlidePage { +Dialog { id: subscribe - SlidePageHeader { - title: 'Add subscription' - color: Constants.colors.download - } + contentHeight: contentColumn.height Column { + id: contentColumn + anchors.centerIn: parent spacing: 30 * pgst.scalef diff --git a/touch/icons/icons.js b/touch/icons/icons.js index 8548881..ed6b658 100644 --- a/touch/icons/icons.js +++ b/touch/icons/icons.js @@ -17,3 +17,4 @@ var eye = '\ue025'; var loop_alt2 = '\ue033'; var folder = '\ue065'; var magnifying_glass = '\ue074'; +var cog = '\u2699';