summaryrefslogtreecommitdiff
path: root/libopie
Side-by-side diff
Diffstat (limited to 'libopie') (more/less context) (show whitespace changes)
-rw-r--r--libopie/pim/README_COMPILE11
-rw-r--r--libopie/pim/libopie.pro11
-rw-r--r--libopie/pim/ocontact.cpp1433
-rw-r--r--libopie/pim/ocontact.h311
-rw-r--r--libopie/pim/ocontactaccess.cpp174
-rw-r--r--libopie/pim/ocontactaccess.h197
-rw-r--r--libopie/pim/ocontactaccessbackend.h70
-rw-r--r--libopie/pim/ocontactaccessbackend_xml.h550
8 files changed, 2755 insertions, 2 deletions
diff --git a/libopie/pim/README_COMPILE b/libopie/pim/README_COMPILE
new file mode 100644
index 0000000..d9f13ce
--- a/dev/null
+++ b/libopie/pim/README_COMPILE
@@ -0,0 +1,11 @@
+To compile successfully ocontact there have to be the
+following symbolic links created:
+
+ln -s ../../library/backend/qfiledirect_p.h
+ln -s ../../library/backend/vobject_p.h
+
+
+This "dirty" solution will be fixed, soon !
+
+
+Bye, Stefan (Eilers.Stefan@epost.de) \ No newline at end of file
diff --git a/libopie/pim/libopie.pro b/libopie/pim/libopie.pro
index b17758a..1dacbe7 100644
--- a/libopie/pim/libopie.pro
+++ b/libopie/pim/libopie.pro
@@ -24,5 +24,10 @@ HEADERS = ofontmenu.h \
pim/opimaccessbackend.h \
pim/otodoaccess.h \
- pim/otodacessbackend.h
+ pim/otodacessbackend.h \
+ pim/ocontact.h \
+ pim/ocontactaccess.h \
+ pim/ocontactaccessbackend.h \
+ pim/ocontactaccessbackend_xml.h
+
SOURCES = ofontmenu.cc \
xmltree.cc \
@@ -44,5 +49,7 @@ SOURCES = ofontmenu.cc \
pim/opimrecord.cpp \
pim/otodoaccess.cpp \
- pim/otodoaccessbackend.cpp
+ pim/otodoaccessbackend.cpp \
+ pim/ocontact.cpp \
+ pim/ocontactaccess.cpp
TARGET = opie
diff --git a/libopie/pim/ocontact.cpp b/libopie/pim/ocontact.cpp
new file mode 100644
index 0000000..66632f5
--- a/dev/null
+++ b/libopie/pim/ocontact.cpp
@@ -0,0 +1,1433 @@
+/**********************************************************************
+** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
+**
+** This file is part of the Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#define QTOPIA_INTERNAL_CONTACT_MRE
+
+#include "ocontact.h"
+#include "vobject_p.h"
+#include "qfiledirect_p.h"
+
+#include <qpe/stringutil.h>
+#include <qpe/timeconversion.h>
+
+#include <qobject.h>
+#include <qregexp.h>
+#include <qstylesheet.h>
+#include <qfileinfo.h>
+#include <qmap.h>
+
+#include <stdio.h>
+
+/*!
+ \class Contact contact.h
+ \brief The Contact class holds the data of an address book entry.
+
+ This data includes information the name of the person, contact
+ information, and business information such as deparment and job title.
+
+ \ingroup qtopiaemb
+ \ingroup qtopiadesktop
+*/
+
+Qtopia::UidGen OContact::sUidGen( Qtopia::UidGen::Qtopia );
+
+/*!
+ Creates a new, empty contact.
+*/
+OContact::OContact()
+ : OPimRecord(), mMap(), d( 0 )
+{
+}
+
+/*!
+ \internal
+ Creates a new contact. The properties of the contact are
+ set from \a fromMap.
+*/
+OContact::OContact( const QMap<int, QString> &fromMap ) :
+ OPimRecord(), mMap( fromMap ), d( 0 )
+{
+ QString cats = mMap[ Qtopia::AddressCategory ];
+ if ( !cats.isEmpty() )
+ setCategories( idsFromString( cats ) );
+ QString uidStr = find( Qtopia::AddressUid );
+
+ if ( uidStr.isEmpty() )
+ setUid( uidGen().generate() );
+ else
+ setUid( uidStr.toInt() );
+
+ if ( !uidStr.isEmpty() )
+ setUid( uidStr.toInt() );
+}
+
+/*!
+ Destroys a contact.
+*/
+OContact::~OContact()
+{
+}
+
+/*! \fn void OContact::setTitle( const QString &str )
+ Sets the title of the contact to \a str.
+*/
+
+/*! \fn void OContact::setFirstName( const QString &str )
+ Sets the first name of the contact to \a str.
+*/
+
+/*! \fn void OContact::setMiddleName( const QString &str )
+ Sets the middle name of the contact to \a str.
+*/
+
+/*! \fn void OContact::setLastName( const QString &str )
+ Sets the last name of the contact to \a str.
+*/
+
+/*! \fn void OContact::setSuffix( const QString &str )
+ Sets the suffix of the contact to \a str.
+*/
+
+/*! \fn void OContact::setFileAs( const QString &str )
+ Sets the contact to filed as \a str.
+*/
+
+/*! \fn void OContact::setDefaultEmail( const QString &str )
+ Sets the default email of the contact to \a str.
+*/
+
+/*! \fn void OContact::setHomeStreet( const QString &str )
+ Sets the home street address of the contact to \a str.
+*/
+
+/*! \fn void OContact::setHomeCity( const QString &str )
+ Sets the home city of the contact to \a str.
+*/
+
+/*! \fn void OContact::setHomeState( const QString &str )
+ Sets the home state of the contact to \a str.
+*/
+
+/*! \fn void OContact::setHomeZip( const QString &str )
+ Sets the home zip code of the contact to \a str.
+*/
+
+/*! \fn void OContact::setHomeCountry( const QString &str )
+ Sets the home country of the contact to \a str.
+*/
+
+/*! \fn void OContact::setHomePhone( const QString &str )
+ Sets the home phone number of the contact to \a str.
+*/
+
+/*! \fn void OContact::setHomeFax( const QString &str )
+ Sets the home fax number of the contact to \a str.
+*/
+
+/*! \fn void OContact::setHomeMobile( const QString &str )
+ Sets the home mobile phone number of the contact to \a str.
+*/
+
+/*! \fn void OContact::setHomeWebpage( const QString &str )
+ Sets the home webpage of the contact to \a str.
+*/
+
+/*! \fn void OContact::setCompany( const QString &str )
+ Sets the company for contact to \a str.
+*/
+
+/*! \fn void OContact::setJobTitle( const QString &str )
+ Sets the job title of the contact to \a str.
+*/
+
+/*! \fn void OContact::setDepartment( const QString &str )
+ Sets the department for contact to \a str.
+*/
+
+/*! \fn void OContact::setOffice( const QString &str )
+ Sets the office for contact to \a str.
+*/
+
+/*! \fn void OContact::setBusinessStreet( const QString &str )
+ Sets the business street address of the contact to \a str.
+*/
+
+/*! \fn void OContact::setBusinessCity( const QString &str )
+ Sets the business city of the contact to \a str.
+*/
+
+/*! \fn void OContact::setBusinessState( const QString &str )
+ Sets the business state of the contact to \a str.
+*/
+
+/*! \fn void OContact::setBusinessZip( const QString &str )
+ Sets the business zip code of the contact to \a str.
+*/
+
+/*! \fn void OContact::setBusinessCountry( const QString &str )
+ Sets the business country of the contact to \a str.
+*/
+
+/*! \fn void OContact::setBusinessPhone( const QString &str )
+ Sets the business phone number of the contact to \a str.
+*/
+
+/*! \fn void OContact::setBusinessFax( const QString &str )
+ Sets the business fax number of the contact to \a str.
+*/
+
+/*! \fn void OContact::setBusinessMobile( const QString &str )
+ Sets the business mobile phone number of the contact to \a str.
+*/
+
+/*! \fn void OContact::setBusinessPager( const QString &str )
+ Sets the business pager number of the contact to \a str.
+*/
+
+/*! \fn void OContact::setBusinessWebpage( const QString &str )
+ Sets the business webpage of the contact to \a str.
+*/
+
+/*! \fn void OContact::setProfession( const QString &str )
+ Sets the profession of the contact to \a str.
+*/
+
+/*! \fn void OContact::setAssistant( const QString &str )
+ Sets the assistant of the contact to \a str.
+*/
+
+/*! \fn void OContact::setManager( const QString &str )
+ Sets the manager of the contact to \a str.
+*/
+
+/*! \fn void OContact::setSpouse( const QString &str )
+ Sets the spouse of the contact to \a str.
+*/
+
+/*! \fn void OContact::setGender( const QString &str )
+ Sets the gender of the contact to \a str.
+*/
+
+/*! \fn void OContact::setBirthday( const QString &str )
+ Sets the birthday for the contact to \a str.
+*/
+
+/*! \fn void OContact::setAnniversary( const QString &str )
+ Sets the anniversary of the contact to \a str.
+*/
+
+/*! \fn void OContact::setNickname( const QString &str )
+ Sets the nickname of the contact to \a str.
+*/
+
+/*! \fn void OContact::setNotes( const QString &str )
+ Sets the notes about the contact to \a str.
+*/
+
+/*! \fn QString OContact::title() const
+ Returns the title of the contact.
+*/
+
+/*! \fn QString OContact::firstName() const
+ Returns the first name of the contact.
+*/
+
+/*! \fn QString OContact::middleName() const
+ Returns the middle name of the contact.
+*/
+
+/*! \fn QString OContact::lastName() const
+ Returns the last name of the contact.
+*/
+
+/*! \fn QString OContact::suffix() const
+ Returns the suffix of the contact.
+*/
+
+/*! \fn QString OContact::fileAs() const
+ Returns the string the contact is filed as.
+*/
+
+/*! \fn QString OContact::defaultEmail() const
+ Returns the default email address of the contact.
+*/
+
+/*! \fn QString OContact::emails() const
+ Returns the list of email address for a contact separated by ';'s in a single
+ string.
+*/
+
+/*! \fn QString OContact::homeStreet() const
+ Returns the home street address of the contact.
+*/
+
+/*! \fn QString OContact::homeCity() const
+ Returns the home city of the contact.
+*/
+
+/*! \fn QString OContact::homeState() const
+ Returns the home state of the contact.
+*/
+
+/*! \fn QString OContact::homeZip() const
+ Returns the home zip of the contact.
+*/
+
+/*! \fn QString OContact::homeCountry() const
+ Returns the home country of the contact.
+*/
+
+/*! \fn QString OContact::homePhone() const
+ Returns the home phone number of the contact.
+*/
+
+/*! \fn QString OContact::homeFax() const
+ Returns the home fax number of the contact.
+*/
+
+/*! \fn QString OContact::homeMobile() const
+ Returns the home mobile number of the contact.
+*/
+
+/*! \fn QString OContact::homeWebpage() const
+ Returns the home webpage of the contact.
+*/
+
+/*! \fn QString OContact::company() const
+ Returns the company for the contact.
+*/
+
+/*! \fn QString OContact::department() const
+ Returns the department for the contact.
+*/
+
+/*! \fn QString OContact::office() const
+ Returns the office for the contact.
+*/
+
+/*! \fn QString OContact::jobTitle() const
+ Returns the job title of the contact.
+*/
+
+/*! \fn QString OContact::profession() const
+ Returns the profession of the contact.
+*/
+
+/*! \fn QString OContact::assistant() const
+ Returns the assistant of the contact.
+*/
+
+/*! \fn QString OContact::manager() const
+ Returns the manager of the contact.
+*/
+
+/*! \fn QString OContact::businessStreet() const
+ Returns the business street address of the contact.
+*/
+
+/*! \fn QString OContact::businessCity() const
+ Returns the business city of the contact.
+*/
+
+/*! \fn QString OContact::businessState() const
+ Returns the business state of the contact.
+*/
+
+/*! \fn QString OContact::businessZip() const
+ Returns the business zip of the contact.
+*/
+
+/*! \fn QString OContact::businessCountry() const
+ Returns the business country of the contact.
+*/
+
+/*! \fn QString OContact::businessPhone() const
+ Returns the business phone number of the contact.
+*/
+
+/*! \fn QString OContact::businessFax() const
+ Returns the business fax number of the contact.
+*/
+
+/*! \fn QString OContact::businessMobile() const
+ Returns the business mobile number of the contact.
+*/
+
+/*! \fn QString OContact::businessPager() const
+ Returns the business pager number of the contact.
+*/
+
+/*! \fn QString OContact::businessWebpage() const
+ Returns the business webpage of the contact.
+*/
+
+/*! \fn QString OContact::spouse() const
+ Returns the spouse of the contact.
+*/
+
+/*! \fn QString OContact::gender() const
+ Returns the gender of the contact.
+*/
+
+/*! \fn QString OContact::birthday() const
+ Returns the birthday of the contact.
+*/
+
+/*! \fn QString OContact::anniversary() const
+ Returns the anniversary of the contact.
+*/
+
+/*! \fn QString OContact::nickname() const
+ Returns the nickname of the contact.
+*/
+
+/*! \fn QString OContact::children() const
+ Returns the children of the contact.
+*/
+
+/*! \fn QString OContact::notes() const
+ Returns the notes relating to the the contact.
+*/
+
+/*! \fn QString OContact::groups() const
+ \internal
+ Returns the groups for the contact.
+*/
+
+/*! \fn QStringList OContact::groupList() const
+ \internal
+*/
+
+/*! \fn QString OContact::field(int) const
+ \internal
+*/
+
+/*! \fn void OContact::saveJournal( journal_action, const QString & = QString::null )
+ \internal
+*/
+
+/*! \fn void OContact::setUid( int id )
+ \internal
+ Sets the uid for this record to \a id.
+*/
+
+/*! \enum OContact::journal_action
+ \internal
+*/
+
+/*!
+ \internal
+*/
+QMap<int, QString> OContact::toMap() const
+{
+ QMap<int, QString> map = mMap;
+ QString cats = idsToString( categories() );
+ if ( !cats.isEmpty() )
+ map.insert( Qtopia::AddressCategory, cats );
+ return map;
+}
+
+/*!
+ Returns a rich text formatted QString representing the contents the contact.
+*/
+QString OContact::toRichText() const
+{
+ QString text;
+ QString value, comp, state;
+
+ // name, jobtitle and company
+ if ( !(value = fullName()).isEmpty() )
+ text += "<b>" + Qtopia::escapeString(value) + "</b><br>";
+ if ( !(value = jobTitle()).isEmpty() )
+ text += Qtopia::escapeString(value) + "<br>";
+
+ comp = company();
+ if ( !(value = department()).isEmpty() ) {
+ text += Qtopia::escapeString(value);
+ if ( comp )
+ text += ", ";
+ else
+ text += "<br>";
+ }
+ if ( !comp.isEmpty() )
+ text += Qtopia::escapeString(comp) + "<br>";
+
+ // business address
+ if ( !businessStreet().isEmpty() || !businessCity().isEmpty() ||
+ !businessZip().isEmpty() || !businessCountry().isEmpty() ) {
+ text += "<br>";
+ text += QObject::tr( "<b>Work Address:</b>" );
+ text += "<br>";
+ }
+
+ if ( !(value = businessStreet()).isEmpty() )
+ text += Qtopia::escapeString(value) + "<br>";
+ state = businessState();
+ if ( !(value = businessCity()).isEmpty() ) {
+ text += Qtopia::escapeString(value);
+ if ( state )
+ text += ", " + Qtopia::escapeString(state);
+ text += "<br>";
+ } else if ( !state.isEmpty() )
+ text += Qtopia::escapeString(state) + "<br>";
+ if ( !(value = businessZip()).isEmpty() )
+ text += Qtopia::escapeString(value) + "<br>";
+ if ( !(value = businessCountry()).isEmpty() )
+ text += Qtopia::escapeString(value) + "<br>";
+
+ // home address
+ if ( !homeStreet().isEmpty() || !homeCity().isEmpty() ||
+ !homeZip().isEmpty() || !homeCountry().isEmpty() ) {
+ text += "<br>";
+ text += QObject::tr( "<b>Home Address:</b>" );
+ text += "<br>";
+ }
+
+ if ( !(value = homeStreet()).isEmpty() )
+ text += Qtopia::escapeString(value) + "<br>";
+ state = homeState();
+ if ( !(value = homeCity()).isEmpty() ) {
+ text += Qtopia::escapeString(value);
+ if ( !state.isEmpty() )
+ text += ", " + Qtopia::escapeString(state);
+ text += "<br>";
+ } else if (!state.isEmpty())
+ text += Qtopia::escapeString(state) + "<br>";
+ if ( !(value = homeZip()).isEmpty() )
+ text += Qtopia::escapeString(value) + "<br>";
+ if ( !(value = homeCountry()).isEmpty() )
+ text += Qtopia::escapeString(value) + "<br>";
+
+ // the others...
+ QString str;
+ str = emails();
+ if ( !str.isEmpty() )
+ text += "<b>" + QObject::tr("Email Addresses: ") + "</b>"
+ + Qtopia::escapeString(str) + "<br>";
+ str = homePhone();
+ if ( !str.isEmpty() )
+ text += "<b>" + QObject::tr("Home Phone: ") + "</b>"
+ + Qtopia::escapeString(str) + "<br>";
+ str = homeFax();
+ if ( !str.isEmpty() )
+ text += "<b>" + QObject::tr("Home Fax: ") + "</b>"
+ + Qtopia::escapeString(str) + "<br>";
+ str = homeMobile();
+ if ( !str.isEmpty() )
+ text += "<b>" + QObject::tr("Home Mobile: ") + "</b>"
+ + Qtopia::escapeString(str) + "<br>";
+ str = homeWebpage();
+ if ( !str.isEmpty() )
+ text += "<b>" + QObject::tr("Home Web Page: ") + "</b>"
+ + Qtopia::escapeString(str) + "<br>";
+ str = businessWebpage();
+ if ( !str.isEmpty() )
+ text += "<b>" + QObject::tr("Business Web Page: ") + "</b>"
+ + Qtopia::escapeString(str) + "<br>";
+ str = office();
+ if ( !str.isEmpty() )
+ text += "<b>" + QObject::tr("Office: ") + "</b>"
+ + Qtopia::escapeString(str) + "<br>";
+ str = businessPhone();
+ if ( !str.isEmpty() )
+ text += "<b>" + QObject::tr("Business Phone: ") + "</b>"
+ + Qtopia::escapeString(str) + "<br>";
+ str = businessFax();
+ if ( !str.isEmpty() )
+ text += "<b>" + QObject::tr("Business Fax: ") + "</b>"
+ + Qtopia::escapeString(str) + "<br>";
+ str = businessMobile();
+ if ( !str.isEmpty() )
+ text += "<b>" + QObject::tr("Business Mobile: ") + "</b>"
+ + Qtopia::escapeString(str) + "<br>";
+ str = businessPager();
+ if ( !str.isEmpty() )
+ text += "<b>" + QObject::tr("Business Pager: ") + "</b>"
+ + Qtopia::escapeString(str) + "<br>";
+ str = profession();
+ if ( !str.isEmpty() )
+ text += "<b>" + QObject::tr("Profession: ") + "</b>"
+ + Qtopia::escapeString(str) + "<br>";
+ str = assistant();
+ if ( !str.isEmpty() )
+ text += "<b>" + QObject::tr("Assistant: ") + "</b>"
+ + Qtopia::escapeString(str) + "<br>";
+ str = manager();
+ if ( !str.isEmpty() )
+ text += "<b>" + QObject::tr("Manager: ") + "</b>"
+ + Qtopia::escapeString(str) + "<br>";
+ str = gender();
+ if ( !str.isEmpty() && str.toInt() != 0 ) {
+ if ( str.toInt() == 1 )
+ str = QObject::tr( "Male" );
+ else if ( str.toInt() == 2 )
+ str = QObject::tr( "Female" );
+ text += "<b>" + QObject::tr("Gender: ") + "</b>" + str + "<br>";
+ }
+ str = spouse();
+ if ( !str.isEmpty() )
+ text += "<b>" + QObject::tr("Spouse: ") + "</b>"
+ + Qtopia::escapeString(str) + "<br>";
+ str = birthday();
+ if ( !str.isEmpty() )
+ text += "<b>" + QObject::tr("Birthday: ") + "</b>"
+ + Qtopia::escapeString(str) + "<br>";
+ str = anniversary();
+ if ( !str.isEmpty() )
+ text += "<b>" + QObject::tr("Anniversary: ") + "</b>"
+ + Qtopia::escapeString(str) + "<br>";
+ str = nickname();
+ if ( !str.isEmpty() )
+ text += "<b>" + QObject::tr("Nickname: ") + "</b>"
+ + Qtopia::escapeString(str) + "<br>";
+
+ // notes last
+ if ( (value = notes()) ) {
+ QRegExp reg("\n");
+
+ //QString tmp = Qtopia::escapeString(value);
+ QString tmp = QStyleSheet::convertFromPlainText(value);
+ //tmp.replace( reg, "<br>" );
+ text += "<br>" + tmp + "<br>";
+ }
+ return text;
+}
+
+/*!
+ \internal
+*/
+void OContact::insert( int key, const QString &v )
+{
+ QString value = v.stripWhiteSpace();
+ if ( value.isEmpty() )
+ mMap.remove( key );
+ else
+ mMap.insert( key, value );
+}
+
+/*!
+ \internal
+*/
+void OContact::replace( int key, const QString & v )
+{
+ QString value = v.stripWhiteSpace();
+ if ( value.isEmpty() )
+ mMap.remove( key );
+ else
+ mMap.replace( key, value );
+}
+
+/*!
+ \internal
+*/
+QString OContact::find( int key ) const
+{
+ return mMap[key];
+}
+
+/*!
+ \internal
+*/
+QString OContact::displayAddress( const QString &street,
+ const QString &city,
+ const QString &state,
+ const QString &zip,
+ const QString &country ) const
+{
+ QString s = street;
+ if ( !street.isEmpty() )
+ s+= "\n";
+ s += city;
+ if ( !city.isEmpty() && !state.isEmpty() )
+ s += ", ";
+ s += state;
+ if ( !state.isEmpty() && !zip.isEmpty() )
+ s += " ";
+ s += zip;
+ if ( !country.isEmpty() && !s.isEmpty() )
+ s += "\n";
+ s += country;
+ return s;
+}
+
+/*!
+ \internal
+*/
+QString OContact::displayBusinessAddress() const
+{
+ return displayAddress( businessStreet(), businessCity(),
+ businessState(), businessZip(),
+ businessCountry() );
+}
+
+/*!
+ \internal
+*/
+QString OContact::displayHomeAddress() const
+{
+ return displayAddress( homeStreet(), homeCity(),
+ homeState(), homeZip(),
+ homeCountry() );
+}
+
+/*!
+ Returns the full name of the contact
+*/
+QString OContact::fullName() const
+{
+ QString title = find( Qtopia::Title );
+ QString firstName = find( Qtopia::FirstName );
+ QString middleName = find( Qtopia::MiddleName );
+ QString lastName = find( Qtopia::LastName );
+ QString suffix = find( Qtopia::Suffix );
+
+ QString name = title;
+ if ( !firstName.isEmpty() ) {
+ if ( !name.isEmpty() )
+ name += " ";
+ name += firstName;
+ }
+ if ( !middleName.isEmpty() ) {
+ if ( !name.isEmpty() )
+ name += " ";
+ name += middleName;
+ }
+ if ( !lastName.isEmpty() ) {
+ if ( !name.isEmpty() )
+ name += " ";
+ name += lastName;
+ }
+ if ( !suffix.isEmpty() ) {
+ if ( !name.isEmpty() )
+ name += " ";
+ name += suffix;
+ }
+ return name.simplifyWhiteSpace();
+}
+
+/*!
+ Returns a list of the names of the children of the contact.
+*/
+QStringList OContact::childrenList() const
+{
+ return QStringList::split( " ", find( Qtopia::Children ) );
+}
+
+/*! \fn void OContact::insertEmail( const QString &email )
+
+ Insert \a email into the email list. Ensures \a email can only be added
+ once. If there is no default email address set, it sets it to the \a email.
+*/
+
+/*! \fn void OContact::removeEmail( const QString &email )
+
+ Removes the \a email from the email list. If the default email was \a email,
+ then the default email address is assigned to the first email in the
+ email list
+*/
+
+/*! \fn void OContact::clearEmails()
+
+ Clears the email list.
+ */
+
+/*! \fn void OContact::insertEmails( const QStringList &emailList )
+
+ Appends the \a emailList to the exiting email list
+ */
+
+/*!
+ Returns a list of email addresses belonging to the contact, including
+ the default email address.
+*/
+QStringList OContact::emailList() const
+{
+ QString emailStr = emails();
+
+ QStringList r;
+ if ( !emailStr.isEmpty() ) {
+ qDebug(" emailstr ");
+ QStringList l = QStringList::split( emailSeparator(), emailStr );
+ for ( QStringList::ConstIterator it = l.begin();it != l.end();++it )
+ r += (*it).simplifyWhiteSpace();
+ }
+
+ return r;
+}
+
+/*!
+ \overload
+
+ Generates the string for the contact to be filed as from the first,
+ middle and last name of the contact.
+*/
+void OContact::setFileAs()
+{
+ QString lastName, firstName, middleName, fileas;
+
+ lastName = find( Qtopia::LastName );
+ firstName = find( Qtopia::FirstName );
+ middleName = find( Qtopia::MiddleName );
+ if ( !lastName.isEmpty() && !firstName.isEmpty()
+ && !middleName.isEmpty() )
+ fileas = lastName + ", " + firstName + " " + middleName;
+ else if ( !lastName.isEmpty() && !firstName.isEmpty() )
+ fileas = lastName + ", " + firstName;
+ else if ( !lastName.isEmpty() || !firstName.isEmpty() ||
+ !middleName.isEmpty() )
+ fileas = firstName + ( firstName.isEmpty() ? "" : " " )
+ + middleName + ( middleName.isEmpty() ? "" : " " )
+ + lastName;
+
+ replace( Qtopia::FileAs, fileas );
+}
+
+/*!
+ \internal
+ Appends the contact information to \a buf.
+*/
+void OContact::save( QString &buf ) const
+{
+ static const QStringList SLFIELDS = fields();
+ // I'm expecting "<Contact " in front of this...
+ for ( QMap<int, QString>::ConstIterator it = mMap.begin();
+ it != mMap.end(); ++it ) {
+ const QString &value = it.data();
+ int key = it.key();
+ if ( !value.isEmpty() ) {
+ if ( key == Qtopia::AddressCategory || key == Qtopia::AddressUid)
+ continue;
+
+ key -= Qtopia::AddressCategory+1;
+ buf += SLFIELDS[key];
+ buf += "=\"" + Qtopia::escapeString(value) + "\" ";
+ }
+ }
+ buf += customToXml();
+ if ( categories().count() > 0 )
+ buf += "Categories=\"" + idsToString( categories() ) + "\" ";
+ buf += "Uid=\"" + QString::number( uid() ) + "\" ";
+ // You need to close this yourself
+}
+
+/*!
+ \internal
+ Returns the list of fields belonging to a contact
+*/
+QStringList OContact::fields()
+{
+ QStringList list;
+
+ list.append( "Title" ); // Not Used!
+ list.append( "FirstName" );
+ list.append( "MiddleName" );
+ list.append( "LastName" );
+ list.append( "Suffix" );
+ list.append( "FileAs" );
+
+ list.append( "JobTitle" );
+ list.append( "Department" );
+ list.append( "Company" );
+ list.append( "BusinessPhone" );
+ list.append( "BusinessFax" );
+ list.append( "BusinessMobile" );
+
+ list.append( "DefaultEmail" );
+ list.append( "Emails" );
+
+ list.append( "HomePhone" );
+ list.append( "HomeFax" );
+ list.append( "HomeMobile" );
+
+ list.append( "BusinessStreet" );
+ list.append( "BusinessCity" );
+ list.append( "BusinessState" );
+ list.append( "BusinessZip" );
+ list.append( "BusinessCountry" );
+ list.append( "BusinessPager" );
+ list.append( "BusinessWebPage" );
+
+ list.append( "Office" );
+ list.append( "Profession" );
+ list.append( "Assistant" );
+ list.append( "Manager" );
+
+ list.append( "HomeStreet" );
+ list.append( "HomeCity" );
+ list.append( "HomeState" );
+ list.append( "HomeZip" );
+ list.append( "HomeCountry" );
+ list.append( "HomeWebPage" );
+
+ list.append( "Spouse" );
+ list.append( "Gender" );
+ list.append( "Birthday" );
+ list.append( "Anniversary" );
+ list.append( "Nickname" );
+ list.append( "Children" );
+
+ list.append( "Notes" );
+ list.append( "Groups" );
+
+ return list;
+}
+
+/*!
+ \internal
+ Returns a translated list of field names for a contact.
+*/
+QStringList OContact::trfields()
+{
+ QStringList list;
+
+ list.append( QObject::tr( "Name Title") );
+ list.append( QObject::tr( "First Name" ) );
+ list.append( QObject::tr( "Middle Name" ) );
+ list.append( QObject::tr( "Last Name" ) );
+ list.append( QObject::tr( "Suffix" ) );
+ list.append( QObject::tr( "File As" ) );
+
+ list.append( QObject::tr( "Job Title" ) );
+ list.append( QObject::tr( "Department" ) );
+ list.append( QObject::tr( "Company" ) );
+ list.append( QObject::tr( "Business Phone" ) );
+ list.append( QObject::tr( "Business Fax" ) );
+ list.append( QObject::tr( "Business Mobile" ) );
+
+ list.append( QObject::tr( "Default Email" ) );
+ list.append( QObject::tr( "Emails" ) );
+
+ list.append( QObject::tr( "Home Phone" ) );
+ list.append( QObject::tr( "Home Fax" ) );
+ list.append( QObject::tr( "Home Mobile" ) );
+
+ list.append( QObject::tr( "Business Street" ) );
+ list.append( QObject::tr( "Business City" ) );
+ list.append( QObject::tr( "Business State" ) );
+ list.append( QObject::tr( "Business Zip" ) );
+ list.append( QObject::tr( "Business Country" ) );
+ list.append( QObject::tr( "Business Pager" ) );
+ list.append( QObject::tr( "Business WebPage" ) );
+
+ list.append( QObject::tr( "Office" ) );
+ list.append( QObject::tr( "Profession" ) );
+ list.append( QObject::tr( "Assistant" ) );
+ list.append( QObject::tr( "Manager" ) );
+
+ list.append( QObject::tr( "Home Street" ) );
+ list.append( QObject::tr( "Home City" ) );
+ list.append( QObject::tr( "Home State" ) );
+ list.append( QObject::tr( "Home Zip" ) );
+ list.append( QObject::tr( "Home Country" ) );
+ list.append( QObject::tr( "Home Web Page" ) );
+
+ list.append( QObject::tr( "Spouse" ) );
+ list.append( QObject::tr( "Gender" ) );
+ list.append( QObject::tr( "Birthday" ) );
+ list.append( QObject::tr( "Anniversary" ) );
+ list.append( QObject::tr( "Nickname" ) );
+ list.append( QObject::tr( "Children" ) );
+
+ list.append( QObject::tr( "Notes" ) );
+ list.append( QObject::tr( "Groups" ) );
+
+ return list;
+}
+
+/*!
+ Sets the list of email address for contact to those contained in \a str.
+ Email address should be separated by ';'s.
+*/
+void OContact::setEmails( const QString &str )
+{
+ replace( Qtopia::Emails, str );
+ if ( str.isEmpty() )
+ setDefaultEmail( QString::null );
+}
+
+/*!
+ Sets the list of children for the contact to those contained in \a str.
+*/
+void OContact::setChildren( const QString &str )
+{
+ replace( Qtopia::Children, str );
+}
+
+// vcard conversion code
+/*!
+ \internal
+*/
+static inline VObject *safeAddPropValue( VObject *o, const char *prop, const QString &value )
+{
+ VObject *ret = 0;
+ if ( o && !value.isEmpty() )
+ ret = addPropValue( o, prop, value.latin1() );
+ return ret;
+}
+
+/*!
+ \internal
+*/
+static inline VObject *safeAddProp( VObject *o, const char *prop)
+{
+ VObject *ret = 0;
+ if ( o )
+ ret = addProp( o, prop );
+ return ret;
+}
+
+/*!
+ \internal
+*/
+static VObject *createVObject( const OContact &c )
+{
+ VObject *vcard = newVObject( VCCardProp );
+ safeAddPropValue( vcard, VCVersionProp, "2.1" );
+ safeAddPropValue( vcard, VCLastRevisedProp, TimeConversion::toISO8601( QDateTime::currentDateTime() ) );
+ safeAddPropValue( vcard, VCUniqueStringProp, QString::number(c.uid()) );
+
+ // full name
+ safeAddPropValue( vcard, VCFullNameProp, c.fullName() );
+
+ // name properties
+ VObject *name = safeAddProp( vcard, VCNameProp );
+ safeAddPropValue( name, VCFamilyNameProp, c.lastName() );
+ safeAddPropValue( name, VCGivenNameProp, c.firstName() );
+ safeAddPropValue( name, VCAdditionalNamesProp, c.middleName() );
+ safeAddPropValue( name, VCNamePrefixesProp, c.title() );
+ safeAddPropValue( name, VCNameSuffixesProp, c.suffix() );
+
+ // home properties
+ VObject *home_adr= safeAddProp( vcard, VCAdrProp );
+ safeAddProp( home_adr, VCHomeProp );
+ safeAddPropValue( home_adr, VCStreetAddressProp, c.homeStreet() );
+ safeAddPropValue( home_adr, VCCityProp, c.homeCity() );
+ safeAddPropValue( home_adr, VCRegionProp, c.homeState() );
+ safeAddPropValue( home_adr, VCPostalCodeProp, c.homeZip() );
+ safeAddPropValue( home_adr, VCCountryNameProp, c.homeCountry() );
+
+ VObject *home_phone = safeAddPropValue( vcard, VCTelephoneProp, c.homePhone() );
+ safeAddProp( home_phone, VCHomeProp );
+ home_phone = safeAddPropValue( vcard, VCTelephoneProp, c.homeMobile() );
+ safeAddProp( home_phone, VCHomeProp );
+ safeAddProp( home_phone, VCCellularProp );
+ home_phone = safeAddPropValue( vcard, VCTelephoneProp, c.homeFax() );
+ safeAddProp( home_phone, VCHomeProp );
+ safeAddProp( home_phone, VCFaxProp );
+
+ VObject *url = safeAddPropValue( vcard, VCURLProp, c.homeWebpage() );
+ safeAddProp( url, VCHomeProp );
+
+ // work properties
+ VObject *work_adr= safeAddProp( vcard, VCAdrProp );
+ safeAddProp( work_adr, VCWorkProp );
+ safeAddPropValue( work_adr, VCStreetAddressProp, c.businessStreet() );
+ safeAddPropValue( work_adr, VCCityProp, c.businessCity() );
+ safeAddPropValue( work_adr, VCRegionProp, c.businessState() );
+ safeAddPropValue( work_adr, VCPostalCodeProp, c.businessZip() );
+ safeAddPropValue( work_adr, VCCountryNameProp, c.businessCountry() );
+
+ VObject *work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessPhone() );
+ safeAddProp( work_phone, VCWorkProp );
+ work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessMobile() );
+ safeAddProp( work_phone, VCWorkProp );
+ safeAddProp( work_phone, VCCellularProp );
+ work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessFax() );
+ safeAddProp( work_phone, VCWorkProp );
+ safeAddProp( work_phone, VCFaxProp );
+ work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessPager() );
+ safeAddProp( work_phone, VCWorkProp );
+ safeAddProp( work_phone, VCPagerProp );
+
+ url = safeAddPropValue( vcard, VCURLProp, c.businessWebpage() );
+ safeAddProp( url, VCWorkProp );
+
+ VObject *title = safeAddPropValue( vcard, VCTitleProp, c.jobTitle() );
+ safeAddProp( title, VCWorkProp );
+
+
+ QStringList emails = c.emailList();
+ emails.prepend( c.defaultEmail() );
+ for( QStringList::Iterator it = emails.begin(); it != emails.end(); ++it ) {
+ VObject *email = safeAddPropValue( vcard, VCEmailAddressProp, *it );
+ safeAddProp( email, VCInternetProp );
+ }
+
+ safeAddPropValue( vcard, VCNoteProp, c.notes() );
+
+ safeAddPropValue( vcard, VCBirthDateProp, c.birthday() );
+
+ if ( !c.company().isEmpty() || !c.department().isEmpty() || !c.office().isEmpty() ) {
+ VObject *org = safeAddProp( vcard, VCOrgProp );
+ safeAddPropValue( org, VCOrgNameProp, c.company() );
+ safeAddPropValue( org, VCOrgUnitProp, c.department() );
+ safeAddPropValue( org, VCOrgUnit2Prop, c.office() );
+ }
+
+ // some values we have to export as custom fields
+ safeAddPropValue( vcard, "X-Qtopia-Profession", c.profession() );
+ safeAddPropValue( vcard, "X-Qtopia-Manager", c.manager() );
+ safeAddPropValue( vcard, "X-Qtopia-Assistant", c.assistant() );
+
+ safeAddPropValue( vcard, "X-Qtopia-Spouse", c.spouse() );
+ safeAddPropValue( vcard, "X-Qtopia-Gender", c.gender() );
+ safeAddPropValue( vcard, "X-Qtopia-Anniversary", c.anniversary() );
+ safeAddPropValue( vcard, "X-Qtopia-Nickname", c.nickname() );
+ safeAddPropValue( vcard, "X-Qtopia-Children", c.children() );
+
+ return vcard;
+}
+
+
+/*!
+ \internal
+*/
+static OContact parseVObject( VObject *obj )
+{
+ OContact c;
+
+ VObjectIterator it;
+ initPropIterator( &it, obj );
+ while( moreIteration( &it ) ) {
+ VObject *o = nextVObject( &it );
+ QCString name = vObjectName( o );
+ QCString value = vObjectStringZValue( o );
+ if ( name == VCNameProp ) {
+ VObjectIterator nit;
+ initPropIterator( &nit, o );
+ while( moreIteration( &nit ) ) {
+ VObject *o = nextVObject( &nit );
+ QCString name = vObjectTypeInfo( o );
+ QString value = vObjectStringZValue( o );
+ if ( name == VCNamePrefixesProp )
+ c.setTitle( value );
+ else if ( name == VCNameSuffixesProp )
+ c.setSuffix( value );
+ else if ( name == VCFamilyNameProp )
+ c.setLastName( value );
+ else if ( name == VCGivenNameProp )
+ c.setFirstName( value );
+ else if ( name == VCAdditionalNamesProp )
+ c.setMiddleName( value );
+ }
+ }
+ else if ( name == VCAdrProp ) {
+ bool work = TRUE; // default address is work address
+ QString street;
+ QString city;
+ QString region;
+ QString postal;
+ QString country;
+
+ VObjectIterator nit;
+ initPropIterator( &nit, o );
+ while( moreIteration( &nit ) ) {
+ VObject *o = nextVObject( &nit );
+ QCString name = vObjectName( o );
+ QString value = vObjectStringZValue( o );
+ if ( name == VCHomeProp )
+ work = FALSE;
+ else if ( name == VCWorkProp )
+ work = TRUE;
+ else if ( name == VCStreetAddressProp )
+ street = value;
+ else if ( name == VCCityProp )
+ city = value;
+ else if ( name == VCRegionProp )
+ region = value;
+ else if ( name == VCPostalCodeProp )
+ postal = value;
+ else if ( name == VCCountryNameProp )
+ country = value;
+ }
+ if ( work ) {
+ c.setBusinessStreet( street );
+ c.setBusinessCity( city );
+ c.setBusinessCountry( country );
+ c.setBusinessZip( postal );
+ c.setBusinessState( region );
+ } else {
+ c.setHomeStreet( street );
+ c.setHomeCity( city );
+ c.setHomeCountry( country );
+ c.setHomeZip( postal );
+ c.setHomeState( region );
+ }
+ }
+ else if ( name == VCTelephoneProp ) {
+ enum {
+ HOME = 0x01,
+ WORK = 0x02,
+ VOICE = 0x04,
+ CELL = 0x08,
+ FAX = 0x10,
+ PAGER = 0x20,
+ UNKNOWN = 0x80
+ };
+ int type = 0;
+
+ VObjectIterator nit;
+ initPropIterator( &nit, o );
+ while( moreIteration( &nit ) ) {
+ VObject *o = nextVObject( &nit );
+ QCString name = vObjectTypeInfo( o );
+ if ( name == VCHomeProp )
+ type |= HOME;
+ else if ( name == VCWorkProp )
+ type |= WORK;
+ else if ( name == VCVoiceProp )
+ type |= VOICE;
+ else if ( name == VCCellularProp )
+ type |= CELL;
+ else if ( name == VCFaxProp )
+ type |= FAX;
+ else if ( name == VCPagerProp )
+ type |= PAGER;
+ else if ( name == VCPreferredProp )
+ ;
+ else
+ type |= UNKNOWN;
+ }
+ if ( (type & UNKNOWN) != UNKNOWN ) {
+ if ( ( type & (HOME|WORK) ) == 0 ) // default
+ type |= HOME;
+ if ( ( type & (VOICE|CELL|FAX|PAGER) ) == 0 ) // default
+ type |= VOICE;
+
+ if ( (type & (VOICE|HOME) ) == (VOICE|HOME) )
+ c.setHomePhone( value );
+ if ( ( type & (FAX|HOME) ) == (FAX|HOME) )
+ c.setHomeFax( value );
+ if ( ( type & (CELL|HOME) ) == (CELL|HOME) )
+ c.setHomeMobile( value );
+ if ( ( type & (VOICE|WORK) ) == (VOICE|WORK) )
+ c.setBusinessPhone( value );
+ if ( ( type & (FAX|WORK) ) == (FAX|WORK) )
+ c.setBusinessFax( value );
+ if ( ( type & (CELL|WORK) ) == (CELL|WORK) )
+ c.setBusinessMobile( value );
+ if ( ( type & (PAGER|WORK) ) == (PAGER|WORK) )
+ c.setBusinessPager( value );
+ }
+ }
+ else if ( name == VCEmailAddressProp ) {
+ QString email = vObjectStringZValue( o );
+ bool valid = TRUE;
+ VObjectIterator nit;
+ initPropIterator( &nit, o );
+ while( moreIteration( &nit ) ) {
+ VObject *o = nextVObject( &nit );
+ QCString name = vObjectTypeInfo( o );
+ if ( name != VCInternetProp && name != VCHomeProp &&
+ name != VCWorkProp &&
+ name != VCPreferredProp )
+ // ### preffered should map to default email
+ valid = FALSE;
+ }
+ if ( valid ) {
+ c.insertEmail( email );
+ }
+ }
+ else if ( name == VCURLProp ) {
+ VObjectIterator nit;
+ initPropIterator( &nit, o );
+ while( moreIteration( &nit ) ) {
+ VObject *o = nextVObject( &nit );
+ QCString name = vObjectTypeInfo( o );
+ if ( name == VCHomeProp )
+ c.setHomeWebpage( value );
+ else if ( name == VCWorkProp )
+ c.setBusinessWebpage( value );
+ }
+ }
+ else if ( name == VCOrgProp ) {
+ VObjectIterator nit;
+ initPropIterator( &nit, o );
+ while( moreIteration( &nit ) ) {
+ VObject *o = nextVObject( &nit );
+ QCString name = vObjectName( o );
+ QString value = vObjectStringZValue( o );
+ if ( name == VCOrgNameProp )
+ c.setCompany( value );
+ else if ( name == VCOrgUnitProp )
+ c.setDepartment( value );
+ else if ( name == VCOrgUnit2Prop )
+ c.setOffice( value );
+ }
+ }
+ else if ( name == VCTitleProp ) {
+ c.setJobTitle( value );
+ }
+ else if ( name == "X-Qtopia-Profession" ) {
+ c.setProfession( value );
+ }
+ else if ( name == "X-Qtopia-Manager" ) {
+ c.setManager( value );
+ }
+ else if ( name == "X-Qtopia-Assistant" ) {
+ c.setAssistant( value );
+ }
+ else if ( name == "X-Qtopia-Spouse" ) {
+ c.setSpouse( value );
+ }
+ else if ( name == "X-Qtopia-Gender" ) {
+ c.setGender( value );
+ }
+ else if ( name == "X-Qtopia-Anniversary" ) {
+ c.setAnniversary( value );
+ }
+ else if ( name == "X-Qtopia-Nickname" ) {
+ c.setNickname( value );
+ }
+ else if ( name == "X-Qtopia-Children" ) {
+ c.setChildren( value );
+ }
+
+
+#if 0
+ else {
+ printf("Name: %s, value=%s\n", name.data(), vObjectStringZValue( o ) );
+ VObjectIterator nit;
+ initPropIterator( &nit, o );
+ while( moreIteration( &nit ) ) {
+ VObject *o = nextVObject( &nit );
+ QCString name = vObjectName( o );
+ QString value = vObjectStringZValue( o );
+ printf(" subprop: %s = %s\n", name.data(), value.latin1() );
+ }
+ }
+#endif
+ }
+ c.setFileAs();
+ return c;
+}
+
+/*!
+ Writes the list of \a contacts as a set of VCards to the file \a filename.
+*/
+void OContact::writeVCard( const QString &filename, const QValueList<OContact> &contacts)
+{
+ QFileDirect f( filename.utf8().data() );
+ if ( !f.open( IO_WriteOnly ) ) {
+ qWarning("Unable to open vcard write");
+ return;
+ }
+
+ QValueList<OContact>::ConstIterator it;
+ for( it = contacts.begin(); it != contacts.end(); ++it ) {
+ VObject *obj = createVObject( *it );
+ writeVObject(f.directHandle() , obj );
+ cleanVObject( obj );
+ }
+ cleanStrTbl();
+}
+
+/*!
+ writes \a contact as a VCard to the file \a filename.
+*/
+void OContact::writeVCard( const QString &filename, const OContact &contact)
+{
+ QFileDirect f( filename.utf8().data() );
+ if ( !f.open( IO_WriteOnly ) ) {
+ qWarning("Unable to open vcard write");
+ return;
+ }
+
+ VObject *obj = createVObject( contact );
+ writeVObject( f.directHandle() , obj );
+ cleanVObject( obj );
+
+ cleanStrTbl();
+}
+
+/*!
+ Returns the set of contacts read as VCards from the file \a filename.
+*/
+QValueList<OContact> OContact::readVCard( const QString &filename )
+{
+ qDebug("trying to open %s, exists=%d", filename.utf8().data(), QFileInfo( filename.utf8().data() ).size() );
+ VObject *obj = Parse_MIME_FromFileName( (char *)filename.utf8().data() );
+
+ qDebug("vobject = %p", obj );
+
+ QValueList<OContact> contacts;
+
+ while ( obj ) {
+ contacts.append( parseVObject( obj ) );
+
+ VObject *t = obj;
+ obj = nextVObjectInList(obj);
+ cleanVObject( t );
+ }
+
+ return contacts;
+}
+
+/*!
+ Returns TRUE if the contact matches the regular expression \a regexp.
+ Otherwise returns FALSE.
+*/
+bool OContact::match( const QString &regexp ) const
+{
+ return match(QRegExp(regexp));
+}
+
+/*!
+ \overload
+ Returns TRUE if the contact matches the regular expression \a regexp.
+ Otherwise returns FALSE.
+*/
+bool OContact::match( const QRegExp &r ) const
+{
+ bool match;
+ match = false;
+ QMap<int, QString>::ConstIterator it;
+ for ( it = mMap.begin(); it != mMap.end(); ++it ) {
+ if ( (*it).find( r ) > -1 ) {
+ match = true;
+ break;
+ }
+ }
+ return match;
+}
+
+
+// Noch nicht definiert ! :SX
+QString OContact::toShortText() const
+{
+ return ( QString::fromLatin1( "Not defined!") );
+}
+QString OContact::type() const
+{
+ return QString::fromLatin1( "OContact" );
+}
+
+// Noch nicht definiert ! :SX
+QMap<QString,QString> OContact::toExtraMap() const
+{
+ QMap <QString,QString> useless;
+ return useless;
+}
+
+// Noch nicht definiert ! :SX
+class QString OContact::recordField(int) const
+{
+ return QString::fromLatin1( "Noch nicht implementiert !" );
+}
diff --git a/libopie/pim/ocontact.h b/libopie/pim/ocontact.h
new file mode 100644
index 0000000..e0555c8
--- a/dev/null
+++ b/libopie/pim/ocontact.h
@@ -0,0 +1,311 @@
+/**********************************************************************
+** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
+**
+** This file is part of the Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#ifndef __OCONTACT_H__
+#define __OCONTACT_H__
+
+#include <opie/opimrecord.h>
+#include <qpe/recordfields.h>
+
+#include <qstringlist.h>
+
+#if defined(QPC_TEMPLATEDLL)
+// MOC_SKIP_BEGIN
+QPC_TEMPLATEEXTERN template class QPC_EXPORT QMap<int, QString>;
+// MOC_SKIP_END
+#endif
+
+class ContactPrivate; // Wozu ist das gut und wo ist das decrariert ? (se)
+class QPC_EXPORT OContact : public OPimRecord
+{
+ friend class DataSet;
+public:
+ OContact();
+ OContact( const QMap<int, QString> &fromMap );
+ virtual ~OContact();
+
+ static void writeVCard( const QString &filename, const QValueList<OContact> &contacts);
+ static void writeVCard( const QString &filename, const OContact &c );
+ static QValueList<OContact> readVCard( const QString &filename );
+
+ enum journal_action { ACTION_ADD, ACTION_REMOVE, ACTION_REPLACE };
+
+ void setTitle( const QString &v ) { replace( Qtopia::Title, v ); }
+ void setFirstName( const QString &v ) { replace( Qtopia::FirstName, v ); }
+ void setMiddleName( const QString &v ) { replace( Qtopia::MiddleName, v ); }
+ void setLastName( const QString &v ) { replace( Qtopia::LastName, v ); }
+ void setSuffix( const QString &v ) { replace( Qtopia::Suffix, v ); }
+ void setFileAs( const QString &v ) { replace( Qtopia::FileAs, v ); }
+ void setFileAs();
+
+ // default email address
+ void setDefaultEmail( const QString &v );
+ // inserts email to list and ensure's doesn't already exist
+ void insertEmail( const QString &v );
+ void removeEmail( const QString &v );
+ void clearEmails();
+ void insertEmails( const QStringList &v );
+
+ // home
+ void setHomeStreet( const QString &v ) { replace( Qtopia::HomeStreet, v ); }
+ void setHomeCity( const QString &v ) { replace( Qtopia::HomeCity, v ); }
+ void setHomeState( const QString &v ) { replace( Qtopia::HomeState, v ); }
+ void setHomeZip( const QString &v ) { replace( Qtopia::HomeZip, v ); }
+ void setHomeCountry( const QString &v ) { replace( Qtopia::HomeCountry, v ); }
+ void setHomePhone( const QString &v ) { replace( Qtopia::HomePhone, v ); }
+ void setHomeFax( const QString &v ) { replace( Qtopia::HomeFax, v ); }
+ void setHomeMobile( const QString &v ) { replace( Qtopia::HomeMobile, v ); }
+ void setHomeWebpage( const QString &v ) { replace( Qtopia::HomeWebPage, v ); }
+
+ // business
+ void setCompany( const QString &v ) { replace( Qtopia::Company, v ); }
+ void setBusinessStreet( const QString &v ) { replace( Qtopia::BusinessStreet, v ); }
+ void setBusinessCity( const QString &v ) { replace( Qtopia::BusinessCity, v ); }
+ void setBusinessState( const QString &v ) { replace( Qtopia::BusinessState, v ); }
+ void setBusinessZip( const QString &v ) { replace( Qtopia::BusinessZip, v ); }
+ void setBusinessCountry( const QString &v ) { replace( Qtopia::BusinessCountry, v ); }
+ void setBusinessWebpage( const QString &v ) { replace( Qtopia::BusinessWebPage, v ); }
+ void setJobTitle( const QString &v ) { replace( Qtopia::JobTitle, v ); }
+ void setDepartment( const QString &v ) { replace( Qtopia::Department, v ); }
+ void setOffice( const QString &v ) { replace( Qtopia::Office, v ); }
+ void setBusinessPhone( const QString &v ) { replace( Qtopia::BusinessPhone, v ); }
+ void setBusinessFax( const QString &v ) { replace( Qtopia::BusinessFax, v ); }
+ void setBusinessMobile( const QString &v ) { replace( Qtopia::BusinessMobile, v ); }
+ void setBusinessPager( const QString &v ) { replace( Qtopia::BusinessPager, v ); }
+ void setProfession( const QString &v ) { replace( Qtopia::Profession, v ); }
+ void setAssistant( const QString &v ) { replace( Qtopia::Assistant, v ); }
+ void setManager( const QString &v ) { replace( Qtopia::Manager, v ); }
+
+ // personal
+ void setSpouse( const QString &v ) { replace( Qtopia::Spouse, v ); }
+ void setGender( const QString &v ) { replace( Qtopia::Gender, v ); }
+ void setBirthday( const QString &v ) { replace( Qtopia::Birthday, v ); }
+ void setAnniversary( const QString &v ) { replace( Qtopia::Anniversary, v ); }
+ void setNickname( const QString &v ) { replace( Qtopia::Nickname, v ); }
+ void setChildren( const QString &v );
+
+ // other
+ void setNotes( const QString &v ) { replace( Qtopia::Notes, v); }
+
+ bool match( const QString &regexp ) const;
+
+// DON'T ATTEMPT TO USE THIS
+#ifdef QTOPIA_INTERNAL_CONTACT_MRE
+ bool match( const QRegExp &regexp ) const;
+#endif
+
+// // custom
+// void setCustomField( const QString &key, const QString &v )
+// { replace(Custom- + key, v ); }
+
+ // name
+ QString fullName() const;
+ QString title() const { return find( Qtopia::Title ); }
+ QString firstName() const { return find( Qtopia::FirstName ); }
+ QString middleName() const { return find( Qtopia::MiddleName ); }
+ QString lastName() const { return find( Qtopia::LastName ); }
+ QString suffix() const { return find( Qtopia::Suffix ); }
+ QString fileAs() const { return find( Qtopia::FileAs ); }
+
+ // email
+ QString defaultEmail() const { return find( Qtopia::DefaultEmail ); }
+ QStringList emailList() const;
+
+ // home
+ QString homeStreet() const { return find( Qtopia::HomeStreet ); }
+ QString homeCity() const { return find( Qtopia::HomeCity ); }
+ QString homeState() const { return find( Qtopia::HomeState ); }
+ QString homeZip() const { return find( Qtopia::HomeZip ); }
+ QString homeCountry() const { return find( Qtopia::HomeCountry ); }
+ QString homePhone() const { return find( Qtopia::HomePhone ); }
+ QString homeFax() const { return find( Qtopia::HomeFax ); }
+ QString homeMobile() const { return find( Qtopia::HomeMobile ); }
+ QString homeWebpage() const { return find( Qtopia::HomeWebPage ); }
+ /** Multi line string containing all non-empty address info in the form
+ * Street
+ * City, State Zip
+ * Country
+ */
+ QString displayHomeAddress() const;
+
+ // business
+ QString company() const { return find( Qtopia::Company ); }
+ QString businessStreet() const { return find( Qtopia::BusinessStreet ); }
+ QString businessCity() const { return find( Qtopia::BusinessCity ); }
+ QString businessState() const { return find( Qtopia::BusinessState ); }
+ QString businessZip() const { return find( Qtopia::BusinessZip ); }
+ QString businessCountry() const { return find( Qtopia::BusinessCountry ); }
+ QString businessWebpage() const { return find( Qtopia::BusinessWebPage ); }
+ QString jobTitle() const { return find( Qtopia::JobTitle ); }
+ QString department() const { return find( Qtopia::Department ); }
+ QString office() const { return find( Qtopia::Office ); }
+ QString businessPhone() const { return find( Qtopia::BusinessPhone ); }
+ QString businessFax() const { return find( Qtopia::BusinessFax ); }
+ QString businessMobile() const { return find( Qtopia::BusinessMobile ); }
+ QString businessPager() const { return find( Qtopia::BusinessPager ); }
+ QString profession() const { return find( Qtopia::Profession ); }
+ QString assistant() const { return find( Qtopia::Assistant ); }
+ QString manager() const { return find( Qtopia::Manager ); }
+ /** Multi line string containing all non-empty address info in the form
+ * Street
+ * City, State Zip
+ * Country
+ */
+ QString displayBusinessAddress() const;
+
+ //personal
+ QString spouse() const { return find( Qtopia::Spouse ); }
+ QString gender() const { return find( Qtopia::Gender ); }
+ QString birthday() const { return find( Qtopia::Birthday ); }
+ QString anniversary() const { return find( Qtopia::Anniversary ); }
+ QString nickname() const { return find( Qtopia::Nickname ); }
+ QString children() const { return find( Qtopia::Children ); }
+ QStringList childrenList() const;
+
+ // other
+ QString notes() const { return find( Qtopia::Notes ); }
+ QString groups() const { return find( Qtopia::Groups ); }
+ QStringList groupList() const;
+
+// // custom
+// const QString &customField( const QString &key )
+// { return find( Custom- + key ); }
+
+ static QStringList fields();
+ static QStringList trfields();
+
+ QString toRichText() const;
+ QMap<int, QString> toMap() const;
+ QString field( int key ) const { return find( key ); }
+
+
+ // journaling...
+ void saveJournal( journal_action action, const QString &key = QString::null );
+ void save( QString &buf ) const;
+
+ void setUid( int i )
+{ Record::setUid(i); replace( Qtopia::AddressUid , QString::number(i)); }
+
+ QString toShortText()const;
+ QString OContact::type()const;
+ QMap<QString,QString> OContact::toExtraMap() const;
+ class QString OContact::recordField(int) const;
+
+private:
+ friend class AbEditor;
+ friend class AbTable;
+ friend class AddressBookAccessPrivate;
+ friend class XMLIO;
+
+ QString emailSeparator() const { return " "; }
+ // the emails should be seperated by a comma
+ void setEmails( const QString &v );
+ QString emails() const { return find( Qtopia::Emails ); }
+
+ void insert( int key, const QString &value );
+ void replace( int key, const QString &value );
+ QString find( int key ) const;
+
+ QString displayAddress( const QString &street,
+ const QString &city,
+ const QString &state,
+ const QString &zip,
+ const QString &country ) const;
+
+ Qtopia::UidGen &uidGen() { return sUidGen; }
+ static Qtopia::UidGen sUidGen;
+ QMap<int, QString> mMap;
+ ContactPrivate *d;
+};
+
+// these methods are inlined to keep binary compatability with Qtopia 1.5
+inline void OContact::insertEmail( const QString &v )
+{
+ //qDebug("insertEmail %s", v.latin1());
+ QString e = v.simplifyWhiteSpace();
+ QString def = defaultEmail();
+
+ // if no default, set it as the default email and don't insert
+ if ( def.isEmpty() ) {
+ setDefaultEmail( e ); // will insert into the list for us
+ return;
+ }
+
+ // otherwise, insert assuming doesn't already exist
+ QString emailsStr = find( Qtopia::Emails );
+ if ( emailsStr.contains( e ))
+ return;
+ if ( !emailsStr.isEmpty() )
+ emailsStr += emailSeparator();
+ emailsStr += e;
+ replace( Qtopia::Emails, emailsStr );
+}
+
+inline void OContact::removeEmail( const QString &v )
+{
+ QString e = v.simplifyWhiteSpace();
+ QString def = defaultEmail();
+ QString emailsStr = find( Qtopia::Emails );
+ QStringList emails = emailList();
+
+ // otherwise, must first contain it
+ if ( !emailsStr.contains( e ) )
+ return;
+
+ // remove it
+ //qDebug(" removing email from list %s", e.latin1());
+ emails.remove( e );
+ // reset the string
+ emailsStr = emails.join(emailSeparator()); // Sharp's brain dead separator
+ replace( Qtopia::Emails, emailsStr );
+
+ // if default, then replace the default email with the first one
+ if ( def == e ) {
+ //qDebug("removeEmail is default; setting new default");
+ if ( !emails.count() )
+ clearEmails();
+ else // setDefaultEmail will remove e from the list
+ setDefaultEmail( emails.first() );
+ }
+}
+inline void OContact::clearEmails()
+{
+ mMap.remove( Qtopia::DefaultEmail );
+ mMap.remove( Qtopia::Emails );
+}
+inline void OContact::setDefaultEmail( const QString &v )
+{
+ QString e = v.simplifyWhiteSpace();
+
+ //qDebug("OContact::setDefaultEmail %s", e.latin1());
+ replace( Qtopia::DefaultEmail, e );
+
+ if ( !e.isEmpty() )
+ insertEmail( e );
+
+}
+
+inline void OContact::insertEmails( const QStringList &v )
+{
+ for ( QStringList::ConstIterator it = v.begin(); it != v.end(); ++it )
+ insertEmail( *it );
+}
+
+#endif
diff --git a/libopie/pim/ocontactaccess.cpp b/libopie/pim/ocontactaccess.cpp
new file mode 100644
index 0000000..2d808f7
--- a/dev/null
+++ b/libopie/pim/ocontactaccess.cpp
@@ -0,0 +1,174 @@
+/*
+ * Class to manage the Contacts.
+ *
+ * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
+ *
+ * =====================================================================
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ * =====================================================================
+ * Info: This class could just work with a change in the header-file
+ * of the Contact class ! Therefore our libopie only compiles
+ * with our version of libqpe
+ * =====================================================================
+ * ToDo: XML-Backend: Automatic reload if something was changed...
+ *
+ *
+ * =====================================================================
+ * Version: $Id$
+ * =====================================================================
+ * History:
+ * $Log$
+ * Revision 1.1 2002/09/27 17:11:44 eilers
+ * Added API for accessing the Contact-Database ! It is compiling, but
+ * please do not expect that anything is working !
+ * I will debug that stuff in the next time ..
+ * Please read README_COMPILE for compiling !
+ *
+ *
+ */
+
+#include "ocontactaccess.h"
+
+#include <qasciidict.h>
+#include <qdatetime.h>
+#include <qfile.h>
+#include <qregexp.h>
+#include <qlist.h>
+#include <qcopchannel_qws.h>
+
+//#include <qpe/qcopenvelope_qws.h>
+#include <qpe/global.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "ocontactaccessbackend_xml.h"
+
+
+OContactAccess::OContactAccess ( const QString appname, const QString filename,
+ OContactAccessBackend* end, bool autosync ):
+ OPimAccessTemplate<OContact>( end ),
+ m_changed ( false )
+{
+ /* take care of the backend. If there is no one defined, we
+ * will use the XML-Backend as default (until we have a cute SQL-Backend..).
+ */
+ if( end == 0 ) {
+ end = new OContactAccessBackend_XML( appname, filename );
+ }
+ m_backEnd = end;
+
+ /* Connect signal of external db change to function */
+ QCopChannel *dbchannel = new QCopChannel( "QPE/PIM", this );
+ connect( dbchannel, SIGNAL(received(const QCString &, const QByteArray &)),
+ this, SLOT(copMessage( const QCString &, const QByteArray &)) );
+ if ( autosync ){
+ QCopChannel *syncchannel = new QCopChannel( "QPE/Sync", this );
+ connect( syncchannel, SIGNAL(received(const QCString &, const QByteArray &)),
+ this, SLOT(copMessage( const QCString &, const QByteArray &)) );
+ }
+
+
+}
+OContactAccess::~OContactAccess ()
+{
+ /* The user may forget to save the changed database, therefore try to
+ * do it for him..
+ */
+ if ( m_changed )
+ save();
+ delete m_backEnd;
+}
+
+bool OContactAccess::load()
+{
+ return ( m_backEnd->load() );
+}
+
+bool OContactAccess::save ()
+{
+ /* If the database was changed externally, we could not save the
+ * Data. This will remove added items which is unacceptable !
+ * Therefore: Reload database and merge the data...
+ */
+ if ( m_backEnd->wasChangedExternally() )
+ reload();
+
+ if ( m_changed ){
+ bool status = m_backEnd->save();
+ if ( !status ) return false;
+
+ m_changed = false;
+ /* Now tell everyone that new data is available.
+ */
+ QCopEnvelope e( "QPE/PIM", "addressbookUpdated()" );
+
+ }
+
+ return true;
+}
+
+const uint OContactAccess::querySettings()
+{
+ return ( m_backEnd->querySettings() );
+}
+
+bool OContactAccess::hasQuerySettings ( int querySettings ) const
+{
+ return ( m_backEnd->hasQuerySettings ( querySettings ) );
+}
+
+bool OContactAccess::add ( const OContact& newcontact )
+{
+ m_changed = true;
+ return ( m_backEnd->add ( newcontact ) );
+}
+
+bool OContactAccess::replace ( const OContact& contact )
+{
+ m_changed = true;
+ return ( m_backEnd->replace ( contact ) );
+}
+
+bool OContactAccess::remove ( const OContact& t )
+{
+ m_changed = true;
+ return ( m_backEnd->remove ( t.uid() ) );
+}
+
+bool OContactAccess::remove ( int uid )
+{
+ m_changed = true;
+ return ( m_backEnd->remove ( uid ) );
+}
+
+bool OContactAccess::wasChangedExternally()const
+{
+ return ( m_backEnd->wasChangedExternally() );
+}
+
+
+bool OContactAccess::reload()
+{
+ return ( m_backEnd->reload() );
+}
+
+void OContactAccess::copMessage( const QCString &msg, const QByteArray & )
+{
+ if ( msg == "addressbookUpdated()" ){
+ qWarning ("OContactAccess: Received addressbokUpdated()");
+ emit signalChanged ( this );
+ } else if ( msg == "flush()" ) {
+ qWarning ("OContactAccess: Received flush()");
+ save ();
+ } else if ( msg == "reload()" ) {
+ qWarning ("OContactAccess: Received reload()");
+ reload ();
+ emit signalChanged ( this );
+ }
+}
diff --git a/libopie/pim/ocontactaccess.h b/libopie/pim/ocontactaccess.h
new file mode 100644
index 0000000..54f7f07
--- a/dev/null
+++ b/libopie/pim/ocontactaccess.h
@@ -0,0 +1,197 @@
+/*
+ * Class to manage the Contacts.
+ *
+ * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
+ * Copyright (c) 2002 by Holger Freyther (zecke@handhelds.org)
+ *
+ * =====================================================================
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation;
+ * either version 2 of the License, or (at your option) any later
+ * version.
+ * =====================================================================
+ * ToDo: Define enum for query settings
+ * =====================================================================
+ * Version: $Id$
+ * =====================================================================
+ * History:
+ * $Log$
+ * Revision 1.1 2002/09/27 17:11:44 eilers
+ * Added API for accessing the Contact-Database ! It is compiling, but
+ * please do not expect that anything is working !
+ * I will debug that stuff in the next time ..
+ * Please read README_COMPILE for compiling !
+ *
+ * =====================================================================
+ */
+#ifndef _OCONTACTACCESS_H
+#define _OCONTACTACCESS_H
+
+#include <qobject.h>
+
+#include <qpe/qcopenvelope_qws.h>
+
+#include <qvaluelist.h>
+#include <qfileinfo.h>
+
+#include "ocontact.h"
+#include "ocontactaccessbackend.h"
+#include "opimaccesstemplate.h"
+
+/** Class to access the contacts database.
+ * This is just a frontend for the real database handling which is
+ * done by the backend.
+ */
+class OContactAccess: public QObject, public OPimAccessTemplate<OContact>
+{
+ Q_OBJECT
+
+
+ /* class Iterator{
+ friend OContactAccess;
+ public:
+ Iterator();
+ Iterator ( const Iterator& copy );
+
+ bool operator== ( const Iterator& it );
+ bool operator!= ( const Iterator& it );
+ Iterator& operator= ( const Iterator& it );
+ Iterator& operator++ (); // prefix
+ Iterator operator++ ( int ); // postfix
+ Iterator& operator-- (); // prefix
+ Iterator operator-- ( int ); // postfix
+ Contact operator*() const;
+ Contact operator->() const;
+
+ Iterator begin();
+ Iterator end();
+
+ uint count() const;
+
+ private:
+ QValueList<int> m_uids;
+ int m_cur_position;
+ bool m_end_reached;
+ OContactAccess *m_db;
+
+ };
+
+ */
+
+ public:
+ /** Create Database with contacts (addressbook).
+ * @param appname Name of application which wants access to the database
+ * (i.e. "todolist")
+ * @param filename The name of the database file. If not set, the default one
+ * is used.
+ * @param backend Pointer to an alternative Backend. If not set, we will use
+ * the default backend.
+ * @param handlesync If <b>true</b> the database stores the current state
+ * automatically if it receives the signals <i>flush()</i> and <i>reload()</i>
+ * which are used before and after synchronisation. If the application wants
+ * to react itself, it should be disabled by setting it to <b>false</b>
+ * @see OContactBackend
+ */
+ OContactAccess (const QString appname, const QString filename = 0l,
+ OContactAccessBackend* backend = 0l, bool handlesync = true);
+ ~OContactAccess ();
+
+ /** Constants for query.
+ * Use this constants to set the query parameters.
+ * Note: <i>query_IgnoreCase</i> just make sense with one of the other attributes !
+ * @see queryByExample()
+ * - why not enum - zecke?
+ * -> Had some implementation problems .. Will use enum soon ! .. (se)
+ */
+ static const int query_WildCards = 0x0001;
+ static const int query_IgnoreCase = 0x0002;
+ static const int query_RegExp = 0x0004;
+ static const int query_ExactMatch = 0x0008;
+
+ /** Return all possible settings.
+ * @return All settings provided by the current backend
+ * (i.e.: query_WildCards & query_IgnoreCase)
+ */
+ const uint querySettings();
+
+ /** Check whether settings are correct.
+ * @return <i>true</i> if the given settings are correct and possible.
+ */
+ bool hasQuerySettings ( int querySettings ) const;
+
+ /** Add Contact to database.
+ * @param newcontact The contact to add.
+ * @return <i>true</i> if added successfully.
+ */
+ bool add (const OContact& newcontact);
+
+ /** Replace contact.
+ * Replaces given contact with contact with the user id <i>uid</i>.
+ * @param uid The user ID
+ * @param contact The new contact
+ * @return <i>true</i> if successful.
+ */
+ bool replace ( const OContact& contact );
+
+ /** Remove contact.
+ * Removes contact with the user id <i>uid</i>.
+ * @param The contact to remove
+ * @return <i>true</i> if successful.
+ */
+ bool remove ( const OContact& t );
+
+ /** Remove contact.
+ * Removes contact with the user id <i>uid</i>.
+ * @param The user id of the contact to remove
+ * @return <i>true</i> if successful.
+ */
+ bool remove ( int uid );
+
+ /** Load Database *
+ */
+ bool load();
+
+ /**
+ * if the resource was changed externally.
+ * You should use the signal instead of polling possible changes !
+ */
+ bool wasChangedExternally()const;
+
+ /** Reload database.
+ * You should execute this function if the external database
+ * was changed.
+ * This function will load the external database and afterwards
+ * rejoin the local changes. Therefore the local database will be set consistent.
+ */
+ bool reload();
+
+ /** Save contacts database.
+ * Save is more a "commit". After calling this function, all changes are public available.
+ * @return true if successful
+ */
+ bool save();
+
+ signals:
+ /* Signal is emitted if the database was changed. Therefore
+ * we may need to reload to stay consistent.
+ * @param which Pointer to the database who created this event. This pointer
+ * is useful if an application has to handle multiple databases at the same time.
+ * @see reload()
+ */
+ void signalChanged ( const OContactAccess *which );
+
+
+ private:
+ // class OContactAccessPrivate;
+ // OContactAccessPrivate* d;
+ OContactAccessBackend *m_backEnd;
+ bool m_loading:1;
+ bool m_changed;
+
+ private slots:
+ void copMessage( const QCString &msg, const QByteArray &data );
+
+
+};
+#endif
diff --git a/libopie/pim/ocontactaccessbackend.h b/libopie/pim/ocontactaccessbackend.h
new file mode 100644
index 0000000..9469bbc
--- a/dev/null
+++ b/libopie/pim/ocontactaccessbackend.h
@@ -0,0 +1,70 @@
+/**
+ * The class responsible for managing a backend.
+ * The implementation of this abstract class contains
+ * the complete database handling.
+ *
+ * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
+ * Copyright (c) 2002 by Holger Freyther (zecke@handhelds.org)
+ *
+ * =====================================================================
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation;
+ * either version 2 of the License, or (at your option) any later
+ * version.
+ * =====================================================================
+ * ToDo: Define enum for query settings
+ * =====================================================================
+ * Version: $Id$
+ * =====================================================================
+ * History:
+ * $Log$
+ * Revision 1.1 2002/09/27 17:11:44 eilers
+ * Added API for accessing the Contact-Database ! It is compiling, but
+ * please do not expect that anything is working !
+ * I will debug that stuff in the next time ..
+ * Please read README_COMPILE for compiling !
+ *
+ * =====================================================================
+ *
+ */
+
+#ifndef _OCONTACTACCESSBACKEND_H_
+#define _OCONTACTACCESSBACKEND_H_
+
+#include "opimaccessbackend.h"
+
+class OContactAccessBackend: public OPimAccessBackend<OContact> {
+ public:
+ OContactAccessBackend() {}
+ virtual ~OContactAccessBackend() {}
+
+
+ /** Return if database was changed externally.
+ * This may just make sense on file based databases like a XML-File.
+ * It is used to prevent to overwrite the current database content
+ * if the file was already changed by something else !
+ * If this happens, we have to reload before save our data.
+ * If we use real databases, this should be handled by the database
+ * management system themselve, therefore this function should always return false in
+ * this case. It is not our problem to handle this conflict ...
+ * @return <i>true</i> if the database was changed and if save without reload will
+ * be dangerous. <i>false</i> if the database was not changed or it is save to write
+ * in this situation.
+ */
+ virtual bool wasChangedExternally() = 0;
+
+ /** Return all possible settings.
+ * @return All settings provided by the current backend
+ * (i.e.: query_WildCards & query_IgnoreCase)
+ */
+ virtual const uint querySettings() = 0;
+
+ /** Check whether settings are correct.
+ * @return <i>true</i> if the given settings are correct and possible.
+ */
+ virtual bool hasQuerySettings (uint querySettings) const = 0;
+
+
+};
+#endif
diff --git a/libopie/pim/ocontactaccessbackend_xml.h b/libopie/pim/ocontactaccessbackend_xml.h
new file mode 100644
index 0000000..2cdb45b
--- a/dev/null
+++ b/libopie/pim/ocontactaccessbackend_xml.h
@@ -0,0 +1,550 @@
+/*
+ * XML Backend for the OPIE-Contact Database.
+ *
+ * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
+ *
+ * =====================================================================
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ * =====================================================================
+ * ToDo: XML-Backend: Automatic reload if something was changed...
+ *
+ *
+ * =====================================================================
+ * Version: $Id$
+ * =====================================================================
+ * History:
+ * $Log$
+ * Revision 1.1 2002/09/27 17:11:44 eilers
+ * Added API for accessing the Contact-Database ! It is compiling, but
+ * please do not expect that anything is working !
+ * I will debug that stuff in the next time ..
+ * Please read README_COMPILE for compiling !
+ *
+ *
+ */
+
+#ifndef _OContactAccessBackend_XML_
+#define _OContactAccessBackend_XML_
+
+#include <qasciidict.h>
+#include <qdatetime.h>
+#include <qfile.h>
+#include <qregexp.h>
+#include <qarray.h>
+
+#include <opie/xmltree.h>
+#include "ocontactaccessbackend.h"
+
+using namespace Opie;
+
+/* the default xml implementation */
+class OContactAccessBackend_XML : public OContactAccessBackend {
+ public:
+ OContactAccessBackend_XML ( QString appname, QString filename = 0l )
+ {
+ m_appName = appname;
+
+ /* Set journalfile name ... */
+ m_journalName = getenv("HOME");
+ m_journalName +="/.abjournal" + appname;
+
+ /* Expecting to access the default filename if nothing else is set */
+ if ( filename.isEmpty() ){
+ m_fileName = Global::applicationFileName( "addressbook","addressbook.xml" );
+ } else
+ m_fileName = filename;
+
+ /* Load Database now */
+ load ();
+ }
+
+ bool save() {
+ QString strNewFile = m_fileName + ".new";
+ QFile f( strNewFile );
+ if ( !f.open( IO_WriteOnly|IO_Raw ) )
+ return false;
+
+ int total_written;
+ QString out;
+ out = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE Addressbook ><AddressBook>\n"
+ " <Groups>\n"
+ " </Groups>\n"
+ " <Contacts>\n";
+ //QValueList<Contact>::iterator it;
+ QValueListConstIterator<OContact> it;
+ for ( it = m_contactList.begin(); it != m_contactList.end(); ++it ) {
+ out += "<Contact ";
+ (*it).save( out );
+ out += "/>\n";
+ QCString cstr = out.utf8();
+ total_written = f.writeBlock( cstr.data(), cstr.length() );
+ if ( total_written != int(cstr.length()) ) {
+ f.close();
+ QFile::remove( strNewFile );
+ return false;
+ }
+ out = "";
+ }
+ out += " </Contacts>\n</AddressBook>\n";
+
+ QCString cstr = out.utf8();
+ total_written = f.writeBlock( cstr.data(), cstr.length() );
+ if ( total_written != int( cstr.length() ) ) {
+ f.close();
+ QFile::remove( strNewFile );
+ return false;
+ }
+ f.close();
+
+ // move the file over, I'm just going to use the system call
+ // because, I don't feel like using QDir.
+ if ( ::rename( strNewFile.latin1(), m_fileName.latin1() ) < 0 ) {
+ qWarning( "problem renaming file %s to %s, errno: %d",
+ strNewFile.latin1(), m_journalName.latin1(), errno );
+ // remove the tmp file...
+ QFile::remove( strNewFile );
+ }
+
+ /* The journalfile should be removed now... */
+ removeJournal();
+ return true;
+ }
+
+ bool load () {
+ m_contactList.clear();
+
+ /* Load XML-File and journal if it exists */
+ if ( !load ( m_fileName, false ) )
+ return false;
+ /* The returncode of the journalfile is ignored due to the
+ * fact that it does not exist when this class is instantiated !
+ * But there may such a file exist, if the application crashed.
+ * Therefore we try to load it to get the changes before the #
+ * crash happened...
+ */
+ load (m_journalName, true);
+
+ return true;
+ }
+
+ void clear () {
+ m_contactList.clear();
+
+ }
+
+ bool wasChangedExternally()
+ {
+ QFileInfo fi( m_fileName );
+
+ QDateTime lastmod = fi.lastModified ();
+
+ return (lastmod != m_readtime);
+ }
+
+ QArray<int> allRecords() const {
+ QArray<int> uid_list( m_contactList.count() );
+
+ uint counter = 0;
+ QValueListConstIterator<OContact> it;
+ for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
+ uid_list[counter++] = (*it).uid();
+ }
+
+ return ( uid_list );
+ }
+
+ OContact find ( int uid ) const
+ {
+ bool found = false;
+ OContact foundContact; //Create empty contact
+
+ QValueListConstIterator<OContact> it;
+ for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
+ if ((*it).uid() == uid){
+ found = true;
+ break;
+ }
+ }
+ if ( found ){
+ foundContact = *it;
+ }
+
+ return ( foundContact );
+ }
+
+ QArray<int> queryByExample ( const OContact &query, int settings ){
+
+ QArray<int> m_currentQuery( m_contactList.count() );
+ QValueListConstIterator<OContact> it;
+ uint arraycounter = 0;
+
+ for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
+ /* Search all fields and compare them with query object. Store them into list
+ * if all fields matches.
+ */
+ bool allcorrect = true;
+ for ( int i = 0; i < Qtopia::rid; i++ ) {
+ /* Just compare fields which are not empty in the query object */
+ if ( !query.field(i).isEmpty() ){
+ switch ( settings & ~OContactAccess::query_IgnoreCase ){
+ case OContactAccess::query_RegExp:{
+ QRegExp expr ( query.field(i),
+ !(settings & OContactAccess::query_IgnoreCase),
+ false );
+ if ( expr.find ( (*it).field(i), 0 ) == -1 )
+ allcorrect = false;
+ }
+ break;
+ case OContactAccess::query_WildCards:{
+ QRegExp expr ( query.field(i),
+ !(settings & OContactAccess::query_IgnoreCase),
+ true );
+ if ( expr.find ( (*it).field(i), 0 ) == -1 )
+ allcorrect = false;
+ }
+ break;
+ case OContactAccess::query_ExactMatch:{
+ if (settings & OContactAccess::query_IgnoreCase){
+ if ( query.field(i).upper() !=
+ (*it).field(i).upper() )
+ allcorrect = false;
+ }else{
+ if ( query.field(i) != (*it).field(i) )
+ allcorrect = false;
+ }
+ }
+ break;
+ }
+ }
+ }
+ if ( allcorrect ){
+ m_currentQuery[arraycounter++] = (*it).uid();
+ }
+ }
+
+ // Shrink to fit..
+ m_currentQuery.resize(arraycounter);
+
+ return m_currentQuery;
+ }
+
+ const uint querySettings()
+ {
+ return ( OContactAccess::query_WildCards
+ & OContactAccess::query_IgnoreCase
+ & OContactAccess::query_RegExp
+ & OContactAccess::query_ExactMatch );
+ }
+
+ bool hasQuerySettings (uint querySettings) const
+ {
+ /* OContactAccess::query_IgnoreCase may be added with one
+ * of the other settings, but never used alone.
+ * The other settings are just valid alone...
+ */
+ switch ( querySettings & ~OContactAccess::query_IgnoreCase ){
+ case OContactAccess::query_RegExp:
+ return ( true );
+ case OContactAccess::query_WildCards:
+ return ( true );
+ case OContactAccess::query_ExactMatch:
+ return ( true );
+ default:
+ return ( false );
+ }
+ }
+
+ bool add ( const OContact &newcontact )
+ {
+ //qWarning("odefaultbackend: ACTION::ADD");
+ updateJournal (newcontact, OContact::ACTION_ADD);
+ addContact_p( newcontact );
+ return true;
+ }
+
+ bool replace ( const OContact &contact )
+ {
+ bool found = false;
+
+ QValueListIterator<OContact> it;
+ for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
+ if ( (*it).uid() == contact.uid() ){
+ found = true;
+ break;
+ }
+ }
+ if (found) {
+ updateJournal (contact, OContact::ACTION_REPLACE);
+ m_contactList.remove (it);
+ m_contactList.append (contact);
+ return true;
+ } else
+ return false;
+ }
+
+ bool remove ( int uid )
+ {
+ bool found = false;
+ QValueListIterator<OContact> it;
+ for( it = m_contactList.begin(); it != m_contactList.end(); ++it ){
+ if ((*it).uid() == uid){
+ found = true;
+ break;
+ }
+ }
+ if (found) {
+ updateJournal ( *it, OContact::ACTION_REMOVE);
+ m_contactList.remove (it);
+ return true;
+ } else
+ return false;
+ }
+
+ bool reload(){
+ /* Reload is the same as load in this implementation */
+ return ( load() );
+ }
+
+ private:
+ void addContact_p( const OContact &newcontact ){
+ m_contactList.append (newcontact);
+ }
+
+ /* This function loads the xml-database and the journalfile */
+ bool load( const QString filename, bool isJournal ) {
+
+ /* We use the time of the last read to check if the file was
+ * changed externally.
+ */
+ if ( !isJournal ){
+ QFileInfo fi( filename );
+ m_readtime = fi.lastModified ();
+ }
+
+ const int JOURNALACTION = Qtopia::Notes + 1;
+ const int JOURNALROW = JOURNALACTION + 1;
+
+ bool foundAction = false;
+ OContact::journal_action action = OContact::ACTION_ADD;
+ int journalKey = 0;
+ QMap<int, QString> contactMap;
+ QMap<QString, QString> customMap;
+ QMap<QString, QString>::Iterator customIt;
+ QAsciiDict<int> dict( 47 );
+
+ dict.setAutoDelete( TRUE );
+ dict.insert( "Uid", new int(Qtopia::AddressUid) );
+ dict.insert( "Title", new int(Qtopia::Title) );
+ dict.insert( "FirstName", new int(Qtopia::FirstName) );
+ dict.insert( "MiddleName", new int(Qtopia::MiddleName) );
+ dict.insert( "LastName", new int(Qtopia::LastName) );
+ dict.insert( "Suffix", new int(Qtopia::Suffix) );
+ dict.insert( "FileAs", new int(Qtopia::FileAs) );
+ dict.insert( "Categories", new int(Qtopia::AddressCategory) );
+ dict.insert( "DefaultEmail", new int(Qtopia::DefaultEmail) );
+ dict.insert( "Emails", new int(Qtopia::Emails) );
+ dict.insert( "HomeStreet", new int(Qtopia::HomeStreet) );
+ dict.insert( "HomeCity", new int(Qtopia::HomeCity) );
+ dict.insert( "HomeState", new int(Qtopia::HomeState) );
+ dict.insert( "HomeZip", new int(Qtopia::HomeZip) );
+ dict.insert( "HomeCountry", new int(Qtopia::HomeCountry) );
+ dict.insert( "HomePhone", new int(Qtopia::HomePhone) );
+ dict.insert( "HomeFax", new int(Qtopia::HomeFax) );
+ dict.insert( "HomeMobile", new int(Qtopia::HomeMobile) );
+ dict.insert( "HomeWebPage", new int(Qtopia::HomeWebPage) );
+ dict.insert( "Company", new int(Qtopia::Company) );
+ dict.insert( "BusinessStreet", new int(Qtopia::BusinessStreet) );
+ dict.insert( "BusinessCity", new int(Qtopia::BusinessCity) );
+ dict.insert( "BusinessState", new int(Qtopia::BusinessState) );
+ dict.insert( "BusinessZip", new int(Qtopia::BusinessZip) );
+ dict.insert( "BusinessCountry", new int(Qtopia::BusinessCountry) );
+ dict.insert( "BusinessWebPage", new int(Qtopia::BusinessWebPage) );
+ dict.insert( "JobTitle", new int(Qtopia::JobTitle) );
+ dict.insert( "Department", new int(Qtopia::Department) );
+ dict.insert( "Office", new int(Qtopia::Office) );
+ dict.insert( "BusinessPhone", new int(Qtopia::BusinessPhone) );
+ dict.insert( "BusinessFax", new int(Qtopia::BusinessFax) );
+ dict.insert( "BusinessMobile", new int(Qtopia::BusinessMobile) );
+ dict.insert( "BusinessPager", new int(Qtopia::BusinessPager) );
+ dict.insert( "Profession", new int(Qtopia::Profession) );
+ dict.insert( "Assistant", new int(Qtopia::Assistant) );
+ dict.insert( "Manager", new int(Qtopia::Manager) );
+ dict.insert( "Spouse", new int(Qtopia::Spouse) );
+ dict.insert( "Children", new int(Qtopia::Children) );
+ dict.insert( "Gender", new int(Qtopia::Gender) );
+ dict.insert( "Birthday", new int(Qtopia::Birthday) );
+ dict.insert( "Anniversary", new int(Qtopia::Anniversary) );
+ dict.insert( "Nickname", new int(Qtopia::Nickname) );
+ dict.insert( "Notes", new int(Qtopia::Notes) );
+ dict.insert( "action", new int(JOURNALACTION) );
+ dict.insert( "actionrow", new int(JOURNALROW) );
+
+ //qWarning( "OContactDefaultBackEnd::loading %s", filename.latin1() );
+
+ XMLElement *root = XMLElement::load( filename );
+ if(root != 0l ){ // start parsing
+ /* Parse all XML-Elements and put the data into the
+ * Contact-Class
+ */
+ XMLElement *element = root->firstChild();
+ //qWarning("OContactAccess::load tagName(): %s", root->tagName().latin1() );
+ element = element->firstChild();
+
+ /* Search Tag "Contacts" which is the parent of all Contacts */
+ while( element && !isJournal ){
+ if( element->tagName() != QString::fromLatin1("Contacts") ){
+ //qWarning ("OContactDefBack::Searching for Tag \"Contacts\"! Found: %s",
+ // element->tagName().latin1());
+ element = element->nextChild();
+ } else {
+ element = element->firstChild();
+ break;
+ }
+ }
+ /* Parse all Contacts and ignore unknown tags */
+ while( element ){
+ if( element->tagName() != QString::fromLatin1("Contact") ){
+ //qWarning ("OContactDefBack::Searching for Tag \"Contact\"! Found: %s",
+ // element->tagName().latin1());
+ element = element->nextChild();
+ continue;
+ }
+ /* Found alement with tagname "contact", now parse and store all
+ * attributes contained
+ */
+ //qWarning("OContactDefBack::load element tagName() : %s",
+ // element->tagName().latin1() );
+ QString dummy;
+ foundAction = false;
+
+ XMLElement::AttributeMap aMap = element->attributes();
+ XMLElement::AttributeMap::Iterator it;
+ contactMap.clear();
+ customMap.clear();
+ for( it = aMap.begin(); it != aMap.end(); ++it ){
+ // qWarning ("Read Attribute: %s=%s", it.key().latin1(),it.data().latin1());
+
+ int *find = dict[ it.key() ];
+ /* Unknown attributes will be stored as "Custom" elements */
+ if ( !find ) {
+ qWarning("Attribute %s not known.", it.key().latin1());
+ //contact.setCustomField(it.key(), it.data());
+ customMap.insert( it.key(), it.data() );
+ continue;
+ }
+
+ /* Check if special conversion is needed and add attribute
+ * into Contact class
+ */
+ switch( *find ) {
+ /*
+ case Qtopia::AddressUid:
+ contact.setUid( it.data().toInt() );
+ break;
+ case Qtopia::AddressCategory:
+ contact.setCategories( Qtopia::Record::idsFromString( it.data( )));
+ break;
+ */
+ case JOURNALACTION:
+ action = OContact::journal_action(it.data().toInt());
+ foundAction = true;
+ qWarning ("ODefBack(journal)::ACTION found: %d", action);
+ break;
+ case JOURNALROW:
+ journalKey = it.data().toInt();
+ break;
+ default: // no conversion needed add them to the map
+ contactMap.insert( *find, it.data() );
+ break;
+ }
+ }
+ /* now generate the Contact contact */
+ OContact contact( contactMap );
+
+ for (customIt = customMap.begin(); customIt != customMap.end(); ++customIt ) {
+ contact.setCustomField( customIt.key(), customIt.data() );
+ }
+
+ if (foundAction){
+ foundAction = false;
+ switch ( action ) {
+ case OContact::ACTION_ADD:
+ addContact_p (contact);
+ break;
+ case OContact::ACTION_REMOVE:
+ if ( !remove (contact.uid()) )
+ qWarning ("ODefBack(journal)::Unable to remove uid: %d",
+ contact.uid() );
+ break;
+ case OContact::ACTION_REPLACE:
+ if ( !replace ( contact ) )
+ qWarning ("ODefBack(journal)::Unable to replace uid: %d",
+ contact.uid() );
+ break;
+ default:
+ qWarning ("Unknown action: ignored !");
+ break;
+ }
+ }else{
+ /* Add contact to list */
+ addContact_p (contact);
+ }
+
+ /* Move to next element */
+ element = element->nextChild();
+ }
+ }else {
+ qWarning("ODefBack::could not load");
+ }
+ delete root;
+ qWarning("returning from loading" );
+ return true;
+ }
+
+
+ void updateJournal( const OContact& cnt,
+ OContact::journal_action action ) {
+ QFile f( m_journalName );
+ bool created = !f.exists();
+ if ( !f.open(IO_WriteOnly|IO_Append) )
+ return;
+
+ QString buf;
+ QCString str;
+
+ // if the file was created, we have to set the Tag "<CONTACTS>" to
+ // get a XML-File which is readable by our parser.
+ // This is just a cheat, but better than rewrite the parser.
+ if ( created ){
+ buf = "<Contacts>";
+ QCString cstr = buf.utf8();
+ f.writeBlock( cstr.data(), cstr.length() );
+ }
+
+ buf = "<Contact ";
+ cnt.save( buf );
+ buf += " action=\"" + QString::number( (int)action ) + "\" ";
+ buf += "/>\n";
+ QCString cstr = buf.utf8();
+ f.writeBlock( cstr.data(), cstr.length() );
+ }
+
+ void removeJournal()
+ {
+ QFile f ( m_journalName );
+ if ( f.exists() )
+ f.remove();
+ }
+
+ protected:
+ QString m_journalName;
+ QString m_fileName;
+ QString m_appName;
+ QValueList<OContact> m_contactList;
+ QDateTime m_readtime;
+};
+
+#endif