Hi, After adding the genres to the interface i start to think that I also miss the browse option of iTunes, so I went ahead and added to the 0.10.4; attached is the patch and a screen shot of banshee with browser. regards, Oscar.
Attachment:
Banshee-Browse.png
Description: Portable Network Graphics Format
? INSTALL ? Makefile ? Makefile.in ? aclocal.m4 ? autom4te.cache ? banshee.pc ? config.guess ? config.h ? config.h.in ? config.log ? config.status ? config.sub ? configure ? depcomp ? install-sh ? intltool-extract ? intltool-extract.in ? intltool-merge ? intltool-merge.in ? intltool-update ? intltool-update.in ? libtool ? ltmain.sh ? missing ? mkinstalldirs ? stamp-h1 ? burn-sharp/.deps ? burn-sharp/.libs ? burn-sharp/glue.lo ? burn-sharp/libnautilusburnglue.la ? data/banshee.glade.sec ? libbanshee/.deps ? libbanshee/.libs ? libbanshee/gst-cd-rip-0.8.lo ? libbanshee/gst-misc-0.8.lo ? libbanshee/gst-playback-0.8.lo ? libbanshee/gst-transcode-0.8.lo ? libbanshee/hal-context.lo ? libbanshee/inotify-glue.lo ? libbanshee/libbanshee.la ? libbanshee/xing/.deps ? po/.intltool-merge-cache Index: data/banshee.glade =================================================================== RCS file: /cvs/gnome/banshee/data/banshee.glade,v retrieving revision 1.6 diff -u -r1.6 banshee.glade --- data/banshee.glade 14 Jan 2006 09:11:02 -0000 1.6 +++ data/banshee.glade 31 Jan 2006 14:30:26 -0000 @@ -17,7 +17,6 @@ <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property> <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> <property name="focus_on_map">True</property> - <property name="urgency_hint">False</property> <signal name="delete_event" handler="OnWindowPlayerDeleteEvent" last_modification_time="Sat, 29 Jan 2005 07:50:08 GMT"/> <child> @@ -340,23 +339,65 @@ </child> <child> - <widget class="GtkLabel" id="SearchLabel"> + <widget class="GtkHBox" id="SearchBox"> <property name="visible">True</property> - <property name="sensitive">False</property> - <property name="label" translatable="yes">_Search:</property> - <property name="use_underline">True</property> - <property name="use_markup">False</property> - <property name="justify">GTK_JUSTIFY_LEFT</property> - <property name="wrap">False</property> - <property name="selectable">False</property> - <property name="xalign">0.5</property> - <property name="yalign">0.5</property> - <property name="xpad">0</property> - <property name="ypad">0</property> - <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> - <property name="width_chars">-1</property> - <property name="single_line_mode">False</property> - <property name="angle">0</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkLabel" id="SearchLabel"> + <property name="visible">True</property> + <property name="sensitive">False</property> + <property name="label" translatable="yes">_Search:</property> + <property name="use_underline">True</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="mnemonic_widget">BrowseButton</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkToggleButton" id="BrowseButton"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + + <child> + <widget class="GtkImage" id="image9"> + <property name="visible">True</property> + <property name="stock">gtk-go-down</property> + <property name="icon_size">4</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> </widget> <packing> <property name="padding">0</property> @@ -373,6 +414,112 @@ </child> <child> + <widget class="GtkHBox" id="BrowserBox"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkScrolledWindow" id="scrolledwindow4"> + <property name="border_width">2</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property> + <property name="window_placement">GTK_CORNER_TOP_LEFT</property> + + <child> + <widget class="GtkTreeView" id="GenreList"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="headers_visible">False</property> + <property name="rules_hint">False</property> + <property name="reorderable">False</property> + <property name="enable_search">True</property> + <property name="fixed_height_mode">False</property> + <property name="hover_selection">False</property> + <property name="hover_expand">False</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkScrolledWindow" id="scrolledwindow3"> + <property name="border_width">2</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property> + <property name="window_placement">GTK_CORNER_TOP_LEFT</property> + + <child> + <widget class="GtkTreeView" id="ArtistList"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="headers_visible">False</property> + <property name="rules_hint">False</property> + <property name="reorderable">False</property> + <property name="enable_search">True</property> + <property name="fixed_height_mode">False</property> + <property name="hover_selection">False</property> + <property name="hover_expand">False</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkScrolledWindow" id="scrolledwindow5"> + <property name="border_width">2</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property> + <property name="window_placement">GTK_CORNER_TOP_LEFT</property> + + <child> + <widget class="GtkTreeView" id="AlbumList"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="headers_visible">False</property> + <property name="rules_hint">False</property> + <property name="reorderable">False</property> + <property name="enable_search">True</property> + <property name="fixed_height_mode">False</property> + <property name="hover_selection">False</property> + <property name="hover_expand">False</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> <widget class="GtkAlignment" id="LibraryAlignment"> <property name="visible">True</property> <property name="xalign">0.5</property> @@ -481,7 +628,6 @@ <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property> <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> <property name="focus_on_map">True</property> - <property name="urgency_hint">False</property> <child> <widget class="GtkVBox" id="vbox1"> @@ -839,7 +985,7 @@ <child> <widget class="GtkTable" id="table1"> <property name="visible">True</property> - <property name="n_rows">3</property> + <property name="n_rows">4</property> <property name="n_columns">2</property> <property name="homogeneous">False</property> <property name="row_spacing">8</property> @@ -1111,6 +1257,91 @@ <property name="y_options">fill</property> </packing> </child> + + <child> + <widget class="GtkHBox" id="hbox15"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">5</property> + + <child> + <widget class="GtkButton" id="GenreSync"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + + <child> + <widget class="GtkImage" id="image9"> + <property name="visible">True</property> + <property name="stock">gtk-copy</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label63"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Genre</property> + <property name="use_underline">True</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="mnemonic_widget">Title</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + <property name="x_options">fill</property> + <property name="y_options">fill</property> + </packing> + </child> + + <child> + <widget class="GtkComboBoxEntry" id="Genre"> + <property name="visible">True</property> + <property name="add_tearoffs">False</property> + <property name="has_frame">True</property> + <property name="focus_on_click">True</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + <property name="x_options">fill</property> + <property name="y_options">fill</property> + </packing> + </child> </widget> <packing> <property name="padding">0</property> @@ -1414,7 +1645,7 @@ <widget class="GtkExpander" id="AdvancedExpander"> <property name="visible">True</property> <property name="can_focus">True</property> - <property name="expanded">False</property> + <property name="expanded">True</property> <property name="spacing">0</property> <child> @@ -1432,7 +1663,7 @@ <child> <widget class="GtkTable" id="table2"> <property name="visible">True</property> - <property name="n_rows">4</property> + <property name="n_rows">3</property> <property name="n_columns">4</property> <property name="homogeneous">False</property> <property name="row_spacing">5</property> @@ -1933,7 +2164,6 @@ <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> <property name="focus_on_map">True</property> - <property name="urgency_hint">False</property> <child> <widget class="GtkVBox" id="vbox9"> @@ -2231,7 +2461,6 @@ <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property> <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> <property name="focus_on_map">True</property> - <property name="urgency_hint">False</property> <child> <widget class="GtkVBox" id="vbox4"> Index: src/PlayerInterface.cs =================================================================== RCS file: /cvs/gnome/banshee/src/PlayerInterface.cs,v retrieving revision 1.134 diff -u -r1.134 PlayerInterface.cs --- src/PlayerInterface.cs 17 Jan 2006 16:51:14 -0000 1.134 +++ src/PlayerInterface.cs 31 Jan 2006 14:30:27 -0000 @@ -438,6 +438,7 @@ fields.Add(Catalog.GetString("Song Name")); fields.Add(Catalog.GetString("Artist Name")); fields.Add(Catalog.GetString("Album Title")); + fields.Add(Catalog.GetString("Genre")); searchEntry = new SearchEntry(fields); searchEntry.EnterPress += delegate(object o, EventArgs args) { @@ -448,12 +449,44 @@ }; searchEntry.Changed += OnSimpleSearch; searchEntry.Show(); - ((HBox)gxml["PlaylistHeaderBox"]).PackStart(searchEntry, false, false, 0); + (gxml["SearchBox"] as HBox).PackStart(searchEntry, false, false, 0); gxml["SearchLabel"].Sensitive = false; searchEntry.Sensitive = false; - // Repeat/Shuffle buttons + (gxml["BrowserBox"] as HBox).Visible = false; + (gxml["BrowseButton"] as ToggleButton).Toggled += OnBrowseToggled; + + // Populate Genres List + TreeView genreListView = gxml["GenreList"] as TreeView; + genreListView.AppendColumn ("Genres", new Gtk.CellRendererText (), "text", 0); + genreListView.Selection.Mode = SelectionMode.Single; + ListStore genreModel = new ListStore(typeof(string)); + genreListView.Model = genreModel; + genreModel.AppendValues("All"); + foreach(string genre in Globals.Library.GetGenreList()) { + genreModel.AppendValues(genre); + } + genreListView.Selection.Changed += OnBrowseGenreChanged; + + // Populate Artist List + TreeView artistListView = gxml["ArtistList"] as TreeView; + artistListView.AppendColumn ("Artists", new Gtk.CellRendererText (), "text", 0); + ListStore artistModel = new ListStore(typeof(string)); + artistListView.Model = artistModel; + LoadArtistsForGenre(null); + artistListView.Selection.Changed += OnBrowseArtistChanged; + + // Populate Album List + TreeView albumListView = gxml["AlbumList"] as TreeView; + albumListView.AppendColumn ("Albums", new Gtk.CellRendererText (), "text", 0); + ListStore albumModel = new ListStore(typeof(string)); + albumListView.Model = albumModel; + LoadAlbumsForGenreAndArtist(null,null); + albumListView.Selection.Changed += OnBrowseAlbumChanged; + + + // Repeat/Shuffle buttons /* shuffle_toggle_button = new MultiStateToggleButton(); shuffle_toggle_button.AddState(typeof(ShuffleDisabledToggleState), gxml["ItemShuffle"] as CheckMenuItem, false); @@ -1120,6 +1153,121 @@ } } + private void OnBrowseGenreChanged(object o, EventArgs args) + { + LoadArtistsForGenre(GetSelectedGenre()); + } + + private void OnBrowseArtistChanged(object o, EventArgs args) + { + LoadAlbumsForGenreAndArtist(GetSelectedGenre(), GetSelectedArtist()); + } + + private void OnBrowseAlbumChanged(object o, EventArgs args) + { + playlistModel.Clear(); + + foreach(TrackInfo track in SourceManager.ActiveSource.Tracks) { + try { + if(DoesTrackMatchBrowse(track)) { + playlistModel.AddTrack(track); + } + } catch(Exception) { + continue; + } + } + } + + private bool DoesTrackMatchBrowse(TrackInfo track) + { + return DoesGenreMatch(track) && DoesArtistMatch(track) && DoesAlbumMatch(track); + } + + private bool DoesGenreMatch(TrackInfo track) + { + string genre = GetSelectedGenre(); + return (null == genre) ? true : track.Genre.IndexOf(genre) >=0; + } + + private bool DoesArtistMatch(TrackInfo track) + { + string artist = GetSelectedArtist(); + return (null == artist) ? true : track.Artist.IndexOf(artist) >=0; + } + + private bool DoesAlbumMatch(TrackInfo track) + { + string album = GetSelectedAlbum(); + return (null == album) ? true : track.Album.IndexOf(album) >=0; + } + + private void LoadArtistsForGenre(string genre) + { + TreeView artistListView = gxml["ArtistList"] as TreeView; + ListStore artistsStore = artistListView.Model as ListStore; + artistsStore.Clear(); + artistsStore.AppendValues("All"); + foreach(string artist in Globals.Library.GetArtistsForGenre(genre)) { + artistsStore.AppendValues(artist); + } + TreeIter firstItem; + artistsStore.GetIterFirst(out firstItem); + artistListView.Selection.SelectIter(firstItem); + } + + private void LoadAlbumsForGenreAndArtist(string genre, string artist) + { + TreeView albumListView = gxml["AlbumList"] as TreeView; + ListStore albumsStore = albumListView.Model as ListStore; + albumsStore.Clear(); + albumsStore.AppendValues("All"); + foreach(string album in Globals.Library.GetAlbumsForGenreAndArtist(genre, artist)) { + albumsStore.AppendValues(album); + } + TreeIter firstItem; + albumsStore.GetIterFirst(out firstItem); + albumListView.Selection.SelectIter(firstItem); + } + + private string GetSelectedGenre() + { + TreeView genreListView = gxml["GenreList"] as TreeView; + TreeIter selected; + genreListView.Selection.GetSelected(out selected); + if(TreeIter.Zero.Equals(selected)) { + return null; + } else { + string genre = genreListView.Model.GetValue(selected, 0) as string; + return "All".Equals(genre) ? null : genre; + } + } + + private string GetSelectedArtist() + { + TreeView artistListView = gxml["ArtistList"] as TreeView; + TreeIter selected; + artistListView.Selection.GetSelected(out selected); + if(TreeIter.Zero.Equals(selected)) { + return null; + } else { + string artist = artistListView.Model.GetValue(selected, 0) as string; + return "All".Equals(artist) ? null : artist; + } + } + + private string GetSelectedAlbum() + { + TreeView albumListView = gxml["AlbumList"] as TreeView; + TreeIter selected; + albumListView.Selection.GetSelected(out selected); + if(TreeIter.Zero.Equals(selected)) { + return null; + } else { + string album = albumListView.Model.GetValue(selected, 0) as string; + return "All".Equals(album) ? null : album; + } + } + private void UpdateViewName(Source source) { (gxml["ViewNameLabel"] as Label).Markup = "<b>" + GLib.Markup.EscapeText(source.Name) + "</b>"; @@ -1536,11 +1684,14 @@ match = ti.Title; } else if(field == Catalog.GetString("Album Title")) { match = ti.Album; + } else if(field == Catalog.GetString("Genre")) { + match = ti.Genre; } else { string [] matches = { ti.Artist, ti.Album, - ti.Title + ti.Title, + ti.Genre }; foreach(string m in matches) { @@ -1580,6 +1731,12 @@ } } } + + private void OnBrowseToggled(object o, EventArgs args) + { + (gxml["BrowserBox"] as HBox).Visible = (o as ToggleButton).Active; + (gxml["SearchBox"] as HBox).Visible = ! (o as ToggleButton).Active; + } // PlaylistView DnD Index: src/PlaylistView.cs =================================================================== RCS file: /cvs/gnome/banshee/src/PlaylistView.cs,v retrieving revision 1.37 diff -u -r1.37 PlaylistView.cs --- src/PlaylistView.cs 17 Jan 2006 16:51:14 -0000 1.37 +++ src/PlaylistView.cs 31 Jan 2006 14:30:27 -0000 @@ -55,6 +55,7 @@ Track, Artist, Title, + Genre, Album, Time, Rating, @@ -89,17 +90,20 @@ columns.Add(new PlaylistColumn(this, Catalog.GetString("Title"), "Title", new TreeCellDataFunc(TrackCellTitle), new CellRendererText(), 2, (int)ColumnId.Title)); + columns.Add(new PlaylistColumn(this, Catalog.GetString("Genre"), "Genre", + new TreeCellDataFunc(TrackCellGenre), new CellRendererText(), + 3, (int)ColumnId.Genre)); columns.Add(new PlaylistColumn(this, Catalog.GetString("Album"), "Album", new TreeCellDataFunc(TrackCellAlbum), new CellRendererText(), - 3, (int)ColumnId.Album)); + 4, (int)ColumnId.Album)); columns.Add(new PlaylistColumn(this, Catalog.GetString("Time"), "Time", new TreeCellDataFunc(TrackCellTime), new CellRendererText(), - 4, (int)ColumnId.Time)); + 5, (int)ColumnId.Time)); - PlaylistColumn _RatingColumn = new PlaylistColumn(this, + PlaylistColumn _RatingColumn = new PlaylistColumn(this, Catalog.GetString("Rating"), "Rating", new TreeCellDataFunc(TrackCellRating), new RatingRenderer(), - 5, (int)ColumnId.Rating); + 6, (int)ColumnId.Rating); columns.Add(_RatingColumn); RatingColumn = _RatingColumn.Column; @@ -107,7 +111,7 @@ Catalog.GetString("Plays"), "Plays", new TreeCellDataFunc(TrackCellPlayCount), new CellRendererText(), - 6, (int)ColumnId.PlayCount); + 7, (int)ColumnId.PlayCount); columns.Add(_PlaysColumn); PlaysColumn = _PlaysColumn.Column; @@ -115,7 +119,7 @@ Catalog.GetString("Last Played"), "Last-Played", new TreeCellDataFunc(TrackCellLastPlayed), new CellRendererText(), - 7, (int)ColumnId.LastPlayed); + 8, (int)ColumnId.LastPlayed); columns.Add(_LastPlayedColumn); LastPlayedColumn = _LastPlayedColumn.Column; @@ -395,7 +399,18 @@ SetRendererAttributes((CellRendererText)cell, ti.Title, iter); } - protected void TrackCellAlbum(TreeViewColumn tree_column, + protected void TrackCellGenre(TreeViewColumn tree_column, + CellRenderer cell, TreeModel tree_model, TreeIter iter) + { + TrackInfo ti = model.IterTrackInfo(iter); + if(ti == null) { + return; + } + + SetRendererAttributes((CellRendererText)cell, ti.Genre, iter); + } + + protected void TrackCellAlbum(TreeViewColumn tree_column, CellRenderer cell, TreeModel tree_model, TreeIter iter) { TrackInfo ti = model.IterTrackInfo(iter); Index: src/TrackProperties.cs =================================================================== RCS file: /cvs/gnome/banshee/src/TrackProperties.cs,v retrieving revision 1.21 diff -u -r1.21 TrackProperties.cs --- src/TrackProperties.cs 14 Jan 2006 20:27:11 -0000 1.21 +++ src/TrackProperties.cs 31 Jan 2006 14:30:27 -0000 @@ -44,6 +44,7 @@ public string Artist; public string Album; public string Title; + public string Genre; public Uri Uri; public uint TrackNumber; @@ -60,6 +61,7 @@ Artist = track.Artist; Album = track.Album; Title = track.Title; + Genre = track.Genre; TrackNumber = track.TrackNumber; TrackCount = track.TrackCount; Uri = track.Uri; @@ -70,6 +72,7 @@ track.Artist = Artist; track.Album = Album; track.Title = Title; + track.Genre = Genre; track.TrackNumber = TrackNumber; track.TrackCount = TrackCount; track.Uri = Uri; @@ -97,11 +100,14 @@ [Widget] private Button AlbumSync; [Widget] private Button TitleSync; [Widget] private Label TitleLabel; + [Widget] private Button GenreSync; + [Widget] private Label GenreLabel; [Widget] private SpinButton TrackCount; [Widget] private SpinButton TrackNumber; [Widget] private Entry Artist; [Widget] private Entry Album; [Widget] private Entry Title; + [Widget] private ComboBoxEntry Genre; [Widget] private Container EditorContainer; [Widget] private Expander AdvancedExpander; [Widget] private Label Uri; @@ -149,12 +155,21 @@ ArtistSync.Clicked += OnArtistSyncClicked; AlbumSync.Clicked += OnAlbumSyncClicked; TitleSync.Clicked += OnTitleSyncClicked; + GenreSync.Clicked += OnGenreSyncClicked; Artist.Changed += OnValueEdited; Album.Changed += OnValueEdited; Title.Changed += OnValueEdited; - - Next.Visible = TrackSet.Count > 1; + Genre.Entry.Changed += OnValueEdited; + ListStore genre_model = new ListStore(typeof(string)); + Genre.Model = genre_model; + Genre.TextColumn = 0; + + foreach(string genre in Globals.Library.GetGenreList()) { + genre_model.AppendValues(genre); + } + + Next.Visible = TrackSet.Count > 1; Previous.Visible = TrackSet.Count > 1; glade["MultiTrackHeader"].Visible = TrackSet.Count > 1; @@ -164,6 +179,7 @@ ArtistSync.Visible = TrackSet.Count > 1; AlbumSync.Visible = TrackSet.Count > 1; TitleSync.Visible = TrackSet.Count > 1; + GenreSync.Visible = TrackSet.Count > 1; tips.SetTip(TrackNumberSync, Catalog.GetString("Set all Track Numbers to this value"), "track numbers"); tips.SetTip(TrackNumberIterator, Catalog.GetString("Automatically Set All Track Numbers"), "track iterator"); @@ -171,6 +187,7 @@ tips.SetTip(ArtistSync, Catalog.GetString("Set all Artists to this value"), "artists"); tips.SetTip(AlbumSync, Catalog.GetString("Set all Albums to this value"), "albums"); tips.SetTip(TitleSync, Catalog.GetString("Set all Titles to this value"), "titles"); + tips.SetTip(GenreSync, Catalog.GetString("Set all Genres to this value"), "genres"); LoadTrack(0); @@ -208,6 +225,7 @@ (glade["Artist"] as Entry).Text = track.Artist; (glade["Album"] as Entry).Text = track.Album; (glade["Title"] as Entry).Text = track.Title; + (glade["Genre"] as ComboBoxEntry).Entry.Text = track.Genre; (glade["DurationLabel"] as Label).Markup = PrepareStatistic(String.Format("{0}:{1}", track.Track.Duration.Minutes, (track.Track.Duration.Seconds).ToString("00"))); @@ -321,6 +339,13 @@ } } + private void OnGenreSyncClicked(object o, EventArgs args) + { + foreach(EditorTrack track in TrackSet) { + track.Genre = Genre.Entry.Text; + } + } + private EditorTrack UpdateCurrent() { if(currentIndex < 0 || currentIndex >= TrackSet.Count) { @@ -334,6 +359,7 @@ track.Artist = Artist.Text; track.Album = Album.Text; track.Title = Title.Text; + track.Genre = Genre.Entry.Text; return track; } Index: src/Banshee.Base/Library.cs =================================================================== RCS file: /cvs/gnome/banshee/src/Banshee.Base/Library.cs,v retrieving revision 1.5 diff -u -r1.5 Library.cs --- src/Banshee.Base/Library.cs 6 Jan 2006 03:56:26 -0000 1.5 +++ src/Banshee.Base/Library.cs 31 Jan 2006 14:30:27 -0000 @@ -105,6 +105,46 @@ ThreadAssist.Spawn(ReloadLibraryThread); } + public ArrayList GetGenreList() + { + ArrayList genres = new ArrayList(); + IDataReader reader = Db.Query("SELECT DISTINCT Genre FROM Tracks ORDER BY Genre"); + while(reader.Read()) { + genres.Add(reader["Genre"] as string); + } + return genres; + } + + public ArrayList GetArtistsForGenre(string genre) + { + ArrayList artists = new ArrayList(); + genre = (null == genre) ? "%" : genre; + IDataReader reader = Db.Query( + String.Format("SELECT DISTINCT Artist FROM Tracks WHERE Genre LIKE '{0}' ORDER BY Artist", + genre)); + while(reader.Read()) { + artists.Add(reader["Artist"] as string); + } + return artists; + } + + public ArrayList GetAlbumsForGenreAndArtist(string genre, string artist) + { + ArrayList albums = new ArrayList(); + genre = (null == genre) ? "%" : genre; + artist = (null == artist) ? "%" : artist; + IDataReader reader = Db.Query( + String.Format("SELECT DISTINCT AlbumTitle FROM Tracks WHERE Genre LIKE '{0}'" + + "AND Artist LIKE '{1}'" + + "ORDER BY AlbumTitle", + genre, artist)); + while(reader.Read()) { + albums.Add(reader["AlbumTitle"] as string); + } + return albums; + + } + private void ReloadLibraryThread() { Tracks.Clear();