diff --git a/common/GPodderCore.qml b/common/GPodderCore.qml index 7920d32..a5983f3 100644 --- a/common/GPodderCore.qml +++ b/common/GPodderCore.qml @@ -77,16 +77,6 @@ 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/common/GPodderEpisodeListModel.qml b/common/GPodderEpisodeListModel.qml index a51b540..f8e632f 100644 --- a/common/GPodderEpisodeListModel.qml +++ b/common/GPodderEpisodeListModel.qml @@ -62,6 +62,14 @@ ListModel { }); } + onPodcast_idChanged: { + reload(); + } + + property var worker: ModelWorkerScript { + id: modelWorker + } + function forEachEpisode(callback) { // Go from bottom up (= chronological order) for (var i=count-1; i>=0; i--) { @@ -122,11 +130,12 @@ ListModel { ready = false; py.call('main.load_episodes', [podcast_id, query], function (episodes) { - Util.updateModelFrom(episodeListModel, episodes); - episodeListModel.ready = true; - if (callback !== undefined) { - callback(); - } + modelWorker.updateModelFrom(episodeListModel, episodes, function () { + episodeListModel.ready = true; + if (callback !== undefined) { + callback(); + } + }); }); } } diff --git a/common/GPodderEpisodeListModelConnections.qml b/common/GPodderEpisodeListModelConnections.qml index 9744dab..22806ad 100644 --- a/common/GPodderEpisodeListModelConnections.qml +++ b/common/GPodderEpisodeListModelConnections.qml @@ -26,11 +26,11 @@ Connections { target: py onDownloadProgress: { - Util.updateModelWith(episodeListModel, 'id', episode_id, + episodeListModel.worker.updateModelWith(episodeListModel, 'id', episode_id, {'progress': progress}); } onPlaybackProgress: { - Util.updateModelWith(episodeListModel, 'id', episode_id, + episodeListModel.worker.updateModelWith(episodeListModel, 'id', episode_id, {'playbackProgress': progress}); } onUpdatedEpisode: { diff --git a/common/GPodderPlatform.qml b/common/GPodderPlatform.qml index 57fb97d..3fe70b1 100644 --- a/common/GPodderPlatform.qml +++ b/common/GPodderPlatform.qml @@ -26,11 +26,9 @@ Item { property bool android: (typeof(gpodderAndroid) !== 'undefined') || emulatingAndroid property bool needsBackButton: !android - - property bool toolbarOnTop: true + property bool toolbarOnTop: android property bool invertedToolbar: toolbarOnTop property bool titleInToolbar: toolbarOnTop - - property bool floatingPlayButton: true - property bool hideDisabledMenu: true + property bool floatingPlayButton: android + property bool hideDisabledMenu: android } diff --git a/common/GPodderPodcastListModel.qml b/common/GPodderPodcastListModel.qml index 285bf16..aa17c2f 100644 --- a/common/GPodderPodcastListModel.qml +++ b/common/GPodderPodcastListModel.qml @@ -25,9 +25,13 @@ import 'util.js' as Util ListModel { id: podcastListModel + property var worker: ModelWorkerScript { + id: modelWorker + } + function reload() { py.call('main.load_podcasts', [], function (podcasts) { - Util.updateModelFrom(podcastListModel, podcasts); + modelWorker.updateModelFrom(podcastListModel, podcasts); }); } } diff --git a/common/ModelWorkerScript.qml b/common/ModelWorkerScript.qml new file mode 100644 index 0000000..19c0057 --- /dev/null +++ b/common/ModelWorkerScript.qml @@ -0,0 +1,67 @@ + +/** + * + * 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 + + +WorkerScript { + source: 'modelworker.js' + + property int callbacks_seq: 1 + property var callbacks: ({}) + + function refCallback(callback) { + var id = callbacks_seq++; + callbacks[id] = callback; + return id; + } + + function unrefCallback(callback) { + var result = callbacks[callback]; + delete callbacks[callback]; + return result; + } + + function updateModelFrom(model, data, callback) { + sendMessage({ + action: 'updateModelFrom', + model: model, + data: data, + callback: refCallback(callback), + }); + } + + function updateModelWith(model, key, value, update, callback) { + sendMessage({ + action: 'updateModelWith', + model: model, + key: key, + value: value, + update: update, + callback: refCallback(callback), + }); + } + + onMessage: { + if (messageObject.callback !== undefined) { + unrefCallback(messageObject.callback)(); + } + } +} diff --git a/common/modelworker.js b/common/modelworker.js new file mode 100644 index 0000000..44561bd --- /dev/null +++ b/common/modelworker.js @@ -0,0 +1,42 @@ +function updateModelFrom(model, data) { + // TODO: This is very naive at the moment, we should do proper remove(), + // move(), set() and insert() calls, so that the UI can animate changes. + for (var i=0; i data.length) { + model.remove(model.count-1); + } + + model.sync(); +} + +function updateModelWith(model, key, value, update) { + for (var row=0; row data.length) { - model.remove(model.count-1); - } -} - -function updateModelWith(model, key, value, update) { - for (var row=0; row 0: - yield '%02d:%02d:%02d' % (episode.total_time / (60 * 60), - (episode.total_time / 60) % 60, - episode.total_time % 60) + yield '%02d:%02d:%02d' % (episode.total_time / (60 * 60), (episode.total_time / 60) % 60, episode.total_time % 60) def show_podcast(self, podcast_id): podcast = self._get_podcast_by_id(podcast_id) @@ -423,7 +404,8 @@ class gPotherSide: return [{ 'label': provider.name, 'can_search': provider.kind == provider.PROVIDER_SEARCH - } for provider in sorted(registry.directory.select(select_provider), key=provider_sort_key, reverse=True)] + } for provider in sorted(registry.directory.select(select_provider), + key=provider_sort_key, reverse=True)] def get_directory_entries(self, provider, query): def match_provider(p): @@ -440,116 +422,6 @@ class gPotherSide: return [] - -PILL_TEMPLATE = """ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {left_text} - {left_text} - - - - - - - {right_text} - {right_text} - - - -""" - - -class PillExpression(object): - def __init__(self, **kwargs): - self.kwargs = kwargs - - def __call__(self, matchobj): - return str(eval(matchobj.group(1), self.kwargs)) - - -def pill_image_provider(image_id, requested_size): - left_text, right_text = (int(x) for x in image_id.split('/')) - - width = 44 - height = 24 - radius = 6 - font_size = 13 - - text_lx = width / 4 - text_rx = width * 3 / 4 - - charheight = font_size - charwidth = font_size / 1.3 - - if left_text: - text_lx -= charwidth * len(str(left_text)) / 2 - if right_text: - text_rx -= charwidth * len(str(right_text)) / 2 - - outer_style = 'stroke: #333333; stroke-width: 1; fill-opacity: 0; stroke-opacity: 0.6;' - inner_style = 'stroke: #ffffff; stroke-width: 1; fill-opacity: 0; stroke-opacity: 0.3;' - - expression = PillExpression(height=height, width=width, left_text=left_text, - right_text=right_text, radius=radius, - lx=text_lx, rx=text_rx, font_size=font_size, - outer_style=outer_style, inner_style=inner_style) - svg = re.sub(r'[{]([^}]+)[}]', expression, PILL_TEMPLATE) - return bytearray(svg.encode('utf-8')), (width, height), pyotherside.format_data - - -@pyotherside.set_image_provider -def gpotherside_image_provider(image_id, requested_size): - provider, args = image_id.split('/', 1) - if provider == 'pill': - return pill_image_provider(args, requested_size) - - raise ValueError('Unknown provider: %s' % (provider,)) - - gpotherside = gPotherSide() pyotherside.atexit(gpotherside.atexit) @@ -561,7 +433,6 @@ load_podcasts = gpotherside.load_podcasts load_episodes = gpotherside.load_episodes show_episode = gpotherside.show_episode play_episode = gpotherside.play_episode -import_opml = gpotherside.import_opml subscribe = gpotherside.subscribe unsubscribe = gpotherside.unsubscribe check_for_episodes = gpotherside.check_for_episodes diff --git a/makefile b/makefile index 0d05e9a..27a4fd0 100644 --- a/makefile +++ b/makefile @@ -1,5 +1,5 @@ PROJECT := gpodder-ui-qml -VERSION := 4.6.0 +VERSION := 4.4.0 all: @echo "" diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 68859ad..0000000 --- a/setup.cfg +++ /dev/null @@ -1,2 +0,0 @@ -[pep8] -max-line-length = 120 diff --git a/touch/AboutPage.qml b/touch/AboutPage.qml index 36944a4..fa62f11 100644 --- a/touch/AboutPage.qml +++ b/touch/AboutPage.qml @@ -73,7 +73,7 @@ SlidePage { anchors.horizontalCenter: parent.horizontalCenter wrapMode: Text.WordWrap text: [ - '© 2005-2015 Thomas Perl and the gPodder Team', + '© 2005-2014 Thomas Perl and the gPodder Team', 'License: ISC / GPLv3 or later', 'Website: http://gpodder.org/', '', diff --git a/touch/Dragging.qml b/touch/Dragging.qml index ed9f72d..4225681 100644 --- a/touch/Dragging.qml +++ b/touch/Dragging.qml @@ -31,8 +31,8 @@ MouseArea { drag { target: parent axis: Drag.XAxis - minimumX: 0 - maximumX: canClose ? parent.width : 0 + minimumX: parent.leftDragLimit + maximumX: canClose ? pgst.width : 0 filterChildren: true } @@ -44,7 +44,7 @@ MouseArea { if (pressed) { dragging.stacking.stopAllAnimations(); } else { - if (parent.x > parent.width / 3) { + if (parent.x > pgst.width * 3 / 4) { dragging.stacking.startFadeOut(); } else { dragging.stacking.fadeInAgain(); diff --git a/touch/EpisodeDetail.qml b/touch/EpisodeDetail.qml index 536ed23..2b5a0f9 100644 --- a/touch/EpisodeDetail.qml +++ b/touch/EpisodeDetail.qml @@ -27,6 +27,8 @@ import 'icons/icons.js' as Icons SlidePage { id: detailPage + width: pgst.width / 3 + property int episode_id property string title property string link @@ -43,7 +45,7 @@ SlidePage { visible: !detailPage.ready } - Component.onCompleted: { + onEpisode_idChanged: { py.call('main.show_episode', [episode_id], function (episode) { detailPage.title = episode.title; descriptionLabel.text = episode.description; diff --git a/touch/EpisodeItem.qml b/touch/EpisodeItem.qml index 8a8a55e..8e28d15 100644 --- a/touch/EpisodeItem.qml +++ b/touch/EpisodeItem.qml @@ -135,22 +135,22 @@ Item { Rectangle { anchors { top: parent.top - left: parent.left + left: downloadIndicator.right } height: Constants.layout.padding * pgst.scalef - width: parent.width * progress + width: (parent.width - downloadIndicator.width) * progress color: Constants.colors.download } Rectangle { anchors { bottom: parent.bottom - left: parent.left + left: downloadIndicator.right } height: Constants.layout.padding * pgst.scalef - width: parent.width * playbackProgress + width: (parent.width - downloadIndicator.width) * playbackProgress color: titleLabel.color opacity: episodeItem.isPlaying ? 1 : .2 } @@ -163,17 +163,27 @@ Item { right: parent.right } - RectangleIndicator { + Rectangle { id: downloadIndicator - enabled: downloadState == Constants.state.downloaded + + width: Constants.layout.padding * pgst.scalef * (downloadState == Constants.state.downloaded) + + Behavior on width { PropertyAnimation { } } + + anchors { + top: parent.top + bottom: parent.bottom + left: parent.left + } + color: titleLabel.color } Column { anchors { left: parent.left - leftMargin: Constants.layout.padding * pgst.scalef - right: downloadIndicator.left + leftMargin: 2 * Constants.layout.padding * pgst.scalef + right: parent.right rightMargin: Constants.layout.padding * pgst.scalef verticalCenter: parent.verticalCenter } diff --git a/touch/EpisodeListView.qml b/touch/EpisodeListView.qml index 4fd0088..3430ac9 100644 --- a/touch/EpisodeListView.qml +++ b/touch/EpisodeListView.qml @@ -27,9 +27,14 @@ import 'common/util.js' as Util PListView { id: episodeList + property alias podcast_id: episodeListModel.podcast_id property int selectedIndex: -1 + onPodcast_idChanged: { + selectedIndex = -1; + } + PScrollIntoView { id: scrollIntoView } onSelectedIndexChanged: { diff --git a/touch/EpisodeQueryPage.qml b/touch/EpisodeQueryPage.qml index bf8f423..ebd8d01 100644 --- a/touch/EpisodeQueryPage.qml +++ b/touch/EpisodeQueryPage.qml @@ -44,10 +44,6 @@ SlidePage { title: 'Episodes' section.property: 'section' - section.delegate: SectionHeader { - text: section - color: episodeList.selectedIndex === -1 ? Constants.colors.secondaryHighlight : Constants.colors.text - opacity: episodeList.selectedIndex === -1 ? 1 : 0.2 - } + section.delegate: SectionHeader { text: section } } } diff --git a/touch/EpisodesPage.qml b/touch/EpisodesPage.qml index dc046c2..a4ca5b9 100644 --- a/touch/EpisodesPage.qml +++ b/touch/EpisodesPage.qml @@ -28,6 +28,8 @@ import 'icons/icons.js' as Icons SlidePage { id: page + width: pgst.width / 3 + property int podcast_id property string title @@ -80,12 +82,6 @@ SlidePage { ], undefined, undefined, true); } - - Component.onCompleted: { - episodeList.model.podcast_id = podcast_id; - // List model will be loaded automatically on load - } - EpisodeQueryControl { id: queryControl model: episodeList.model @@ -95,5 +91,6 @@ SlidePage { EpisodeListView { id: episodeList title: page.title + podcast_id: page.podcast_id } } diff --git a/touch/IconContextMenu.qml b/touch/IconContextMenu.qml index 7703956..68711ea 100644 --- a/touch/IconContextMenu.qml +++ b/touch/IconContextMenu.qml @@ -20,8 +20,6 @@ import QtQuick 2.0 -import 'common/constants.js' as Constants - Item { id: contextMenu default property alias children: contextMenuRow.children @@ -29,10 +27,6 @@ Item { Row { id: contextMenuRow - anchors { - verticalCenter: parent.verticalCenter - right: parent.right - margins: Constants.layout.padding * pgst.scalef - } + anchors.centerIn: parent } } diff --git a/touch/Main.qml b/touch/Main.qml index 9d4f850..c55ebea 100644 --- a/touch/Main.qml +++ b/touch/Main.qml @@ -68,7 +68,7 @@ Item { // Initial focus focus: true - property real scalef: (width < height) ? (width / 480) : (height / 480) + property real scalef: 1.0 //(width < height) ? (width / 480) : (height / 480) property int shorterSide: (width < height) ? width : height property int dialogsVisible: 0 @@ -84,9 +84,9 @@ Item { } if (page.isDialog) { - children[index-1].opacity = 1; + //children[index-1].opacity = 1; } else { - children[index-1].opacity = x / width; + //children[index-1].opacity = x / width; } //children[index-1].pushPhase = x / width; @@ -115,6 +115,26 @@ Item { } } + onChildrenChanged: resizePages() + + function resizePages() { + var pages = []; + for (var i=0; i 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(min + (max - min) * (mouse.x / width)) + onPressed: { + slider.temporaryValue = (min + (max - min) * (mouse.x / width)); + } + onPositionChanged: { + slider.temporaryValue = (min + (max - min) * (mouse.x / width)); } - onClicked: slider.valueChangeRequested(updateValue(mouse.x)); - onPressed: updateValue(mouse.x); - onPositionChanged: updateValue(mouse.x); preventStealing: true } @@ -78,14 +68,4 @@ 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 6c33d2e..660d630 100644 --- a/touch/PTextField.qml +++ b/touch/PTextField.qml @@ -50,7 +50,6 @@ Item { right: clipboardIcon.left margins: 5 * pgst.scalef } - clip: true inputMethodHints: Qt.ImhNoAutoUppercase | Qt.ImhNoPredictiveText diff --git a/touch/PodcastDetail.qml b/touch/PodcastDetail.qml index 3f3a594..b710e39 100644 --- a/touch/PodcastDetail.qml +++ b/touch/PodcastDetail.qml @@ -27,6 +27,8 @@ import 'icons/icons.js' as Icons SlidePage { id: page + width: pgst.width / 3 + property int podcast_id property string title property string description diff --git a/touch/PodcastItem.qml b/touch/PodcastItem.qml index 3eb80fd..91c15d5 100644 --- a/touch/PodcastItem.qml +++ b/touch/PodcastItem.qml @@ -33,6 +33,19 @@ ButtonArea { right: parent.right } + Rectangle { + width: Constants.layout.padding * pgst.scalef * (newEpisodes > 0) + Behavior on width { PropertyAnimation { } } + + anchors { + top: cover.top + bottom: cover.bottom + left: parent.left + } + + color: Constants.colors.fresh + } + CoverArt { id: cover visible: !updating @@ -72,7 +85,7 @@ ButtonArea { PLabel { id: downloadsLabel anchors { - right: newEpisodesIndicator.enabled ? newEpisodesIndicator.left : parent.right + right: parent.right rightMargin: Constants.layout.padding * pgst.scalef verticalCenter: parent.verticalCenter } @@ -80,10 +93,4 @@ ButtonArea { text: downloaded ? downloaded : '' color: Constants.colors.text } - - RectangleIndicator { - id: newEpisodesIndicator - enabled: newEpisodes > 0 - color: Constants.colors.fresh - } } diff --git a/touch/PodcastsPage.qml b/touch/PodcastsPage.qml index 6cdab93..2d977a3 100644 --- a/touch/PodcastsPage.qml +++ b/touch/PodcastsPage.qml @@ -28,6 +28,8 @@ import 'common/constants.js' as Constants SlidePage { id: page + width: pgst.width / 3 + canClose: false hasMenuButton: true @@ -47,9 +49,9 @@ SlidePage { } }, { - label: 'Settings', + label: 'About', callback: function () { - pgst.loadPage('SettingsPage.qml'); + pgst.loadPage('AboutPage.qml'); }, }, { @@ -66,20 +68,6 @@ SlidePage { }); }, }, - { - label: 'Add from OPML', - callback: function () { - var ctx = { py: py }; - pgst.loadPage('TextInputDialog.qml', { - buttonText: 'Subscribe', - placeholderText: 'OPML URL', - pasteOnLoad: true, - callback: function (url) { - ctx.py.call('main.import_opml', [url]); - } - }); - }, - }, { label: 'Discover new podcasts', callback: function () { diff --git a/touch/RectangleIndicator.qml b/touch/RectangleIndicator.qml deleted file mode 100644 index 08adccd..0000000 --- a/touch/RectangleIndicator.qml +++ /dev/null @@ -1,36 +0,0 @@ - -/** - * - * 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 - -Rectangle { - width: Constants.layout.padding * 2 * pgst.scalef * enabled - height: width - - Behavior on width { PropertyAnimation { } } - - anchors { - verticalCenter: parent.verticalCenter - right: parent.right - margins: Constants.layout.padding * 2 * pgst.scalef - width / 2 - } -} diff --git a/touch/SectionHeader.qml b/touch/SectionHeader.qml index 7ce75e0..55234f6 100644 --- a/touch/SectionHeader.qml +++ b/touch/SectionHeader.qml @@ -24,29 +24,15 @@ import 'common/constants.js' as Constants Item { property alias text: pLabel.text - property alias color: pLabel.color height: 70 * pgst.scalef - width: parent.width - - Rectangle { - anchors { - verticalCenter: parent.verticalCenter - left: parent.left - right: pLabel.left - margins: Constants.layout.padding * pgst.scalef - } - - color: pLabel.color - height: 1 * pgst.scalef - } PLabel { id: pLabel anchors { - right: parent.right - verticalCenter: parent.verticalCenter - margins: Constants.layout.padding * pgst.scalef + left: parent.left + bottom: parent.bottom + margins: 10 * pgst.scalef } color: Constants.colors.secondaryHighlight diff --git a/touch/SettingsLabel.qml b/touch/SettingsLabel.qml deleted file mode 100644 index 643189e..0000000 --- a/touch/SettingsLabel.qml +++ /dev/null @@ -1,32 +0,0 @@ - -/** - * - * 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 deleted file mode 100644 index 8d47886..0000000 --- a/touch/SettingsPage.qml +++ /dev/null @@ -1,113 +0,0 @@ - -/** - * - * 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 } -} - diff --git a/touch/SlidePage.qml b/touch/SlidePage.qml index cdad75f..b7dd7ef 100644 --- a/touch/SlidePage.qml +++ b/touch/SlidePage.qml @@ -33,10 +33,14 @@ Rectangle { property alias canClose: dragging.canClose property bool isDialog: false + property string filename + property int leftDragLimit + property int nextDragLimit: page.x + page.width + property string title: '' property bool hasMenuButton: false property string menuButtonLabel: 'Menu' - property string menuButtonIcon: Icons.stack + property string menuButtonIcon: Icons.vellipsis signal menuButtonClicked() function closePage() { @@ -54,6 +58,10 @@ Rectangle { Stacking { id: stacking } + function slideToLeft() { + stacking.fadeInAgain(); + } + Dragging { id: dragging stacking: stacking diff --git a/touch/Stacking.qml b/touch/Stacking.qml index 5523552..e85f083 100644 --- a/touch/Stacking.qml +++ b/touch/Stacking.qml @@ -28,7 +28,7 @@ Item { id: fadeIn target: stacking.page property: 'x' - to: 0 + to: page.leftDragLimit duration: 500 easing.type: Easing.OutCubic @@ -41,7 +41,7 @@ Item { id: fadeOut target: stacking.page property: 'x' - to: stacking.page.width + to: pgst.width duration: 500 easing.type: Easing.OutCubic } @@ -62,7 +62,7 @@ Item { Component.onCompleted: { if (pgst.loadPageInProgress) { - page.x = page.width; + page.x = pgst.width; fadeIn.start(); } } diff --git a/touch/gpodder.qml b/touch/gpodder.qml index 122ff47..5df7a5d 100644 --- a/touch/gpodder.qml +++ b/touch/gpodder.qml @@ -24,7 +24,7 @@ import 'common/constants.js' as Constants Rectangle { color: Constants.colors.page - width: 480 + width: 1280 height: 800 Main {} diff --git a/touch/icons/icons.js b/touch/icons/icons.js index 344a50b..4372966 100644 --- a/touch/icons/icons.js +++ b/touch/icons/icons.js @@ -19,8 +19,8 @@ var folder = '\ue065'; var magnifying_glass = '\ue074'; var cog = '\u2699'; var link = '\ue077'; +var vellipsis = '\u22ee'; var paperclip = '\ue08a'; var tag_fill = '\ue02b'; var headphones = '\ue061'; var sleep = '\u263e'; -var stack = '\ue020';