import ConfigParser
import logging
+import webbrowser
import gobject
import gtk
import stream_index
import banners
-import playcontrol
import presenter
gobject.TYPE_NONE,
(gobject.TYPE_BOOLEAN, ),
),
+ 'rotate' : (
+ gobject.SIGNAL_RUN_LAST,
+ gobject.TYPE_NONE,
+ (gobject.TYPE_PYOBJECT, ),
+ ),
}
def __init__(self, app, player, store):
gobject.GObject.__init__(self)
self._isDestroyed = False
+ self._isPortrait = hildonize.IS_FREMANTLE_SUPPORTED
self._app = app
self._player = player
self._errorBanner = banners.StackingBanner()
self._layout = gtk.VBox()
- self._layout.pack_start(self._errorBanner.toplevel, False, True)
self._window = gtk.Window()
- go_utils.AutoSignal.__init__(self, self.window)
self._window.add(self._layout)
self._window = hildonize.hildonize_window(self._app, self._window)
+ go_utils.AutoSignal.__init__(self, self.window)
self._window.set_icon(self._store.get_pixbuf_from_store(self._store.STORE_LOOKUP["icon"]))
self._window.connect("key-press-event", self._on_key_press)
self._window.connect("window-state-event", self._on_window_state_change)
self._window.connect("destroy", self._on_destroy)
+ if hildonize.GTK_MENU_USED:
+ aboutMenuItem = gtk.MenuItem("About")
+ aboutMenuItem.connect("activate", self._on_about)
+
+ helpMenu = gtk.Menu()
+ helpMenu.append(aboutMenuItem)
+
+ helpMenuItem = gtk.MenuItem("Help")
+ helpMenuItem.set_submenu(helpMenu)
+
+ menuBar = gtk.MenuBar()
+ menuBar.append(helpMenuItem)
+
+ self._layout.pack_start(menuBar, False, False)
+ menuBar = hildonize.hildonize_menu(
+ self._window,
+ menuBar,
+ )
+ else:
+ aboutMenuItem = gtk.Button("About")
+ aboutMenuItem.connect("clicked", self._on_about)
+
+ appMenu = hildonize.hildon.AppMenu()
+ appMenu.append(aboutMenuItem)
+ appMenu.show_all()
+ self._window.set_app_menu(appMenu)
+
+ self._layout.pack_start(self._errorBanner.toplevel, False, True)
+
@property
def window(self):
return self._window
def load_settings(self, config, sectionName):
try:
- self._windowInFullscreen = config.getboolean(sectionName, "fullscreen")
+ windowInFullscreen = config.getboolean(sectionName, "fullscreen")
except ConfigParser.NoSectionError, e:
_moduleLogger.info(
"Settings file %s is missing section %s" % (
e.section,
)
)
+ windowInFullscreen = self._windowInFullscreen
- if self._windowInFullscreen:
+ if windowInFullscreen:
self._window.fullscreen()
else:
self._window.unfullscreen()
def jump_to(self, node):
raise NotImplementedError("On %s" % self)
+ def set_orientation(self, orientation):
+ oldIsPortrait = self._isPortrait
+ if orientation == gtk.ORIENTATION_VERTICAL:
+ hildonize.window_to_portrait(self._window)
+ self._isPortrait = True
+ elif orientation == gtk.ORIENTATION_HORIZONTAL:
+ hildonize.window_to_landscape(self._window)
+ self._isPortrait = False
+ else:
+ raise NotImplementedError(orientation)
+ didChange = oldIsPortrait != self._isPortrait
+ if didChange:
+ self.emit("rotate", orientation)
+ return didChange
+
+ def _configure_child(self, childWindow):
+ if not hildonize.IS_FREMANTLE_SUPPORTED:
+ childWindow.window.set_modal(True)
+ childWindow.window.set_transient_for(self._window)
+ childWindow.window.set_default_size(*self._window.get_size())
+ if self._windowInFullscreen:
+ childWindow.window.fullscreen()
+ else:
+ childWindow.window.unfullscreen()
+ childWindow.set_orientation(
+ gtk.ORIENTATION_VERTICAL if self._isPortrait else gtk.ORIENTATION_HORIZONTAL
+ )
+ childWindow.connect_auto(childWindow, "quit", self._on_quit)
+ childWindow.connect_auto(childWindow, "home", self._on_home)
+ childWindow.connect_auto(childWindow, "jump-to", self._on_jump)
+ childWindow.connect_auto(childWindow, "fullscreen", self._on_child_fullscreen)
+ childWindow.connect_auto(childWindow, "rotate", self._on_child_rotate)
+
+ @misc_utils.log_exception(_moduleLogger)
+ def _on_about(self, *args):
+ sourceWindow = AboutWindow(self._app, self._player, self._store)
+ self._configure_child(sourceWindow)
+ sourceWindow.show()
+
@misc_utils.log_exception(_moduleLogger)
def _on_destroy(self, *args):
self._isDestroyed = True
@misc_utils.log_exception(_moduleLogger)
def _on_window_state_change(self, widget, event, *args):
+ oldIsFull = self._windowInFullscreen
if event.new_window_state & gtk.gdk.WINDOW_STATE_FULLSCREEN:
self._windowInFullscreen = True
else:
self._windowInFullscreen = False
- self.emit("fullscreen", self._windowInFullscreen)
+ if oldIsFull != self._windowInFullscreen:
+ _moduleLogger.info("%r Emit fullscreen %s" % (self, self._windowInFullscreen))
+ self.emit("fullscreen", self._windowInFullscreen)
@misc_utils.log_exception(_moduleLogger)
def _on_key_press(self, widget, event, *args):
else:
self._window.fullscreen ()
return True
+ elif event.keyval == gtk.keysyms.o and event.get_state() & gtk.gdk.CONTROL_MASK:
+ if self._isPortrait:
+ self.set_orientation(gtk.ORIENTATION_HORIZONTAL)
+ else:
+ self.set_orientation(gtk.ORIENTATION_VERTICAL)
+ return True
elif (
event.keyval in (gtk.keysyms.w, ) and
event.get_state() & gtk.gdk.CONTROL_MASK
self._window.destroy()
@misc_utils.log_exception(_moduleLogger)
+ def _on_child_fullscreen(self, source, isFull):
+ if isFull:
+ _moduleLogger.info("Full screen %r to mirror child %r" % (self, source))
+ self._window.fullscreen()
+ else:
+ _moduleLogger.info("Unfull screen %r to mirror child %r" % (self, source))
+ self._window.unfullscreen()
+
+ @misc_utils.log_exception(_moduleLogger)
+ def _on_child_rotate(self, source, orientation):
+ self.set_orientation(orientation)
+
+ @misc_utils.log_exception(_moduleLogger)
def _on_jump(self, source, node):
raise NotImplementedError("On %s" % self)
self._treeScroller = hildonize.hildonize_scrollwindow(self._treeScroller)
self._separator = gtk.HSeparator()
- self._playcontrol = playcontrol.NavControl(self._player, self._store)
- self._playcontrol.connect("home", self._on_home)
- self._playcontrol.connect("jump-to", self._on_jump)
+ self._presenter = presenter.NavControl(self._player, self._store)
+ self.connect_auto(self._presenter, "home", self._on_home)
+ self.connect_auto(self._presenter, "jump-to", self._on_jump)
self._contentLayout = gtk.VBox(False)
self._contentLayout.pack_start(self._treeScroller, True, True)
self._contentLayout.pack_start(self._separator, False, True)
- self._contentLayout.pack_start(self._playcontrol.toplevel, False, True)
+ self._contentLayout.pack_start(self._presenter.toplevel, False, True)
self._layout.pack_start(self._loadingBanner.toplevel, False, False)
self._layout.pack_start(self._contentLayout, True, True)
self._loadingBanner.toplevel.hide()
self._refresh()
- self._playcontrol.refresh()
+ self._presenter.refresh()
@classmethod
def _get_columns(cls):
@misc_utils.log_exception(_moduleLogger)
def _on_player_title_change(self, player, node):
+ assert not self._isDestroyed
self._select_row()
@misc_utils.log_exception(_moduleLogger)
self._presenter = presenter.StreamPresenter(self._store)
self._presenter.set_context(
- self._get_background(),
+ self._get_background(
+ gtk.ORIENTATION_VERTICAL if self._isPortrait else gtk.ORIENTATION_HORIZONTAL
+ ),
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.connect_auto(self._presenterNavigation, "action", self._on_nav_action)
+ self.connect_auto(self._presenterNavigation, "navigating", self._on_navigating)
self._seekbar = hildonize.create_seekbar()
self._seekbar.connect("change-value", self._on_user_seek)
self._layout.pack_start(self._presenterNavigation.toplevel, True, True)
self._layout.pack_start(self._seekbar, False, False)
- self._window.set_title(self._node.title)
+ self._window.set_title(self._node.get_parent().title)
- def _get_background(self):
+ def _get_background(self, orientation):
raise NotImplementedError()
def show(self):
def jump_to(self, node):
assert self._node is node
+ def set_orientation(self, orientation):
+ didChange = BasicWindow.set_orientation(self, orientation)
+ if didChange:
+ self._presenter.set_orientation(orientation)
+ self._presenter.set_context(
+ self._get_background(orientation),
+ self._node.title,
+ self._node.subtitle,
+ )
+
@property
def _active(self):
return self._playerNode is self._node
@misc_utils.log_exception(_moduleLogger)
def _on_player_state_change(self, player, newState):
+ assert not self._isDestroyed
if self._active and self._player.state == self._player.STATE_PLAY:
self._seekbar.show()
assert self._updateSeek is None
@misc_utils.log_exception(_moduleLogger)
def _on_player_title_change(self, player, node):
+ assert not self._isDestroyed
if not self._active or node in [None, self._node]:
self._playerNode = node
return
@misc_utils.log_exception(_moduleLogger)
def _on_player_error(self, player, err, debug):
+ assert not self._isDestroyed
_moduleLogger.error("%r - %r" % (err, debug))
@misc_utils.log_exception(_moduleLogger)
def _on_node_search_error(self, e):
self._nextSearch = None
self._errorBanner.push_message(str(e))
+
+
+class AboutWindow(BasicWindow):
+
+ def __init__(self, app, player, store):
+ BasicWindow.__init__(self, app, player, store)
+ self._window.set_title(constants.__pretty_app_name__)
+
+ self._titleLabel = gtk.Label()
+ self._titleLabel.set_markup("""
+<big><b>Waters of Shiloah</b></big>
+<i>Maemo Edition</i>
+Version %s
+""" % (constants.__version__, ))
+ self._titleLabel.set_property("justify", gtk.JUSTIFY_CENTER)
+
+ self._copyLabel = gtk.Label()
+ self._copyLabel.set_markup("""
+<small>Developed by: Ed Page
+Images by: Various Sources, See COPYING for author and license information (mix of various CC licenses, commercial, and non-commercial
+This application nor various images are not endorsed by The Church of Jesus Christ of Latter-day Saints</small>
+""")
+ self._copyLabel.set_property("justify", gtk.JUSTIFY_CENTER)
+
+ self._linkButton = gtk.LinkButton("http://watersofshiloah.garage.maemo.org")
+ self._linkButton.set_label("Waters of Shiloah")
+ self._linkButton.connect("clicked", self._on_website)
+
+ self._radioLinkButton = gtk.LinkButton("http://radio.lds.org")
+ self._radioLinkButton.set_label("Mormon Channel")
+ self._radioLinkButton.connect("clicked", self._on_website)
+
+ self._ldsLinkButton = gtk.LinkButton("http://www.lds.org")
+ self._ldsLinkButton.set_label("LDS.org")
+ self._ldsLinkButton.connect("clicked", self._on_website)
+
+ self._spacedLayout = gtk.VBox(True)
+ self._spacedLayout.pack_start(self._titleLabel, False, False)
+ self._spacedLayout.pack_start(self._copyLabel, False, False)
+ self._spacedLayout.pack_start(self._linkButton, False, False)
+ self._spacedLayout.pack_start(self._radioLinkButton, False, False)
+ self._spacedLayout.pack_start(self._ldsLinkButton, False, False)
+
+ self._separator = gtk.HSeparator()
+ self._presenter = presenter.NavControl(self._player, self._store)
+ self.connect_auto(self._presenter, "home", self._on_home)
+ self.connect_auto(self._presenter, "jump-to", self._on_jump)
+
+ self._layout.pack_start(self._spacedLayout, True, True)
+ self._layout.pack_start(self._presenter.toplevel, False, True)
+
+ def show(self):
+ BasicWindow.show(self)
+ self._window.show_all()
+ self._errorBanner.toplevel.hide()
+ self._presenter.refresh()
+
+ @misc_utils.log_exception(_moduleLogger)
+ def _on_about(self, *args):
+ pass
+
+ @misc_utils.log_exception(_moduleLogger)
+ def _on_website(self, widget):
+ uri = widget.get_uri()
+ webbrowser.open(uri)
+
+ @misc_utils.log_exception(_moduleLogger)
+ def _on_jump(self, source, node):
+ self.emit("jump-to", node)
+ self._window.destroy()