Fixing the window switching bug on Maemo
[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                 issuesWindow.window.set_modal(True)
97                 issuesWindow.window.set_transient_for(self._window)
98                 if self._windowInFullscreen:
99                         issuesWindow.window.fullscreen()
100                 else:
101                         issuesWindow.window.unfullscreen()
102                 issuesWindow.connect_auto(issuesWindow, "quit", self._on_quit)
103                 issuesWindow.connect_auto(issuesWindow, "home", self._on_home)
104                 issuesWindow.connect_auto(issuesWindow, "jump-to", self._on_jump)
105                 issuesWindow.connect_auto(issuesWindow, "fullscreen", self._on_child_fullscreen)
106                 issuesWindow.show()
107                 return issuesWindow
108
109
110 gobject.type_register(MagazinesWindow)
111
112
113 class MagazineIssuesWindow(windows._base.ListWindow):
114
115         def __init__(self, app, player, store, node):
116                 windows._base.ListWindow.__init__(self, app, player, store, node)
117                 self._window.set_title(self._node.title)
118
119         @classmethod
120         def _get_columns(cls):
121                 yield gobject.TYPE_PYOBJECT, None
122
123                 pixrenderer = gtk.CellRendererPixbuf()
124                 column = gtk.TreeViewColumn("Covers")
125                 column.set_property("sizing", gtk.TREE_VIEW_COLUMN_FIXED)
126                 column.set_property("fixed-width", 96)
127                 column.pack_start(pixrenderer, expand=True)
128                 column.add_attribute(pixrenderer, "pixbuf", 1)
129                 yield gobject.TYPE_OBJECT, column
130
131                 textrenderer = gtk.CellRendererText()
132                 hildonize.set_cell_thumb_selectable(textrenderer)
133                 column = gtk.TreeViewColumn("Issue")
134                 column.set_property("sizing", gtk.TREE_VIEW_COLUMN_FIXED)
135                 column.pack_start(textrenderer, expand=True)
136                 column.add_attribute(textrenderer, "text", 2)
137                 yield gobject.TYPE_STRING, column
138
139         def _refresh(self):
140                 windows._base.ListWindow._refresh(self)
141                 self._node.get_children(
142                         self._on_magazine_issues,
143                         self._on_error,
144                 )
145
146         @misc_utils.log_exception(_moduleLogger)
147         def _on_magazine_issues(self, programs):
148                 if self._isDestroyed:
149                         _moduleLogger.info("Download complete but window destroyed")
150                         return
151
152                 self._hide_loading()
153                 for programNode in programs:
154                         program = programNode.get_properties()
155                         img = self._store.get_pixbuf_from_store(self._store.STORE_LOOKUP["nomagazineimage"])
156                         row = programNode, img, program["title"]
157                         self._model.append(row)
158
159                         self._store.get_pixbuf_from_url(
160                                 program["pictureURL"],
161                                 self._create_on_image(programNode),
162                                 self._on_error,
163                         )
164
165                 self._select_row()
166                 go_utils.Async(self._on_delay_scroll).start()
167
168         @misc_utils.log_exception(_moduleLogger)
169         def _on_error(self, exception):
170                 self._hide_loading()
171                 self._errorBanner.push_message(str(exception))
172
173         def _create_on_image(self, programNode):
174                 return lambda pix: self._on_image(programNode, pix)
175
176         @misc_utils.log_exception(_moduleLogger)
177         def _on_image(self, childNode, pix):
178                 for i, row in enumerate(self._model):
179                         if row[0] is childNode:
180                                 break
181                 else:
182                         raise RuntimeError("Could not find %r" % childNode)
183                 treeiter = self._model.iter_nth_child(None, i)
184                 self._model.set_value(treeiter, 1, pix)
185                 treeiter = self._model.iter_nth_child(None, i)
186                 self._model.row_changed((i, ), treeiter)
187
188         def _window_from_node(self, node):
189                 issuesWindow = MagazineArticlesWindow(self._app, self._player, self._store, node)
190                 issuesWindow.window.set_modal(True)
191                 issuesWindow.window.set_transient_for(self._window)
192                 if self._windowInFullscreen:
193                         issuesWindow.window.fullscreen()
194                 else:
195                         issuesWindow.window.unfullscreen()
196                 issuesWindow.connect_auto(issuesWindow, "quit", self._on_quit)
197                 issuesWindow.connect_auto(issuesWindow, "home", self._on_home)
198                 issuesWindow.connect_auto(issuesWindow, "jump-to", self._on_jump)
199                 issuesWindow.connect_auto(issuesWindow, "fullscreen", self._on_child_fullscreen)
200                 issuesWindow.show()
201                 return issuesWindow
202
203
204 gobject.type_register(MagazineIssuesWindow)
205
206
207 class MagazineArticlesWindow(windows._base.ListWindow):
208
209         def __init__(self, app, player, store, node):
210                 windows._base.ListWindow.__init__(self, app, player, store, node)
211                 self._window.set_title(self._node.title)
212
213         @classmethod
214         def _get_columns(cls):
215                 yield gobject.TYPE_PYOBJECT, None
216
217                 textrenderer = gtk.CellRendererText()
218                 column = gtk.TreeViewColumn("Article")
219                 column.set_property("sizing", gtk.TREE_VIEW_COLUMN_FIXED)
220                 column.pack_start(textrenderer, expand=True)
221                 column.add_attribute(textrenderer, "markup", 1)
222                 yield gobject.TYPE_STRING, column
223
224         def _refresh(self):
225                 windows._base.ListWindow._refresh(self)
226                 self._node.get_children(
227                         self._on_magazine_articles,
228                         self._on_error,
229                 )
230
231         @misc_utils.log_exception(_moduleLogger)
232         def _on_magazine_articles(self, programs):
233                 if self._isDestroyed:
234                         _moduleLogger.info("Download complete but window destroyed")
235                         return
236
237                 self._hide_loading()
238                 for programNode in programs:
239                         program = programNode.get_properties()
240                         row = programNode, "%s\n<small>%s</small>" % (programNode.title, programNode.subtitle)
241                         self._model.append(row)
242
243                 self._select_row()
244                 go_utils.Async(self._on_delay_scroll).start()
245
246         @misc_utils.log_exception(_moduleLogger)
247         def _on_error(self, exception):
248                 self._hide_loading()
249                 self._errorBanner.push_message(str(exception))
250
251         def _window_from_node(self, node):
252                 issuesWindow = MagazineArticleWindow(self._app, self._player, self._store, node)
253                 issuesWindow.window.set_modal(True)
254                 issuesWindow.window.set_transient_for(self._window)
255                 if self._windowInFullscreen:
256                         issuesWindow.window.fullscreen()
257                 else:
258                         issuesWindow.window.unfullscreen()
259                 issuesWindow.connect_auto(issuesWindow, "quit", self._on_quit)
260                 issuesWindow.connect_auto(issuesWindow, "home", self._on_home)
261                 issuesWindow.connect_auto(issuesWindow, "jump-to", self._on_jump)
262                 issuesWindow.connect_auto(issuesWindow, "fullscreen", self._on_child_fullscreen)
263                 issuesWindow.show()
264                 return issuesWindow
265
266
267 gobject.type_register(MagazineArticlesWindow)
268
269
270 class MagazineArticleWindow(windows._base.PresenterWindow):
271
272         def __init__(self, app, player, store, node):
273                 windows._base.PresenterWindow.__init__(self, app, player, store, node)
274
275         def _get_background(self):
276                 return self._store.STORE_LOOKUP["magazine_background"]
277
278
279 gobject.type_register(MagazineArticleWindow)