ui: Several UI changes
[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_VERTICAL)
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
171         content_area.add(self._movies_view)
172         self.add(content_area)
173
174         self.show_all()
175
176     def _simulate_search(self):
177         self._show_banner()
178         hildon.hildon_gtk_window_set_progress_indicator(self, True)
179         gobject.timeout_add(constants.TIMEOUT_TIME_MILLIS, self._populate_view)
180
181     def _populate_view(self):
182         self._movies_view.add_movies([MovieDecorator("The Lord of the Rings"),
183                                       MovieDecorator("The Lord of the flies"),
184                                       MovieDecorator("Gone by the wind"),
185                                       MovieDecorator("Madagascar"),
186                                       MovieDecorator("Madagascar 2"),
187                                       MovieDecorator("2 Fast 2 Furious"),
188                                       MovieDecorator("Fast &amp; Furious"),
189                                       MovieDecorator("Pitch Black"),
190                                       ])
191         hildon.hildon_gtk_window_set_progress_indicator(self, False)
192         return False
193
194     def _show_banner(self):
195         message = "Searching <i>%(category)s</i> for <i>%(term)s</i>" % {'category': self.search_category,
196                                                                          'term' : self.search_term}
197         banner = hildon.hildon_banner_show_information_with_markup(self,
198                                                                    "ignored",
199                                                                    message)
200         banner.set_timeout(constants.TIMEOUT_TIME_MILLIS)
201         pass
202
203 class MoviesView(gtk.TreeView):
204
205     def __init__(self):
206         super(MoviesView, self).__init__()
207         model = MoviesListStore()
208         self.set_model(model)
209
210         movie_image_renderer = gtk.CellRendererPixbuf()
211         column = gtk.TreeViewColumn('Image', movie_image_renderer, pixbuf = model.IMAGE_COLUMN)
212         self.append_column(column)
213
214         movie_text_renderer = gtk.CellRendererText()
215         movie_text_renderer.set_property('ellipsize', pango.ELLIPSIZE_END)
216         column = gtk.TreeViewColumn('Name', movie_text_renderer, markup = model.INFO_COLUMN)
217         self.append_column(column)
218
219         self.show_all()
220
221     def add_movies(self, movie_list):
222         model = self.get_model()
223         model.add(movie_list)
224
225 class MoviesListStore(gtk.ListStore):
226
227     IMAGE_COLUMN = 0
228     INFO_COLUMN = 1
229     MOVIE_COLUMN = 2
230
231     def __init__(self):
232         super(MoviesListStore, self).__init__(gtk.gdk.Pixbuf,
233                                               str,
234                                               gobject.TYPE_PYOBJECT)
235
236     def add(self, movies_found):
237         self.clear()
238         for movie in movies_found:
239             row = {self.IMAGE_COLUMN: movie.get_image(),
240                    self.INFO_COLUMN: movie.get_info(),
241                    self.MOVIE_COLUMN: movie,
242                   }
243             self.append(row.values())
244
245 class AboutDialog(gtk.Dialog):
246
247     def __init__(self, parent):
248         super(AboutDialog, self).__init__(parent = parent,
249                                           flags = gtk.DIALOG_DESTROY_WITH_PARENT)
250         self.set_title("About Maevies")
251         self.show_all()
252
253 class MovieDecorator:
254
255     def __init__(self, name):
256         self._name = name
257         pass
258
259     def get_name(self):
260         return self._name
261
262     def get_length(self):
263         return "%sh:%sm" % (random.randrange(1, 2), random.randrange(0, 59))
264
265     def get_score(self):
266         return "%s" % (random.randrange(6, 9))
267
268     def get_info(self):
269         return "<b>%s</b>\n<small><i>Length: </i>%s || <i>Score: </i>%s</small>" % (
270                                                                                      self.get_name(),
271                                                                                      self.get_length(),
272                                                                                      self.get_score())
273
274     def get_image(self):
275         return self._get_placeholder_pixbuf()
276
277     def _get_placeholder_pixbuf(self):
278         pixbuf = gtk.IconTheme().load_icon('general_video_file', 48, 0)
279         return pixbuf
280
281 if __name__ == "__main__":
282     maevies = Maevies()
283     maevies.run()