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