Amarok/Archives/PlaylistHeader

From KDE Community Wiki

So the idea, as leinir puts it, is to have a "header" at the top of the playlist which is capable of rearranging what is displayed in each playlist item, and also in what order the playlist is sorted by.

A lovely mockup of this can be found here.

As you can see the idea is to create a mockup or archetype of what a playlist item will look like, and use a tile-based drag and drop system to modify that as users see fit. By default only the header will be shown, however hovering over it will expand it to reveal the tile pool and also a similar dialog to create a sort of flowing sort order (However let's get functionality working first, then worry about how to effectively show/hide it?)

Currently, the metadata displayed in the playlist is not-only fixed, but also is divided up into four aspects: topLeft, topRight, bottomLeft and bottomRight. Whilst this is certainly easy enough to modify, perhaps afterwards it would be beneficial to look into a more free-flowing system?

Also, an album art checkbox for toggling is present in the mockup. Perhaps clicking on the album art itself in the archetype would toggle as well? Just a thought :D

Anyway:

Here's the science

Note this is pretty much directly copied from my HD, so it may seem a little incoherent: Okay, so the core displaying occurs in PlaylistGraphicsItem.cpp, in the resize() function. That's where what gets displayed is determined. Example:

           m_items->topLeftText->setEditableText( artist, spaceForTopLeft );
           m_items->topLeftText->setPos( leftAlignX, MARGIN );

That really isn't as abstract as people would like to believe. However, the lack of abstraction on this makes it absolutely perfect to meddle with!

As I was talking about with leinir, easiest way to do this is to use the fridge magnet example in combination with the various elements (title, album, etc) to create a playlist item archetype. This is pretty simple to express in data terms. We have four QStrings, five if you include the album art, but that's a boolean toggle fo sho. Anyway, these four QStrings correspond to the four places to display data. topLeft, topRight, bottomLeft and bottomRight. The easiest way to determine what's to be displayed is to have enumerations for each one (ie: TITLE, ALBUM, etc) contained within the archetype class like such:

enum PlaylistElement { Title, Album, Time, ArtistAlbum, etc }

PlaylistElement topLeft; PlaylistElement topRight; PlaylistElement bottomLeft; PlaylistElement bottomRight;

Have each fridge magnet contain a member of this enum, and then at time of save or another appropriate time, scan what magnet is in each place and set the elements appropriately.

Now, when it comes to displaying the text, rather than having "setEditableText( artist ...", we would have:

m_items->topLeftText->setEditableText ( archetype->topLeftText(track), spaceForTopLeft);

archetype->topLeftText() would in turn look something like this:

QString Playlist::Archetype::topLeftText(Meta::TrackPtr track) {

 return getMetaData(topLeft, track);

}

QString Playlist::Archetype::getMetaData(Meta::TrackPtr track, PlaylistElement element) {

 switch (element) {
   case PlaylistElement.Title:	return track->prettyName();
   case PlaylistElement.Album: (insert check that album exists!) return track->album()->name();
   // and so forth!
   default: return null;
 }

}

So then, when the topLeftText for playlist element X needs to be displayed, archetype has all the metadata of the track and what part of it to return.

Streamlining possibilities: Rather than calling each one at a time, perhaps an array/struct containing all the metadata needed could be returned? Whatever happens though, DON'T pass over rendering to the archetype, that's just ASKING for trouble!

As for album art displaying, that's simple enough. Tick box in the dialog, which sets a boolean (int?) to either 0 (false) or 1 (true). Then in methods such as paintHead() in PlaylistGraphicsItem.cpp, we modify:

   QPixmap albumPixmap;
   if( m_items->track->album() )
       albumPixmap =  m_items->track->album()->image( int( ALBUM_WIDTH ) );

to:

   QPixmap albumPixmap;
   if( m_items->track->album() && archetype->paintAlbum )
       albumPixmap =  m_items->track->album()->image( int( ALBUM_WIDTH ) );

So if paintAlbum is true, it gets painted. Otherwise, it doesn't. However this does just leave a big space where the album art should be. Should look into where to specify topLeft and bottomLeft x coordinates, and put in mechanisms to adjust if no album art is displayed.