Subcommander Development Blog

Qt4 Item View Models..

leave a comment »

Today I learned something about implementing your own QAbstractItemModel with Qt4.

I worked on the subcommander (2.0) bookmark view to hide incomplete bookmarks (as in 1.2). If a bookmark has no source url, it is hidden. That’s useful if you don’t need the trunk/branches/tag repository bookmarks. Hiding them also removes some noise the bookmark view.

The second reason is that you can’t trigger a command on an incomplete bookmark from the gui. This avoids checks at various places if a bookmark is valid. The code is a lot cleaner if it can rely on a properly filled bookmark object.

The bookmark view is already based on a custom item model, so the easiest was to wrap the existing item model in a filter proxy model (QSortFilterProxyModel) and overwrite filterAcceptsRow().

Implementing the proxy model was just a few lines. No problem. Replacing the old model with the proxy model was a bit more work because the bookmark view class directly calls custom methods on the item model (to get a bookmark for a given index and getting the model index based on a bookmark object) that are not available in Qt’s interface.

That didn’t look right. I would have to change all this places to use the proxy model and have to delegate my custom methods through it? Ideally, it should be transparent. Just wrap the model into the proxy model, set it on the view, done.

I solved the “get bookmark for id” issue by making 2 changes. First I introduced a custom “role” to the item model. I can now call the data() method on the model to get the bookmark object. No need for a custom method. The second change is, that I call the data() method on the model index instead of the item model. I didn’t know until now that QModelIndex has its own data() method that delegates to the model. That way I don’t even need to know the model object.

old code:

void BookmarkView::contextMenuEvent( QContextMenuEvent* e )
  Bookmark* bookmark = _itemModel->bookmark( indexAt(e->pos()) );
  if( ! bookmark )

new code:

(since i need the interesting part multiple times I moved it to an extra method)

Bookmark* BookmarkView::getBookmark( const QModelIndex& index )

void BookmarkView::contextMenuEvent( QContextMenuEvent* e )
  Bookmark* bookmark = getBookmark(indexAt(e->pos()));
  if( ! bookmark )

I don’t have an idea for to the reverse lookup (bookmark to index) so I added a delegating method to the proxy model until I have a better idea.

So, what I have learned is:

  • avoid custom methods in an item model.
  • use custom roles to get data from the model (looks obvious now..;).
  • call data() on the index instead of the model.

Written by hauner

Sunday, 20 April, 2008 at 23:33

Posted in subcommander

Tagged with

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

%d bloggers like this: