Use table for the edit view layout
[mussorgsky] / src / edit_panel.py
1 #!/usr/bin/env python2.5
2 import hildon
3 import gtk
4 from mutagen_backend import MutagenBackend
5 from player_backend import MediaPlayer
6
7 # Fields in the tuple!
8 FILE_URI = 0
9 ARTIST_KEY = 2
10 TITLE_KEY = 3
11 ALBUM_KEY = 4
12 MIME_KEY = 5
13
14 class MussorgskyEditPanel (hildon.StackableWindow):
15
16     def __init__ (self, songs_list=None, albums_list=None, artists_list=None):
17         hildon.StackableWindow.__init__ (self)
18         self.set_title ("Edit")
19         self.writer = MutagenBackend ()
20         self.player = MediaPlayer ()
21         self.albums_list = albums_list
22         self.artists_list = artists_list
23         self.add (self.__create_view ())
24         if (songs_list):
25             self.set_songs_list (songs_list)
26         self.banner = None
27
28         self.artists_selector = None
29         self.artists_dialog = None
30
31         self.albums_selector = None
32         self.albums_dialog = None
33         
34     def set_songs_list (self, songs_list):
35             self.songs_list = songs_list
36             self.set_data_in_view (songs_list [0])
37             self.song_counter = 0
38
39     def press_back_cb (self, widget):
40         if (self.player.is_playing ()):
41             self.player.stop ()
42
43         if (self.banner and self.banner.get_property("visible")):
44             self.banner.destroy ()
45
46         if self.__is_view_dirty ():
47             print "Modified data. Save!"
48             self.save_metadata ()
49             
50         if (self.song_counter > 0):
51             self.song_counter -= 1
52             self.set_data_in_view (self.songs_list [self.song_counter])
53
54     def press_next_cb (self, widget):
55         if (self.player.is_playing ()):
56             self.player.stop ()
57
58         if (self.banner and self.banner.get_property("visible")):
59             self.banner.destroy ()
60
61         if self.__is_view_dirty ():
62             print "Modified data. Save!"
63             self.save_metadata ()
64
65         if (self.song_counter < len (self.songs_list) -1):
66             self.song_counter += 1
67             self.set_data_in_view (self.songs_list [self.song_counter])
68         else:
69             self.destroy ()
70
71     def save_metadata (self):
72         # Save the data in the online model to show the appropiate data
73         # in the UI while tracker process the update.
74         song = self.songs_list [self.song_counter]
75
76         new_song = (song[FILE_URI], song[1],
77                     self.artist_entry.get_text (),
78                     self.title_entry.get_text (),
79                     self.album_entry.get_text (),
80                     song[MIME_KEY])
81         self.songs_list [self.song_counter] = new_song
82         try:
83             self.writer.save_metadata_on_file (new_song[FILE_URI],
84                                                new_song[MIME_KEY],
85                                                self.artist_entry.get_text (),
86                                                self.title_entry.get_text (),
87                                                self.album_entry.get_text ())
88         except IOError, e:
89             # This error in case of tracker returning unexistent files.
90             # Uhm.... for instance after removing a memory card we are editing!
91             dialog = gtk.MessageDialog (self,
92                                         gtk.DIALOG_DESTROY_WITH_PARENT,
93                                         gtk.MESSAGE_ERROR,
94                                         gtk.BUTTONS_CLOSE,
95                                         "%s" % str(e));
96             dialog.run ()
97
98         
99
100     def __is_view_dirty (self):
101         """
102         True if the data has been modified in the widgets
103         """
104         song = self.songs_list [self.song_counter]
105
106         return not (self.filename_data.get_text() == song[FILE_URI] and
107                     self.artist_entry.get_text () == song[ARTIST_KEY] and
108                     self.title_entry.get_text () == song[TITLE_KEY] and
109                     self.album_entry.get_text () == song[ALBUM_KEY] )
110         
111
112     def __create_view (self):
113         view_vbox = gtk.VBox (homogeneous=False, spacing = 24)
114
115         filename_row = gtk.HBox ()
116         filename_label = gtk.Label ("Filename:")
117         filename_row.pack_start (filename_label, expand=False, padding=12);
118         self.filename_data = gtk.Label ("")
119         filename_row.pack_start (self.filename_data, expand=True)
120
121         play_button = gtk.Button (stock=gtk.STOCK_MEDIA_PLAY)
122         play_button.connect ("clicked", self.clicked_play)
123         filename_row.pack_start (play_button, expand=False, fill=False, padding=12)
124         view_vbox.pack_start (filename_row, expand=True);
125
126         central_panel = gtk.VBox ()
127
128         table = gtk.Table (3, 2, False)
129         table.set_col_spacings (12)
130         table.set_row_spacings (12)
131
132         central_panel.pack_start (table)
133         view_vbox.pack_start (central_panel, expand=True, fill=True)
134
135         # Artist row
136         button_artist = gtk.Button ("Artist:")
137         if (not self.artists_list):
138             button_artist.set_sensitive (False)
139         button_artist.connect ("clicked", self.artist_selection_cb)
140         table.attach (button_artist, 0, 1, 0, 1, 0, gtk.FILL|gtk.EXPAND)
141         self.artist_entry = gtk.Entry()
142         table.attach (self.artist_entry, 1, 2, 0, 1)
143
144         # Title row
145         label_title = gtk.Label ("Title:")
146         table.attach (label_title, 0, 1, 1, 2, 0)
147         self.title_entry = gtk.Entry()
148         table.attach (self.title_entry, 1, 2, 1, 2)
149
150         # Album row
151         button_album = gtk.Button ("Album:")
152         if (not self.albums_list):
153             button_album.set_sensitive (False)
154         button_album.connect ("clicked", self.album_selection_cb)
155         table.attach (button_album, 0, 1, 2, 3, 0)
156         self.album_entry = gtk.Entry()
157         table.attach (self.album_entry, 1, 2, 2, 3)
158
159         # Buttons row
160         button_box = gtk.HButtonBox ()
161         button_box.set_layout (gtk.BUTTONBOX_END)
162
163         back_button = gtk.Button (stock=gtk.STOCK_GO_BACK)
164         back_button.connect ("clicked", self.press_back_cb)
165         button_box.pack_start (back_button, expand=True, fill=True, padding=6)
166         
167         next_button = gtk.Button (stock=gtk.STOCK_GO_FORWARD)
168         next_button.connect ("clicked", self.press_next_cb)
169         button_box.pack_start (next_button, expand=True, fill=True, padding=6)
170         
171         view_vbox.pack_start (button_box, expand=False, fill=True, padding=12)
172         
173         return view_vbox
174
175
176     def set_data_in_view (self, song):
177         """
178         Place in the screen the song information.
179         Song is a tuple like (filename, 'Music', title, artist, album, mime)
180         """
181         assert len (song) == 6
182         self.filename_data.set_text (song[FILE_URI])
183         self.artist_entry.set_text (song[ARTIST_KEY])
184         self.title_entry.set_text (song[TITLE_KEY])
185         self.album_entry.set_text (song[ALBUM_KEY])
186
187         if (not song[MIME_KEY] in self.writer.get_supported_mimes ()):
188             print "show notification"
189             self.banner = hildon.Banner ()
190             self.banner.set_text ("Unsupported format (%s)" % song[MIME_KEY])
191             self.banner.show_all ()
192
193     def clicked_play (self, widget):
194         if (self.player.is_playing ()):
195             self.player.stop ()
196         else:
197             song = self.songs_list [self.song_counter]
198             self.player.play ("file://" + song[FILE_URI])
199
200     def album_selection_cb (self, widget):
201         if (not self.albums_selector):
202             self.albums_selector = hildon.hildon_touch_selector_new_text ()
203             for album in self.albums_list :
204                 self.albums_selector.append_text (album[0])
205
206         if (not self.albums_dialog):
207             self.albums_dialog = hildon.PickerDialog (self)
208             self.albums_dialog.set_title ("Choose album...")
209             self.albums_dialog.set_selector (self.albums_selector)
210
211         response = self.albums_dialog.run ()
212         if (response == gtk.RESPONSE_OK):
213             print "Ok (%s)" % (self.albums_selector.get_current_text ())
214             self.album_entry.set_text (self.albums_selector.get_current_text ())
215         self.albums_dialog.hide ()
216
217     def artist_selection_cb (self, widget):
218         if (not self.artists_selector):
219             self.artists_selector = hildon.hildon_touch_selector_new_text ()
220             for artist in self.artists_list :
221                 self.artists_selector.append_text (artist[0])
222                 
223         if (not self.artists_dialog):
224             self.artists_dialog = hildon.PickerDialog (self)
225             self.artists_dialog.set_title ("Choose artist...")
226             self.artists_dialog.set_selector (self.artists_selector)
227
228         response = self.artists_dialog.run ()
229
230         if (response == gtk.RESPONSE_OK):
231             print "Ok (%s)" % (self.artists_selector.get_current_text ())
232             self.artist_entry.set_text (str(self.artists_selector.get_current_text ()))
233         self.artists_dialog.hide ()
234
235 # Testing porpuses
236 if __name__ == "__main__":
237
238     TEST_DATA = [("/a/b/c/d.mp3", "Music", "", "title", "album", "audio/mpeg"),
239                  ("/home/user/mufix/dejame.mp3", "Music", "", "title", "album 2", "a/b"),
240                  ("/home/user/mufix/3.mp2", "Music", "", "titlex", "album 3", "audio/mpeg")]
241     ALBUMS = [["Album %d" % i] for i in range (0, 10)]
242     ARTISTS = [["Artist %d" % i] for i in range (0, 10)]
243     window = MussorgskyEditPanel (TEST_DATA, ALBUMS, ARTISTS)
244     window.connect ("destroy", gtk.main_quit)
245     window.show_all ()
246     gtk.main ()