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 libkabc may be helpful. General Concepts ================= In libkabc 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 libkabc 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 KIO 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 libkabc 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 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 #include 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 libkabc 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 libkabc 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 ------------------- libkabc 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 #include 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. 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 1: connect( TDEABC::DistributionListWatcher::self(), SIGNAL( changed() ), 2: this, SLOT( slotDistributionListChanged() ) ); You see, as usual, easy ;)