1 # -*- coding: utf-8 -*-
3 ###########################################################################
5 # Copyright (C) 2010 Simón Pena <spenap@gmail.com>
7 # This program is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation, either version 3 of the License, or
10 # (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 ###########################################################################
29 from maeviesui.util import constants
30 from maeviesui.util.asyncworker import AsyncWorker, AsyncItem
31 from maeviesui.util.util import image_downloader
32 from maeviesui.util.moviemanager import MovieManager
34 class Maevies(hildon.StackableWindow):
42 super(Maevies, self).__init__()
43 self.set_title('Maevies - 0.1')
44 self.connect('delete-event',
45 lambda widget, event: gtk.main_quit())
47 self.add(self._create_contents())
48 self.set_app_menu(self._create_app_menu())
52 def _create_button(self, title, subtitle, action):
54 box.set_border_width(20)
56 button = hildon.Button(gtk.HILDON_SIZE_THUMB_HEIGHT,
57 hildon.BUTTON_ARRANGEMENT_VERTICAL,
59 button.connect('clicked', self._button_clicked, action)
61 box.pack_start(button, expand=True, fill=False)
65 def _create_contents(self):
67 contents.set_border_width(60)
68 contents.set_homogeneous(True)
69 contents.pack_start(self._create_button('On Theaters',
71 self.ACTION_THEATERS),
72 expand=True, fill=True)
73 contents.pack_start(self._create_button('Favorites',
74 'Your saved searches',
75 self.ACTION_FAVORITES),
76 expand=True, fill=True)
77 contents.pack_start(self._create_button('Search',
80 expand=True, fill=True)
84 def _button_clicked(self, button, action):
85 if action == self.ACTION_SEARCH:
86 search_dialog = SearchDialog(self)
87 if search_dialog.run() == gtk.RESPONSE_ACCEPT:
88 results_window = ResultsWindow()
89 results_window.start_search(search_dialog.get_search_term(),
90 search_dialog.get_search_category())
91 search_dialog.destroy()
92 elif action == self.ACTION_ABOUT:
93 about_dialog = AboutDialog(self)
95 about_dialog.destroy()
97 def _create_app_menu(self):
98 menu = hildon.AppMenu()
100 about = hildon.GtkButton(gtk.HILDON_SIZE_AUTO)
101 about.set_label('About')
102 about.connect('clicked', self._button_clicked, self.ACTION_ABOUT)
113 class SearchDialog(gtk.Dialog):
120 def __init__(self, parent):
121 super(SearchDialog, self).__init__(parent=parent,
122 flags=gtk.DIALOG_DESTROY_WITH_PARENT)
123 self.set_title('Enter search terms')
125 self.vbox.pack_start(self._create_contents(), True, False, 0)
126 self.add_button(gtk.STOCK_OK, gtk.RESPONSE_ACCEPT)
130 def _create_contents(self):
131 self._search_entry = hildon.Entry(gtk.HILDON_SIZE_FINGER_HEIGHT)
132 search_button = self._create_picker_button()
134 search_contents = gtk.VBox()
136 search_contents.pack_start(self._search_entry,
137 expand=True, fill=True)
138 search_contents.pack_start(search_button,
139 expand=True, fill=True)
141 return search_contents
143 def _create_picker_button(self):
144 self._picker_button = hildon.PickerButton(gtk.HILDON_SIZE_FINGER_HEIGHT,
145 hildon.BUTTON_ARRANGEMENT_HORIZONTAL)
146 self._picker_button.set_title('Search for')
148 selector = hildon.TouchSelector(text=True)
149 selector.set_column_selection_mode(hildon.TOUCH_SELECTOR_SELECTION_MODE_SINGLE)
151 for field in self._search_fields:
152 selector.append_text(field)
154 self._picker_button.set_selector(selector)
155 self._picker_button.set_active(0)
157 return self._picker_button
159 def get_search_term(self):
160 return self._search_entry.get_text()
162 def get_search_category(self):
163 return self._search_fields[self._picker_button.get_active()]
165 class ResultsWindow(hildon.StackableWindow):
168 super(ResultsWindow, self).__init__()
169 self.set_title('Search results')
171 self.add(self._create_contents())
173 self.moviemanager = MovieManager(response_received_cb=self._response_received_cb)
176 def _create_contents(self):
177 content_area = hildon.PannableArea()
178 self._movies_view = MoviesView()
179 self._movies_view.connect('row-activated', self._row_activated_cb)
181 content_area.add(self._movies_view)
184 def _row_activated_cb(self, view, path, column):
185 movie = view.get_movie_from_path(path)
188 def start_search(self, search_term, search_category):
189 self._show_banner(search_term, search_category)
190 hildon.hildon_gtk_window_set_progress_indicator(self, True)
191 self.moviemanager.query(search_term)
193 def _response_received_cb(self, movies):
194 self._movies_view.add_movies(movies)
195 hildon.hildon_gtk_window_set_progress_indicator(self, False)
197 def _show_banner(self, search_term, search_category):
198 message = ('Searching <i>%(category)s</i> for <i>%(term)s</i>' %
199 {'category': search_category,
200 'term' : search_term})
201 banner = hildon.hildon_banner_show_information_with_markup(self,
204 banner.set_timeout(constants.TIMEOUT_TIME_MILLIS)
206 class MoviesView(gtk.TreeView):
209 super(MoviesView, self).__init__()
210 model = MoviesListStore()
211 self.set_model(model)
213 movie_image_renderer = gtk.CellRendererPixbuf()
214 column = gtk.TreeViewColumn('Image', movie_image_renderer,
215 pixbuf=model.IMAGE_COLUMN)
216 self.append_column(column)
218 movie_text_renderer = gtk.CellRendererText()
219 movie_text_renderer.set_property('ellipsize', pango.ELLIPSIZE_END)
220 column = gtk.TreeViewColumn('Name', movie_text_renderer,
221 markup=model.INFO_COLUMN)
222 self.append_column(column)
226 def add_movies(self, movie_list):
227 model = self.get_model()
229 model.add(movie_list)
231 def get_movie_from_path(self, path):
232 model = self.get_model()
233 return model[path][model.MOVIE_COLUMN]
235 class MoviesListStore(gtk.ListStore):
242 super(MoviesListStore, self).__init__(gtk.gdk.Pixbuf,
244 gobject.TYPE_PYOBJECT)
246 def add(self, movies_found):
248 for movie in movies_found:
249 row = {self.IMAGE_COLUMN: movie.get_placeholder_image(),
250 self.INFO_COLUMN: movie.get_info(),
251 self.MOVIE_COLUMN: movie,
253 self.append(row.values())
255 class AboutDialog(gtk.Dialog):
257 def __init__(self, parent):
258 super(AboutDialog, self).__init__(parent=parent,
259 flags=gtk.DIALOG_DESTROY_WITH_PARENT)
260 self.set_title('About Maevies')
264 class MovieWindow(hildon.StackableWindow):
266 def _fetch_movie_image(self, movie):
269 movie_image = movie.get_image('poster', 'mid')
270 image_file = os.path.abspath('/tmp/' + movie_image.get_id() + '.jpg')
272 if os.path.isfile(image_file):
273 image.set_from_pixbuf(gtk.gdk.pixbuf_new_from_file_at_size(image_file,
277 image.set_from_pixbuf(gtk.IconTheme().load_icon('general_video',
279 banner = hildon.hildon_banner_show_information_with_markup(self,
281 'Fetching movie poster')
282 banner.set_timeout(constants.TIMEOUT_TIME_MILLIS)
283 hildon.hildon_gtk_window_set_progress_indicator(self, True)
285 async_item = AsyncItem(image_downloader, (movie_image.get_url(),
286 '/tmp/' + movie_image.get_id()),
287 self._set_fetched_image, (image,))
288 self.async_worker.queue.put(async_item)
289 self.async_worker.start()
293 def _set_fetched_image(self, image, target, error):
295 image_file = os.path.abspath(target)
296 image.set_from_pixbuf(gtk.gdk.pixbuf_new_from_file_at_size(image_file,
299 hildon.hildon_gtk_window_set_progress_indicator(self, False)
301 def _create_contents(self, movie):
302 main_area = hildon.PannableArea()
304 main_box = gtk.VBox(False, 20)
305 main_box.set_border_width(20)
306 upper_content = gtk.HBox(False, 40)
307 upper_content.set_border_width(20)
309 image = self._fetch_movie_image(movie)
311 side_content = gtk.VBox(False, 30)
313 for key in movie.fields:
315 label.set_markup('<b>%(field)s:</b> <small>%(value)s</small>' %
317 'value' : movie.get_value(key)})
318 label.set_alignment(constants.LEFT_ALIGNMENT,
319 constants.CENTER_ALIGNMENT)
320 side_content.pack_start(label, False, False)
322 upper_content.pack_start(image, False, False)
323 upper_content.pack_start(side_content, False, False)
325 movie_overview = hildon.TextView()
326 movie_overview.set_placeholder('Overview')
327 movie_overview.set_wrap_mode(gtk.WRAP_WORD)
328 movie_overview.get_buffer().set_text(movie.get_overview())
331 label.set_markup('<b>Overview:</b>')
332 label.set_alignment(constants.LEFT_ALIGNMENT,
333 constants.CENTER_ALIGNMENT)
335 main_box.pack_start(upper_content, False, False)
336 main_box.pack_start(label, False, False)
337 main_box.pack_start(movie_overview, False, False)
339 main_area.add_with_viewport(main_box)
340 main_area.set_size_request_policy(hildon.SIZE_REQUEST_CHILDREN)
344 def __init__(self, movie):
345 super(MovieWindow, self).__init__()
346 self.async_worker = AsyncWorker()
347 self.set_title('Movie info')
348 self.add(self._create_contents(movie))
351 if __name__ == '__main__':