The KDE Address Book Framework
===============================

The KDE address book framework tries to provide an easy to use and powerful
mechanism to handle contacts in all KDE applications.

If you want to make use of it, this small introduction to programming
with libtdeabc may be helpful.


General Concepts
=================

In libtdeabc the storage and management of contacts is devided in 2 layers.

******************
Management Layer *
******************

     .-------------------.
     | TDEABC::AddressBook |
    .--------------------------------.
    | TDEABC::Addressee                |  => Iterators
    | TDEABC::Addressee                |
    | TDEABC::Addressee                |  => Search functions
    | ...                            |
    `--------------------------------'
                       |
 - - - - - - - - - - - | - - - - - - - - - - - - -
                       |
***************        |
Storage Layer *        |
***************        |  .......................
                       |  .                     . - Network
  .---------------.    |  .  .---------------.  .
  | ResourceFile  |----+-----| ResourceLDAP  |  .
  `---------------'    |  .  `---------------'  .
  .---------------.    |  .  .---------------.  .
  | ResourceDir   |----+-----| ResourceNet   |  .
  `---------------'       .  `---------------'  .
                          .                     .
                          .......................


The Management Layer
---------------------
The Management Layer consists of the two classes TDEABC::AddressBook and
TDEABC::Addressee. TDEABC::AddressBook is a container for TDEABC::Addressee objects
and provides 2 kinds of access methods.
1) Iterators
    With iterators you can iterate over each of the contacts of the
    address book and perform an action on it

2) Search functions
    With search functions you can search for contacts with special attributes
    such as "all contacts with the name 'Harald'"

The class TDEABC::Addressee represents a single contact and contains all data
a vCard could store (as specified in RFC 2426).

The Storage Layer
------------------
The Storage Layer consists of the class TDEABC::Resource and its derived classes.
These classes are used by TDEABC::AddressBook to load and store the contacts to
the single backends.
At the moment libtdeabc provides 4 types of resources:
1) ResourceFile
  - stores all contacts in a single file

2) ResourceDir
  - stores each contact in its own file with the unique identifier of the
    contact as a filename, will all of the files together in one directory

3) ResourceLDAP
  - stores all of the contacts on a LDAP server

4) ResourceNet
  - stores all contacts in a single file, which can be accessable via HTTP,
    FTP, Fish, WebDAV, POP3, IMAP or whatever the TDEIO frame work supports

In general the developer does not have to take how to save the single contacts.
He just has to plug one of the above mentioned resources into TDEABC::AddressBook
and perform a save action.

Examples
=========
Like a picture, C/C++ code is worth a 1000 words I'd like to give you a
lot of examples now, how to use libtdeabc for several tasks:


Using TDEABC::StdAddressBook and Iterators
-----------------------------------------
Normally you have to plugin the resources manually into the addressbook object
and call the load() function before you can access the contacts, but there is
a special class TDEABC::StdAddressBook, which loads all resources of the standard
address book of the user automatically. You can use it the following way:


     #include <tdeabc/stdaddressbook.h>

 1:  TDEABC::AddressBook *ab = TDEABC::StdAddressBook::self();
 2:  TDEABC::AddressBook::Iterator it;
 3:  for ( it = ab->begin(); it != ab->end(); ++it ) {
 4:    TDEABC::Addressee addr = (*it);
 5:
 6:    kdDebug() << "Name = " << addr.formattedName() << endl;
 7:  }

The above example prints out the names of all the contacts in the user's address
book. In line 1 you retrieve a pointer to the user's standard address book
(provided by TDEABC::StdAddressBook via a singleton design pattern).
In line 2 an iterator is defined, which is used in line 3 to iterate over the
whole address book. The assignment in line 4 is intended only to show more
clearly how iterators function.
You could also use (*it).formattedName() directly. In line 6 the formatted name
of the current contact is printed out to stderr.
As you can see that's all magic, and it's quite easy ;)


Using TDEABC::AddressBook manually
---------------------------------
In some cases you don't want to load the user's standard address book, but,
for example, just a single vCard. For this purpose you have to use the
class TDEABC::AddressBook and handle the resource stuff manually.
The following code will create a file resource and save a contact into it:


     #include <tdeabc/addressbook.h>
     #include <tdeabc/resourcefile.h>

 1:  TDEABC::AddressBook ab;
 2:
 3:  // create a file resource
 4:  TDEABC::Resource *res = new TDEABC::ResourceFile( "/home/user/myvcard.vcf", "vcard" );
 5:
 6:  if ( !ab.addResource( res ) ) {
 7:    kdDebug() << "Unable to open resource" << endl;
 8:    return 1;
 9:  }
10:
11:  if ( !ab.load() ) {
12:    kdDebug() << "Unable to load address book!" << endl;
13:    return 2;
14:  }
15:
16:  TDEABC::Addressee addr;
17:  addr.setNameFromString( "Otto Harald Meyer" );
18:  addr.setBirthday( QDate( 1982, 07, 19 ) );
19:  addr.setNickName( "otto" );
20:  addr.setMailer( "kmail" );
21:
22:  // TZ
23:  TDEABC::TimeZone tz( 60 );  // takes time shift in minutes as argument
24:  addr.setTimeZone( tz );
25:
26:  // GEO
27:  TDEABC::Geo geo( 52.5, 13.36 ); // takes latitude and longitude as argument
28:  addr.setGeo( geo );
29:
30:  addr.setTitle( "dude, the" );
31:  addr.setRole( "developer" );
32:  addr.setOrganization( "KDE e.V." );
33:  addr.setNote( "Yet another senseless note..." );
34:  addr.setUrl( KURL( "http://kaddressbook.org" ) );
35:
36:  // CLASS
37:  TDEABC::Secrecy secrecy( TDEABC::Secrecy::Confidential );
38:  addr.setSecrecy( secrecy );
39:
40:  // PHOTO or LOGO
41:  TDEABC::Picture photo;
42:  QImage img;
43:  if ( img.load( "face.png", "PNG" ) ) {
44:    photo.setData( img );
45:    photo.setType( "image/png" );
46:    addr.setPhoto( photo );
47:  }
48:
49:  addr.insertEmail( "otto@kde.se", true );  // preferred email
50:  addr.insertEmail( "otti@yahoo.com", false );
51:
52:  // TEL
53:  TDEABC::PhoneNumber phoneHome( "0351 5466738", TDEABC::PhoneNumber::Home );
54:  TDEABC::PhoneNumber phoneWork( "0351 2335411", TDEABC::PhoneNumber::Work );
55:  addr.insertPhoneNumber( phoneHome );
56:  addr.insertPhoneNumber( phoneWork );
57:
58:  // ADR
59:  TDEABC::Address homeAddr( TDEABC::Address::Home );
60:  homeAddr.setStreet( "Milliwaystreet 42" );
61:  homeAddr.setLocality( "London" );
62:  homeAddr.setRegion( "Saxony" );
63:  homeAddr.setPostalCode( "43435" );
64:  homeAddr.setCountry( "Germany" );
65:  addr.insertAddress( homeAddr );
66:
67:  addr.insertCategory( "LUG-Dresden-Members" );
68:
69:  addr.insertCustom( "KADDRESSBOOK", "X-Anniversary", "21.04.2009" );
70:
71:  ab.insertAddressee( addr ); // will be assigned to the standard resource
72:                              // automatically
73:
74:  TDEABC::Ticket *ticket = ab.requestSaveTicket( res );
75:  if ( !ticket ) {
76:    kdError() << "Resource is locked by other application!" << endl;
77:  } else {
78:    if ( !ab.save( ticket ) ) {
79:      kdError() << "Saving failed!" << endl;
80:      ab.releaseSaveTicket( ticket );
81:    }
82:
83:  }
84:
85:  return 0;

In line 1 the TDEABC::AddressBook is created.  In line 4 you creat the
TDEABC::ResourceFile (which will handle the loading/saving).
The resource takes 2 arguments, the first is the file name and the
second one the file format. At the moment libtdeabc supports two file formats:
1) vCard, as specified in RFC 2426
2) Binary, which increases performance during loading and saving

In line 6 we try to plug the resource into the addressbook. The addressbook
class tries to open the resource immediately and returns whether opening was
successful. We add here only one resource, but you can add as many resources
as you want.

In line 11 we try to load all contacts from the backends into the address book.
As before, it returns whether opening was successful.

In line 16 a TDEABC::Addressee is created, which we will fill now with data,
before inserting it into the TDEABC::AddressBook.
The setNameFromString() function in the following line takes a string as
argument and tries to parse it into the single name components such as: given
name, family name, additional names, honoric prefix and honoric suffix.
You can set these values manually as well by calling
  addr.setGivenName( "Otto" );
and
  addr.setFamilyName( "Meyer" );
etc. etc.

In line 23 we use the class TDEABC::TimeZone to store the timezone. This class
takes the time shift in minutes.

In line 27 the TDEABC::Geo class is used for storing the geographical
information. The arguments are the latitude and longitude as float values.

TDEABC::Secrecy in line 37 represents the CLASS entity of a vCard and can take
TDEABC::Secrecy::Public, TDEABC::Secrecy::Private or TDEABC::Secrecy::Confidential
as argument.

In line 41 we make use of TDEABC::Picture class to store the photo of the
contact. This class can contain either an URL or the raw image data in form
of a QImage, in this example we use the latter.

In line 43 we try to load the image "face.png" from the local directory and
assign this QImage to the TDEABC::Picture class via the setData() function.
Additionally we set the type of the picture to "image/png".

From 49 - 50 we insert 2 email addresses with the first one as preferred
(second argument is true).

In 53 and the following 3 lines we add two telephone numbers. For this purpose
libtdeabc provides the TDEABC::PhoneNumber class, which takes the phone number in
string representation as first argument and the type as second. The types can
be combined, so 'TDEABC::PhoneNumber::Home | TDEABC::PhoneNumber::Fax' would be
the Home Fax.

In line 59 we create a TDEABC::Address object and set the single parts in the
following lines.

In line 67 we assign the contact to a special category.

A contact can also contain custom entries, which are not specified in the API,
so you can add custom values with insertCustom() as shown in line 69.
The first argument of this function should be the name of the application, so
2 applications which use the same custom entry accidentally, do not overwrite
the data for each other. The second argument contains the name of the
custom entry and the third argument the value in string representation.

In line 71 we finally insert the TDEABC::Addressee object into the
TDEABC::AddressBook. Since we have only one resource loaded, the contact is
automatically assigned to this resource. If you have several writeable
resources loaded, you should ask the user which resource the contact shall
belong to and assign the selected resource to the contact with
  TDEABC::Addressee.setResource( TDEABC::Resource *resource );
before inserting it into the address book.

To prevent multiple access to one resource and possible resulting data loss
we have to lock the resource before saving our changes.
For this purpose TDEABC::AddressBook provides the function
  requestSaveTicket( TDEABC::Resource* )
which takes a pointer to the resource which shall be saved as argument and
returns a so called 'Save Ticket' if locking succeeded or a null pointer
if the resource is already locked by another application.

So when we retrieved a valid ticket in line 74, we try to save our changes in
line 78.
The TDEABC::AddressBook::save() function takes the save ticket as argument and
returns whether saving succeeded.  It also releases the save ticket when successful.

Important!
If the save() call fails, you have to release the save ticket manually, as is
done in line 80, otherwise possible locks, created by the resources, won't be
removed.

You can see also, that manual use is quite easy for the TDEABC::AddressBook class
and for the ResourceFile. For more information about the API of TDEABC::Addressee
please take a look at the official API documentation or the header files.


Distribution Lists
-------------------
libtdeabc provides so called distribution lists to group contacts. These lists
just store the uid of contacts, so they can be used for every kind of contact
grouping. There are 2 classes which handle the whole distribution list tasks,
TDEABC::DistributionListManager and TDEABC::DistributionList. The first one keeps
track of all available distribution lists and the latter one is the
representation of one list.


     #include <tdeabc/distributionlist.h>
     #include <tdeabc/stdaddressbook.h>

 1:  TDEABC::DistributionListManager manager( TDEABC::StdAddressBook::self() );
 2:
 3:  // load the lists
 4:  manager.load();
 5:
 6:  QStringList listNames = manager.listNames();
 7:  QStringList::Iterator it;
 8:  for ( it = listNames.begin(); it != listNames.end(); ++it ) {
 9:    TDEABC::DistributionList *list = manager.list( *it );
10:    kdDebug() << list->name() << endl;
11:
12:    QStringList emails = list->emails();
13:    QStringList::Iterator eit;
14:    for ( eit = emails.begin(); eit != emails.end(); ++eit )
15:      kdDebug() << QString( "\t%1" ).arg( (*eit).latin1() ) << endl;
16:  }

In the first line a TDEABC::DistributionListManager is created. The manager takes
a pointer to a TDEABC::AddressBook, because he has to resolve the stored uids to
currently available email addresses.
In line 4 the manager loads all distribution lists from the central config file
$HOME/.trinity/share/apps/tdeabc/distlists.
The next line queries the names of all available distribution lists, which are
used in line 9 to retrieve a pointer to the specific list.
Now that you have a TDEABC::DistributionList object, you can performe the
following actions on it:
 - set / get the name
 - insert an entry
 - remove an entry
 - get a list of all email addresses
 - get a list of all entries (which includes the uids)

In line 12 we query all email addresses of every resource and print them out.

<tdeabc/distributionlist.h> contains also the declaration for the class
TDEABC::DistributionListWatcher. This class exists only once per application and
its only job is to emit a signal as soon as the distribution list file has
changed. So to make your application aware of changes use the following code:


     #include <tdeabc/distributionlist.h>

 1:  connect( TDEABC::DistributionListWatcher::self(), SIGNAL( changed() ),
 2:           this, SLOT( slotDistributionListChanged() ) );

You see, as usual, easy ;)

