From 4b6fa1b07784f48a5f4861726c6c3ecc8f88afd6 Mon Sep 17 00:00:00 2001 From: Thomas Perl Date: Sat, 11 Jun 2011 16:35:11 +0200 Subject: [PATCH] QML UI: Subscription UI and compatibility fixes --- data/ui/qml/ContextMenu.qml | 8 +++++- data/ui/qml/EpisodeDetails.qml | 5 +++- data/ui/qml/EpisodeItem.qml | 1 + data/ui/qml/InputField.qml | 13 +++++++++ data/ui/qml/Main.qml | 42 +++++++++++++++++++++++----- data/ui/qml/SimpleButton.qml | 40 +++++++++++++++++++++++++++ data/ui/qml/Subscribe.qml | 63 +++++++++++++++++++++++++++++------------- data/ui/qml/main_default.qml | 14 +++++++++- data/ui/qml/main_fermintle.qml | 49 +++++++++++++++----------------- src/gpodder/qmlui/__init__.py | 32 ++++++++++++--------- src/gpodder/youtube.py | 2 +- 11 files changed, 200 insertions(+), 69 deletions(-) create mode 100644 data/ui/qml/InputField.qml create mode 100644 data/ui/qml/SimpleButton.qml rewrite data/ui/qml/main_fermintle.qml (81%) diff --git a/data/ui/qml/ContextMenu.qml b/data/ui/qml/ContextMenu.qml index 14a3f043..8969b6bf 100644 --- a/data/ui/qml/ContextMenu.qml +++ b/data/ui/qml/ContextMenu.qml @@ -51,9 +51,15 @@ Item { } } + function showSubscribe() { + contextMenuArea.subscribeMode = true + contextMenuArea.state = 'opened' + subscribe.show() + } + Subscribe { id: subscribe - visible: contextMenuArea.subscribeMode + visible: contextMenuArea.subscribeMode && (contextMenuArea.state == 'opened') anchors.fill: parent anchors.topMargin: Config.headerHeight diff --git a/data/ui/qml/EpisodeDetails.qml b/data/ui/qml/EpisodeDetails.qml index 780290ef..c679c7c2 100644 --- a/data/ui/qml/EpisodeDetails.qml +++ b/data/ui/qml/EpisodeDetails.qml @@ -139,7 +139,10 @@ Item { MouseArea { anchors.fill: parent - onClicked: episodeDetails.fullscreen = !episodeDetails.fullscreen + onClicked: { + episodeDetails.fullscreen = !episodeDetails.fullscreen + rootWindow.showStatusBar = !episodeDetails.fullscreen + } } } diff --git a/data/ui/qml/EpisodeItem.qml b/data/ui/qml/EpisodeItem.qml index 813854d8..939f0241 100644 --- a/data/ui/qml/EpisodeItem.qml +++ b/data/ui/qml/EpisodeItem.qml @@ -59,6 +59,7 @@ SelectableItem { Text { id: positionInfo text: modelData.qpositiontext + font.pixelSize: episodeItem.height * .2 color: '#888' anchors.right: parent.right anchors.rightMargin: Config.largeSpacing diff --git a/data/ui/qml/InputField.qml b/data/ui/qml/InputField.qml new file mode 100644 index 00000000..63a030cf --- /dev/null +++ b/data/ui/qml/InputField.qml @@ -0,0 +1,13 @@ + +import Qt 4.7 + +TextInput { + color: 'white' + font.pixelSize: 20 + inputMethodHints: Qt.ImhNoAutoUppercase + + function closeVirtualKeyboard() { + // noop on this platform + } +} + diff --git a/data/ui/qml/Main.qml b/data/ui/qml/Main.qml index 7cf5b8d8..100d22c3 100644 --- a/data/ui/qml/Main.qml +++ b/data/ui/qml/Main.qml @@ -330,7 +330,7 @@ Rectangle { anchors.verticalCenter: parent.verticalCenter anchors.left: taskSwitcher.visible?taskSwitcher.right:taskSwitcher.left anchors.leftMargin: (contextMenu.state == 'opened')?(Config.largeSpacing):(Config.hasTaskSwitcher?0:Config.largeSpacing) - anchors.right: searchButton.left + anchors.right: (episodeDetails.state == 'visible')?parent.right:searchButton.left clip: true text: (contextMenu.state == 'opened')?(contextMenu.subscribeMode?'Add a new podcast':'Context menu'):(episodeDetails.state == 'visible'?("Now playing - "+((currentEpisode!=undefined)?currentEpisode.qpositiontext:'No episode')):(main.state == 'episodes'?controller.episodeListTitle:"gPodder")) onTextChanged: controller.titleChanged(text) @@ -345,13 +345,9 @@ Rectangle { source: 'artwork/subscriptions.png' - onClicked: { - //controller.searchButtonClicked() - contextMenu.subscribeMode = true - contextMenu.state = 'opened' - } + onClicked: contextMenu.showSubscribe() - visible: contextMenu.state == 'closed' + visible: (contextMenu.state == 'closed' && main.state == 'podcasts' && episodeDetails.state == 'hidden') } TitlebarButton { @@ -376,5 +372,37 @@ Rectangle { } } } + + function showMessage(message) { + messageDialogText.text = message + messageDialog.opacity = 1 + } + + Item { + id: messageDialog + anchors.fill: parent + opacity: 0 + z: 20 + + Behavior on opacity { PropertyAnimation { } } + + Rectangle { + anchors.fill: parent + color: '#ee000000' + } + + Text { + id: messageDialogText + anchors.centerIn: parent + color: 'white' + font.pixelSize: 20 + font.bold: true + } + + MouseArea { + anchors.fill: parent + onClicked: messageDialog.opacity = 0 + } + } } diff --git a/data/ui/qml/SimpleButton.qml b/data/ui/qml/SimpleButton.qml new file mode 100644 index 00000000..ac6a9e5c --- /dev/null +++ b/data/ui/qml/SimpleButton.qml @@ -0,0 +1,40 @@ + +import Qt 4.7 + +import com.nokia.meego 1.0 + +import 'config.js' as Config + +SelectableItem { + property alias text: buttonText.text + property alias image: buttonImage.source + signal clicked() + + property string modelData: '' + width: 100 + height: Config.listItemHeight + + onSelected: clicked() + + anchors { + top: parent.top + right: parent.right + } + + Text { + id: buttonText + anchors.centerIn: parent + color: 'white' + font.pixelSize: 20 + font.bold: true + text: '' + visible: text != '' + } + + ScaledIcon { + id: buttonImage + anchors.centerIn: parent + visible: source != '' + } +} + diff --git a/data/ui/qml/Subscribe.qml b/data/ui/qml/Subscribe.qml index 936843f2..a46a2b8d 100644 --- a/data/ui/qml/Subscribe.qml +++ b/data/ui/qml/Subscribe.qml @@ -1,11 +1,25 @@ import Qt 4.7 +import 'config.js' as Config + Item { id: subscribe signal subscribe(variant url) + function show() { + searchInput.text = '' + opmlListModel.source = '' + searchInput.forceActiveFocus() + } + + onVisibleChanged: { + if (!visible) { + searchInput.closeVirtualKeyboard() + } + } + Item { id: topBar height: 70 @@ -22,44 +36,52 @@ Item { color: 'white' font.pixelSize: 20 anchors { + leftMargin: Config.smallSpacing left: parent.left verticalCenter: parent.verticalCenter } } - TextInput { + InputField { id: searchInput - color: 'white' - font.pixelSize: 20 + anchors { + leftMargin: Config.smallSpacing left: searchLabel.right right: searchButton.left verticalCenter: parent.verticalCenter } } - Rectangle { + SimpleButton { id: searchButton + //text: 'Search' + image: 'artwork/search.png' + + onClicked: opmlListModel.searchFor(searchInput.text) + + width: parent.height + height: parent.height + anchors { top: parent.top - right: parent.right + right: addButton.left } + } - color: 'blue' - height: parent.height - width: 100 + SimpleButton { + id: addButton + //text: 'Add' + image: 'artwork/subscriptions.png' - Text { - id: searchButtonLabel - color: 'white' - anchors.centerIn: parent - text: 'Search' - font.pixelSize: 20 - } + onClicked: subscribe.subscribe(searchInput.text) - MouseArea { - anchors.fill: parent - onClicked: opmlListModel.searchFor(searchInput.text) + width: parent.height + height: parent.height + + anchors { + top: parent.top + right: parent.right } } } @@ -87,7 +109,9 @@ Item { delegate: SelectableItem { property string modelData: url - height: 50; width: parent.width + height: 50 + width: parent.width + Text { text: title anchors.fill: parent @@ -95,6 +119,7 @@ Item { color: 'white' font.pixelSize: 25 } + onSelected: subscribe.subscribe(item) } } diff --git a/data/ui/qml/main_default.qml b/data/ui/qml/main_default.qml index f1f77b8b..885c4139 100644 --- a/data/ui/qml/main_default.qml +++ b/data/ui/qml/main_default.qml @@ -1,5 +1,17 @@ import Qt 4.7 -Main { } +Item { + id: rootWindow + property bool showStatusBar: true + property variant main: mainObject + + width: 800 + height: 480 + + Main { + id: mainObject + anchors.fill: parent + } +} diff --git a/data/ui/qml/main_fermintle.qml b/data/ui/qml/main_fermintle.qml dissimilarity index 81% index 9658e18b..b6dfefcd 100644 --- a/data/ui/qml/main_fermintle.qml +++ b/data/ui/qml/main_fermintle.qml @@ -1,26 +1,23 @@ - -import Qt 4.7 -import com.meego 1.0 - -Window { - id: window - property variant main: mainObject - - PageStack { - id: pageStack - anchors.fill: parent - - Page { - id: mainPage - Main { - id: mainObject - anchors.fill: parent - } - - Component.onCompleted: { - pageStack.push(mainPage) - } - } - } -} - + +import Qt 4.7 +import com.nokia.meego 1.0 + +PageStackWindow { + id: rootWindow + property variant main: mainObject + + initialPage: Page { + id: mainPage + + Main { + id: mainObject + anchors.fill: parent + } + + } + + Component.onCompleted: { + theme.inverted = true + } +} + diff --git a/src/gpodder/qmlui/__init__.py b/src/gpodder/qmlui/__init__.py index 1e06cfe3..de5f932e 100644 --- a/src/gpodder/qmlui/__init__.py +++ b/src/gpodder/qmlui/__init__.py @@ -132,25 +132,28 @@ class Controller(UiData): helper.Action(toggle_new, 'episode-toggle-new', episode), ]) - @Slot() - def searchButtonClicked(self): - # FIXME: This is not used at the moment - remove later? - self.show_context_menu([ - helper.Action('Search podcasts', 'search-podcasts'), - helper.Action('Filter current list', 'filter-list'), - ]) - @Slot(str) def addSubscription(self, url): url = util.normalize_feed_url(url) + for podcast in self.root.podcast_model.get_objects(): + if isinstance(podcast, model.EpisodeSubsetView): + continue + + if podcast.url == url: + self.root.show_message('Podcast already added') + self.podcastSelected(podcast) + return + def subscribe_proc(self, url): + # TODO: Show progress indicator channel = model.Model.load_podcast(self.root.db, url=url, \ create=True, \ max_episodes=self.root.config.max_episodes_per_feed, \ mimetype_prefs=self.root.config.mimetype_prefs) channel.save() self.root.podcast_list_changed.emit() + # TODO: Present the podcast to the user t = threading.Thread(target=subscribe_proc, args=[self, url]) t.start() @@ -230,7 +233,8 @@ class qtPodder(QObject): QObject.__init__(self) # Enable OpenGL rendering without requiring QtOpenGL - if '-graphicssystem' not in args: + # On Fermintle we let the system choose the best graphicssystem + if '-graphicssystem' not in args and not gpodder.ui.fermintle: args += ['-graphicssystem', 'opengl'] self.app = QApplication(args) @@ -266,12 +270,11 @@ class qtPodder(QObject): # Load the QML UI (this could take a while...) if gpodder.ui.fermintle: self.view.setSource(QML('main_fermintle.qml')) - # Proxy to the "main" QML object for direct access to Qt Properties - self.main = helper.QObjectProxy(self.view.rootObject().property('main')) else: self.view.setSource(QML('main_default.qml')) - # Proxy to the "main" QML object for direct access to Qt Properties - self.main = helper.QObjectProxy(self.view.rootObject()) + + # Proxy to the "main" QML object for direct access to Qt Properties + self.main = helper.QObjectProxy(self.view.rootObject().property('main')) self.main.podcastModel = self.podcast_model self.main.episodeModel = self.episode_model @@ -312,6 +315,9 @@ class qtPodder(QObject): self.core.shutdown() self.app.quit() + def show_message(self, message): + self.main.showMessage(message) + def open_context_menu(self, items): self.main.openContextMenu(items) diff --git a/src/gpodder/youtube.py b/src/gpodder/youtube.py index 5dbebbdc..22bf30ed 100644 --- a/src/gpodder/youtube.py +++ b/src/gpodder/youtube.py @@ -54,7 +54,7 @@ def get_real_download_url(url, preferred_fmt_id=None): preferred_fmt_id = 18 # For Maemo 5, we force fmt_id 5 for performance reasons - if gpodder.ui.fremantle: + if gpodder.ui.fremantle and not gpodder.ui.fermintle: preferred_fmt_id = 5 vid = get_youtube_id(url) -- 2.11.4.GIT