QAction separation (Re: Towards Amarok Mobile: Beginning separation)

Bart Cerneels bart.cerneels at kde.org
Sat Mar 20 08:44:31 CET 2010


On Fri, Mar 19, 2010 at 22:49, Jeff Mitchell <mitchell at kde.org> wrote:
> Hi guys,
>
> With commit 316911d22 I have taken my official first step towards Amarok
> Mobile  :-)
>
> This was discussed on IRC a while back, but for those not aware, the
> idea is to reuse as much code as possible...which basically means that
> two things are needed:
>
> 1) The ability to control which parts to build on a mobile system
> 2) Separation of GUI/logic

I've been using a GUI sep. trick in the Meta::Playlists/Podcasts that
could be used all over amarok.

I'm passing a QList<QAction *> as data through the QAbstractItemModels
and proxies using a custom role. The main reason for this was being
able to use an unmodified QSortFilterProxyModel and it completely
rules out mapTo/FromSource errors when these actions are retrieved
"out-of-band".

- First I create QAction objects for the common actions
(appendToPlaylist, loadPlaylist, removeTrackFromPlaylist,
deletePlaylist, updatePodcastChannel).

- Then actions are being queried though QAbstractItemModel::data() for
each item separately. I add a pointer to the item in the QVariant
though QAction::data() QAction::setData(). If the action can be
preformed on multiple items this will be a list, otherwise a single
pointer.

- In the slot connected to each action I call QObject::sender(), cast
to QAction * and call QAction::data() to get the items I need to
perform the action on.

- The view does need to call QAction::setData( QVariant() ) to clear
the lists. Otherwise the action will contain to many items the next
time it's called. For the same reason these actions, more accurately:
the data of the ActionRole, is not allowed to be cached. Standard
QAProxyModels don't do that anyway.

I do use some dialogs in these slots. Depending on the complexity of
the dialog you might say that this is not GUI separation. A simple
KDialog with OK and Cancel buttons can fit on any mobile screen just
fine assuming it's done in the platform's style. I assume Qt's
abstraction handles that.

There is some overhead in getting those actions, clearly, but less
complicated work in the view and it's selection-model as well.
Another big benefit, and this is the real GUI separation, is that the
view has full control over which actions are shown to the user and the
way they are triggered. use cases:

- On desktop, in current git, the action performed on doubleclicking
an item is the first one in the action list. By convention this is
append-to-playlist.

- Multiple items are selected and each item has a different custom
action. Ex. a downloaded podcast episode and a non-downloaded are
selected. The actions for these: addToPlaylist, loadPlaylist for both
and deleteDownloadedEpisode, downloadEpisode respectively. I we only
show the intersecting set of both lists of actions  we get
(addToPlaylist, loadPlaylist). Which clearly is less confusion then
showing an action that can't be performed on one of the selected
items.
Before this logic was partially implemented in the model using the
selectionModel, now it's completely in the view and there is no longer
a risk of bad mapping in an intermediate proxy.

- We can show all the actions that can be performed as icons on the
item. An example of this are the root items in the collectionbrowser
(non-merged). Mediadevices root items for instance display the actions
because the delegate paints them and the view will trigger an action
when clicks are performed in that area. This concept is very useful
for touchscreen only interaction.

Bart


More information about the Amarok-devel mailing list