QML split: Touch, Desktop, Common
2
README
|
@ -14,3 +14,5 @@ Qt Multimedia 5.0.2 http://qt-project.org/
|
|||
Python 3.3.0 http://python.org/
|
||||
PyOtherSide 1.0.0 http://thp.io/2011/pyotherside/
|
||||
gPodder 4.0.0 http://gpodder.org/
|
||||
|
||||
On the Desktop: Qt Quick Controls 5.1
|
||||
|
|
59
common/GPodderCore.qml
Normal file
|
@ -0,0 +1,59 @@
|
|||
|
||||
/**
|
||||
*
|
||||
* gPodder QML UI Reference Implementation
|
||||
* Copyright (c) 2013, 2014, 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
|
||||
|
||||
|
||||
Python {
|
||||
id: py
|
||||
|
||||
property bool ready: false
|
||||
signal downloading(int episode_id)
|
||||
signal downloadProgress(int episode_id, real progress)
|
||||
signal downloaded(int episode_id)
|
||||
|
||||
Component.onCompleted: {
|
||||
setHandler('hello', function (version, copyright) {
|
||||
console.log('gPodder version ' + version + ' starting up');
|
||||
console.log('Copyright: ' + copyright);
|
||||
});
|
||||
|
||||
setHandler('downloading', py.downloading);
|
||||
setHandler('download-progress', py.downloadProgress);
|
||||
setHandler('downloaded', py.downloaded);
|
||||
|
||||
var path = Qt.resolvedUrl('../..').substr('file://'.length);
|
||||
addImportPath(path);
|
||||
|
||||
// Load the Python side of things
|
||||
importModule('main', function() {
|
||||
py.ready = true;
|
||||
});
|
||||
}
|
||||
|
||||
onReceived: {
|
||||
console.log('unhandled message: ' + data);
|
||||
}
|
||||
|
||||
onError: {
|
||||
console.log('Python failure: ' + traceback);
|
||||
}
|
||||
}
|
1
desktop/common
Symbolic link
|
@ -0,0 +1 @@
|
|||
../common
|
88
desktop/gpodder.qml
Normal file
|
@ -0,0 +1,88 @@
|
|||
import QtQuick 2.0
|
||||
import QtQuick.Controls 1.0
|
||||
import QtQuick.Layouts 1.0
|
||||
|
||||
import 'common'
|
||||
import 'common/util.js' as Util
|
||||
|
||||
ApplicationWindow {
|
||||
width: 500
|
||||
height: 400
|
||||
|
||||
title: 'gPodder'
|
||||
|
||||
GPodderCore {
|
||||
id: py
|
||||
|
||||
onReadyChanged: {
|
||||
if (ready) {
|
||||
py.call('main.load_podcasts', [], function (podcasts) {
|
||||
Util.updateModelFrom(podcastListModel, podcasts);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
menuBar: MenuBar {
|
||||
Menu { title: 'File'; MenuItem { text: 'Quit' } }
|
||||
}
|
||||
|
||||
SplitView {
|
||||
anchors.fill: parent
|
||||
|
||||
TableView {
|
||||
width: 200
|
||||
model: ListModel { id: podcastListModel }
|
||||
headerVisible: false
|
||||
alternatingRowColors: false
|
||||
|
||||
rowDelegate: Rectangle {
|
||||
height: 60
|
||||
color: styleData.selected ? '#eee' : '#fff'
|
||||
}
|
||||
|
||||
TableViewColumn {
|
||||
role: 'coverart'
|
||||
title: 'Image'
|
||||
delegate: Item {
|
||||
height: 60
|
||||
width: 60
|
||||
Image {
|
||||
source: styleData.value
|
||||
width: 50
|
||||
height: 50
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
}
|
||||
|
||||
width: 60
|
||||
}
|
||||
|
||||
TableViewColumn {
|
||||
role: 'title'
|
||||
title: 'Podcast'
|
||||
delegate: Item {
|
||||
height: 60
|
||||
Text {
|
||||
text: styleData.value
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onCurrentRowChanged: {
|
||||
var id = podcastListModel.get(currentRow).id;
|
||||
py.call('main.load_episodes', [id], function (episodes) {
|
||||
Util.updateModelFrom(episodeListModel, episodes);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
TableView {
|
||||
Layout.fillWidth: true
|
||||
model: ListModel { id: episodeListModel }
|
||||
|
||||
TableViewColumn { role: 'title'; title: 'Title' }
|
||||
}
|
||||
}
|
||||
}
|
2
main.py
|
@ -19,7 +19,7 @@
|
|||
import sys
|
||||
import os
|
||||
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'gpodder', 'src'))
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'gpodder-core', 'src'))
|
||||
|
||||
import pyotherside
|
||||
import gpodder
|
||||
|
|
|
@ -19,9 +19,8 @@
|
|||
*/
|
||||
|
||||
import QtQuick 2.0
|
||||
import io.thp.pyotherside 1.0
|
||||
|
||||
import 'util.js' as Util
|
||||
import 'common/util.js' as Util
|
||||
|
||||
SlidePage {
|
||||
id: episodesPage
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
import QtQuick 2.0
|
||||
|
||||
import 'util.js' as Util
|
||||
import 'common/util.js' as Util
|
||||
|
||||
SlidePage {
|
||||
id: freshEpisodes
|
||||
|
@ -51,7 +51,7 @@ SlidePage {
|
|||
onClicked: py.call('main.download_episode', [id]);
|
||||
|
||||
Connections {
|
||||
target: pgst
|
||||
target: py
|
||||
onDownloadProgress: {
|
||||
if (episode_id == id) {
|
||||
freshEpisodesListModel.setProperty(index, 'progress', progress);
|
|
@ -19,11 +19,12 @@
|
|||
*/
|
||||
|
||||
import QtQuick 2.0
|
||||
import io.thp.pyotherside 1.0
|
||||
import 'common'
|
||||
|
||||
Item {
|
||||
id: pgst
|
||||
property bool ready: false
|
||||
|
||||
GPodderCore { id: py }
|
||||
|
||||
property real scalef: width / 480
|
||||
|
||||
|
@ -41,10 +42,6 @@ Item {
|
|||
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) {
|
||||
|
@ -58,50 +55,17 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
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
|
||||
visible: !py.ready
|
||||
}
|
||||
|
||||
StartPage {
|
||||
id: startPage
|
||||
visible: pgst.ready
|
||||
visible: py.ready
|
||||
}
|
||||
}
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
import QtQuick 2.0
|
||||
|
||||
import 'util.js' as Util
|
||||
import 'common/util.js' as Util
|
||||
|
||||
SlidePage {
|
||||
id: podcastsPage
|
|
@ -44,9 +44,9 @@ SlidePage {
|
|||
|
||||
Flickable {
|
||||
Connections {
|
||||
target: pgst
|
||||
target: py
|
||||
onReadyChanged: {
|
||||
if (pgst.ready) {
|
||||
if (py.ready) {
|
||||
startPage.update_stats();
|
||||
}
|
||||
}
|
||||
|
@ -229,9 +229,9 @@ SlidePage {
|
|||
spacing: 20 * pgst.scalef
|
||||
|
||||
Connections {
|
||||
target: pgst
|
||||
target: py
|
||||
onReadyChanged: {
|
||||
if (pgst.ready) {
|
||||
if (py.ready) {
|
||||
py.call('main.load_podcasts', [], function (podcasts) {
|
||||
recommendationsRepeater.model = podcasts.splice(0, 4);
|
||||
});
|
1
touch/common
Symbolic link
|
@ -0,0 +1 @@
|
|||
../common
|
|
@ -18,7 +18,6 @@
|
|||
*/
|
||||
|
||||
import QtQuick 2.0
|
||||
import 'qml'
|
||||
|
||||
Rectangle {
|
||||
color: '#336688'
|
||||
|
@ -28,12 +27,12 @@ Rectangle {
|
|||
|
||||
Image {
|
||||
anchors.fill: parent
|
||||
source: 'qml/images/mask.png'
|
||||
source: 'images/mask.png'
|
||||
}
|
||||
|
||||
Image {
|
||||
anchors.fill: parent
|
||||
source: 'qml/images/noise.png'
|
||||
source: 'images/noise.png'
|
||||
fillMode: Image.Tile
|
||||
}
|
||||
|
Before Width: | Height: | Size: 394 B After Width: | Height: | Size: 394 B |
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 151 KiB After Width: | Height: | Size: 151 KiB |
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 74 KiB |
Before Width: | Height: | Size: 162 B After Width: | Height: | Size: 162 B |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |