prev
Issue 94
20th January 2008
by Danny Allen
next


This Week...
Taskbar and KMenu functionality from KDE 3.5 returns to the Plasma panel, and work on clocks in Plasma, with the move of the binary-clock Plasmoid to kdereview. Improvements in annotation handling in Okular (which has been officially capitalised). Essential support for viewing bug contents in the rewrite of KBugBuster. More data export options (CSV, HTML, etc) in Kalzium. The CVS implementation in KDevelop moves to the Model/View framework. The start of JavaScript functionality in Kst plugins. Usability refinements in Konsole. Mailody begins to be ported to the Akonadi service. A "mirror search" plugin for KGet. IPv6 work in KTorrent. Colour docker improvements across KOffice. Optimisations in KDevelop and NEPOMUK. Various work in KJS and KHTML. Support for the MPRIS multimedia player interaction specification in Dragon Player, with Dragon Player moving from playground/multimedia into kdemultimedia for KDE 4.1. The Kopete Bonjour protocol moves to kdereview. The copy of Qt within KDE SVN is updated to be GPL version 3 compatible.

Aaron Seigo talks about Plasma and Release Events:
Plasma development is going on at a furious pace right now, with the focus remaining on polishing the 4.0 code base. 145 bugs were closed in the last month and a great commit rate is being achieved:


The line graph shows the rate of resolved bugs climbing at a rather steady pace. As for the commit level, the following image (thanks Simon St James!) shows all commits (green), code commits (red) and Plasma-related commits (yellow). Over the last year, Plasma-related commits have really taken off, as you can see.


So what have we been up to exactly? Besides bug fixes by the ton, we've been filling in missing features to the taskbar, like multiple rows of windows (all nicely animated!) and "show only windows on this desktop", to name a couple. Desktop icon loading has improved substantially, as has performance of many of the Plasma components.

Script support for DataEngines and Runners was recently added, and the Plasmoids continue to grow in number. The continued development has helped solidify the Plasma library even further as we discover common patterns in Plasmoids. It really didn't occur to me, for instance, how many Plasmoids would need to keep themselves in a perfect square shape. =)

In between all this great work, we also had the KDE 4.0 Release Event in Mountain View, California. Thanks to Google's amazing help in organization and financial sponsorship, the event was truly an impressive thing. The presentations were streamed lived around the world and now appear on Google Video. I've seen photos of the keynote on walls in German taverns, so I know the streaming was indeed working. ;)

It was terrific to see both industry people there, hard core developers (including kernel developers) and general community members. Highlights for me were experiencing Patrick Volkderding's first karaoke performance, the KDE-branded wine (thanks Celeste!), the truly astounding Konqi and Katie mascots, and listening to the KDE people who came to express just how much closer they felt to the project as a whole.


It was pretty hectic for me personally, with meetings lasting well into the night. That was exactly why we did this, of course: to gain exposure, get our message out, connect the community and do something worthy of a release such as this.

It will be a hard event to top, but then we don't get a 4.0 every year. However, it seems we'll be doing a KDE Americas event at the beginning of every year as a counterpoint to the Akademy events in Europe in the middle of the year.

In a Digest special, Tom Albers of Mailody presents "How to write a mail client in 10 minutes":
Currently the Mailody crew is working to rewrite Mailody using the Akonadi backend. Akonadi is a cross-desktop PIM Storage Service. It basically acts like a cache or proxy if you like.

On the one hand, you can feed things into it. This is done by agents or resources. This can be a simple Maildir resource, Mailody is developing an IMAP library resource, NNTP-resource, etc. etc. On the other hand it provides ways to get the data to the applications that want to use it. Not only an addressbook or mail client, but also it makes it possible for strigi to search it and recently I saw soneone interested in making a SyncML connection.

We (Mailody) were surprised how simple it is to display the data in Akonadi. How the data gets into Akonadi will be out of scope for this article, but I wil get back to that later. For now, I just assume the data is in Akonadi, for example by the Maildir resource, which simply reads the mails you have in a Maildir.

We will now show how to write a mail client, or rather a mail reader to keep it simple. First, let's see what we need for this basic client. If we look at a traditional mail client, it is usually build up out of three parts: we need an overview of the folders on the left, the headers at the top right and the display of messages happens on the bottom right.

The listing of the folders. A folder is represented in Akonadi by a Collection. The Collections hold the name to display, an internal value so you can map it in your resource and things like the amount of unread messages. Akonadi provides funtions to retrieve all those collection from a certain resource, but Akonadi goes further, it also provides a ready to use models and views to use.

So here we go with the mainwidget:

{
  QHBoxLayout *layout = new QHBoxLayout( this );
  QSplitter *splitter = new QSplitter( Qt::Horizontal, this );
  layout->addWidget( splitter );

  mCollectionList = new Akonadi::CollectionView();
  connect( mCollectionList, SIGNAL(clicked(QModelIndex)),    SLOT(collectionActivated(QModelIndex)) );
  splitter->addWidget( mCollectionList );

  mCollectionModel = new Akonadi::CollectionModel( this );
  mCollectionProxyModel = new Akonadi::CollectionFilterProxyModel( this );
  mCollectionProxyModel->setSourceModel( mCollectionModel );
  mCollectionList->setModel( mCollectionProxyModel );
}

That's it. Now it will show the collections on the left side. If you want to see columns for unread messages and a total count, use the Akonadi::MessageCollectionModel instead. The proxy in above code is needed because Akonadi can hold different types of collection, it can also hold a bunch of vcards for example. We don't want to see those in the mail client (at least not here), we ideally we want to add a m_folderProxyModel->addMimeType("message/rfc822"); to the code.

So, next up is the headerlist. Akonadi provides the model for this as well. This model can be applied to the standard QTtreeView to show the headers. But you obviously want to have the messages displayed threaded, so you can easily spot which message is a reply to another. Here we go with the headerlist:

  QSplitter *rightSplitter = new QSplitter( Qt::Vertical, this );
  splitter->addWidget( rightSplitter );
  mMessageList = new QTreeView( this );
  mMessageList->setDragEnabled( true );
  mMessageList->setSelectionMode( QAbstractItemView::ExtendedSelection );
  connect( mMessageList, SIGNAL(clicked(QModelIndex)),
    SLOT(itemActivated(QModelIndex)) );
  rightSplitter->addWidget( mMessageList );

  mMessageModel = new Akonadi::MessageModel( this );
  mMessageProxyModel = new Akonadi::MessageThreaderProxyModel( this );
  mMessageProxyModel->setSourceModel( mMessageModel );
  mMessageList->setModel( mMessageProxyModel );

For the display of messages, we will keep it simple. You don't expect this to be a finished mail client, right?

  mMessageView = new QTextEdit( this );
  rightSplitter->addWidget( mMessageView );

So, that are the basic display items. Of course we need to implement the two slots. CollectionActivated makes sure the correct headers are shown when you click on a Collection. Remember Collection is the term for a folder in our case.

  mCurrentCollectionId = mCollectionList->model()->data( index,
    CollectionModel::CollectionIdRole ).toInt();
  mMessageModel->setCollection( Collection( mCurrentCollectionId ) );

The other slot has to show the correct message when you click on a header. In fact, this creates a KJob to fetch the message from Akonadi. It can happen that Akonadi does not yet have the complete message. In that case it will ask the resource for the missing part and will emit the itemFetchDone after that.

  DataReference ref = mMessageModel->referenceForIndex(
    mMessageProxyModel->mapToSource( index ) );

  ItemFetchJob *job = new ItemFetchJob( ref, this );
  job->addFetchPart( Item::PartBody );
  connect( job, SIGNAL( result(KJob*) ), SLOT( itemFetchDone(KJob*) ) );
  job->start();

You might be confused by the DataReference. A message is represented by an Akonadi::Item. That Item holds the actual data, for example via the payload functions. To reference a certain Item in the Collection a DataReference is used, basically a unique id. In our case you can use a mailbox name in combination with the message-id or uid as a unique key.

When the data arrives, we can display it to the user:

  ItemFetchJob *fetch = static_cast<ItemFetchJob*>( job );
  if ( job->error() ) {
    qWarning() << "Mail fetch failed: " << job->errorString();
  } else if ( fetch->items().isEmpty() ) {
    qWarning() << "No mail found!";
  } else {
    const Item item = fetch->items().first();
    mMessageView->setPlainText( item.part( Item::PartBody ) );
  }

That is it. Now you have your basic mail reader. I bet it took less than 10 minutes. You can understand that rewriting an existing mail client to use Akonadi is a bit more work. But it is fun, as it's deleting most of your own work (isn't that the real meaning of 'eating your children'??), and replacing it by Akonadi elements.


Of course when you have this foundation you want to extend it with more features. But you can easily do that, for example by writing the delegates. I hope this "how to" inspires you to write your own mail client, or to join the Mailody or Akonadi team.

Note: the above sections of code come from the mail client which is part of Akonadi. You can find it in KDE SVN. It is called "Akonamail", and is written by Bruno Virlet.

The post-KDE 4.0 commit surge continues this week, with 3043 commits. Part of this increase can be explained by the return of development branches (after several years of less-strict development), where certain feature and bugfix work is done in trunk/ and backported to the KDE 4.0 branch, essentially creating two commits for a single change.

However, that is not the whole story... there is something more, something that I can't readily prove with statistics. There is a real buzz to KDE development right now, an extra edge to what is already a vibrant atmosphere, and it is evident everywhere, from IRC to SVN.

More commits mean more work for me, but i'm definitely not complaining!


Statistics
Commits: 3043 by 231 developers, 7049 lines modified, 1420 new files.
Open Bugs: 15750
Open Wishes: 13554
Bugs Opened: 477 in the last 7 days.
Bugs Closed: 360 in the last 7 days.

Commit Summary
Module Commits
/trunk/l10n-kde4
742
/trunk/KDE
670
/branches/KDE
271
/branches/stable
257
/trunk/playground
202
/trunk/www
151
/trunk/koffice
117
/trunk/extragear
113
/trunk/kdesupport
105
/branches/work
93
Lines Developer Commits
108
Keld Simonsen
109
197
Laurent Montel
81
269
Luboš Luňák
75
365
Maksim Orlovich
73
41
Pradeepto Bhattacharya
56
133
Gilles Caulier
54
80
Andras Mantia
53
72
Sébastien Renard
52
170
David Faure
50
66
Ralf Habacker
48

Internationalisation (i18n) Status
Language Percentage Complete
Greek
99%
Swedish
99%
Portuguese
98%
Japanese
93%
Estonian
90%
German
89%
Polish
88%
Spanish
88%
French
87%
Dutch
87%

Bug Killers and Buzz
Bug Killer Number Of Bugs Closed
Luboš Luňák
40
Aaron J. Seigo
28
Pino Toscano
27
Cláudio da Silveira Pinheiro
22
Charles Connell
19
Tommi Tervo
16
Lex Hider
16
Peter Penz
15
Andras Mantia
11
George Goldberg
11

Program Buzz
Plasma
  9555
Amarok
  6010
KMail
  3450
K3B
  3330
Kopete
  3075
Solid
  2155
KDevelop
  2029
SuperKaramba
  1982
Phonon
  1904
digiKam
  1426


Person Buzz
Tobias Hunger
  5180
David Faure
  2135
Stephan Kulow
  1935
Jonathan Riddell
  1385
Torsten Rahn
  1371
Aaron Seigo
  1204
Laurent Montel
  982
Bram Schoenmakers
  962
Stephan Binner
  888
Allen Winter
  800
Commit Countries

Commit Demographics
Sex
89.9 %       Male
13.1 %       (unknown)
1.29 %       Female
Motivation
44.5 %       (unknown)
43.5 %       Volunteer
16.3 %       Commercial
 
Ages
70.2 %       (unknown)
17.7 %       25 to 34
8.58 %       18 to 24
3.64 %       35 to 44
2.72 %       45 to 54
1.46 %       Under 18


Contents
  Bug Fixes Features Optimise Security Other
Accessibility
Development Tools [*] [*] [*]
Educational [*] [*]
Graphics [*]
KDE-Base [*] [*] [*] [*]
KDE-PIM [*] [*] [*]
Office [*] [*] [*]
Konqueror [*]
Multimedia [*] [*] [*]
Networking Tools [*] [*] [*] [*]
User Interface [*]
Utilities [*] [*]
Games [*] [*]
Other [*] [*]


Bug Fixes
Educational
Jason Harris committed changes in /trunk/KDE/kdeedu/kstars/kstars:
Fixing bug #132994: We come to bury Pluto, not praise him.

We have already been deriving Pluto from the KSAsteroid class for practical reasons. With this change, Pluto is now labeled an "asteroid" in the details dialog.
Bug 132994: Pluto is not a planet
Diffs: 1, 2, 3 Revision 762902

KDE-Base
Maksim Orlovich committed a change to /branches/KDE/4.0/kdebase/workspace/kcontrol/input/mouse.cpp:
Ubreak support for left-handed mice on recent X versions.
This code assumed that all mice had less than 20 buttons, but for some reason new Xorg thinks that lots of mice have 32(!!)
Bug 150361: left handed option for mouse broken with xorg-7.3
Diff Revision 760911

Maksim Orlovich committed changes in /branches/KDE/4.0/kdelibs/kjs:
Limit stack usage of libPCRE (and raise an exception when it runs out of stack space, for diagnosibility).

Also, do not accept some super old (>4 year old) pcre versions; as they can severely cripple regexp support, and intefere with this bugfix. Also tweak the message about missing PCRE in configure check --- libPCRE doesn't result in "better" regexp support; the support w/o it is a last-resort fallback...

Based on patch by Sune Vuorela (username debian, hostname pusling, tld com)
Bug 149191: Browser closes when hitting page history on wikidot.com
Bug 151477: Konqueror segfault when parsing too large string as javascript ob...
Diffs: 1, 2,