UI: Added simulated results
[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 from random import randint
28 import random
29 pygtk.require("2.0")
30 import gtk
31
32 class Maevies(hildon.StackableWindow):
33
34     ACTION_SEARCH = 0
35     ACTION_ABOUT = 1
36     ACTION_THEATERS = 2
37     ACTION_FAVORITES = 3
38
39     def __init__(self):
40         super(Maevies, self).__init__()
41         self.set_title("Maevies - 0.1")
42         self.connect('delete-event',
43                      lambda widget, event: gtk.main_quit())
44
45         self.add(self._create_contents())
46         self.set_app_menu(self._create_app_menu())
47
48         self.show_all()
49
50     def _create_box(self, title, action):
51         box = gtk.VBox()
52         box.set_border_width(20)
53
54         button = gtk.Button()
55         button.connect("clicked", self._button_clicked, action)
56         foot_label = gtk.Label()
57         foot_label.set_text(title)
58
59         box.pack_start(button,
60                              expand = True, fill = True)
61         box.pack_start(foot_label,
62                              expand = False, fill = False)
63
64         return box
65
66     def _create_contents(self):
67         contents = gtk.HBox()
68         contents.set_border_width(60)
69         contents.set_homogeneous(True)
70         contents.pack_start(self._create_box(title = "On Theaters",
71                                              action = self.ACTION_THEATERS),
72                             expand = True, fill = True)
73         contents.pack_start(self._create_box(title = "Favorites",
74                                              action = self.ACTION_FAVORITES),
75                             expand = True, fill = True)
76         contents.pack_start(self._create_box(title = "Search",
77                                              action = self.ACTION_SEARCH),
78                             expand = True, fill = True)
79
80         return contents;
81
82     def _button_clicked(self, button, action):
83         if action == self.ACTION_SEARCH:
84             search_dialog = SearchDialog(self)
85             if search_dialog.run() == gtk.RESPONSE_ACCEPT:
86                 ResultsWindow(search_term = search_dialog.get_search_term(),
87                               search_category = search_dialog.get_search_category())
88             search_dialog.destroy()
89         elif action == self.ACTION_ABOUT:
90             about_dialog = AboutDialog(self)
91             about_dialog.run()
92             about_dialog.destroy()
93
94     def _create_app_menu(self):
95         menu = hildon.AppMenu()
96
97         about = hildon.GtkButton(gtk.HILDON_SIZE_AUTO)
98         about.set_label("About")
99         about.connect("clicked", self._button_clicked, self.ACTION_ABOUT)
100
101         menu.append(about)
102
103         menu.show_all()
104
105         return menu
106
107     def run(self):
108         gtk.main()
109
110 class SearchDialog(gtk.Dialog):
111
112     _search_fields = [
113            "Movies",
114            "People",
115            ]
116
117     def __init__(self, parent):
118         super(SearchDialog, self).__init__(parent = parent,
119                                             flags = gtk.DIALOG_DESTROY_WITH_PARENT)
120         self.set_title("Enter search terms")
121
122         self.vbox.pack_start(self._create_contents(), True, False, 0)
123         self.add_button(gtk.STOCK_OK, gtk.RESPONSE_ACCEPT)
124
125         self.show_all()
126
127     def _create_contents(self):
128         self._search_entry = hildon.Entry(gtk.HILDON_SIZE_FINGER_HEIGHT)
129         search_button = self._create_picker_button()
130
131         search_contents = gtk.VBox()
132
133         search_contents.pack_start(self._search_entry,
134                                    expand = True, fill = True)
135         search_contents.pack_start(search_button,
136                                    expand = True, fill = True)
137
138         return search_contents
139
140     def _create_picker_button(self):
141         self._picker_button = hildon.PickerButton(gtk.HILDON_SIZE_FINGER_HEIGHT,
142                                             hildon.BUTTON_ARRANGEMENT_VERTICAL)
143         self._picker_button.set_title("Search for")
144
145         selector = hildon.TouchSelector(text = True)
146         selector.set_column_selection_mode(hildon.TOUCH_SELECTOR_SELECTION_MODE_SINGLE)
147
148         for field in self._search_fields:
149             selector.append_text(field)
150
151         self._picker_button.set_selector(selector)
152         self._picker_button.set_active(0)
153
154         return self._picker_button
155
156     def get_search_term(self):
157         return self._search_entry.get_text()
158
159     def get_search_category(self):
160         return self._search_fields[self._picker_button.get_active()]
161
162 class ResultsWindow(hildon.StackableWindow):
163
164     def __init__(self, search_term, search_category):
165         super(ResultsWindow, self).__init__()
166         self.set_title("Search results")
167
168         self.search_term = search_term
169         self.search_category = search_category
170
171         self._simulate_search()
172         content_area = hildon.PannableArea()
173         self._movies_view = MoviesView()
174
175         content_area.add(self._movies_view)
176         self.add(content_area)
177
178         self.show_all()
179
180     def _simulate_search(self):
181         self._show_banner()
182         hildon.hildon_gtk_window_set_progress_indicator(self, True)
183         gobject.timeout_add(constants.TIMEOUT_TIME_MILLIS, self._populate_view)
184
185     def _populate_view(self):
186         self._movies_view.add_movies([MovieDecorator("The Lord of the Rings"),
187                                       MovieDecorator("The Lord of the flies"),
188                                       MovieDecorator("Gone by the wind"),
189                                       MovieDecorator("Madagascar"),
190                                       MovieDecorator("Madagascar 2"),
191                                       MovieDecorator("2 Fast 2 Furious"),
192                                       MovieDecorator("Fast &amp; Furious"),
193                                       MovieDecorator("Pitch Black"),
194                                       ])
195         hildon.hildon_gtk_window_set_progress_indicator(self, False)
196         return False
197
198     def _show_banner(self):
199         message = "Searching <i>%(category)s</i> for <i>%(term)s</i>" % {'category': self.search_category,
200                                                                          'term' : self.search_term}
201         banner = hildon.hildon_banner_show_information_with_markup(self,
202                                                                    "ignored",
203                                                                    message)
204         banner.set_timeout(constants.TIMEOUT_TIME_MILLIS)
205         pass
206
207 class MoviesView(gtk.TreeView):
208
209     def __init__(self):
210         super(MoviesView, self).__init__()
211         model = MoviesListStore()
212         self.set_model(model)
213
214         movie_image_renderer = gtk.CellRendererPixbuf()
215         column = gtk.TreeViewColumn('Image', movie_image_renderer, pixbuf = model.IMAGE_COLUMN)
216         self.append_column(column)
217
218         movie_text_renderer = gtk.CellRendererText()
219         movie_text_renderer.set_property('ellipsize', pango.ELLIPSIZE_END)
220         column = gtk.TreeViewColumn('Name', movie_text_renderer, markup = model.INFO_COLUMN)
221         self.append_column(column)
222
223         self.show_all()
224
225     def add_movies(self, movie_list):
226         model = self.get_model()
227         model.add(movie_list)
228
229 class MoviesListStore(gtk.ListStore):
230
231     IMAGE_COLUMN = 0
232     INFO_COLUMN = 1
233     MOVIE_COLUMN = 2
234
235     def __init__(self):
236         super(MoviesListStore, self).__init__(gtk.gdk.Pixbuf,
237                                               str,
238                                               gobject.TYPE_PYOBJECT)
239
240     def add(self, movies_found):
241         self.clear()
242         for movie in movies_found:
243             row = {self.IMAGE_COLUMN: movie.get_image(),
244                    self.INFO_COLUMN: movie.get_info(),
245                    self.MOVIE_COLUMN: movie,
246                   }
247             self.append(row.values())
248
249 if __name__ == "__main__":
250     maevies = Maevies()
251     maevies.run()
252
253 class AboutDialog(gtk.Dialog):
254
255     def __init__(self, parent):
256         super(AboutDialog, self).__init__(parent = parent,
257                                           flags = gtk.DIALOG_DESTROY_WITH_PARENT)
258         self.set_title("About Maevies")
259         self.show_all()
260
261 class MovieDecorator:
262
263     def __init__(self, name):
264         self._name = name
265         pass
266
267     def get_name(self):
268         return self._name
269
270     def get_length(self):
271         return "%sh:%sm" % (random.randrange(1, 2), random.randrange(0, 59))
272
273     def get_score(self):
274         return "%s" % (random.randrange(6, 9))
275
276     def get_info(self):
277         return "<b>%s</b>\n<small><i>Length: </i>%s || <i>Score: </i>%s</small>" % (
278                                                                                      self.get_name(),
279                                                                                      self.get_length(),
280                                                                                      self.get_score())
281
282     def get_image(self):
283         return self._get_placeholder_pixbuf()
284
285     def _get_placeholder_pixbuf(self):
286         pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(constants.PLACEHOLDER_IMAGE,
287                                                     constants.IMAGE_WIDTH,
288                                                     constants.IMAGE_HEIGHT)
289         return pixbuf