When I started working on my proposal for what would eventually become my Google Summer of Code 2009 project, I was a much less skilled coder with no experience on something as large as this project turned out to be. I’m not bragging about becoming so insanely wiser now, but I have certainly gained tons of valuable experience, learned a lot about software development, and had a great time doing it!
So what exactly have I accomplished this summer?
Those who have been following my updates might remember the first part.
Well, the initial idea was to implement multilevel sorting in Amarok’s playlist, with a nice GUI, and throw in configurable grouping if there’s time. However right from the start it was clear that much more invasive changes were needed. As I already mentioned, Amarok’s playlist uses Qt’s Model/View design pattern. When I began working on my project the playlist had a source model (a class which feeds the rows), a filter proxy model (which filters out some rows that don’t need to be shown when a filter is active), a grouping proxy model (which decides which tracks should be grouped together because they belong to the same album) and finally, the view. Ideally, each model should talk only to the model right below it (if any), and the view should only talk to the “topmost” model to avoid any screw-ups in row presence and order. Failure to enforce this results in spaghetti code, which is exactly what was going on in the playlist code at the time.
So most of my first GSoC month I spent despaghettifying these Model/View classes, so that the Playlist::Model feeds data only to the FilterProxy, which feeds data only to the GroupingProxy, which feeds data only to the view. During this despaghettification, I also added a new proxy model: SortProxy, which is the class that actually implements the multilevel sorting backend. A month or so later I also added another proxy, SearchProxy, by decoupling searching from filtering. So the final result, as I already mentioned, is Playlist::Model->Filter->Sort->Search->Grouping->View: 5 models and one view. Doing all this without Qt’s Model/View classes would have been *a lot* harder and much more chaotic. So by the end of the second month the playlist code was refactored and made much clearer, the right auxiliary classes had been associated with the right model or proxy (mostly the topmost one, GroupingProxy) and a simple testing GUI was in place for multilevel sorting.
For the GUI, I chose to adapt a familiar paradigm to a new use case, so I used a breadcrumb path based widget. A sort scheme is a progression of levels, which represent sorting criteria, and those are applied to the playlist in real time. What’s even better, sorting is not an action but a state, which means that the original sort order can be recalled at any time. One of the sorting levels is also “Random”, so almost for free this interface also implements configurable multilevel shuffle!
In the last weeks, which were quite busy, I implemented configurable grouping, so the user is no longer forced just to group by album or not group at all. Finally, as a bonus, I took advantage of the existing Amarok URL infrastructure to implement playlist view bookmarks. These bookmarks define a URL for each playlist configuration, which aggregates a sorting scheme, a grouping category, a playlist layout and a filtering expression, and store it in the bookmark manager. The user can then instantly apply these bookmarked states and avoid having to rebuild a sorting scheme, a grouping category, select a layout and enter a filter string manually.
Playlist view bookmarks make it much easier to control this mighty playlist, which will be landing on a GNU/Linux distribution near you with Amarok 2.2 some time this fall!
I’d like to take this chance to thank my GSoC mentor Nikolaj Hald Nielsen and the whole Amarok team for their patience, dedication and help.