1 from __future__ import with_statement
11 import util.misc as misc_utils
12 import util.go_utils as go_utils
19 _moduleLogger = logging.getLogger(__name__)
22 class BasicWindow(gobject.GObject, go_utils.AutoSignal):
26 gobject.SIGNAL_RUN_LAST,
31 gobject.SIGNAL_RUN_LAST,
36 gobject.SIGNAL_RUN_LAST,
38 (gobject.TYPE_PYOBJECT, ),
41 gobject.SIGNAL_RUN_LAST,
43 (gobject.TYPE_BOOLEAN, ),
46 gobject.SIGNAL_RUN_LAST,
48 (gobject.TYPE_BOOLEAN, ),
52 def __init__(self, app, player, store):
53 gobject.GObject.__init__(self)
54 self._isDestroyed = False
60 self._clipboard = gtk.clipboard_get()
61 self._windowInFullscreen = False
63 self._errorBanner = banners.StackingBanner()
65 self._layout = gtk.VBox()
66 self._layout.pack_start(self._errorBanner.toplevel, False, True)
68 self._window = gtk.Window()
69 go_utils.AutoSignal.__init__(self, self.window)
70 self._window.add(self._layout)
71 self._window = hildonize.hildonize_window(self._app, self._window)
73 self._window.set_icon(self._store.get_pixbuf_from_store(self._store.STORE_LOOKUP["icon"]))
74 self._window.connect("key-press-event", self._on_key_press)
75 self._window.connect("window-state-event", self._on_window_state_change)
76 self._window.connect("destroy", self._on_destroy)
83 hildonize.window_to_portrait(self._window)
84 self._window.show_all()
86 def save_settings(self, config, sectionName):
87 config.add_section(sectionName)
88 config.set(sectionName, "fullscreen", str(self._windowInFullscreen))
90 def load_settings(self, config, sectionName):
92 self._windowInFullscreen = config.getboolean(sectionName, "fullscreen")
93 except ConfigParser.NoSectionError, e:
95 "Settings file %s is missing section %s" % (
96 constants._user_settings_,
101 if self._windowInFullscreen:
102 self._window.fullscreen()
104 self._window.unfullscreen()
106 def jump_to(self, node):
107 raise NotImplementedError("On %s" % self)
109 @misc_utils.log_exception(_moduleLogger)
110 def _on_destroy(self, *args):
111 self._isDestroyed = True
113 @misc_utils.log_exception(_moduleLogger)
114 def _on_window_state_change(self, widget, event, *args):
115 if event.new_window_state & gtk.gdk.WINDOW_STATE_FULLSCREEN:
116 self._windowInFullscreen = True
118 self._windowInFullscreen = False
119 self.emit("fullscreen", self._windowInFullscreen)
121 @misc_utils.log_exception(_moduleLogger)
122 def _on_key_press(self, widget, event, *args):
123 RETURN_TYPES = (gtk.keysyms.Return, gtk.keysyms.ISO_Enter, gtk.keysyms.KP_Enter)
124 isCtrl = bool(event.get_state() & gtk.gdk.CONTROL_MASK)
126 event.keyval == gtk.keysyms.F6 or
127 event.keyval in RETURN_TYPES and isCtrl
129 # The "Full screen" hardware key has been pressed
130 if self._windowInFullscreen:
131 self._window.unfullscreen ()
133 self._window.fullscreen ()
136 event.keyval in (gtk.keysyms.w, ) and
137 event.get_state() & gtk.gdk.CONTROL_MASK
139 self._window.destroy()
141 event.keyval in (gtk.keysyms.q, ) and
142 event.get_state() & gtk.gdk.CONTROL_MASK
145 elif event.keyval == gtk.keysyms.l and event.get_state() & gtk.gdk.CONTROL_MASK:
146 with open(constants._user_logpath_, "r") as f:
147 logLines = f.xreadlines()
148 log = "".join(logLines)
149 self._clipboard.set_text(str(log))
152 @misc_utils.log_exception(_moduleLogger)
153 def _on_home(self, *args):
155 self._window.destroy()
157 @misc_utils.log_exception(_moduleLogger)
158 def _on_jump(self, source, node):
159 raise NotImplementedError("On %s" % self)
161 @misc_utils.log_exception(_moduleLogger)
162 def _on_quit(self, *args):
164 self._window.destroy()
167 class ListWindow(BasicWindow):
169 def __init__(self, app, player, store, node):
170 BasicWindow.__init__(self, app, player, store)
173 self.connect_auto(self._player, "title-change", self._on_player_title_change)
175 self._loadingBanner = banners.GenericBanner()
177 modelTypes, columns = zip(*self._get_columns())
179 self._model = gtk.ListStore(*modelTypes)
181 self._treeView = gtk.TreeView()
182 self._treeView.connect("row-activated", self._on_row_activated)
183 self._treeView.set_property("fixed-height-mode", True)
184 self._treeView.set_headers_visible(False)
185 self._treeView.set_model(self._model)
186 for column in columns:
187 if column is not None:
188 self._treeView.append_column(column)
190 viewport = gtk.Viewport()
191 viewport.add(self._treeView)
193 self._treeScroller = gtk.ScrolledWindow()
194 self._treeScroller.add(viewport)
195 self._treeScroller.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
196 self._treeScroller = hildonize.hildonize_scrollwindow(self._treeScroller)
198 self._separator = gtk.HSeparator()
199 self._playcontrol = playcontrol.NavControl(self._player, self._store)
200 self._playcontrol.connect("home", self._on_home)
201 self._playcontrol.connect("jump-to", self._on_jump)
203 self._contentLayout = gtk.VBox(False)
204 self._contentLayout.pack_start(self._treeScroller, True, True)
205 self._contentLayout.pack_start(self._separator, False, True)
206 self._contentLayout.pack_start(self._playcontrol.toplevel, False, True)
208 self._layout.pack_start(self._loadingBanner.toplevel, False, False)
209 self._layout.pack_start(self._contentLayout, True, True)
212 BasicWindow.show(self)
214 self._errorBanner.toplevel.hide()
215 self._loadingBanner.toplevel.hide()
218 self._playcontrol.refresh()
221 def _get_columns(cls):
222 raise NotImplementedError("")
224 def _get_current_row(self):
225 if self._player.node is None:
227 ancestors, current, descendants = stream_index.common_paths(self._player.node, self._node)
230 activeChild = descendants[0]
231 for i, row in enumerate(self._model):
232 if activeChild is row[0]:
237 def jump_to(self, node):
238 ancestors, current, descendants = stream_index.common_paths(node, self._node)
240 raise RuntimeError("Cannot jump to node %s" % node)
242 _moduleLogger.info("Current node is the target")
244 child = descendants[0]
245 window = self._window_from_node(child)
248 def _window_from_node(self, node):
249 raise NotImplementedError("")
251 @misc_utils.log_exception(_moduleLogger)
252 def _on_row_activated(self, view, path, column):
253 raise NotImplementedError("")
255 @misc_utils.log_exception(_moduleLogger)
256 def _on_player_title_change(self, player, node):
259 @misc_utils.log_exception(_moduleLogger)
260 def _on_jump(self, source, node):
261 ancestors, current, descendants = stream_index.common_paths(node, self._node)
263 _moduleLogger.info("%s is not the target, moving up" % self._node)
264 self.emit("jump-to", node)
265 self._window.destroy()
268 _moduleLogger.info("Current node is the target")
270 child = descendants[0]
271 window = self._window_from_node(child)
274 def _show_loading(self):
275 animationPath = self._store.STORE_LOOKUP["loading"]
276 animation = self._store.get_pixbuf_animation_from_store(animationPath)
277 self._loadingBanner.show(animation, "Loading...")
279 def _hide_loading(self):
280 self._loadingBanner.hide()
286 def _select_row(self):
287 rowIndex = self._get_current_row()
291 self._treeView.scroll_to_cell(path)
292 self._treeView.get_selection().select_path(path)