Replace pull menu with header icon; more dialogs

This commit is contained in:
Thomas Perl 2014-03-15 20:06:48 +01:00
parent 96cbdd4b64
commit debc6519be
17 changed files with 121 additions and 201 deletions

View file

@ -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

View file

@ -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();

View file

@ -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', {

View file

@ -48,7 +48,7 @@ SlidePage {
id: episodeList
property int selectedIndex: -1
title: 'Episodes'
headerHasIcon: true
headerIcon: Icons.magnifying_glass
headerIconText: 'Filter'
onHeaderIconClicked: queryControl.showSelectionDialog();

View file

@ -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'

View file

@ -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

View file

@ -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()
}

View file

@ -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

View file

@ -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

View file

@ -1,38 +0,0 @@
/**
*
* gPodder QML UI Reference Implementation
* Copyright (c) 2013, Thomas Perl <m@thp.io>
*
* 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
}
}

View file

@ -1,33 +0,0 @@
/**
*
* gPodder QML UI Reference Implementation
* Copyright (c) 2013, Thomas Perl <m@thp.io>
*
* 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
}

View file

@ -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
}

View file

@ -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

View file

@ -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

View file

@ -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) {

View file

@ -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

View file

@ -17,3 +17,4 @@ var eye = '\ue025';
var loop_alt2 = '\ue033';
var folder = '\ue065';
var magnifying_glass = '\ue074';
var cog = '\u2699';