diff --git a/common/GPodderCore.qml b/common/GPodderCore.qml index a5983f3..7920d32 100644 --- a/common/GPodderCore.qml +++ b/common/GPodderCore.qml @@ -77,6 +77,16 @@ Python { }); } + function setConfig(key, value) { + py.call('main.set_config_value', [key, value]); + } + + function getConfig(key, callback) { + py.call('main.get_config_value', [key], function (result) { + callback(result); + }); + } + onReceived: { console.log('unhandled message: ' + data); } diff --git a/touch/PSlider.qml b/touch/PSlider.qml index eb32ad3..2f6855f 100644 --- a/touch/PSlider.qml +++ b/touch/PSlider.qml @@ -28,6 +28,7 @@ Item { property real value property real min: 0.0 property real max: 1.0 + property real step: 0.0 property color color: Constants.colors.highlight property real displayedValue: mouseArea.pressed ? temporaryValue : value @@ -42,13 +43,22 @@ Item { MouseArea { id: mouseArea anchors.fill: parent - onClicked: slider.valueChangeRequested(min + (max - min) * (mouse.x / width)) - onPressed: { - slider.temporaryValue = (min + (max - min) * (mouse.x / width)); - } - onPositionChanged: { - slider.temporaryValue = (min + (max - min) * (mouse.x / width)); + function updateValue(x) { + if (x > width) { + x = width; + } else if (x < 0) { + x = 0; + } + var v = (max - min) * (x / width); + if (slider.step > 0.0) { + v = slider.step * parseInt(0.5 + v / slider.step); + } + slider.temporaryValue = min + v; + return slider.temporaryValue; } + onClicked: slider.valueChangeRequested(updateValue(mouse.x)); + onPressed: updateValue(mouse.x); + onPositionChanged: updateValue(mouse.x); preventStealing: true } @@ -68,4 +78,14 @@ Item { verticalCenter: parent.verticalCenter } } + + Repeater { + model: slider.step ? ((slider.max - slider.min) / slider.step - 1) : 0 + delegate: Rectangle { + width: Math.max(1, 1 * pgst.scalef) + height: parent.height + color: Constants.colors.area + x: parent.width * ((slider.step * (1 + index)) / (slider.max - slider.min)); + } + } } diff --git a/touch/PTextField.qml b/touch/PTextField.qml index 660d630..6c33d2e 100644 --- a/touch/PTextField.qml +++ b/touch/PTextField.qml @@ -50,6 +50,7 @@ Item { right: clipboardIcon.left margins: 5 * pgst.scalef } + clip: true inputMethodHints: Qt.ImhNoAutoUppercase | Qt.ImhNoPredictiveText diff --git a/touch/PodcastsPage.qml b/touch/PodcastsPage.qml index b07129f..882252b 100644 --- a/touch/PodcastsPage.qml +++ b/touch/PodcastsPage.qml @@ -47,9 +47,9 @@ SlidePage { } }, { - label: 'About', + label: 'Settings', callback: function () { - pgst.loadPage('AboutPage.qml'); + pgst.loadPage('SettingsPage.qml'); }, }, { diff --git a/touch/SettingsLabel.qml b/touch/SettingsLabel.qml new file mode 100644 index 0000000..643189e --- /dev/null +++ b/touch/SettingsLabel.qml @@ -0,0 +1,32 @@ + +/** + * + * gPodder QML UI Reference Implementation + * Copyright (c) 2015, 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 + +PLabel { + anchors { + left: parent.left + right: parent.right + margins: Constants.layout.padding * pgst.scalef + } + color: Constants.colors.secondaryHighlight +} diff --git a/touch/SettingsPage.qml b/touch/SettingsPage.qml new file mode 100644 index 0000000..8d47886 --- /dev/null +++ b/touch/SettingsPage.qml @@ -0,0 +1,113 @@ + +/** + * + * gPodder QML UI Reference Implementation + * Copyright (c) 2015, 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 + +SlidePage { + id: page + + Component.onCompleted: { + py.getConfig('plugins.youtube.api_key_v3', function (value) { + youtube_api_key_v3.text = value; + }); + py.getConfig('limit.episodes', function (value) { + limit_episodes.value = value; + }); + } + + Component.onDestruction: { + py.setConfig('plugins.youtube.api_key_v3', youtube_api_key_v3.text); + py.setConfig('limit.episodes', parseInt(limit_episodes.value)); + } + + Flickable { + id: flickable + anchors.fill: parent + boundsBehavior: Flickable.StopAtBounds + + contentWidth: detailColumn.width + contentHeight: detailColumn.height + detailColumn.spacing + + Column { + id: detailColumn + + width: page.width + spacing: 15 * pgst.scalef + + SlidePageHeader { title: 'Settings' } + + SectionHeader { text: 'YouTube' } + + SettingsLabel { text: 'API Key (v3)' } + + PTextField { + id: youtube_api_key_v3 + anchors { + left: parent.left + right: parent.right + margins: Constants.layout.padding * pgst.scalef + } + } + + SectionHeader { text: 'Limits' } + + SettingsLabel { text: 'Maximum episodes per feed' } + + PSlider { + id: limit_episodes + min: 100 + step: 100 + max: 1000 + anchors { + left: parent.left + right: parent.right + margins: Constants.layout.padding * pgst.scalef + } + onValueChangeRequested: { value = newValue; } + } + + PLabel { + text: parseInt(limit_episodes.displayedValue) + anchors { + left: parent.left + right: parent.right + margins: Constants.layout.padding * pgst.scalef + } + } + + SectionHeader { text: 'About' } + + ButtonArea { + width: parent.width + height: Constants.layout.item.height * pgst.scalef + PLabel { + anchors.centerIn: parent + text: 'About gPodder ' + py.uiversion + } + onClicked: pgst.loadPage('AboutPage.qml') + } + } + } + + PScrollDecorator { flickable: flickable } +} +