Avoid useless refilters when the user is typing fast
[mussorgsky] / src / aa_selection_dialog.py
1 import hildon
2 import gtk
3 import gobject
4 from album_art_thread import MussorgskyAlbumArt
5
6 RESPONSE_CLICK = 1
7
8 import i18n
9 _ = i18n.language.gettext
10
11 class ClickableImage (gtk.EventBox):
12
13     def __init__ (self, isRemoveOption=False):
14         gtk.EventBox.__init__ (self)
15
16         self.isRemoveOption = isRemoveOption
17
18         self.img = gtk.Image ()
19         self.img.set_size_request (124, 124)
20         self.add (self.img)
21         self.set_sensitive (False)
22
23         self.img_path = None
24         self.thumb_path = None
25
26         if (self.isRemoveOption):
27             self.img.set_from_icon_name ("mediaplayer_default_album",
28                                          gtk.ICON_SIZE_MENU)
29             self.img.set_pixel_size (124)
30             self.set_sensitive (True)
31             
32     def set_image (self, tmp_img, tmp_thumb):
33         assert not self.isRemoveOption
34         self.img_path = tmp_img
35         self.thumb_path = tmp_thumb
36         self.img.set_from_file (self.thumb_path)
37         self.set_sensitive (True)
38
39     def set_default_image (self):
40         self.img.set_from_stock (gtk.STOCK_CDROM, gtk.ICON_SIZE_DIALOG)
41
42     def get_paths (self):
43         return self.img_path, self.thumb_path
44
45     def is_remove_option (self):
46         return self.isRemoveOption
47         
48
49 class AlbumArtSelectionDialog (gtk.Dialog):
50
51     def __init__ (self, parent, artist, album, size, downloader=None):
52         """
53         parent window, amount of images to offer
54         Optionally downloader (for testing porpouses)
55         """
56         gtk.Dialog.__init__ (self,
57                              _("Select album art"), parent,
58                              gtk.DIALOG_DESTROY_WITH_PARENT,
59                              (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT))
60         self.artist = artist
61         self.album = album
62         self.size = size
63         self.__create_view (size)
64         self.cancel = False
65         self.connect ("response", self.handle_response)
66
67         if (downloader):
68             self.downloader = downloader
69         else:
70             self.downloader = MussorgskyAlbumArt ()
71
72         gobject.idle_add (self.__get_alternatives_async)
73         self.selection_img = None
74         self.selection_thumb = None
75         hildon.hildon_gtk_window_set_progress_indicator (self, 1)
76
77
78     def __create_view (self, size):
79         hbox = gtk.HBox (homogeneous=True)
80
81         self.images = []
82         for i in range (0, size):
83             image = ClickableImage ()
84             image.connect ("button-release-event", self.click_on_img)
85             self.images.append (image)
86             hbox.pack_start (image, expand=False, fill=True)
87             
88         # default empty option
89         image = ClickableImage (isRemoveOption=True)
90         image.connect ("button-release-event", self.click_on_img)
91         self.images.append (image)
92         hbox.pack_start (image, expand=False, fill=True)
93         self.vbox.pack_start (hbox, padding=24)
94         
95         label = gtk.Label (_("New search:"))
96         self.entry = hildon.Entry (gtk.HILDON_SIZE_FINGER_HEIGHT)
97         self.entry.set_text (self.artist + " " +  self.album)
98
99         img = gtk.Image ()
100         img.set_from_icon_name ("general_search", gtk.ICON_SIZE_LARGE_TOOLBAR)
101         button = hildon.Button (gtk.HILDON_SIZE_FINGER_HEIGHT,
102                                 hildon.BUTTON_ARRANGEMENT_HORIZONTAL)
103         button.set_image (img)
104         button.connect ("clicked", self.user_text_search_cb, self.entry)
105         self.hbox_research = gtk.HBox (homogeneous=False, spacing=6)
106         self.hbox_research.pack_start (label, expand=False)
107         self.hbox_research.pack_start (self.entry)
108         self.hbox_research.pack_start (button, expand=False)
109         self.hbox_research.set_sensitive (False)
110         self.vbox.pack_start (self.hbox_research, padding=6)
111
112     def __get_alternatives_async (self):
113         results = self.downloader.get_alternatives (self.album,
114                                                     self.artist,
115                                                     self.size)
116         self.__show_results (results)
117         
118     def __show_results (self, generator):
119         counter = 0
120         for (path, thumb) in generator:
121             print path, thumb
122             if (self.cancel):
123                 return False
124             if (thumb):
125                 print "Setting", thumb, "as image"
126                 self.images[counter].set_image (path, thumb)
127             else:
128                 continue
129             counter += 1
130             while (gtk.events_pending()):
131                 gtk.main_iteration()
132
133         while (counter < self.size):
134                 self.images[counter].set_default_image ()
135                 counter += 1
136                 
137         hildon.hildon_gtk_window_set_progress_indicator (self, 0)
138         self.hbox_research.set_sensitive (True)
139         self.entry.grab_focus ()
140         self.entry.select_region (0, -1)
141         
142     def user_text_search_cb (self, w, entry):
143         user_text = entry.get_text ()
144         if user_text and len (user_text) > 0:
145             hildon.hildon_gtk_window_set_progress_indicator (self, 1)
146             for ev in self.images[:-1]:
147                 ev.set_sensitive (False)
148             self.hbox_research.set_sensitive (False)
149             while (gtk.events_pending()):
150                 gtk.main_iteration()
151
152             results = self.downloader.get_alternatives_free_text (user_text,
153                                                                   self.size)
154             self.__show_results (results)
155             
156
157     def click_on_img (self, image, event):
158         if (image.is_remove_option ()):
159             self.selection_img = None
160             self.selection_thumb = None
161             self.downloader.reset_alternative (self.artist, self.album)
162         else:
163             tmp_img, tmp_thumb = image.get_paths ()
164             img, thumb = self.downloader.save_alternative (self.artist,
165                                                            self.album,
166                                                            tmp_img,
167                                                            tmp_thumb)
168             self.selection_img, self.selection_thumb = img, thumb
169         self.response (RESPONSE_CLICK)
170
171     def get_selection (self):
172         return (self.selection_img, self.selection_thumb)
173     
174     def handle_response (self, widget, response_id):
175         self.cancel = True
176         # Return False to continue propagating the signal
177         return False
178
179 if __name__ == "__main__":
180
181     import time
182     class MockDownloader:
183         def __init__ (self):
184             self.alt = [("../hendrix.jpeg", "../thumb1.124.jpeg"),
185                         ("../hoover.jpeg", "../thumb2.124.jpeg"),
186                         ("../backbeat.jpeg", "../thumb3.124.jpeg"),
187                         ("../dylan.jpeg", "../thumb5.jpeg")]
188         def get_alternatives (self, album, artist, amount):
189             for a in self.alt:
190                 time.sleep (1)
191                 yield a
192         def get_alternatives_free_text (self, user_text, amount=4):
193             for a in [("free%d" % i, "thumb%d" %i) for i in range (0, amount)]:
194                 time.sleep (1)
195                 yield a
196         def save_alternative (self, artist, album, img, thumb):
197             return ("/home/user/.cache/media-art/" + img, "/home/user/.thumbnails/normal/" + thumb)
198         def reset_alternative (self, artist, album):
199             print "Removing the album-art and the thumbnail"
200                               
201
202     def clicked_button (self):
203         aadd = AlbumArtSelectionDialog (w, "joe henderson", "blue note", 4, MockDownloader ())
204         aadd.show_all ()
205         response = aadd.run ()
206         if response == gtk.RESPONSE_CLOSE or response == gtk.RESPONSE_DELETE_EVENT or response == gtk.RESPONSE_REJECT:
207             print "Noooo"
208         else:
209             print "RESPONSE_CLICK", response == RESPONSE_CLICK
210             print "Selected", aadd.get_selection ()
211         aadd.hide ()
212         
213     w = gtk.Window ()
214     w.connect ("destroy", gtk.main_quit)
215     box = gtk.VBox ()
216
217     button = gtk.Button ("click")
218     button.connect ("clicked", clicked_button)
219     box.add (button)
220
221     w.add (box)
222     w.show_all ()
223
224
225     gtk.main ()
226