From ed27fe5f073929a7b3de7ea3ef2966f0cac8c72d Mon Sep 17 00:00:00 2001 From: Ed Page Date: Sun, 2 May 2010 00:10:11 -0500 Subject: [PATCH] First try at starting on the UI --- src/banners.py | 91 ++++++++++++++++++++++++++++++++++++++++++++++ src/imagestore.py | 4 +- src/mormonchannel_gtk.py | 10 +++++ src/playcontrol.py | 10 ++--- src/player.py | 64 ++++++++++++++++++++++++++++++++ src/presenter.py | 3 -- src/windows.py | 62 +++++++++++++++++++++++++++++++ 7 files changed, 235 insertions(+), 9 deletions(-) create mode 100644 src/banners.py create mode 100644 src/player.py create mode 100644 src/windows.py diff --git a/src/banners.py b/src/banners.py new file mode 100644 index 0000000..328029a --- /dev/null +++ b/src/banners.py @@ -0,0 +1,91 @@ +import sys +import logging + +import gtk + +import util.misc as misc_utils + + +_moduleLogger = logging.getLogger(__name__) + + +class GenericBanner(object): + + def __init__(self): + self._label = gtk.Label() + + self._layout = gtk.VBox() + self._layout.pack_start(self._label) + + @property + def toplevel(self): + return self._layout + + def show(self, message): + assert not self._label.get_text(), self._label.get_text() + self._label.set_text(message) + self.toplevel.show() + + def hide(self): + assert self._label.get_text(), self._label.get_text() + self._label.set_text("") + self.toplevel.hide() + + +class StackingBanner(object): + + ICON_SIZE = 32 + + def __init__(self): + self._indicator = gtk.Image() + + self._message = gtk.Label() + + self._closeImage = gtk.Image() + self._closeImage.set_from_stock("gtk-close", self.ICON_SIZE) + + self._layout = gtk.HBox() + self._layout.pack_start(self._indicator, False, False) + self._layout.pack_start(self._message, True, True) + self._layout.pack_start(self._closeImage, False, False) + + self._events = gtk.EventBox() + self._events.add(self._layout) + self._events.connect("button_release_event", self._on_close) + + self._messages = [] + + @property + def toplevel(self): + return self._events + + def push_message(self, message, icon=""): + self._messages.append((message, icon)) + if 1 == len(self.__messages): + self._update_message() + + def push_exception(self): + userMessage = str(sys.exc_info()[1]) + self.push_message(userMessage, "gtk-dialog-error") + _moduleLogger.exception(userMessage) + + def pop_message(self): + del self.__messages[0] + self._update_message() + + def _update_message(self): + if 0 == len(self.__messages): + self.toplevel.hide() + else: + message, icon = self._message[0] + self._message.set_text(message) + if icon: + self._indicator.set_from_stock(icon) + self._indicator.show() + else: + self._indicator.hide() + self.toplevel.show() + + @misc_utils.log_exception(_moduleLogger) + def _on_close(self, *args): + self.pop_message() diff --git a/src/imagestore.py b/src/imagestore.py index e5e351c..cc2ea55 100644 --- a/src/imagestore.py +++ b/src/imagestore.py @@ -12,12 +12,14 @@ class ImageStore(object): "pause": "pause.png", "play": "play.png", "stop": "stop.png", + "generic_background": "radiobackground_01.png", "night_temple_background": "radiobackground_02.png", "day_temple_background": "radiobackground_03.png", "presidency_background": "radiobackground_04.png", "scriptures_background": "radiobackground_05.png", - "conference": "conference.png", + + "conferences": "conference.png", "magazines": "magazines.png", "more": "more.png", "mormonmessages": "mormonmessages.png", diff --git a/src/mormonchannel_gtk.py b/src/mormonchannel_gtk.py index ddcd8f3..09ebb5d 100755 --- a/src/mormonchannel_gtk.py +++ b/src/mormonchannel_gtk.py @@ -23,6 +23,10 @@ import constants import hildonize import gtk_toolbox +import imagestore +import player +import windows + _moduleLogger = logging.getLogger(__name__) PROFILE_STARTUP = False @@ -113,6 +117,12 @@ class MormonChannelProgram(hildonize.get_app_class()): self._window.connect("window-state-event", self._on_window_state_change) self._window.show_all() + + self._player = player.Player() + self._store = imagestore.ImageStore("../data", "../data") + self._windowStack = [windows.SourceSelector(self._player, self._store)] + vbox.pack_start(self._windowStack[0].toplevel, True, True) + self._load_settings() def _save_settings(self): diff --git a/src/playcontrol.py b/src/playcontrol.py index 2e31d0a..0802ebe 100644 --- a/src/playcontrol.py +++ b/src/playcontrol.py @@ -21,27 +21,27 @@ class PlayControl(object): self._player.connect("state-change", self._on_player_state_change) self._player.connect("navigate-change", self._on_player_nav_change) - img = store.get_image_from_store("prev.png") + img = store.get_image_from_store(store.STORE_LOOKUP["prev"]) self._back = gtk.Button() self._back.set_image(img) self._back.connect("clicked", self._on_back_clicked) - img = store.get_image_from_store("stop.png") + img = store.get_image_from_store(store.STORE_LOOKUP["stop"]) self._stop = gtk.Button() self._stop.set_image(img) self._stop.connect("clicked", self._on_stop_clicked) - img = store.get_image_from_store("pause.png") + img = store.get_image_from_store(store.STORE_LOOKUP["pause"]) self._pause = gtk.Button() self._pause.set_image(img) self._pause.connect("clicked", self._on_pause_clicked) - img = store.get_image_from_store("play.png") + img = store.get_image_from_store(store.STORE_LOOKUP["play"]) self._play = gtk.Button() self._play.set_image(img) self._play.connect("clicked", self._on_play_clicked) - img = store.get_image_from_store("next.png") + img = store.get_image_from_store(store.STORE_LOOKUP["next"]) self._next = gtk.Button() self._next.set_image(img) self._next.connect("clicked", self._on_next_clicked) diff --git a/src/player.py b/src/player.py new file mode 100644 index 0000000..b99d1c6 --- /dev/null +++ b/src/player.py @@ -0,0 +1,64 @@ +import logging + +import gobject + + +_moduleLogger = logging.getLogger(__name__) + + +class Player(gobject.GObject): + + __gsignals__ = { + 'state_change' : ( + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, + (gobject.TYPE_PYOBJECT, ), + ), + 'navigate_change' : ( + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, + (gobject.TYPE_PYOBJECT, ), + ), + 'title_change' : ( + gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, + (gobject.TYPE_PYOBJECT, ), + ), + } + + def __init__(self): + gobject.GObject.__init__(self) + + @property + def title(self): + return "" + + @property + def can_navigate(self): + return True + + @property + def state(self): + return "play" + + @property + def background(self): + return "night_temple_background" + + def play(self): + _moduleLogger.info("play") + + def pause(self): + _moduleLogger.info("pause") + + def stop(self): + _moduleLogger.info("stop") + + def back(self): + _moduleLogger.info("back") + + def next(self): + _moduleLogger.info("next") + + +gobject.type_register(Player) diff --git a/src/presenter.py b/src/presenter.py index 20359af..335d118 100644 --- a/src/presenter.py +++ b/src/presenter.py @@ -42,9 +42,6 @@ class StreamPresenter(object): self._image.connect("expose_event", self._on_expose) self._imageEvents = gtk.EventBox() self._imageEvents.connect("motion_notify_event", self._on_motion_notify) - #self._imageEvents.connect("leave_notify_event", self._on_leave_notify) - #self._imageEvents.connect("proximity_in_event", self._on_motion_notify) - #self._imageEvents.connect("proximity_out_event", self._on_leave_notify) self._imageEvents.connect("button_press_event", self._on_button_press) self._imageEvents.connect("button_release_event", self._on_button_release) self._imageEvents.add(self._image) diff --git a/src/windows.py b/src/windows.py new file mode 100644 index 0000000..6ad1192 --- /dev/null +++ b/src/windows.py @@ -0,0 +1,62 @@ +import gtk + +import banners +import playcontrol + + +class SourceSelector(object): + + def __init__(self, player, store): + self._player = player + self._store = store + + self._errorBanner = banners.StackingBanner() + + self._radioButton = self._create_button("radio", "Radio") + self._radioWrapper = gtk.VBox() + self._radioWrapper.pack_start(self._radioButton, False, True) + self._conferenceButton = self._create_button("conferences", "Conferences") + self._conferenceWrapper = gtk.VBox() + self._conferenceWrapper.pack_start(self._conferenceButton, False, True) + self._magazineButton = self._create_button("magazines", "Magazines") + self._magazineWrapper = gtk.VBox() + self._magazineWrapper.pack_start(self._magazineButton, False, True) + self._scriptureButton = self._create_button("scriptures", "Scriptures") + self._scriptureWrapper = gtk.VBox() + self._scriptureWrapper.pack_start(self._scriptureButton, False, True) + + self._buttonLayout = gtk.VBox(True, 5) + self._buttonLayout.set_property("border-width", 5) + self._buttonLayout.pack_start(self._radioWrapper, True, True) + self._buttonLayout.pack_start(self._conferenceWrapper, True, True) + self._buttonLayout.pack_start(self._magazineWrapper, True, True) + self._buttonLayout.pack_start(self._scriptureWrapper, True, True) + + self._playcontrol = playcontrol.PlayControl(player, store) + + self._layout = gtk.VBox() + self._layout.pack_start(self._errorBanner.toplevel, False, True) + self._layout.pack_start(self._buttonLayout, True, True) + self._layout.pack_start(self._playcontrol.toplevel, False, True) + + self._layout.show_all() + self._errorBanner.toplevel.hide() + self._playcontrol.toplevel.hide() + + @property + def toplevel(self): + return self._layout + + def _create_button(self, icon, message): + image = self._store.get_image_from_store(self._store.STORE_LOOKUP[icon]) + + label = gtk.Label() + label.set_text(message) + + buttonLayout = gtk.HBox(False, 5) + buttonLayout.pack_start(image, False, False) + buttonLayout.pack_start(label, False, True) + button = gtk.Button() + button.add(buttonLayout) + + return button -- 1.7.9.5