Consolidating the Presenter Window code for making changes easier
authorEd Page <eopage@byu.net>
Tue, 18 May 2010 03:03:01 +0000 (22:03 -0500)
committerEd Page <eopage@byu.net>
Tue, 18 May 2010 03:05:32 +0000 (22:05 -0500)
src/windows/_base.py
src/windows/conferences.py
src/windows/magazines.py
src/windows/scriptures.py

index 25007da..721aeec 100644 (file)
@@ -14,6 +14,7 @@ import util.go_utils as go_utils
 import stream_index
 import banners
 import playcontrol
+import presenter
 
 
 _moduleLogger = logging.getLogger(__name__)
@@ -292,3 +293,202 @@ class ListWindow(BasicWindow):
                path = (rowIndex, )
                self._treeView.scroll_to_cell(path)
                self._treeView.get_selection().select_path(path)
+
+
+class PresenterWindow(BasicWindow):
+
+       def __init__(self, app, player, store, node):
+               BasicWindow.__init__(self, app, player, store)
+               self._node = node
+               self._playerNode = self._player.node
+               self._nextSearch = None
+               self._updateSeek = None
+
+               self.connect_auto(self._player, "state-change", self._on_player_state_change)
+               self.connect_auto(self._player, "title-change", self._on_player_title_change)
+               self.connect_auto(self._player, "error", self._on_player_error)
+
+               self._loadingBanner = banners.GenericBanner()
+
+               self._presenter = presenter.StreamPresenter(self._store)
+               self._presenter.set_context(
+                       self._get_background(),
+                       self._node.title,
+                       self._node.subtitle,
+               )
+               self._presenterNavigation = presenter.NavigationBox()
+               self._presenterNavigation.toplevel.add(self._presenter.toplevel)
+               self._presenterNavigation.connect("action", self._on_nav_action)
+               self._presenterNavigation.connect("navigating", self._on_navigating)
+
+               self._seekbar = hildonize.create_seekbar()
+               self._seekbar.connect("change-value", self._on_user_seek)
+
+               self._layout.pack_start(self._loadingBanner.toplevel, False, False)
+               self._layout.pack_start(self._presenterNavigation.toplevel, True, True)
+               self._layout.pack_start(self._seekbar, False, False)
+
+               self._window.set_title(self._node.title)
+
+       def _get_background(self):
+               raise NotImplementedError()
+
+       def show(self):
+               BasicWindow.show(self)
+               self._window.show_all()
+               self._errorBanner.toplevel.hide()
+               self._loadingBanner.toplevel.hide()
+               self._set_context(self._player.state)
+               self._seekbar.hide()
+
+       def jump_to(self, node):
+               assert self._node is node
+
+       @property
+       def _active(self):
+               return self._playerNode is self._node
+
+       def _show_loading(self):
+               animationPath = self._store.STORE_LOOKUP["loading"]
+               animation = self._store.get_pixbuf_animation_from_store(animationPath)
+               self._loadingBanner.show(animation, "Loading...")
+
+       def _hide_loading(self):
+               self._loadingBanner.hide()
+
+       def _set_context(self, state):
+               if state == self._player.STATE_PLAY:
+                       if self._active:
+                               self._presenter.set_state(self._store.STORE_LOOKUP["pause"])
+                       else:
+                               self._presenter.set_state(self._store.STORE_LOOKUP["play"])
+               elif state == self._player.STATE_PAUSE:
+                       self._presenter.set_state(self._store.STORE_LOOKUP["play"])
+               elif state == self._player.STATE_STOP:
+                       self._presenter.set_state(self._store.STORE_LOOKUP["play"])
+               else:
+                       _moduleLogger.info("Unhandled player state %s" % state)
+
+       @misc_utils.log_exception(_moduleLogger)
+       def _on_user_seek(self, widget, scroll, value):
+               self._player.seek(value / 100.0)
+
+       @misc_utils.log_exception(_moduleLogger)
+       def _on_player_update_seek(self):
+               if self._isDestroyed:
+                       return False
+               self._seekbar.set_value(self._player.percent_elapsed * 100)
+               return True
+
+       @misc_utils.log_exception(_moduleLogger)
+       def _on_player_state_change(self, player, newState):
+               if self._active and self._player.state == self._player.STATE_PLAY:
+                       self._seekbar.show()
+                       assert self._updateSeek is None
+                       self._updateSeek = go_utils.Timeout(self._on_player_update_seek, once=False)
+                       self._updateSeek.start(seconds=1)
+               else:
+                       self._seekbar.hide()
+                       if self._updateSeek is not None:
+                               self._updateSeek.cancel()
+                               self._updateSeek = None
+
+               if not self._presenterNavigation.is_active():
+                       self._set_context(newState)
+
+       @misc_utils.log_exception(_moduleLogger)
+       def _on_player_title_change(self, player, node):
+               if not self._active or node in [None, self._node]:
+                       self._playerNode = player.node
+                       return
+               self._playerNode = player.node
+               self.emit("jump-to", node)
+               self._window.destroy()
+
+       @misc_utils.log_exception(_moduleLogger)
+       def _on_player_error(self, player, err, debug):
+               _moduleLogger.error("%r - %r" % (err, debug))
+
+       @misc_utils.log_exception(_moduleLogger)
+       def _on_navigating(self, widget, navState):
+               if navState == "clicking":
+                       if self._player.state == self._player.STATE_PLAY:
+                               if self._active:
+                                       imageName = "pause_pressed"
+                               else:
+                                       imageName = "play_pressed"
+                       elif self._player.state == self._player.STATE_PAUSE:
+                               imageName = "play_pressed"
+                       elif self._player.state == self._player.STATE_STOP:
+                               imageName = "play_pressed"
+                       else:
+                               _moduleLogger.info("Unhandled player state %s" % self._player.state)
+               elif navState == "down":
+                       imageName = "home"
+               elif navState == "up":
+                       if self._player.state == self._player.STATE_PLAY:
+                               if self._active:
+                                       imageName = "pause"
+                               else:
+                                       imageName = "play"
+                       elif self._player.state == self._player.STATE_PAUSE:
+                               imageName = "play"
+                       elif self._player.state == self._player.STATE_STOP:
+                               imageName = "play"
+                       else:
+                               _moduleLogger.info("Unhandled player state %s" % self._player.state)
+               elif navState == "left":
+                       imageName = "next"
+               elif navState == "right":
+                       imageName = "prev"
+
+               self._presenter.set_state(self._store.STORE_LOOKUP[imageName])
+
+       @misc_utils.log_exception(_moduleLogger)
+       def _on_nav_action(self, widget, navState):
+               self._set_context(self._player.state)
+
+               if navState == "clicking":
+                       if self._player.state == self._player.STATE_PLAY:
+                               if self._active:
+                                       self._player.pause()
+                               else:
+                                       self._player.set_piece_by_node(self._node)
+                                       self._player.play()
+                       elif self._player.state == self._player.STATE_PAUSE:
+                               self._player.play()
+                       elif self._player.state == self._player.STATE_STOP:
+                               self._player.set_piece_by_node(self._node)
+                               self._player.play()
+                       else:
+                               _moduleLogger.info("Unhandled player state %s" % self._player.state)
+               elif navState == "down":
+                       self.emit("home")
+                       self._window.destroy()
+               elif navState == "up":
+                       pass
+               elif navState == "left":
+                       if self._active:
+                               self._player.next()
+                       else:
+                               assert self._nextSearch is None
+                               self._nextSearch = stream_index.AsyncWalker(stream_index.get_next)
+                               self._nextSearch.start(self._node, self._on_next_node, self._on_node_search_error)
+               elif navState == "right":
+                       if self._active:
+                               self._player.back()
+                       else:
+                               assert self._nextSearch is None
+                               self._nextSearch = stream_index.AsyncWalker(stream_index.get_previous)
+                               self._nextSearch.start(self._node, self._on_next_node, self._on_node_search_error)
+
+       @misc_utils.log_exception(_moduleLogger)
+       def _on_next_node(self, node):
+               self._nextSearch = None
+               self.emit("jump-to", node)
+               self._window.destroy()
+
+       @misc_utils.log_exception(_moduleLogger)
+       def _on_node_search_error(self, e):
+               self._nextSearch = None
+               self._errorBanner.push_message(str(e))
index 9370d4a..7f11b95 100644 (file)
@@ -7,7 +7,6 @@ import hildonize
 import util.go_utils as go_utils
 import util.misc as misc_utils
 import banners
-import presenter
 import stream_index
 
 import windows
@@ -201,200 +200,13 @@ class ConferenceTalksWindow(windows._base.ListWindow):
 gobject.type_register(ConferenceTalksWindow)
 
 
-class ConferenceTalkWindow(windows._base.BasicWindow):
+class ConferenceTalkWindow(windows._base.PresenterWindow):
 
        def __init__(self, app, player, store, node):
-               windows._base.BasicWindow.__init__(self, app, player, store)
-               self._node = node
-               self._playerNode = self._player.node
-               self._nextSearch = None
-               self._updateSeek = None
-
-               self.connect_auto(self._player, "state-change", self._on_player_state_change)
-               self.connect_auto(self._player, "title-change", self._on_player_title_change)
-               self.connect_auto(self._player, "error", self._on_player_error)
-
-               self._loadingBanner = banners.GenericBanner()
-
-               self._presenter = presenter.StreamPresenter(self._store)
-               self._presenter.set_context(
-                       self._store.STORE_LOOKUP["conference_background"],
-                       self._node.title,
-                       self._node.subtitle,
-               )
-               self._presenterNavigation = presenter.NavigationBox()
-               self._presenterNavigation.toplevel.add(self._presenter.toplevel)
-               self._presenterNavigation.connect("action", self._on_nav_action)
-               self._presenterNavigation.connect("navigating", self._on_navigating)
-
-               self._seekbar = hildonize.create_seekbar()
-               self._seekbar.connect("change-value", self._on_user_seek)
-
-               self._layout.pack_start(self._loadingBanner.toplevel, False, False)
-               self._layout.pack_start(self._presenterNavigation.toplevel, True, True)
-               self._layout.pack_start(self._seekbar, False, False)
-
-               self._window.set_title(self._node.title)
-
-       def show(self):
-               windows._base.BasicWindow.show(self)
-               self._window.show_all()
-               self._errorBanner.toplevel.hide()
-               self._loadingBanner.toplevel.hide()
-               self._set_context(self._player.state)
-               self._seekbar.hide()
-
-       def jump_to(self, node):
-               assert self._node is node
-
-       @property
-       def _active(self):
-               return self._playerNode is self._node
-
-       def _show_loading(self):
-               animationPath = self._store.STORE_LOOKUP["loading"]
-               animation = self._store.get_pixbuf_animation_from_store(animationPath)
-               self._loadingBanner.show(animation, "Loading...")
-
-       def _hide_loading(self):
-               self._loadingBanner.hide()
-
-       def _set_context(self, state):
-               if state == self._player.STATE_PLAY:
-                       if self._active:
-                               self._presenter.set_state(self._store.STORE_LOOKUP["pause"])
-                       else:
-                               self._presenter.set_state(self._store.STORE_LOOKUP["play"])
-               elif state == self._player.STATE_PAUSE:
-                       self._presenter.set_state(self._store.STORE_LOOKUP["play"])
-               elif state == self._player.STATE_STOP:
-                       self._presenter.set_state(self._store.STORE_LOOKUP["play"])
-               else:
-                       _moduleLogger.info("Unhandled player state %s" % state)
-
-       @misc_utils.log_exception(_moduleLogger)
-       def _on_user_seek(self, widget, scroll, value):
-               self._player.seek(value / 100.0)
-
-       @misc_utils.log_exception(_moduleLogger)
-       def _on_player_update_seek(self):
-               if self._isDestroyed:
-                       return False
-               self._seekbar.set_value(self._player.percent_elapsed * 100)
-               return True
-
-       @misc_utils.log_exception(_moduleLogger)
-       def _on_player_state_change(self, player, newState):
-               if self._active and self._player.state == self._player.STATE_PLAY:
-                       self._seekbar.show()
-                       assert self._updateSeek is None
-                       self._updateSeek = go_utils.Timeout(self._on_player_update_seek, once=False)
-                       self._updateSeek.start(seconds=1)
-               else:
-                       self._seekbar.hide()
-                       if self._updateSeek is not None:
-                               self._updateSeek.cancel()
-                               self._updateSeek = None
-
-               if not self._presenterNavigation.is_active():
-                       self._set_context(newState)
+               windows._base.PresenterWindow.__init__(self, app, player, store, node)
 
-       @misc_utils.log_exception(_moduleLogger)
-       def _on_player_title_change(self, player, node):
-               if not self._active or node in [None, self._node]:
-                       self._playerNode = player.node
-                       return
-               self._playerNode = player.node
-               self.emit("jump-to", node)
-               self._window.destroy()
-
-       @misc_utils.log_exception(_moduleLogger)
-       def _on_player_error(self, player, err, debug):
-               _moduleLogger.error("%r - %r" % (err, debug))
-
-       @misc_utils.log_exception(_moduleLogger)
-       def _on_navigating(self, widget, navState):
-               if navState == "clicking":
-                       if self._player.state == self._player.STATE_PLAY:
-                               if self._active:
-                                       imageName = "pause_pressed"
-                               else:
-                                       imageName = "play_pressed"
-                       elif self._player.state == self._player.STATE_PAUSE:
-                               imageName = "play_pressed"
-                       elif self._player.state == self._player.STATE_STOP:
-                               imageName = "play_pressed"
-                       else:
-                               _moduleLogger.info("Unhandled player state %s" % self._player.state)
-               elif navState == "down":
-                       imageName = "home"
-               elif navState == "up":
-                       if self._player.state == self._player.STATE_PLAY:
-                               if self._active:
-                                       imageName = "pause"
-                               else:
-                                       imageName = "play"
-                       elif self._player.state == self._player.STATE_PAUSE:
-                               imageName = "play"
-                       elif self._player.state == self._player.STATE_STOP:
-                               imageName = "play"
-                       else:
-                               _moduleLogger.info("Unhandled player state %s" % self._player.state)
-               elif navState == "left":
-                       imageName = "next"
-               elif navState == "right":
-                       imageName = "prev"
-
-               self._presenter.set_state(self._store.STORE_LOOKUP[imageName])
-
-       @misc_utils.log_exception(_moduleLogger)
-       def _on_nav_action(self, widget, navState):
-               self._set_context(self._player.state)
-
-               if navState == "clicking":
-                       if self._player.state == self._player.STATE_PLAY:
-                               if self._active:
-                                       self._player.pause()
-                               else:
-                                       self._player.set_piece_by_node(self._node)
-                                       self._player.play()
-                       elif self._player.state == self._player.STATE_PAUSE:
-                               self._player.play()
-                       elif self._player.state == self._player.STATE_STOP:
-                               self._player.set_piece_by_node(self._node)
-                               self._player.play()
-                       else:
-                               _moduleLogger.info("Unhandled player state %s" % self._player.state)
-               elif navState == "down":
-                       self.emit("home")
-                       self._window.destroy()
-               elif navState == "up":
-                       pass
-               elif navState == "left":
-                       if self._active:
-                               self._player.next()
-                       else:
-                               assert self._nextSearch is None
-                               self._nextSearch = stream_index.AsyncWalker(stream_index.get_next)
-                               self._nextSearch.start(self._node, self._on_next_node, self._on_node_search_error)
-               elif navState == "right":
-                       if self._active:
-                               self._player.back()
-                       else:
-                               assert self._nextSearch is None
-                               self._nextSearch = stream_index.AsyncWalker(stream_index.get_previous)
-                               self._nextSearch.start(self._node, self._on_next_node, self._on_node_search_error)
-
-       @misc_utils.log_exception(_moduleLogger)
-       def _on_next_node(self, node):
-               self._nextSearch = None
-               self.emit("jump-to", node)
-               self._window.destroy()
-
-       @misc_utils.log_exception(_moduleLogger)
-       def _on_node_search_error(self, e):
-               self._nextSearch = None
-               self._errorBanner.push_message(str(e))
+       def _get_background(self):
+               return self._store.STORE_LOOKUP["conference_background"]
 
 
 gobject.type_register(ConferenceTalkWindow)
index 68117a1..bff0853 100644 (file)
@@ -255,200 +255,13 @@ class MagazineArticlesWindow(windows._base.ListWindow):
 gobject.type_register(MagazineArticlesWindow)
 
 
-class MagazineArticleWindow(windows._base.BasicWindow):
+class MagazineArticleWindow(windows._base.PresenterWindow):
 
        def __init__(self, app, player, store, node):
-               windows._base.BasicWindow.__init__(self, app, player, store)
-               self._node = node
-               self._playerNode = self._player.node
-               self._nextSearch = None
-               self._updateSeek = None
-
-               self.connect_auto(self._player, "state-change", self._on_player_state_change)
-               self.connect_auto(self._player, "title-change", self._on_player_title_change)
-               self.connect_auto(self._player, "error", self._on_player_error)
-
-               self._loadingBanner = banners.GenericBanner()
-
-               self._presenter = presenter.StreamPresenter(self._store)
-               self._presenter.set_context(
-                       self._store.STORE_LOOKUP["magazine_background"],
-                       self._node.title,
-                       self._node.subtitle,
-               )
-               self._presenterNavigation = presenter.NavigationBox()
-               self._presenterNavigation.toplevel.add(self._presenter.toplevel)
-               self._presenterNavigation.connect("action", self._on_nav_action)
-               self._presenterNavigation.connect("navigating", self._on_navigating)
-
-               self._seekbar = hildonize.create_seekbar()
-               self._seekbar.connect("change-value", self._on_user_seek)
-
-               self._layout.pack_start(self._loadingBanner.toplevel, False, False)
-               self._layout.pack_start(self._presenterNavigation.toplevel, True, True)
-               self._layout.pack_start(self._seekbar, False, False)
-
-               self._window.set_title(self._node.title)
-
-       def show(self):
-               windows._base.BasicWindow.show(self)
-               self._window.show_all()
-               self._errorBanner.toplevel.hide()
-               self._loadingBanner.toplevel.hide()
-               self._set_context(self._player.state)
-               self._seekbar.hide()
-
-       def jump_to(self, node):
-               assert self._node is node
-
-       @property
-       def _active(self):
-               return self._playerNode is self._node
-
-       def _show_loading(self):
-               animationPath = self._store.STORE_LOOKUP["loading"]
-               animation = self._store.get_pixbuf_animation_from_store(animationPath)
-               self._loadingBanner.show(animation, "Loading...")
-
-       def _hide_loading(self):
-               self._loadingBanner.hide()
-
-       def _set_context(self, state):
-               if state == self._player.STATE_PLAY:
-                       if self._active:
-                               self._presenter.set_state(self._store.STORE_LOOKUP["pause"])
-                       else:
-                               self._presenter.set_state(self._store.STORE_LOOKUP["play"])
-               elif state == self._player.STATE_PAUSE:
-                       self._presenter.set_state(self._store.STORE_LOOKUP["play"])
-               elif state == self._player.STATE_STOP:
-                       self._presenter.set_state(self._store.STORE_LOOKUP["play"])
-               else:
-                       _moduleLogger.info("Unhandled player state %s" % state)
-
-       @misc_utils.log_exception(_moduleLogger)
-       def _on_user_seek(self, widget, scroll, value):
-               self._player.seek(value / 100.0)
-
-       @misc_utils.log_exception(_moduleLogger)
-       def _on_player_update_seek(self):
-               if self._isDestroyed:
-                       return False
-               self._seekbar.set_value(self._player.percent_elapsed * 100)
-               return True
-
-       @misc_utils.log_exception(_moduleLogger)
-       def _on_player_state_change(self, player, newState):
-               if self._active and self._player.state == self._player.STATE_PLAY:
-                       self._seekbar.show()
-                       assert self._updateSeek is None
-                       self._updateSeek = go_utils.Timeout(self._on_player_update_seek, once=False)
-                       self._updateSeek.start(seconds=1)
-               else:
-                       self._seekbar.hide()
-                       if self._updateSeek is not None:
-                               self._updateSeek.cancel()
-                               self._updateSeek = None
-
-               if not self._presenterNavigation.is_active():
-                       self._set_context(newState)
-
-       @misc_utils.log_exception(_moduleLogger)
-       def _on_player_title_change(self, player, node):
-               if not self._active or node in [None, self._node]:
-                       self._playerNode = player.node
-                       return
-               self._playerNode = player.node
-               self.emit("jump-to", node)
-               self._window.destroy()
-
-       @misc_utils.log_exception(_moduleLogger)
-       def _on_player_error(self, player, err, debug):
-               _moduleLogger.error("%r - %r" % (err, debug))
+               windows._base.PresenterWindow.__init__(self, app, player, store, node)
 
-       @misc_utils.log_exception(_moduleLogger)
-       def _on_navigating(self, widget, navState):
-               if navState == "clicking":
-                       if self._player.state == self._player.STATE_PLAY:
-                               if self._active:
-                                       imageName = "pause_pressed"
-                               else:
-                                       imageName = "play_pressed"
-                       elif self._player.state == self._player.STATE_PAUSE:
-                               imageName = "play_pressed"
-                       elif self._player.state == self._player.STATE_STOP:
-                               imageName = "play_pressed"
-                       else:
-                               _moduleLogger.info("Unhandled player state %s" % self._player.state)
-               elif navState == "down":
-                       imageName = "home"
-               elif navState == "up":
-                       if self._player.state == self._player.STATE_PLAY:
-                               if self._active:
-                                       imageName = "pause"
-                               else:
-                                       imageName = "play"
-                       elif self._player.state == self._player.STATE_PAUSE:
-                               imageName = "play"
-                       elif self._player.state == self._player.STATE_STOP:
-                               imageName = "play"
-                       else:
-                               _moduleLogger.info("Unhandled player state %s" % self._player.state)
-               elif navState == "left":
-                       imageName = "next"
-               elif navState == "right":
-                       imageName = "prev"
-
-               self._presenter.set_state(self._store.STORE_LOOKUP[imageName])
-
-       @misc_utils.log_exception(_moduleLogger)
-       def _on_nav_action(self, widget, navState):
-               self._set_context(self._player.state)
-
-               if navState == "clicking":
-                       if self._player.state == self._player.STATE_PLAY:
-                               if self._active:
-                                       self._player.pause()
-                               else:
-                                       self._player.set_piece_by_node(self._node)
-                                       self._player.play()
-                       elif self._player.state == self._player.STATE_PAUSE:
-                               self._player.play()
-                       elif self._player.state == self._player.STATE_STOP:
-                               self._player.set_piece_by_node(self._node)
-                               self._player.play()
-                       else:
-                               _moduleLogger.info("Unhandled player state %s" % self._player.state)
-               elif navState == "down":
-                       self.emit("home")
-                       self._window.destroy()
-               elif navState == "up":
-                       pass
-               elif navState == "left":
-                       if self._active:
-                               self._player.next()
-                       else:
-                               assert self._nextSearch is None
-                               self._nextSearch = stream_index.AsyncWalker(stream_index.get_next)
-                               self._nextSearch.start(self._node, self._on_next_node, self._on_node_search_error)
-               elif navState == "right":
-                       if self._active:
-                               self._player.back()
-                       else:
-                               assert self._nextSearch is None
-                               self._nextSearch = stream_index.AsyncWalker(stream_index.get_previous)
-                               self._nextSearch.start(self._node, self._on_next_node, self._on_node_search_error)
-
-       @misc_utils.log_exception(_moduleLogger)
-       def _on_next_node(self, node):
-               self._nextSearch = None
-               self.emit("jump-to", node)
-               self._window.destroy()
-
-       @misc_utils.log_exception(_moduleLogger)
-       def _on_node_search_error(self, e):
-               self._nextSearch = None
-               self._errorBanner.push_message(str(e))
+       def _get_background(self):
+               return self._store.STORE_LOOKUP["magazine_background"]
 
 
 gobject.type_register(MagazineArticleWindow)
index 013f3f6..7c26aed 100644 (file)
@@ -193,200 +193,13 @@ class ScriptureChaptersWindow(windows._base.ListWindow):
 gobject.type_register(ScriptureChaptersWindow)
 
 
-class ScriptureChapterWindow(windows._base.BasicWindow):
+class ScriptureChapterWindow(windows._base.PresenterWindow):
 
        def __init__(self, app, player, store, node):
-               windows._base.BasicWindow.__init__(self, app, player, store)
-               self._node = node
-               self._playerNode = self._player.node
-               self._nextSearch = None
-               self._updateSeek = None
-
-               self.connect_auto(self._player, "state-change", self._on_player_state_change)
-               self.connect_auto(self._player, "title-change", self._on_player_title_change)
-               self.connect_auto(self._player, "error", self._on_player_error)
-
-               self._loadingBanner = banners.GenericBanner()
-
-               self._presenter = presenter.StreamPresenter(self._store)
-               self._presenter.set_context(
-                       self._store.STORE_LOOKUP["scripture_background"],
-                       self._node.title,
-                       self._node.subtitle,
-               )
-               self._presenterNavigation = presenter.NavigationBox()
-               self._presenterNavigation.toplevel.add(self._presenter.toplevel)
-               self._presenterNavigation.connect("action", self._on_nav_action)
-               self._presenterNavigation.connect("navigating", self._on_navigating)
-
-               self._seekbar = hildonize.create_seekbar()
-               self._seekbar.connect("change-value", self._on_user_seek)
-
-               self._layout.pack_start(self._loadingBanner.toplevel, False, False)
-               self._layout.pack_start(self._presenterNavigation.toplevel, True, True)
-               self._layout.pack_start(self._seekbar, False, False)
-
-               self._window.set_title(self._node.title)
-
-       def show(self):
-               windows._base.BasicWindow.show(self)
-               self._window.show_all()
-               self._errorBanner.toplevel.hide()
-               self._loadingBanner.toplevel.hide()
-               self._set_context(self._player.state)
-               self._seekbar.hide()
-
-       def jump_to(self, node):
-               assert self._node is node
-
-       @property
-       def _active(self):
-               return self._playerNode is self._node
-
-       def _show_loading(self):
-               animationPath = self._store.STORE_LOOKUP["loading"]
-               animation = self._store.get_pixbuf_animation_from_store(animationPath)
-               self._loadingBanner.show(animation, "Loading...")
-
-       def _hide_loading(self):
-               self._loadingBanner.hide()
-
-       def _set_context(self, state):
-               if state == self._player.STATE_PLAY:
-                       if self._active:
-                               self._presenter.set_state(self._store.STORE_LOOKUP["pause"])
-                       else:
-                               self._presenter.set_state(self._store.STORE_LOOKUP["play"])
-               elif state == self._player.STATE_PAUSE:
-                       self._presenter.set_state(self._store.STORE_LOOKUP["play"])
-               elif state == self._player.STATE_STOP:
-                       self._presenter.set_state(self._store.STORE_LOOKUP["play"])
-               else:
-                       _moduleLogger.info("Unhandled player state %s" % state)
-
-       @misc_utils.log_exception(_moduleLogger)
-       def _on_user_seek(self, widget, scroll, value):
-               self._player.seek(value / 100.0)
-
-       @misc_utils.log_exception(_moduleLogger)
-       def _on_player_update_seek(self):
-               if self._isDestroyed:
-                       return False
-               self._seekbar.set_value(self._player.percent_elapsed * 100)
-               return True
-
-       @misc_utils.log_exception(_moduleLogger)
-       def _on_player_state_change(self, player, newState):
-               if self._active and self._player.state == self._player.STATE_PLAY:
-                       self._seekbar.show()
-                       assert self._updateSeek is None
-                       self._updateSeek = go_utils.Timeout(self._on_player_update_seek, once=False)
-                       self._updateSeek.start(seconds=1)
-               else:
-                       self._seekbar.hide()
-                       if self._updateSeek is not None:
-                               self._updateSeek.cancel()
-                               self._updateSeek = None
-
-               if not self._presenterNavigation.is_active():
-                       self._set_context(newState)
+               windows._base.PresenterWindow.__init__(self, app, player, store, node)
 
-       @misc_utils.log_exception(_moduleLogger)
-       def _on_player_title_change(self, player, node):
-               if not self._active or node in [None, self._node]:
-                       self._playerNode = player.node
-                       return
-               self._playerNode = player.node
-               self.emit("jump-to", node)
-               self._window.destroy()
-
-       @misc_utils.log_exception(_moduleLogger)
-       def _on_player_error(self, player, err, debug):
-               _moduleLogger.error("%r - %r" % (err, debug))
-
-       @misc_utils.log_exception(_moduleLogger)
-       def _on_navigating(self, widget, navState):
-               if navState == "clicking":
-                       if self._player.state == self._player.STATE_PLAY:
-                               if self._active:
-                                       imageName = "pause_pressed"
-                               else:
-                                       imageName = "play_pressed"
-                       elif self._player.state == self._player.STATE_PAUSE:
-                               imageName = "play_pressed"
-                       elif self._player.state == self._player.STATE_STOP:
-                               imageName = "play_pressed"
-                       else:
-                               _moduleLogger.info("Unhandled player state %s" % self._player.state)
-               elif navState == "down":
-                       imageName = "home"
-               elif navState == "up":
-                       if self._player.state == self._player.STATE_PLAY:
-                               if self._active:
-                                       imageName = "pause"
-                               else:
-                                       imageName = "play"
-                       elif self._player.state == self._player.STATE_PAUSE:
-                               imageName = "play"
-                       elif self._player.state == self._player.STATE_STOP:
-                               imageName = "play"
-                       else:
-                               _moduleLogger.info("Unhandled player state %s" % self._player.state)
-               elif navState == "left":
-                       imageName = "next"
-               elif navState == "right":
-                       imageName = "prev"
-
-               self._presenter.set_state(self._store.STORE_LOOKUP[imageName])
-
-       @misc_utils.log_exception(_moduleLogger)
-       def _on_nav_action(self, widget, navState):
-               self._set_context(self._player.state)
-
-               if navState == "clicking":
-                       if self._player.state == self._player.STATE_PLAY:
-                               if self._active:
-                                       self._player.pause()
-                               else:
-                                       self._player.set_piece_by_node(self._node)
-                                       self._player.play()
-                       elif self._player.state == self._player.STATE_PAUSE:
-                               self._player.play()
-                       elif self._player.state == self._player.STATE_STOP:
-                               self._player.set_piece_by_node(self._node)
-                               self._player.play()
-                       else:
-                               _moduleLogger.info("Unhandled player state %s" % self._player.state)
-               elif navState == "down":
-                       self.emit("home")
-                       self._window.destroy()
-               elif navState == "up":
-                       pass
-               elif navState == "left":
-                       if self._active:
-                               self._player.next()
-                       else:
-                               assert self._nextSearch is None
-                               self._nextSearch = stream_index.AsyncWalker(stream_index.get_next)
-                               self._nextSearch.start(self._node, self._on_next_node, self._on_node_search_error)
-               elif navState == "right":
-                       if self._active:
-                               self._player.back()
-                       else:
-                               assert self._nextSearch is None
-                               self._nextSearch = stream_index.AsyncWalker(stream_index.get_previous)
-                               self._nextSearch.start(self._node, self._on_next_node, self._on_node_search_error)
-
-       @misc_utils.log_exception(_moduleLogger)
-       def _on_next_node(self, node):
-               self._nextSearch = None
-               self.emit("jump-to", node)
-               self._window.destroy()
-
-       @misc_utils.log_exception(_moduleLogger)
-       def _on_node_search_error(self, e):
-               self._nextSearch = None
-               self._errorBanner.push_message(str(e))
+       def _get_background(self):
+               return self._store.STORE_LOOKUP["scripture_background"]
 
 
 gobject.type_register(ScriptureChapterWindow)