Difference between revisions of "Development/AkonadiPorting/AddressBook"

Jump to: navigation, search
(Adding buildsystem section)
m (Text replace - "<code cppqt>" to "<syntaxhighlight lang="cpp-qt">")
Line 21: Line 21:
 
A common use case is to look for a contact object by its identifier, e.g. acquired by user selection somewhen in the past.
 
A common use case is to look for a contact object by its identifier, e.g. acquired by user selection somewhen in the past.
 
The code to do that usually looks like this:
 
The code to do that usually looks like this:
<code cppqt>
+
<syntaxhighlight lang="cpp-qt">
 
KABC::AddressBook *addressBook = KABC::StdAddressBook::self();
 
KABC::AddressBook *addressBook = KABC::StdAddressBook::self();
  
Line 28: Line 28:
  
 
The equivalent using Akonadi API looks like this
 
The equivalent using Akonadi API looks like this
<code cppqt>
+
<syntaxhighlight lang="cpp-qt">
 
Akonadi::ContactSearchJob *job = new Akonadi::ContactSearchJob( this );
 
Akonadi::ContactSearchJob *job = new Akonadi::ContactSearchJob( this );
 
job->setQuery( Akonadi::ContactSearchJob::ContactUid, uidString );
 
job->setQuery( Akonadi::ContactSearchJob::ContactUid, uidString );
Line 35: Line 35:
 
</code>
 
</code>
 
and
 
and
<code cppqt>
+
<syntaxhighlight lang="cpp-qt">
 
void contactSearchResult( KJob *job )
 
void contactSearchResult( KJob *job )
 
{
 
{
Line 54: Line 54:
  
 
Another common use case is searching for matching contacts by email address. The code for that with KABC classes is almost identical:
 
Another common use case is searching for matching contacts by email address. The code for that with KABC classes is almost identical:
<code cppqt>
+
<syntaxhighlight lang="cpp-qt">
 
KABC::AddressBook *addressBook = KABC::StdAddressBook::self();
 
KABC::AddressBook *addressBook = KABC::StdAddressBook::self();
  
Line 61: Line 61:
  
 
Unsurprisingly, the Akonadi code looks also quite similar to the previous use case:
 
Unsurprisingly, the Akonadi code looks also quite similar to the previous use case:
<code cppqt>
+
<syntaxhighlight lang="cpp-qt">
 
Akonadi::ContactSearchJob *job = new Akonadi::ContactSearchJob( this );
 
Akonadi::ContactSearchJob *job = new Akonadi::ContactSearchJob( this );
 
job->setQuery( Akonadi::ContactSearchJob::Email, emailString );
 
job->setQuery( Akonadi::ContactSearchJob::Email, emailString );
Line 73: Line 73:
  
 
Another use case for KABC::AddressBook is not directly available in Akonadi:
 
Another use case for KABC::AddressBook is not directly available in Akonadi:
<code cppqt>
+
<syntaxhighlight lang="cpp-qt">
 
KABC::AddressBook *addressBook = KABC::StdAddressBook::self();
 
KABC::AddressBook *addressBook = KABC::StdAddressBook::self();
  
Line 88: Line 88:
  
 
When using KABC::StdAddressBook, modifying a contact (for example one retrieved by findByUid()) worked like this:
 
When using KABC::StdAddressBook, modifying a contact (for example one retrieved by findByUid()) worked like this:
<code cppqt>
+
<syntaxhighlight lang="cpp-qt">
 
addressBook->insertAddressee( contact );
 
addressBook->insertAddressee( contact );
  
Line 105: Line 105:
  
 
Lets say there is just the item's identifier:
 
Lets say there is just the item's identifier:
<code cppqt>
+
<syntaxhighlight lang="cpp-qt">
 
Akonadi::Item item( itemId );
 
Akonadi::Item item( itemId );
 
item.setPayload<KABC::Addressee>( contact );
 
item.setPayload<KABC::Addressee>( contact );
Line 134: Line 134:
  
 
Includes for Akonadi core classes are like
 
Includes for Akonadi core classes are like
<code cppqt>
+
<syntaxhighlight lang="cpp-qt">
 
#include <Akonadi/Item>
 
#include <Akonadi/Item>
 
</code>
 
</code>
  
 
for contact related specializations they are like
 
for contact related specializations they are like
<code cppqt>
+
<syntaxhighlight lang="cpp-qt">
 
#include <Akonadi/Contact/ContactSearchJob>
 
#include <Akonadi/Contact/ContactSearchJob>
 
</code>
 
</code>

Revision as of 19:22, 29 June 2011


Contents

Development/AkonadiPorting/AddressBook


Introduction

The address book API KABC has been available for application developers for several major version releases of KDE.

Its main entry point for applications is the KABC::StdAddressBook singleton.

The most prevelant usage is loading all address book contents synchronously and the working with the loaded data set, e.g. by calling "find" methods or even iterating over the whole contact pool.

Aside from often needlessly loading the all contacts into memory in every application accessing the address book, the synchronous I/O either meant blocking the application or introducing unexpected re-entrancy when the address book plugins were using nested event loops to process jobs without returning from the called function.

noframe
 
Warning
Akonadi's job based API is capable of doing synchronous execution as well, so one might be tempted to use this instead of the signal/slot approach shown on this page. The recommendation is to only use this as an intermediate step at best, the potential re-entrancy due to the nested event loop can lead to hard to debug problems.


Common Usage Patterns

Most usage patterns involve one of the KABC::AddressBook's "find" methods. Their functionality is now mostly available through Akonadi::ContactSearchJob

Find By Uid

A common use case is to look for a contact object by its identifier, e.g. acquired by user selection somewhen in the past. The code to do that usually looks like this:

KABC::AddressBook *addressBook = KABC::StdAddressBook::self();
 
KABC::Addressee contact = addressBook->findByUid( uidString );
</code>
 
The equivalent using Akonadi API looks like this
<syntaxhighlight lang="cpp-qt">
Akonadi::ContactSearchJob *job = new Akonadi::ContactSearchJob( this );
job->setQuery( Akonadi::ContactSearchJob::ContactUid, uidString );
 
connect( job, SIGNAL( result( KJob* ) ), SLOT( contactSearchResult( KJob* ) ) );
</code>
and
<syntaxhighlight lang="cpp-qt">
void contactSearchResult( KJob *job )
{
  if ( job->error() != 0 ) {
    // error handling, see job->errorString()
    return;
  }
 
  Akonadi::ContactSearchJob *searchJob = qobject_cast<Akonadi::ContactSearchJob*>( job );
 
  const KABC::Addressee::List contacts = searchJob->contacts();
}
</code>
 
{{tip|Sometimes it is necessary to transport some context from the method which creates the job to the result slot. A convenient way to do this is using the job's [http://doc.qt.nokia.com/latest/qobject.html#setProperty setProperty()] method.}}
 
=== Find By Email ===
 
Another common use case is searching for matching contacts by email address. The code for that with KABC classes is almost identical:
<syntaxhighlight lang="cpp-qt">
KABC::AddressBook *addressBook = KABC::StdAddressBook::self();
 
KABC::Addressee contact = addressBook->findByEmail( emailString );
</code>
 
Unsurprisingly, the Akonadi code looks also quite similar to the previous use case:
<syntaxhighlight lang="cpp-qt">
Akonadi::ContactSearchJob *job = new Akonadi::ContactSearchJob( this );
job->setQuery( Akonadi::ContactSearchJob::Email, emailString );
 
connect( job, SIGNAL( result( KJob* ) ), SLOT( contactSearchResult( KJob* ) ) );
</code>
 
The code for the result slot is the same as above.
 
=== Who Am I ===
 
Another use case for KABC::AddressBook is not directly available in Akonadi:
<syntaxhighlight lang="cpp-qt">
KABC::AddressBook *addressBook = KABC::StdAddressBook::self();
 
KABC::Addressee contact = addressBook->whoAmI();
</code>
 
{{Note|Even this had its shortcomings, because this depends on the users adding themselves to the address book and marking the respective entry as "this is me".}}
 
Concrete use cases this has been deployed for are getting the user's full name and/or their email address, which might be better served by using KDE's identity management instead, see [http://api.kde.org/4.x-api/kdepimlibs/kpimidentities/classKPIMIdentities_1_1IdentityManager.html KPIMIdentities::IdentityManager].
 
It contains the identity users can configure in the Systemsettings module for personal information, so if there is data yet, the application can just embed the respective KCM in a dialog and let the user configure this centrally for all of KDE.
 
=== Modifying A Contact ===
 
When using KABC::StdAddressBook, modifying a contact (for example one retrieved by findByUid()) worked like this:
<syntaxhighlight lang="cpp-qt">
addressBook->insertAddressee( contact );
 
KABC::Ticket *ticket = addressBook->requestSaveTicket();
if ( !ticket ) {
  // error
} else if ( !addressBook->save( ticket ) ) {
    // error
    addressBook->releaseSaveTicket( ticket );
  }
}
</code>
 
With Akonadi, the application will need the [http://api.kde.org/4.x-api/kdepimlibs/akonadi/classAkonadi_1_1Item.html Akonadi::Item] or at least the item's identifier.
Assuming the contact got retrieved using ContactSearchJob, consider keeping the item or Item::id() around, see [http://api.kde.org/4.x-api/kdepimlibs/akonadi/classAkonadi_1_1ItemSearchJob.html#bf8f7a6037f632d3384637e08c99c77a ContactSearchJob::items()].
 
Lets say there is just the item's identifier:
<syntaxhighlight lang="cpp-qt">
Akonadi::Item item( itemId );
item.setPayload<KABC::Addressee>( contact );
item.setMimeType( KABC::Addressee::mimeType() );
 
Akonadi::ItemModifyJob *job = new Akonadi::ItemModifyJob( item );
connect( job, SIGNAL( result( KJob* ) ), SLOT( contactModifyResult( KJob* ) ) );
</code>
 
The code for the result slot is similar to the one for search.
 
== Buildsystem Adjustments ==
 
Since the application is already linking against KDE PIM Libs classes, its CMakeList.txt already has the necessary
<code>
find_package( KdepimLibs 4.5 REQUIRED )
</code>
 
However, "target_link_libraries" need to be extended to contain
<code>
${KDEPIMLIBS_AKONADI_LIBS}
</code>
for code classes like Akonadi::Item and
<code>
${KDEPIMLIBS_AKONADI_CONTACT_LIBS}
</code>
for contact related classes like Akonadi::ContactSearchJob.
 
Includes for Akonadi core classes are like
<syntaxhighlight lang="cpp-qt">
#include <Akonadi/Item>
</code>
 
for contact related specializations they are like
<syntaxhighlight lang="cpp-qt">
#include <Akonadi/Contact/ContactSearchJob>
</code>
 
In both cases also available in lowercase variants with ".h" suffix.
 
== Further Reading ==
 
Akonadi porting efforts have resulted in a couple of useful classes for various aspects of dealing with PIM data.
 
For contacts such classes would be:
* [http://api.kde.org/4.x-api/kdepimlibs/akonadi/contact/classAkonadi_1_1ContactEditor.html Akonadi::ContactEditor] (also available as a dialog)
* [http://api.kde.org/4.x-api/kdepimlibs/akonadi/contact/classAkonadi_1_1ContactViewer.html Akonadi::ContactViewer] (again also available as a dialog)
* [http://api.kde.org/4.x-api/kdepimlibs/akonadi/contact/classAkonadi_1_1ContactsTreeModel.html Akonadi::ContactsTreeModel]

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V.Legal