3 Playlist UI for MusicBox application.
5 Copyright 2004 Kenneth Hayber <khayber@socal.rr.com>
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License.
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.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 from __future__
import generators
24 import gtk
, gobject
, os
, sys
, re
27 from rox
import Menu
, saving
, loading
, mime
30 from playlist
import COL_FILE
, COL_TITLE
, COL_TRACK
, COL_ALBUM
, COL_ARTIST
, COL_GENRE
, COL_LENGTH
, COL_TYPE
33 #Who am I and how did I get here?
38 VIEW_DEFAULT_SIZE
= (760, 400)
42 # (_("Filename"), COL_FILE, str, 100),
43 (_("Artist"), COL_ARTIST
, str, 200),
44 (_("Album"), COL_ALBUM
, str, 200),
45 (_("Title"), COL_TITLE
, str, 200),
46 (_("Track"), COL_TRACK
, int, 50),
47 (_("Genre"), COL_GENRE
, str, 80),
48 # (_("Length"), COL_LENGTH, int, 60),
49 # (_("Type"), COL_TYPE, str, 60),
52 DND_TYPES
= ['audio/x-mp3' 'application/ogg' 'inode/directory']
54 class PlaylistUI(rox
.Window
, loading
.XDSLoader
):
55 """the playlist UI for MusicBox"""
57 def __init__(self
, the_playlist
, musicbox
):
59 rox
.Window
.__init
__(self
)
60 loading
.XDSLoader
.__init
__(self
, DND_TYPES
)
62 self
.playlist
= the_playlist
#this is a reference to the main playlist
64 self
.replace_library
= True
65 self
.musicbox
= musicbox
67 self
.set_title(APP_NAME
+' - '+_("Playlist"))
68 self
.set_role("PlayList")
69 self
.set_border_width(0)
70 self
.set_default_size(VIEW_DEFAULT_SIZE
[0], VIEW_DEFAULT_SIZE
[1])
71 self
.set_position(gtk
.WIN_POS_NONE
)
73 #capture wm delete event
74 self
.connect('delete_event', self
.delete_event
)
77 self
.add_events(gtk
.gdk
.BUTTON_PRESS_MASK
)
78 self
.connect('button-press-event', self
.button_press
)
80 Menu
.set_save_name(APP_NAME
)
81 self
.menu
= Menu
.Menu('main', [
82 # Menu.SubMenu(_('Filter'), [
83 # Menu.Action(_("All songs"), 'filter_none', ''),
84 # Menu.Action(_("This Artist"), 'filter_artist', ''),
85 # Menu.Action(_("This Album"), 'filter_album', ''),
86 # Menu.Action(_("This Genre"), 'filter_genre', ''),
87 # Menu.Action(_("New Filter..."), 'filter_new', '')
90 Menu
.Action(_("Save"), 'save', '', gtk
.STOCK_SAVE
),
92 Menu
.Action(_("Close"), 'close', '', gtk
.STOCK_CLOSE
),
94 self
.menu
.attach(self
,self
)
97 swin
= gtk
.ScrolledWindow()
98 self
.scroll_window
= swin
100 swin
.set_border_width(0)
101 swin
.set_policy(gtk
.POLICY_AUTOMATIC
, gtk
.POLICY_AUTOMATIC
)
103 # view = gtk.TreeView(self.playlist.song_list.filter_new())
104 view
= gtk
.TreeView(self
.playlist
.song_list
)
107 view
.set_rules_hint(True)
108 self
.view
.set_reorderable(True)
109 self
.view
.set_search_column(COL_TITLE
)
111 #enable for drag from playlist to other apps (doesn't work yet)
112 # self.view.drag_source_set(gtk.gdk.BUTTON_PRESS_MASK, [('text/uri-list', 0, 0)], gtk.gdk.ACTION_COPY)
113 # self.view.connect('drag_data_get', self.drag_data_get)
115 self
.view
.add_events(gtk
.gdk
.BUTTON_PRESS_MASK
)
116 self
.view
.connect('button-press-event', self
.button_press
)
118 #TODO: A little icon showing the current song playing...
119 #cell = gtk.CellRendererPixbuf()
120 #column = gtk.TreeViewColumn('', cell)
121 #view.append_column(column)
122 #column.set_resizable(False)
123 #column.set_reorderable(False)
125 for n
in range(len(COLUMNS
)):
126 cell
= gtk
.CellRendererText()
127 column
= gtk
.TreeViewColumn(COLUMNS
[n
][0], cell
, text
= COLUMNS
[n
][1])
128 view
.append_column(column
)
129 column
.set_sort_column_id(COLUMNS
[n
][1])
130 column
.set_resizable(True)
131 column
.set_reorderable(True)
132 column
.set_sizing(gtk
.TREE_VIEW_COLUMN_FIXED
)
133 column
.set_fixed_width(COLUMNS
[n
][3])
134 column
.connect('clicked', self
.col_activate
)
136 view
.connect('row-activated', self
.activate
)
137 self
.selection
= view
.get_selection()
138 self
.handler
= self
.selection
.connect('changed', self
.set_selection
)
139 self
.view
.set_search_column(COL_ARTIST
)
141 #TODO: Multiple Selections
142 #self.selection.set_mode(gtk.SELECTION_MULTIPLE)
144 # Create layout, pack and show widgets
145 self
.vbox
= gtk
.VBox()
147 self
.vbox
.pack_start(self
.scroll_window
, True, True, 0)
153 def drag_data_get(self
, widget
, context
, selection
, targetType
, eventTime
):
154 print >>sys
.stderr
, selection
.target
, selection
.format
, selection
.data
155 if selection
.target
== 'text/uri-list':
156 selection
.set(selection
.target
, 8, 'test.fil\n')
159 """Load the playlist either from a saved xml file, or from source dirs"""
161 if self
.replace_library
:
162 self
.musicbox
.load_songs(self
.library
)
164 self
.musicbox
.add_songs(self
.library
)
166 rox
.report_exception()
169 """Save the current list"""
170 box
= saving
.SaveBox(self
.playlist
, rox
.choices
.save(APP_NAME
, 'Library.xml'), 'text/xml')
174 """Scroll the playlistUI to the currently selected song"""
176 index
= self
.playlist
.get_index()
177 self
.view
.set_cursor((index
,))
178 self
.view
.scroll_to_cell((index
,))
183 """Play the current song"""
187 rox
.report_exception()
189 def activate(self
, view
, path
, column
):
190 """Double-click handler, plays the song"""
191 self
.playlist
.set(path
[0])
194 def set_selection(self
, selection
):
195 """Tell the playlist what we currently have selected"""
199 def delete_event(self
, ev
, e1
):
200 """Same as close, but called from the window manager"""
203 def close(self
, button
= None):
204 """Destroy ourselves and all our children"""
207 def button_press(self
, text
, event
):
208 """Popup menu handler"""
209 if event
.button
!= 3:
211 self
.menu
.popup(self
, event
)
214 def col_activate(self
, column
):
215 """Set the selected column as the search <Ctrl-S> column"""
216 self
.view
.set_search_column(column
.get_sort_column_id())
218 def xds_drag_drop(self
, widget
, context
, data
, info
, time
):
219 """Check if the Shift key is pressed or not when Dropping files"""
220 if context
.actions
& gtk
.gdk
.ACTION_COPY
:
221 self
.replace_library
= False
223 self
.replace_library
= True
224 return loading
.XDSLoader
.xds_drag_drop(self
, widget
, context
, data
, info
, time
)
226 def xds_load_uris(self
, uris
):
227 """Accept files and folders dropped on us as new Library"""
229 #strip off the 'file://' part and concatenate them
231 path
.append(rox
.get_local_path(s
))