ui: Added MovieWindow
[maevies] / ui / maeviesui / maeviesui / gui.py
1 # -*- coding: utf-8 -*-
2
3 ###########################################################################
4 #    Maevies
5 #    Copyright (C) 2010 Simón Pena <spenap@gmail.com>
6 #
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.
11 #
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.
16 #
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 ###########################################################################
20
21 from maeviesui.util import constants
22
23 import hildon
24 import pygtk
25 import pango
26 import gobject
27 import random
28 pygtk.require("2.0")
29 import gtk
30
31 class Maevies(hildon.StackableWindow):
32
33     ACTION_SEARCH = 0
34     ACTION_ABOUT = 1
35     ACTION_THEATERS = 2
36     ACTION_FAVORITES = 3
37
38     def __init__(self):
39         super(Maevies, self).__init__()
40         self.set_title("Maevies - 0.1")
41         self.connect('delete-event',
42                      lambda widget, event: gtk.main_quit())
43
44         self.add(self._create_contents())
45         self.set_app_menu(self._create_app_menu())
46
47         self.show_all()
48
49     def _create_button(self, title, subtitle, action):
50         box = gtk.VBox()
51         box.set_border_width(20)
52
53         button = hildon.Button(gtk.HILDON_SIZE_THUMB_HEIGHT,
54                                hildon.BUTTON_ARRANGEMENT_VERTICAL, title, subtitle)
55         button.connect("clicked", self._button_clicked, action)
56
57         box.pack_start(button,
58                              expand = True, fill = False)
59
60         return box
61
62     def _create_contents(self):
63         contents = gtk.HBox()
64         contents.set_border_width(60)
65         contents.set_homogeneous(True)
66         contents.pack_start(self._create_button("On Theaters", "Movies playing",
67                                              self.ACTION_THEATERS),
68                             expand = True, fill = True)
69         contents.pack_start(self._create_button("Favorites", "Your saved searches",
70                                              self.ACTION_FAVORITES),
71                             expand = True, fill = True)
72         contents.pack_start(self._create_button("Search", "Enter a new search",
73                                              self.ACTION_SEARCH),
74                             expand = True, fill = True)
75
76         return contents;
77
78     def _button_clicked(self, button, action):
79         if action == self.ACTION_SEARCH:
80             search_dialog = SearchDialog(self)
81             if search_dialog.run() == gtk.RESPONSE_ACCEPT:
82                 ResultsWindow(search_term = search_dialog.get_search_term(),
83                               search_category = search_dialog.get_search_category())
84             search_dialog.destroy()
85         elif action == self.ACTION_ABOUT:
86             about_dialog = AboutDialog(self)
87             about_dialog.run()
88             about_dialog.destroy()
89
90     def _create_app_menu(self):
91         menu = hildon.AppMenu()
92
93         about = hildon.GtkButton(gtk.HILDON_SIZE_AUTO)
94         about.set_label("About")
95         about.connect("clicked", self._button_clicked, self.ACTION_ABOUT)
96
97         menu.append(about)
98
99         menu.show_all()
100
101         return menu
102
103     def run(self):
104         gtk.main()
105
106 class SearchDialog(gtk.Dialog):
107
108     _search_fields = [
109            "Movies",
110            "People",
111            ]
112
113     def __init__(self, parent):
114         super(SearchDialog, self).__init__(parent = parent,
115                                             flags = gtk.DIALOG_DESTROY_WITH_PARENT)
116         self.set_title("Enter search terms")
117
118         self.vbox.pack_start(self._create_contents(), True, False, 0)
119         self.add_button(gtk.STOCK_OK, gtk.RESPONSE_ACCEPT)
120
121         self.show_all()
122
123     def _create_contents(self):
124         self._search_entry = hildon.Entry(gtk.HILDON_SIZE_FINGER_HEIGHT)
125         search_button = self._create_picker_button()
126
127         search_contents = gtk.VBox()
128
129         search_contents.pack_start(self._search_entry,
130                                    expand = True, fill = True)
131         search_contents.pack_start(search_button,
132                                    expand = True, fill = True)
133
134         return search_contents
135
136     def _create_picker_button(self):
137         self._picker_button = hildon.PickerButton(gtk.HILDON_SIZE_FINGER_HEIGHT,
138                                             hildon.BUTTON_ARRANGEMENT_HORIZONTAL)
139         self._picker_button.set_title("Search for")
140
141         selector = hildon.TouchSelector(text = True)
142         selector.set_column_selection_mode(hildon.TOUCH_SELECTOR_SELECTION_MODE_SINGLE)
143
144         for field in self._search_fields:
145             selector.append_text(field)
146
147         self._picker_button.set_selector(selector)
148         self._picker_button.set_active(0)
149
150         return self._picker_button
151
152     def get_search_term(self):
153         return self._search_entry.get_text()
154
155     def get_search_category(self):
156         return self._search_fields[self._picker_button.get_active()]
157
158 class ResultsWindow(hildon.StackableWindow):
159
160     def __init__(self, search_term, search_category):
161         super(ResultsWindow, self).__init__()
162         self.set_title("Search results")
163
164         self.search_term = search_term
165         self.search_category = search_category
166
167         self._simulate_search()
168         content_area = hildon.PannableArea()
169         self._movies_view = MoviesView()
170         self._movies_view.connect('row-activated', self._row_activated_cb)
171
172         content_area.add(self._movies_view)
173         self.add(content_area)
174
175         self.show_all()
176
177     def _row_activated_cb(self, view, path, column):
178         #movie = view.get_movie_from_path(path)
179         MovieWindow(None)
180
181
182     def _simulate_search(self):
183         self._show_banner()
184         hildon.hildon_gtk_window_set_progress_indicator(self, True)
185         gobject.timeout_add(constants.TIMEOUT_TIME_MILLIS, self._populate_view)
186
187     def _populate_view(self):
188         self._movies_view.add_movies([MovieDecorator("The Lord of the Rings"),
189                                       MovieDecorator("The Lord of the flies"),
190                                       MovieDecorator("Gone by the wind"),
191                                       MovieDecorator("Madagascar"),
192                                       MovieDecorator("Madagascar 2"),
193                                       MovieDecorator("2 Fast 2 Furious"),
194                                       MovieDecorator("Fast &amp; Furious"),
195                                       MovieDecorator("Pitch Black"),
196                                       ])
197         hildon.hildon_gtk_window_set_progress_indicator(self, False)
198         return False
199
200     def _show_banner(self):
201         message = "Searching <i>%(category)s</i> for <i>%(term)s</i>" % {'category': self.search_category,
202                                                                          'term' : self.search_term}
203         banner = hildon.hildon_banner_show_information_with_markup(self,
204                                                                    "ignored",
205                                                                    message)
206         banner.set_timeout(constants.TIMEOUT_TIME_MILLIS)
207         pass
208
209 class MoviesView(gtk.TreeView):
210
211     def __init__(self):
212         super(MoviesView, self).__init__()
213         model = MoviesListStore()
214         self.set_model(model)
215
216         movie_image_renderer = gtk.CellRendererPixbuf()
217         column = gtk.TreeViewColumn('Image', movie_image_renderer, pixbuf = model.IMAGE_COLUMN)
218         self.append_column(column)
219
220         movie_text_renderer = gtk.CellRendererText()
221         movie_text_renderer.set_property('ellipsize', pango.ELLIPSIZE_END)
222         column = gtk.TreeViewColumn('Name', movie_text_renderer, markup = model.INFO_COLUMN)
223         self.append_column(column)
224
225         self.show_all()
226
227     def add_movies(self, movie_list):
228         model = self.get_model()
229         model.add(movie_list)
230
231 class MoviesListStore(gtk.ListStore):
232
233     IMAGE_COLUMN = 0
234     INFO_COLUMN = 1
235     MOVIE_COLUMN = 2
236
237     def __init__(self):
238         super(MoviesListStore, self).__init__(gtk.gdk.Pixbuf,
239                                               str,
240                                               gobject.TYPE_PYOBJECT)
241
242     def add(self, movies_found):
243         self.clear()
244         for movie in movies_found:
245             row = {self.IMAGE_COLUMN: movie.get_image(),
246                    self.INFO_COLUMN: movie.get_info(),
247                    self.MOVIE_COLUMN: movie,
248                   }
249             self.append(row.values())
250
251 class AboutDialog(gtk.Dialog):
252
253     def __init__(self, parent):
254         super(AboutDialog, self).__init__(parent = parent,
255                                           flags = gtk.DIALOG_DESTROY_WITH_PARENT)
256         self.set_title("About Maevies")
257         self.show_all()
258
259 class MovieDecorator:
260
261     def __init__(self, name):
262         self._name = name
263         pass
264
265     def get_name(self):
266         return self._name
267
268     def get_length(self):
269         return "%sh:%sm" % (random.randrange(1, 2), random.randrange(0, 59))
270
271     def get_score(self):
272         return "%s" % (random.randrange(6, 9))
273
274     def get_info(self):
275         return "<b>%s</b>\n<small><i>Length: </i>%s || <i>Score: </i>%s</small>" % (
276                                                                                      self.get_name(),
277                                                                                      self.get_length(),
278                                                                                      self.get_score())
279
280     def get_image(self):
281         return self._get_placeholder_pixbuf()
282
283     def _get_placeholder_pixbuf(self):
284         pixbuf = gtk.IconTheme().load_icon('general_video_file', 48, 0)
285         return pixbuf
286
287 class MovieWindow(hildon.StackableWindow):
288
289     _zombieland = {'Title' : "Zombieland", 'Release date' : "27 November 2009",
290                    'Genre' : "Action | Adventure | Comedy", 'Score' : "7.8",
291                    'Popularity' : "down 4%", 'Overview' : constants.LOREM_IPSUM}
292
293     def _create_contents(self, movie):
294         main_area = hildon.PannableArea()
295
296         main_box = gtk.VBox(False, 20)
297         main_box.set_border_width(20)
298         upper_content = gtk.HBox(False, 20)
299         upper_content.set_border_width(20)
300
301         image = gtk.Image()
302         image.set_from_pixbuf(gtk.IconTheme().load_icon('mediaplayer_default_album', 256, 0))
303
304         side_content = gtk.VBox(False, 30)
305
306         for key in ["Title", "Release date", "Genre", "Score", "Popularity"]:
307             label = gtk.Label()
308             label.set_markup("<b>%(field)s:</b> <small>%(value)s</small>" % {'field' : key,
309                                                                              'value' : movie[key]})
310             label.set_alignment(constants.LEFT_ALIGNMENT, constants.CENTER_ALIGNMENT)
311             side_content.pack_start(label, False, False)
312
313         upper_content.pack_start(image, False, False)
314         upper_content.pack_start(side_content, True, True)
315
316         label = gtk.Label()
317         label.set_markup("<b>%(field)s:</b>\n %(value)s" % {'field' : 'Overview',
318                                                             'value' : movie['Overview']})
319         label.set_alignment(constants.LEFT_ALIGNMENT, constants.CENTER_ALIGNMENT)
320
321         main_box.pack_start(upper_content, False, False)
322         main_box.pack_start(label, False, False)
323
324         main_area.add_with_viewport(main_box)
325         return main_area
326
327     def __init__(self, movie):
328         super(MovieWindow, self).__init__()
329         self.add(self._create_contents(self._zombieland))
330         self.show_all()
331
332 if __name__ == "__main__":
333     maevies = Maevies()
334     maevies.run()