From 66bc949a2e37a4ba53c88d7dbafb3439d2028ff6 Mon Sep 17 00:00:00 2001 From: Thomas Perl Date: Tue, 26 Feb 2013 17:45:55 +0100 Subject: [PATCH] QML UI: Decouple Python upcalls from QML UI --- share/gpodder/ui/qml/Main.qml | 17 +++++- src/gpodder/qmlui/__init__.py | 137 +++++++++++++++--------------------------- 2 files changed, 64 insertions(+), 90 deletions(-) diff --git a/share/gpodder/ui/qml/Main.qml b/share/gpodder/ui/qml/Main.qml index f85ceb85..dfe78c46 100644 --- a/share/gpodder/ui/qml/Main.qml +++ b/share/gpodder/ui/qml/Main.qml @@ -34,13 +34,24 @@ Item { episodeListModel.clear(); } - function setEpisodeListModel(model) { - for (var i=0; i %s)', name, old_value, new_value) @@ -236,10 +243,10 @@ class Controller(QObject): if not episode.payment_url: return if not self._flattr.has_token(): - self.root.show_message(_('Sign in to Flattr in the settings.')) + self.showMessage.emit(_('Sign in to Flattr in the settings.')) return - self.root.start_progress(_('Flattring episode...')) + self.startProgress.emit(_('Flattring episode...')) @util.run_in_background def flattr_episode(): @@ -248,9 +255,9 @@ class Controller(QObject): if success: self.updateFlattrButtonText(qepisode) else: - self.root.show_message(message) + self.showMessage.emit(message) finally: - self.root.end_progress() + self.endProgress.emit() @Slot(result=str) def getFlattrLoginURL(self): @@ -263,7 +270,7 @@ class Controller(QObject): @Slot(str) def processFlattrCode(self, url): if not self._flattr.process_retrieved_code(url): - self.root.show_message(_('Could not log in to Flattr.')) + self.showMessage.emit(_('Could not log in to Flattr.')) @Slot(result='QStringList') def getEpisodeListFilterNames(self): @@ -275,12 +282,13 @@ class Controller(QObject): return count = len(selected) - episodes = map(self.root.episode_model.get_object_by_index, selected) + episodes = map(lambda idx: self.root.episode_model._filtered[idx], selected) def delete(): for episode in episodes: if not episode.qarchive: episode.delete_episode() + self.episodeUpdated.emit(episode.id) self.update_subset_stats() self.root.mygpo_client.on_delete(episodes) self.root.mygpo_client.flush() @@ -302,6 +310,7 @@ class Controller(QObject): elif action == 'play': for episode in episodes: self.root.enqueue_episode(episode) + self.episodeUpdated.emit(episode.id) @Slot(str, result=str) def translate(self, x): @@ -346,7 +355,7 @@ class Controller(QObject): @Slot(QObject, int, int) def storePlaybackAction(self, episode, start, end): - self.root.main.episodeUpdated(episode.id) + self.episodeUpdated.emit(episode.id) if end - 5 < start: logger.info('Ignoring too short playback action.') return @@ -389,16 +398,16 @@ class Controller(QObject): @Slot() def myGpoUploadList(self): def upload_proc(self): - self.root.start_progress(_('Uploading subscriptions...')) + self.startProgress.emit(_('Uploading subscriptions...')) try: try: self.root.mygpo_client.set_subscriptions([podcast.url for podcast in self.root.podcast_model.get_podcasts()]) except Exception, e: - self.root.show_message('\n'.join((_('Error on upload:'), unicode(e)))) + self.showMessage.emit('\n'.join((_('Error on upload:'), unicode(e)))) finally: - self.root.end_progress() + self.endProgress.emit() util.run_in_background(lambda: upload_proc(self)) @@ -508,11 +517,11 @@ class Controller(QObject): # Process episode actions received from gpodder.net def merge_proc(self): - self.root.start_progress(_('Merging episode actions...')) + self.startProgress.emit(_('Merging episode actions...')) def find_episode(podcast_url, episode_url, counter): counter['x'] += 1 - self.root.start_progress(_('Merging episode actions (%d)') + self.startProgress.emit(_('Merging episode actions (%d)') % counter['x']) return self.find_episode(podcast_url, episode_url) @@ -521,7 +530,7 @@ class Controller(QObject): self.root.mygpo_client.process_episode_actions(lambda x, y: find_episode(x, y, d)) finally: - self.root.end_progress() + self.endProgress.emit() util.run_in_background(lambda: merge_proc(self)) @@ -542,7 +551,7 @@ class Controller(QObject): # TODO: Try to request the network connection dialog, and wait # for a connection - if a connection is available, return True - self.root.show_message('\n\n'.join((_('No network connection'), + self.showMessage.emit('\n\n'.join((_('No network connection'), _('Please connect to a network, then try again.')))) return False @@ -576,11 +585,11 @@ class Controller(QObject): _('Unsubscribe'), unsubscribe) elif action.action == 'episode-toggle-new': action.target.toggle_new() - self.root.main.episodeUpdated(action.target.id) + self.episodeUpdated.emit(action.target.id) self.update_subset_stats() elif action.action == 'episode-toggle-archive': action.target.toggle_archive() - self.root.main.episodeUpdated(action.target.id) + self.episodeUpdated.emit(action.target.id) self.update_subset_stats() elif action.action == 'episode-delete': self.deleteEpisode(action.target) @@ -672,7 +681,7 @@ class Controller(QObject): @Slot(QObject) def downloadEpisode(self, episode): episode.qdownload(self.root.config, self.update_subset_stats, - self.root.episodeUpdated.emit) + self.episodeUpdated.emit) self.root.mygpo_client.on_download([episode]) self.root.mygpo_client.flush() @@ -680,13 +689,13 @@ class Controller(QObject): def cancelDownload(self, episode): episode.download_task.cancel() episode.download_task.removed_from_list() - self.root.main.episodeUpdated(episode.id) + self.episodeUpdated.emit(episode.id) @Slot(QObject) def deleteEpisode(self, episode): def delete(): episode.delete_episode() - self.root.main.episodeUpdated(episode.id) + self.episodeUpdated.emit(episode.id) self.update_subset_stats() self.root.mygpo_client.on_delete([episode]) self.root.mygpo_client.flush() @@ -741,11 +750,11 @@ class Controller(QObject): urls = filter(not_yet_subscribed, urls) def subscribe_proc(self, urls): - self.root.start_progress(_('Adding podcasts...')) + self.startProgress.emit(_('Adding podcasts...')) try: for idx, url in enumerate(urls): print idx, url - self.root.start_progress(_('Adding podcasts...') + ' (%d/%d)' % (idx, len(urls))) + self.startProgress.emit(_('Adding podcasts...') + ' (%d/%d)' % (idx, len(urls))) try: podcast = self.root.model.load_podcast(url=url, create=True, max_episodes=self.root.config.max_episodes_per_feed) @@ -755,7 +764,7 @@ class Controller(QObject): logger.warn('Cannot add pocast: %s', e) # XXX: Visual feedback in the QML UI finally: - self.root.end_progress() + self.endProgress.emit() util.run_in_background(lambda: subscribe_proc(self, urls)) @@ -859,7 +868,7 @@ class gPodderEpisodeListModel(gPodderListModel): self.sort() def sort(self): - self._root.main.clearEpisodeListModel() + self._root.controller.clearEpisodeListModel.emit() @util.run_in_background def filter_and_load_episodes(): @@ -892,21 +901,28 @@ class gPodderEpisodeListModel(gPodderListModel): 'archive': episode.qarchive, } - processed = map(to_dict, self._filtered[:EPISODE_LIST_LIMIT]) - self._root.setEpisodeListModel.emit(processed) + self._processed = map(to_dict, self._filtered[:EPISODE_LIST_LIMIT]) + self.reset() - # Keep a reference here to avoid crashes - self._processed = processed + self._root.controller.setEpisodeListModel.emit() def get_objects(self): - return self._filtered + return self._processed def get_object(self, index): - return self._filtered[index.row()] + return self._processed[index.row()] + + @Slot(int, result='QVariant') + def get_object_by_index(self, index): + return self._processed[int(index)] - @Slot(int, result=QObject) + @Slot(int, result='QVariant') def get_object_by_index(self, index): - return self._filtered[int(index)] + return self._processed[int(index)] + + @Slot(result=int) + def getCount(self): + return len(self._processed) @Slot(result=int) def getFilter(self): @@ -957,8 +973,6 @@ class qtPodder(QObject): self.app = QApplication(args) signal.signal(signal.SIGINT, signal.SIG_DFL) self.quit.connect(self.on_quit) - self.episodeUpdated.connect(self.on_episode_updated) - self.setEpisodeListModel.connect(self.on_set_episode_list_model) self.core = gpodder_core self.config = self.core.config @@ -1026,10 +1040,6 @@ class qtPodder(QObject): self.view.resize(size) self.view.show() - self.do_start_progress.connect(self.on_start_progress) - self.do_end_progress.connect(self.on_end_progress) - self.do_show_message.connect(self.on_show_message) - podcasts = self.load_podcasts() self.resumable_episodes = None @@ -1038,15 +1048,15 @@ class qtPodder(QObject): def find_partial_downloads(self, podcasts): def start_progress_callback(count): - self.start_progress(_('Loading incomplete downloads')) + self.controller.startProgress.emit(_('Loading incomplete downloads')) def progress_callback(title, progress): - self.start_progress('%s (%d%%)' % ( + self.controller.startProgress.emit('%s (%d%%)' % ( _('Loading incomplete downloads'), progress*100)) def finish_progress_callback(resumable_episodes): - self.end_progress() + self.controller.endProgress.emit() self.resumable_episodes = resumable_episodes self.do_offer_download_resume.emit() @@ -1103,11 +1113,6 @@ class qtPodder(QObject): # Remove episode from play queue (if it's in there) self.main.removeQueuedEpisode(episode) - # If the episode that has been deleted is currently - # being played back (or paused), stop playback now. - if self.main.currentEpisode == episode: - self.main.togglePlayback(None) - def enqueue_episode(self, episode): self.main.enqueueEpisode(episode) @@ -1124,25 +1129,6 @@ class qtPodder(QObject): self.core.shutdown() self.app.quit() - episodeUpdated = Signal(int) - - def on_episode_updated(self, episode_id): - self.main.episodeUpdated(episode_id) - - setEpisodeListModel = Signal(object) - - def on_set_episode_list_model(self, prepared): - self.main.setEpisodeListModel(prepared) - - do_show_message = Signal(unicode) - - @Slot(unicode) - def on_show_message(self, message): - self.main.showMessage(message) - - def show_message(self, message): - self.do_show_message.emit(message) - def show_input_dialog(self, message, value='', accept=_('OK'), reject=_('Cancel'), is_text=True): self.main.showInputDialog(message, value, accept, reject, is_text) @@ -1150,24 +1136,6 @@ class qtPodder(QObject): def open_context_menu(self, items): self.main.openContextMenu(items) - do_start_progress = Signal(str) - - @Slot(str) - def on_start_progress(self, text): - self.main.startProgress(text) - - def start_progress(self, text=_('Please wait...')): - self.do_start_progress.emit(text) - - do_end_progress = Signal() - - @Slot() - def on_end_progress(self): - self.main.endProgress() - - def end_progress(self): - self.do_end_progress.emit() - def resort_podcast_list(self): self.podcast_model.sort() @@ -1180,11 +1148,6 @@ class qtPodder(QObject): # Remove queued episodes for this specific podcast self.main.removeQueuedEpisodesForPodcast(podcast) - if self.main.currentEpisode is not None: - # If the currently-playing episode is in the podcast - # that is to be deleted, stop playback immediately. - if self.main.currentEpisode.qpodcast == podcast: - self.main.togglePlayback(None) self.podcast_model.remove_object(podcast) self.mygpo_client.on_unsubscribe([podcast.url]) self.mygpo_client.flush() -- 2.11.4.GIT