Protecting the shutdown path
[watersofshiloah] / src / windows / magazines.py
1 import logging
2
3 import gobject
4 import gtk
5
6 import hildonize
7 import util.go_utils as go_utils
8 import util.misc as misc_utils
9
10 import windows
11
12
13 _moduleLogger = logging.getLogger(__name__)
14
15
16 class MagazinesWindow(windows._base.ListWindow):
17
18         def __init__(self, app, player, store, node):
19                 windows._base.ListWindow.__init__(self, app, player, store, node)
20                 self._window.set_title(self._node.title)
21
22         @classmethod
23         def _get_columns(cls):
24                 yield gobject.TYPE_PYOBJECT, None
25
26                 pixrenderer = gtk.CellRendererPixbuf()
27                 column = gtk.TreeViewColumn("Covers")
28                 column.set_property("sizing", gtk.TREE_VIEW_COLUMN_FIXED)
29                 column.set_property("fixed-width", 96)
30                 column.pack_start(pixrenderer, expand=True)
31                 column.add_attribute(pixrenderer, "pixbuf", 1)
32                 yield gobject.TYPE_OBJECT, column
33
34                 textrenderer = gtk.CellRendererText()
35                 hildonize.set_cell_thumb_selectable(textrenderer)
36                 column = gtk.TreeViewColumn("Magazine")
37                 column.set_property("sizing", gtk.TREE_VIEW_COLUMN_FIXED)
38                 column.pack_start(textrenderer, expand=True)
39                 column.add_attribute(textrenderer, "text", 2)
40                 yield gobject.TYPE_STRING, column
41
42         def _refresh(self):
43                 windows._base.ListWindow._refresh(self)
44                 self._node.get_children(
45                         self._on_magazines,
46                         self._on_error,
47                 )
48
49         @misc_utils.log_exception(_moduleLogger)
50         def _on_magazines(self, programs):
51                 if self._isDestroyed:
52                         _moduleLogger.info("Download complete but window destroyed")
53                         return
54
55                 self._hide_loading()
56                 for i, programNode in enumerate(programs):
57                         program = programNode.get_properties()
58                         img = self._store.get_pixbuf_from_store(self._store.STORE_LOOKUP["nomagazineimage"])
59                         row = programNode, img, program["title"]
60                         self._model.append(row)
61
62                         programNode.get_children(self._create_on_issues(i), self._on_error)
63
64                 self._select_row()
65                 go_utils.Async(self._on_delay_scroll).start()
66
67         def _create_on_issues(self, row):
68                 return lambda issues: self._on_issues(row, issues)
69
70         @misc_utils.log_exception(_moduleLogger)
71         def _on_issues(self, row, issues):
72                 for issue in issues:
73                         self._store.get_pixbuf_from_url(
74                                 issue.get_properties()["pictureURL"],
75                                 lambda pix: self._on_image(row, pix),
76                                 self._on_error,
77                         )
78                         break
79                 else:
80                         _moduleLogger.info("No issues for magazine %s" % row)
81
82         @misc_utils.log_exception(_moduleLogger)
83         def _on_image(self, row, pix):
84                 treeiter = self._model.iter_nth_child(None, row)
85                 self._model.set_value(treeiter, 1, pix)
86                 treeiter = self._model.iter_nth_child(None, row)
87                 self._model.row_changed((row, ), treeiter)
88
89         @misc_utils.log_exception(_moduleLogger)
90         def _on_error(self, exception):
91                 self._hide_loading()
92                 self._errorBanner.push_message(str(exception))
93
94         def _window_from_node(self, node):
95                 issuesWindow = MagazineIssuesWindow(self._app, self._player, self._store, node)
96                 if not hildonize.IS_FREMANTLE_SUPPORTED:
97                         issuesWindow.window.set_modal(True)
98                         issuesWindow.window.set_transient_for(self._window)
99                 if self._windowInFullscreen:
100                         issuesWindow.window.fullscreen()
101                 else:
102                         issuesWindow.window.unfullscreen()
103                 issuesWindow.connect_auto(issuesWindow, "quit", self._on_quit)
104                 issuesWindow.connect_auto(issuesWindow, "home", self._on_home)
105                 issuesWindow.connect_auto(issuesWindow, "jump-to", self._on_jump)
106                 issuesWindow.connect_auto(issuesWindow, "fullscreen", self._on_child_fullscreen)
107                 issuesWindow.show()
108                 return issuesWindow
109
110
111 gobject.type_register(MagazinesWindow)
112
113
114 class MagazineIssuesWindow(windows._base.ListWindow):
115
116         def __init__(self, app, player, store, node):
117                 windows._base.ListWindow.__init__(self, app, player, store, node)
118                 self._window.set_title(self._node.title)
119
120         @classmethod
121         def _get_columns(cls):
122                 yield gobject.TYPE_PYOBJECT, None
123
124                 pixrenderer = gtk.CellRendererPixbuf()
125                 column = gtk.TreeViewColumn("Covers")
126                 column.set_property("sizing", gtk.TREE_VIEW_COLUMN_FIXED)
127                 column.set_property("fixed-width", 96)
128                 column.pack_start(pixrenderer, expand=True)
129                 column.add_attribute(pixrenderer, "pixbuf", 1)
130                 yield gobject.TYPE_OBJECT, column
131
132                 textrenderer = gtk.CellRendererText()
133                 hildonize.set_cell_thumb_selectable(textrenderer)
134                 column = gtk.TreeViewColumn("Issue")
135                 column.set_property("sizing", gtk.TREE_VIEW_COLUMN_FIXED)
136                 column.pack_start(textrenderer, expand=True)
137                 column.add_attribute(textrenderer, "text", 2)
138                 yield gobject.TYPE_STRING, column
139
140         def _refresh(self):
141                 windows._base.ListWindow._refresh(self)
142                 self._node.get_children(
143                         self._on_magazine_issues,
144                         self._on_error,
145                 )
146
147         @misc_utils.log_exception(_moduleLogger)
148         def _on_magazine_issues(self, programs):
149                 if self._isDestroyed:
150                         _moduleLogger.info("Download complete but window destroyed")
151                         return
152
153                 self._hide_loading()
154                 for programNode in programs:
155                         program = programNode.get_properties()
156                         img = self._store.get_pixbuf_from_store(self._store.STORE_LOOKUP["nomagazineimage"])
157                         row = programNode, img, program["title"]
158                         self._model.append(row)
159
160                         self._store.get_pixbuf_from_url(
161                                 program["pictureURL"],
162                                 self._create_on_image(programNode),
163                                 self._on_error,
164                         )
165
166                 self._select_row()
167                 go_utils.Async(self._on_delay_scroll).start()
168
169         @misc_utils.log_exception(_moduleLogger)
170         def _on_error(self, exception):
171                 self._hide_loading()
172                 self._errorBanner.push_message(str(exception))
173
174         def _create_on_image(self, programNode):
175                 return lambda pix: self._on_image(programNode, pix)
176
177         @misc_utils.log_exception(_moduleLogger)
178         def _on_image(self, childNode, pix):
179                 for i, row in enumerate(self._model):
180                         if row[0] is childNode:
181                                 break
182                 else:
183                         raise RuntimeError("Could not find %r" % childNode)
184                 treeiter = self._model.iter_nth_child(None, i)
185                 self._model.set_value(treeiter, 1, pix)
186                 treeiter = self._model.iter_nth_child(None, i)
187                 self._model.row_changed((i, ), treeiter)
188
189         def _window_from_node(self, node):
190                 issuesWindow = MagazineArticlesWindow(self._app, self._player, self._store, node)
191                 if not hildonize.IS_FREMANTLE_SUPPORTED:
192                         issuesWindow.window.set_modal(True)
193                         issuesWindow.window.set_transient_for(self._window)
194                 if self._windowInFullscreen:
195                         issuesWindow.window.fullscreen()
196                 else:
197                         issuesWindow.window.unfullscreen()
198                 issuesWindow.connect_auto(issuesWindow, "quit", self._on_quit)
199                 issuesWindow.connect_auto(issuesWindow, "home", self._on_home)
200                 issuesWindow.connect_auto(issuesWindow, "jump-to", self._on_jump)
201                 issuesWindow.connect_auto(issuesWindow, "fullscreen", self._on_child_fullscreen)
202                 issuesWindow.show()
203                 return issuesWindow
204
205
206 gobject.type_register(MagazineIssuesWindow)
207
208
209 class MagazineArticlesWindow(windows._base.ListWindow):
210
211         def __init__(self, app, player, store, node):
212                 windows._base.ListWindow.__init__(self, app, player, store, node)
213                 self._window.set_title(self._node.title)
214
215         @classmethod
216         def _get_columns(cls):
217                 yield gobject.TYPE_PYOBJECT, None
218
219                 textrenderer = gtk.CellRendererText()
220                 column = gtk.TreeViewColumn("Article")
221                 column.set_property("sizing", gtk.TREE_VIEW_COLUMN_FIXED)
222                 column.pack_start(textrenderer, expand=True)
223                 column.add_attribute(textrenderer, "markup", 1)
224                 yield gobject.TYPE_STRING, column
225
226         def _refresh(self):
227                 windows._base.ListWindow._refresh(self)
228                 self._node.get_children(
229                         self._on_magazine_articles,
230                         self._on_error,
231                 )
232
233         @misc_utils.log_exception(_moduleLogger)
234         def _on_magazine_articles(self, programs):
235                 if self._isDestroyed:
236                         _moduleLogger.info("Download complete but window destroyed")
237                         return
238
239                 self._hide_loading()
240                 for programNode in programs:
241                         program = programNode.get_properties()
242                         row = programNode, "%s\n<small>%s</small>" % (programNode.title, programNode.subtitle)
243                         self._model.append(row)
244
245                 self._select_row()
246                 go_utils.Async(self._on_delay_scroll).start()
247
248         @misc_utils.log_exception(_moduleLogger)
249         def _on_error(self, exception):
250                 self._hide_loading()
251                 self._errorBanner.push_message(str(exception))
252
253         def _window_from_node(self, node):
254                 issuesWindow = MagazineArticleWindow(self._app, self._player, self._store, node)
255                 if not hildonize.IS_FREMANTLE_SUPPORTED:
256                         issuesWindow.window.set_modal(True)
257                         issuesWindow.window.set_transient_for(self._window)
258                 if self._windowInFullscreen:
259                         issuesWindow.window.fullscreen()
260                 else:
261                         issuesWindow.window.unfullscreen()
262                 issuesWindow.connect_auto(issuesWindow, "quit", self._on_quit)
263                 issuesWindow.connect_auto(issuesWindow, "home", self._on_home)
264                 issuesWindow.connect_auto(issuesWindow, "jump-to", self._on_jump)
265                 issuesWindow.connect_auto(issuesWindow, "fullscreen", self._on_child_fullscreen)
266                 issuesWindow.show()
267                 return issuesWindow
268
269
270 gobject.type_register(MagazineArticlesWindow)
271
272
273 class MagazineArticleWindow(windows._base.PresenterWindow):
274
275         def __init__(self, app, player, store, node):
276                 windows._base.PresenterWindow.__init__(self, app, player, store, node)
277
278         def _get_background(self):
279                 return self._store.STORE_LOOKUP["magazine_background"]
280
281
282 gobject.type_register(MagazineArticleWindow)