Import QML content from reference UI for Silica port

This commit is contained in:
Thomas Perl 2014-01-04 12:56:56 +01:00
parent 0a218fc3f5
commit 108d2aabd5
30 changed files with 1855 additions and 2 deletions

37
qml/ButtonArea.qml Normal file
View file

@ -0,0 +1,37 @@
/**
*
* 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
Rectangle {
id: buttonArea
signal clicked
property bool transparent: false
color: mouseArea.pressed?'#33ffffff':(transparent?'#00000000':'#88000000')
MouseArea {
id: mouseArea
anchors.fill: parent
onClicked: buttonArea.clicked();
}
}

45
qml/ButtonRow.qml Normal file
View file

@ -0,0 +1,45 @@
/**
*
* 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
Row {
id: buttonRow
property var model
height: 100 * pgst.scalef
Repeater {
id: repeater
model: buttonRow.model
delegate: ButtonArea {
height: buttonRow.height
width: buttonRow.width / repeater.count
onClicked: buttonRow.model[index].clicked()
PLabel {
anchors.centerIn: parent
text: modelData.label
}
}
}
}

57
qml/Dragging.qml Normal file
View file

@ -0,0 +1,57 @@
/**
*
* 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
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
maximumX: canClose ? parent.width : 0
filterChildren: true
}
onPressedChanged: {
if (pressed) {
dragging.stacking.stopAllAnimations();
} else {
if (hasPull && parent.x < -parent.width / 4 + 10) {
pulled();
parent.x = -parent.width / 4;
//dragging.stacking.fadeInAgain();
} else if (parent.x > parent.width / 3) {
dragging.stacking.startFadeOut();
} else {
dragging.stacking.fadeInAgain();
}
}
}
}

76
qml/EpisodeDetail.qml Normal file
View file

@ -0,0 +1,76 @@
/**
*
* 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 'constants.js' as Constants
SlidePage {
id: detailPage
property int episode_id
property string title
Component.onCompleted: {
label.text = 'Loading...';
py.call('main.show_episode', [episode_id], function (episode) {
label.text = episode.description;
});
}
Flickable {
id: flickable
anchors.fill: parent
contentWidth: detailColumn.width
contentHeight: detailColumn.height + detailColumn.spacing
Column {
id: detailColumn
width: detailPage.width
spacing: 10 * pgst.scalef
SlidePageHeader {
title: detailPage.title
}
ButtonArea {
width: detailPage.width
height: 100 * pgst.scalef
onClicked: player.playbackEpisode(detailPage.episode_id)
PLabel {
anchors.centerIn: parent
text: 'Play'
}
}
PLabel {
id: label
width: parent.width * .8
font.pixelSize: 30 * pgst.scalef
anchors.horizontalCenter: parent.horizontalCenter
wrapMode: Text.WordWrap
}
}
}
}

77
qml/EpisodeItem.qml Normal file
View file

@ -0,0 +1,77 @@
/**
*
* 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 'constants.js' as Constants
ButtonArea {
id: podcastItem
Rectangle {
anchors {
top: parent.top
bottom: parent.bottom
left: parent.left
}
width: parent.width * progress
color: Constants.colors.download
opacity: .4
}
transparent: true
height: 80 * pgst.scalef
anchors {
left: parent.left
right: parent.right
}
PLabel {
anchors {
left: parent.left
right: downloadStatusIcon.left
verticalCenter: parent.verticalCenter
margins: 30 * pgst.scalef
}
elide: Text.ElideRight
text: title
}
Image {
id: downloadStatusIcon
anchors {
right: parent.right
verticalCenter: parent.verticalCenter
margins: 30 * pgst.scalef
}
source: {
switch (downloadState) {
case Constants.state.normal: return '';
case Constants.state.downloaded: return 'images/play.png';
case Constants.state.deleted: return 'images/delete.png';
}
}
}
}

71
qml/EpisodesPage.qml Normal file
View file

@ -0,0 +1,71 @@
/**
*
* 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 io.thp.pyotherside 1.0
import 'util.js' as Util
SlidePage {
id: episodesPage
hasPull: true
property int podcast_id
property string title
width: parent.width
height: parent.height
Component.onCompleted: {
py.call('main.load_episodes', [podcast_id], function (episodes) {
Util.updateModelFrom(episodeListModel, episodes);
});
}
PullMenu {
PullMenuItem {
source: 'images/play.png'
onClicked: {
pgst.loadPage('PlayerPage.qml');
episodesPage.unPull();
}
}
PullMenuItem {
source: 'images/delete.png'
onClicked: {
py.call('main.unsubscribe', [episodesPage.podcast_id]);
episodesPage.closePage();
}
}
}
PListView {
id: episodeList
title: episodesPage.title
model: ListModel { id: episodeListModel }
delegate: EpisodeItem {
onClicked: pgst.loadPage('EpisodeDetail.qml', {episode_id: id, title: title});
}
}
}

71
qml/FreshEpisodes.qml Normal file
View file

@ -0,0 +1,71 @@
/**
*
* 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 'util.js' as Util
SlidePage {
id: freshEpisodes
property bool ready: false
Component.onCompleted: {
py.call('main.get_fresh_episodes', [], function (episodes) {
Util.updateModelFrom(freshEpisodesListModel, episodes);
freshEpisodes.ready = true;
});
}
PBusyIndicator {
visible: !freshEpisodes.ready
anchors.centerIn: parent
}
PListView {
id: freshEpisodesList
title: 'Fresh episodes'
model: ListModel { id: freshEpisodesListModel }
section.property: 'published'
section.delegate: SectionHeader { text: section }
delegate: EpisodeItem {
onClicked: py.call('main.download_episode', [id]);
Connections {
target: pgst
onDownloadProgress: {
if (episode_id == id) {
freshEpisodesListModel.setProperty(index, 'progress', progress);
}
}
onDownloaded: {
if (id == episode_id) {
freshEpisodesListModel.remove(index);
}
}
}
//pgst.loadPage('EpisodeDetail.qml', {episode_id: id, title: title});
}
}
}

107
qml/Main.qml Normal file
View file

@ -0,0 +1,107 @@
/**
*
* 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 io.thp.pyotherside 1.0
Item {
id: pgst
property bool ready: false
property real scalef: width / 480
anchors.fill: parent
function update(page, x) {
var index = -1;
for (var i=0; i<children.length; i++) {
if (children[i] === page) {
index = i;
break;
}
}
children[index-1].opacity = x / width;
}
signal downloading(int episode_id)
signal downloadProgress(int episode_id, real progress)
signal downloaded(int episode_id)
function loadPage(filename, properties) {
var component = Qt.createComponent(filename);
if (component.status != Component.Ready) {
console.log('Error loading ' + filename + ':' +
component.errorString());
}
if (properties === undefined) {
component.createObject(pgst);
} else {
component.createObject(pgst, properties);
}
}
Python {
id: py
Component.onCompleted: {
addImportPath('.');
setHandler('hello', function (version, copyright) {
console.log('gPodder version ' + version + ' starting up');
console.log('Copyright: ' + copyright);
});
setHandler('downloading', pgst.downloading);
setHandler('download-progress', pgst.downloadProgress);
setHandler('downloaded', pgst.downloaded);
var path = Qt.resolvedUrl('..').substr('file://'.length);
addImportPath(path);
// Load the Python side of things
importModule('main', function() {
pgst.ready = true;
});
}
onReceived: {
console.log('unhandled message: ' + data);
}
onError: {
console.log('Python failure: ' + traceback);
}
}
Player {
id: player
}
PBusyIndicator {
anchors.centerIn: parent
visible: !pgst.ready
}
StartPage {
id: startPage
visible: pgst.ready
}
}

53
qml/PBusyIndicator.qml Normal file
View file

@ -0,0 +1,53 @@
/**
*
* 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
Item {
height: 64 * pgst.scalef
width: 64 * pgst.scalef
Image {
anchors {
horizontalCenter: parent.horizontalCenter
bottom: parent.bottom
bottomMargin: 30*Math.abs(Math.sin(phase)) * pgst.scalef
}
transform: Scale {
origin.x: 32 * pgst.scalef
origin.y: 32 * pgst.scalef
xScale: 1.0 - 0.3 * (1.0 - Math.abs(Math.sin(phase)))
}
source: 'images/gpodder.png'
}
property real phase: 0
PropertyAnimation on phase {
loops: Animation.Infinite
duration: 2000
running: parent.visible
from: 0
to: 2*Math.PI
}
}

27
qml/PLabel.qml Normal file
View file

@ -0,0 +1,27 @@
/**
*
* 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
Text {
font.pixelSize: 30 * pgst.scalef
color: 'white'
}

34
qml/PListView.qml Normal file
View file

@ -0,0 +1,34 @@
/**
*
* 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 'constants.js' as Constants
ListView {
id: pListView
anchors.fill: parent
property string title
header: SlidePageHeader { title: pListView.title }
}

53
qml/PSlider.qml Normal file
View file

@ -0,0 +1,53 @@
/**
*
* 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
Rectangle {
id: slider
property real value
property real min: 0.0
property real max: 1.0
signal valueChangeRequested(real newValue)
color: '#aa000000'
height: 50 * pgst.scalef
MouseArea {
anchors.fill: parent
onClicked: slider.valueChangeRequested(min + (max - min) * (mouse.x / width))
}
Rectangle {
height: parent.height * 0.9
width: height
color: '#aaffffff'
anchors {
verticalCenter: parent.verticalCenter
left: parent.left
leftMargin: parent.width * (parent.value - parent.min) / (parent.max - parent.min)
}
}
}

51
qml/PTextField.qml Normal file
View file

@ -0,0 +1,51 @@
/**
*
* 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
Rectangle {
id: textField
property alias text: textInput.text
property string placeholderText: ''
radius: 10 * pgst.scalef
height: 50 * pgst.scalef
color: 'white'
TextInput {
anchors {
fill: parent
margins: 5 * pgst.scalef
}
color: 'black'
id: textInput
font.pixelSize: height
}
Text {
anchors.fill: textInput
visible: !textInput.focus && (textInput.text == '')
text: textField.placeholderText
color: '#aaa'
font.pixelSize: textInput.font.pixelSize
}
}

37
qml/Player.qml Normal file
View file

@ -0,0 +1,37 @@
/**
*
* 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 QtMultimedia 5.0
MediaPlayer {
id: player
property int episode
property var queue: ([])
function playbackEpisode(episode_id) {
player.episode = episode_id;
py.call('main.play_episode', [episode_id], function (episode) {
player.source = episode.source;
player.play();
});
}
}

83
qml/PlayerPage.qml Normal file
View file

@ -0,0 +1,83 @@
/**
*
* 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 'constants.js' as Constants
SlidePage {
id: playerPage
property string episodeTitle
Component.onCompleted: {
py.call('main.show_episode', [player.episode], function (episode) {
playerPage.episodeTitle = episode.title;
});
}
Flickable {
id: flickable
anchors.fill: parent
contentWidth: column.width
contentHeight: column.height + column.spacing
Column {
id: column
width: playerPage.width
spacing: 10 * pgst.scalef
SlidePageHeader {
title: 'Now playing'
}
ButtonRow {
width: playerPage.width
model: [
{ label: 'Play', clicked: function() {
player.play();
}},
{ label: 'Pause', clicked: function() {
player.pause();
}},
{ label: 'Details', clicked: function() {
pgst.loadPage('EpisodeDetail.qml', {
episode_id: player.episode,
title: playerPage.episodeTitle
});
}}
]
}
PSlider {
width: playerPage.width
value: player.playbackRate
min: 0.5
max: 3.0
onValueChangeRequested: {
player.playbackRate = newValue
value = player.playbackRate
}
}
}
}
}

71
qml/PodcastItem.qml Normal file
View file

@ -0,0 +1,71 @@
/**
*
* 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
ButtonArea {
id: podcastItem
transparent: true
height: 100 * pgst.scalef
anchors {
left: parent.left
right: parent.right
}
Image {
id: cover
visible: !updating
anchors {
left: parent.left
leftMargin: 10 * pgst.scalef
verticalCenter: parent.verticalCenter
}
sourceSize.width: width
sourceSize.height: height
width: 80 * pgst.scalef
height: 80 * pgst.scalef
source: coverart
}
PBusyIndicator {
anchors.centerIn: cover
visible: updating
}
PLabel {
anchors {
left: cover.right
leftMargin: 10 * pgst.scalef
rightMargin: 10 * pgst.scalef
right: parent.right
verticalCenter: parent.verticalCenter
}
elide: Text.ElideRight
text: title
}
}

114
qml/PodcastsPage.qml Normal file
View file

@ -0,0 +1,114 @@
/**
*
* 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 'util.js' as Util
SlidePage {
id: podcastsPage
hasPull: true
function reload() {
loading.visible = true;
py.call('main.load_podcasts', [], function (podcasts) {
Util.updateModelFrom(podcastListModel, podcasts);
loading.visible = false;
});
}
Component.onCompleted: {
reload();
py.setHandler('podcast-list-changed', podcastsPage.reload);
py.setHandler('updating-podcast', function (podcast_id) {
for (var i=0; i<podcastListModel.count; i++) {
var podcast = podcastListModel.get(i);
if (podcast.id == podcast_id) {
podcastListModel.setProperty(i, 'updating', true);
break;
}
}
});
py.setHandler('updated-podcast', function (podcast) {
for (var i=0; i<podcastListModel.count; i++) {
if (podcastListModel.get(i).id == podcast.id) {
podcastListModel.set(i, podcast);
break;
}
}
});
}
Component.onDestruction: {
py.setHandler('podcast-list-changed', undefined);
py.setHandler('updating-podcast', undefined);
py.setHandler('updated-podcast', undefined);
}
PullMenu {
PullMenuItem {
source: 'images/play.png'
onClicked: {
pgst.loadPage('PlayerPage.qml');
podcastsPage.unPull();
}
}
PullMenuItem {
source: 'images/search.png'
onClicked: {
podcastsPage.unPull();
py.call('main.check_for_episodes');
}
}
PullMenuItem {
source: 'images/subscriptions.png'
onClicked: {
pgst.loadPage('Subscribe.qml');
podcastsPage.unPull();
}
}
}
PLabel {
id: loading
anchors.centerIn: parent
text: 'Loading'
}
PListView {
id: podcastList
title: 'Subscriptions'
section.property: 'section'
section.delegate: SectionHeader { text: section }
model: ListModel { id: podcastListModel }
delegate: PodcastItem {
onClicked: pgst.loadPage('EpisodesPage.qml', {'podcast_id': id, 'title': title});
}
}
}

35
qml/PullMenu.qml Normal file
View file

@ -0,0 +1,35 @@
/**
*
* 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
Column {
id: pullMenu
width: parent.width / 4
height: parent.height
anchors.top: parent.top
anchors.left: parent.right
Item { width: 1; height: 1 }
spacing: (width - 72 * pgst.scalef) / 2
}

38
qml/PullMenuItem.qml Normal file
View file

@ -0,0 +1,38 @@
/**
*
* 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
Image {
id: pullMenuItem
signal clicked
width: 72 * pgst.scalef
height: 72 * pgst.scalef
anchors.horizontalCenter: parent.horizontalCenter
MouseArea {
anchors.fill: parent
onClicked: pullMenuItem.clicked();
}
}

39
qml/SectionHeader.qml Normal file
View file

@ -0,0 +1,39 @@
/**
*
* 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
Item {
property alias text: pLabel.text
height: 70 * pgst.scalef
PLabel {
id: pLabel
anchors {
left: parent.left
bottom: parent.bottom
margins: 10 * pgst.scalef
}
color: '#aaa'
}
}

33
qml/Settings.qml Normal file
View file

@ -0,0 +1,33 @@
/**
*
* 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
SlidePage {
SlidePageHeader { title: 'Settings' }
Text {
anchors.centerIn: parent
color: 'white'
font.pixelSize: 50 * pgst.scalef
text: 'TODO'
}
}

92
qml/SlidePage.qml Normal file
View file

@ -0,0 +1,92 @@
/**
*
* 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 'constants.js' as Constants
Rectangle {
id: page
color: '#88000000'
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))
function unPull() {
stacking.fadeInAgain();
}
function closePage() {
stacking.startFadeOut();
}
onXChanged: pgst.update(page, x)
width: parent.width
height: parent.height
Stacking { id: stacking }
Dragging {
id: dragging
stacking: stacking
onPulled: console.log('have pulled it!')
}
Rectangle {
color: 'black'
anchors.fill: parent
opacity: page.pullPhase * 0.8
MouseArea {
enabled: parent.opacity > 0
anchors.fill: parent
onClicked: page.unPull();
}
}
Image {
anchors {
right: parent.left
top: parent.top
bottom: parent.bottom
}
width: 10 * pgst.scalef
source: 'images/pageshadow.png'
opacity: .2
}
Image {
anchors {
left: parent.right
top: parent.top
bottom: parent.bottom
}
mirror: true
width: 10 * pgst.scalef
source: 'images/pageshadow.png'
opacity: .2
}
}

60
qml/SlidePageHeader.qml Normal file
View file

@ -0,0 +1,60 @@
/**
*
* 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 'constants.js' as Constants
Item {
id: slidePageHeader
property string title
width: parent.width
height: Constants.layout.header.height * pgst.scalef
Rectangle {
anchors {
left: parent.left
right: parent.right
top: parent.top
topMargin: slidePageHeader.height * 0.15
}
height: slidePageHeader.height * 0.7
color: '#33000000'
}
Text {
anchors {
left: parent.left
right: parent.right
rightMargin: 20 * pgst.scalef
leftMargin: 70 * pgst.scalef
verticalCenter: parent.verticalCenter
}
color: 'white'
horizontalAlignment: Text.AlignRight
font.pixelSize: parent.height * .4 * pgst.scalef
elide: Text.ElideRight
text: parent.title
}
}

63
qml/Stacking.qml Normal file
View file

@ -0,0 +1,63 @@
/**
*
* 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
Item {
id: stacking
property variant page: parent
PropertyAnimation {
id: fadeIn
target: stacking.page
property: 'x'
to: 0
duration: 500
easing.type: Easing.OutCubic
}
PropertyAnimation {
id: fadeOut
target: stacking.page
property: 'x'
to: stacking.page.width
duration: 500
easing.type: Easing.OutCubic
}
function startFadeOut() {
fadeOut.start();
page.destroy(500);
}
function fadeInAgain() {
fadeIn.start();
}
function stopAllAnimations() {
fadeIn.stop();
}
Component.onCompleted: {
page.x = page.width;
fadeIn.start();
}
}

251
qml/StartPage.qml Normal file
View file

@ -0,0 +1,251 @@
/**
*
* 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
SlidePage {
id: startPage
canClose: false
function update_stats() {
py.call('main.get_stats', [], function (result) {
stats.text = result;
});
py.call('main.get_fresh_episodes_summary', [3], function (episodes) {
freshEpisodesRepeater.model = episodes;
});
}
Component.onCompleted: {
py.setHandler('update-stats', startPage.update_stats);
}
Component.onDestruction: {
py.setHandler('update-stats', undefined);
}
Flickable {
Connections {
target: pgst
onReadyChanged: {
if (pgst.ready) {
startPage.update_stats();
}
}
}
anchors.fill: parent
contentWidth: startPageColumn.width
contentHeight: startPageColumn.height + startPageColumn.spacing
Column {
id: startPageColumn
width: startPage.width
spacing: 20 * pgst.scalef
SlidePageHeader {
title: 'gPodder'
}
StartPageButton {
id: subscriptionsPane
title: 'Subscriptions'
onClicked: pgst.loadPage('PodcastsPage.qml');
PLabel {
id: stats
anchors {
verticalCenter: parent.verticalCenter
left: parent.left
margins: 20 * pgst.scalef
}
}
ButtonArea {
anchors {
bottom: parent.bottom
right: parent.right
}
transparent: true
onClicked: pgst.loadPage('Subscribe.qml');
width: subscriptions.width + 2*subscriptions.anchors.margins
height: subscriptions.height + 2*subscriptions.anchors.margins
Image {
id: subscriptions
source: 'images/subscriptions.png'
anchors {
bottom: parent.bottom
right: parent.right
margins: 20 * pgst.scalef
}
}
}
}
StartPageButton {
id: freshEpisodesPage
title: 'Fresh episodes'
onClicked: pgst.loadPage('FreshEpisodes.qml');
Component.onCompleted: {
py.setHandler('refreshing', function (is_refreshing) {
refresherButtonArea.visible = !is_refreshing;
if (!is_refreshing) {
freshEpisodesPage.title = 'Fresh episodes';
}
});
py.setHandler('refresh-progress', function (pos, total) {
freshEpisodesPage.title = 'Refreshing feeds (' + pos + '/' + total + ')';
});
}
Row {
anchors.bottom: parent.bottom
anchors.bottomMargin: 50 * pgst.scalef
anchors.leftMargin: 20 * pgst.scalef
anchors.left: parent.left
spacing: 10 * pgst.scalef
Repeater {
id: freshEpisodesRepeater
Image {
source: modelData.coverart
sourceSize { width: 80 * pgst.scalef; height: 80 * pgst.scalef }
width: 80 * pgst.scalef
height: 80 * pgst.scalef
PLabel {
anchors {
horizontalCenter: parent.horizontalCenter
top: parent.bottom
margins: 5 * pgst.scalef
}
text: modelData.newEpisodes
}
}
}
}
ButtonArea {
id: refresherButtonArea
anchors {
bottom: parent.bottom
right: parent.right
}
transparent: true
onClicked: py.call('main.check_for_episodes');
width: refresher.width + 2*refresher.anchors.margins
height: refresher.height + 2*refresher.anchors.margins
Image {
id: refresher
source: 'images/search.png'
anchors {
bottom: parent.bottom
right: parent.right
margins: 20 * pgst.scalef
}
}
}
}
ButtonArea {
onClicked: pgst.loadPage('PlayerPage.qml');
anchors {
left: recommendationsPane.left
right: recommendationsPane.right
}
height: 100 * pgst.scalef
PLabel {
anchors.centerIn: parent
text: 'Now playing'
}
}
ButtonArea {
onClicked: pgst.loadPage('Settings.qml');
anchors {
left: recommendationsPane.left
right: recommendationsPane.right
}
height: 100 * pgst.scalef
PLabel {
anchors.centerIn: parent
text: 'Settings'
}
}
StartPageButton {
id: recommendationsPane
title: 'Recommendations'
onClicked: pgst.loadPage('Settings.qml');
Row {
anchors {
horizontalCenter: parent.horizontalCenter
bottom: parent.bottom
margins: 40 * pgst.scalef
}
spacing: 20 * pgst.scalef
Connections {
target: pgst
onReadyChanged: {
if (pgst.ready) {
py.call('main.load_podcasts', [], function (podcasts) {
recommendationsRepeater.model = podcasts.splice(0, 4);
});
}
}
}
Repeater {
id: recommendationsRepeater
Image { source: modelData.coverart; sourceSize { width: 80 * pgst.scalef; height: 80 * pgst.scalef } }
}
}
}
}
}
}

42
qml/StartPageButton.qml Normal file
View file

@ -0,0 +1,42 @@
/**
*
* 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
ButtonArea {
id: startPageButton
property string title
anchors.horizontalCenter: parent.horizontalCenter
width: parent.width * .9
height: 200 * pgst.scalef
PLabel {
anchors {
right: parent.right
top: parent.top
margins: 20 * pgst.scalef
}
text: startPageButton.title
}
}

64
qml/Subscribe.qml Normal file
View file

@ -0,0 +1,64 @@
/**
*
* 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
SlidePage {
id: subscribe
SlidePageHeader { title: 'Add subscription' }
Column {
anchors.centerIn: parent
spacing: 30 * pgst.scalef
PTextField {
id: input
width: subscribe.width *.8
placeholderText: 'Feed URL'
}
ButtonArea {
id: button
width: input.width
height: input.height
PLabel {
anchors.centerIn: parent
text: 'Subscribe'
}
onClicked: {
loading.visible = true;
button.visible = false;
input.visible = false;
py.call('main.subscribe', [input.text], function () {
subscribe.closePage();
});
}
}
PBusyIndicator {
id: loading
visible: false
anchors.horizontalCenter: parent.horizontalCenter
}
}
}

39
qml/constants.js Normal file
View file

@ -0,0 +1,39 @@
/**
*
* 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.
*
*/
var layout = {
header: {
height: 100, /* page header height */
},
};
var colors = {
download: '#8ae234', /* download green */
select: '#7f5785', /* gpodder dark purple */
fresh: '#cf65de', /* gpodder purple */
playback: '#729fcf', /* playback blue */
};
var state = {
normal: 0,
downloaded: 1,
deleted: 2,
};

33
qml/util.js Normal file
View file

@ -0,0 +1,33 @@
/**
*
* 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.
*
*/
function updateModelFrom(model, data) {
for (var i=0; i<data.length; i++) {
if (model.count < i) {
model.append(data[i]);
} else {
model.set(i, data[i]);
}
}
while (model.count > data.length) {
model.remove(model.count-1);
}
}

View file

@ -30,7 +30,8 @@ TARGET=%{buildroot}/%{_datadir}/%{name}/qml
mkdir -p $TARGET mkdir -p $TARGET
cp -rpv gpodder-core/src/* $TARGET/ cp -rpv gpodder-core/src/* $TARGET/
cp -rpv podcastparser/podcastparser.py $TARGET/ cp -rpv podcastparser/podcastparser.py $TARGET/
cp -rpv gpodder-ui-qml/main.py gpodder-ui-qml/qml $TARGET/ cp -rpv gpodder-ui-qml/main.py $TARGET/
cp -rpv qml $TARGET/
cp -rpv %{name}.qml $TARGET/ cp -rpv %{name}.qml $TARGET/
TARGET=%{buildroot}/%{_datadir}/applications TARGET=%{buildroot}/%{_datadir}/applications
@ -43,7 +44,6 @@ cp -rpv %{name}.png $TARGET/
%files %files
%defattr(-,root,root,-) %defattr(-,root,root,-)
%doc gpodder-core/README gpodder-core/LICENSE.GPLv3 gpodder-core/LICENSE.ISC
%{_datadir}/%{name} %{_datadir}/%{name}
%{_datadir}/applications/%{name}.desktop %{_datadir}/applications/%{name}.desktop
%{_datadir}/icons/hicolor/*/apps/%{name}.png %{_datadir}/icons/hicolor/*/apps/%{name}.png