summaryrefslogtreecommitdiffabout
path: root/kabc/address.cpp
Side-by-side diff
Diffstat (limited to 'kabc/address.cpp') (more/less context) (show whitespace changes)
-rw-r--r--kabc/address.cpp630
1 files changed, 630 insertions, 0 deletions
diff --git a/kabc/address.cpp b/kabc/address.cpp
new file mode 100644
index 0000000..26e0b6a
--- a/dev/null
+++ b/kabc/address.cpp
@@ -0,0 +1,630 @@
+/*
+ This file is part of libkabc.
+ Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
+
+ This library 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.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/*
+Enhanced Version of the file for platform independent KDE tools.
+Copyright (c) 2004 Ulf Schenk
+
+$Id$
+*/
+
+//US added kglobal.h
+#include <kglobal.h>
+
+#include <kapplication.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <ksimpleconfig.h>
+#include <kstandarddirs.h>
+
+#include <qfile.h>
+
+#include "address.h"
+
+using namespace KABC;
+
+QMap<QString, QString> Address::mISOMap;
+
+Address::Address() :
+ mEmpty( true ), mType( 0 )
+{
+ mId = KApplication::randomString( 10 );
+}
+
+Address::Address( int type ) :
+ mEmpty( true ), mType( type )
+{
+ mId = KApplication::randomString( 10 );
+}
+
+bool Address::operator==( const Address &a ) const
+{
+ if ( mPostOfficeBox != a.mPostOfficeBox ) return false;
+ if ( mExtended != a.mExtended ) return false;
+ if ( mStreet != a.mStreet ) return false;
+ if ( mLocality != a.mLocality ) return false;
+ if ( mRegion != a.mRegion ) return false;
+ if ( mPostalCode != a.mPostalCode ) return false;
+ if ( mCountry != a.mCountry ) return false;
+ if ( mLabel != a.mLabel ) return false;
+
+ return true;
+}
+
+bool Address::operator!=( const Address &a ) const
+{
+ return !( a == *this );
+}
+
+bool Address::isEmpty() const
+{
+ if ( mPostOfficeBox.isEmpty() &&
+ mExtended.isEmpty() &&
+ mStreet.isEmpty() &&
+ mLocality.isEmpty() &&
+ mRegion.isEmpty() &&
+ mPostalCode.isEmpty() &&
+ mCountry.isEmpty() &&
+ mLabel.isEmpty() ) {
+ return true;
+ }
+ return false;
+}
+
+void Address::clear()
+{
+ *this = Address();
+}
+
+void Address::setId( const QString &id )
+{
+ mEmpty = false;
+
+ mId = id;
+}
+
+QString Address::id() const
+{
+ return mId;
+}
+
+void Address::setType( int type )
+{
+ mEmpty = false;
+
+ mType = type;
+}
+
+int Address::type() const
+{
+ return mType;
+}
+
+QString Address::typeLabel() const
+{
+ QString label;
+ bool first = true;
+
+ TypeList list = typeList();
+
+ TypeList::Iterator it;
+ for ( it = list.begin(); it != list.end(); ++it ) {
+ if ( ( type() & (*it) ) && ( (*it) != Pref ) ) {
+ label.append( ( first ? "" : "/" ) + typeLabel( *it ) );
+ if ( first )
+ first = false;
+ }
+ }
+
+ return label;
+}
+
+void Address::setPostOfficeBox( const QString &s )
+{
+ mEmpty = false;
+
+ mPostOfficeBox = s;
+}
+
+QString Address::postOfficeBox() const
+{
+ return mPostOfficeBox;
+}
+
+QString Address::postOfficeBoxLabel()
+{
+ return i18n("Post Office Box");
+}
+
+
+void Address::setExtended( const QString &s )
+{
+ mEmpty = false;
+
+ mExtended = s;
+}
+
+QString Address::extended() const
+{
+ return mExtended;
+}
+
+QString Address::extendedLabel()
+{
+ return i18n("Extended Address Information");
+}
+
+
+void Address::setStreet( const QString &s )
+{
+ mEmpty = false;
+
+ mStreet = s;
+}
+
+QString Address::street() const
+{
+ return mStreet;
+}
+
+QString Address::streetLabel()
+{
+ return i18n("Street");
+}
+
+
+void Address::setLocality( const QString &s )
+{
+ mEmpty = false;
+
+ mLocality = s;
+}
+
+QString Address::locality() const
+{
+ return mLocality;
+}
+
+QString Address::localityLabel()
+{
+ return i18n("Locality");
+}
+
+
+void Address::setRegion( const QString &s )
+{
+ mEmpty = false;
+
+ mRegion = s;
+}
+
+QString Address::region() const
+{
+ return mRegion;
+}
+
+QString Address::regionLabel()
+{
+ return i18n("Region");
+}
+
+
+void Address::setPostalCode( const QString &s )
+{
+ mEmpty = false;
+
+ mPostalCode = s;
+}
+
+QString Address::postalCode() const
+{
+ return mPostalCode;
+}
+
+QString Address::postalCodeLabel()
+{
+ return i18n("Postal Code");
+}
+
+
+void Address::setCountry( const QString &s )
+{
+ mEmpty = false;
+
+ mCountry = s;
+}
+
+QString Address::country() const
+{
+ return mCountry;
+}
+
+QString Address::countryLabel()
+{
+ return i18n("Country");
+}
+
+
+void Address::setLabel( const QString &s )
+{
+ mEmpty = false;
+
+ mLabel = s;
+}
+
+QString Address::label() const
+{
+ return mLabel;
+}
+
+QString Address::labelLabel()
+{
+ return i18n("Delivery Label");
+}
+
+Address::TypeList Address::typeList()
+{
+ TypeList list;
+
+ list << Dom << Intl << Postal << Parcel << Home << Work << Pref;
+
+ return list;
+}
+
+QString Address::typeLabel( int type )
+{
+ switch ( type ) {
+ case Dom:
+ return i18n("Domestic");
+ break;
+ case Intl:
+ return i18n("International");
+ break;
+ case Postal:
+ return i18n("Postal");
+ break;
+ case Parcel:
+ return i18n("Parcel");
+ break;
+ case Home:
+ return i18n("Home Address", "Home");
+ break;
+ case Work:
+ return i18n("Work Address", "Work");
+ break;
+ case Pref:
+ return i18n("Preferred Address");
+ break;
+ default:
+ return i18n("Other");
+ break;
+ }
+}
+
+void Address::dump() const
+{
+ qDebug("Address::dump() +++++++++++++++++ ");
+#if 0
+ kdDebug(5700) << " Address {" << endl;
+ kdDebug(5700) << " Id: " << id() << endl;
+ kdDebug(5700) << " Extended: " << extended() << endl;
+ kdDebug(5700) << " Street: " << street() << endl;
+ kdDebug(5700) << " Postal Code: " << postalCode() << endl;
+ kdDebug(5700) << " Locality: " << locality() << endl;
+ kdDebug(5700) << " }" << endl;
+#endif
+}
+
+
+QString Address::formattedAddress( const QString &realName
+ , const QString &orgaName ) const
+{
+ QString ciso;
+ QString addrTemplate;
+ QString ret;
+
+ // **************************************************************
+ // LR: currently we have no iso handling - we will format the address manually here
+
+ QString text;
+ if ( !street().isEmpty() )
+ text += street() + "\n";
+
+ if ( !postOfficeBox().isEmpty() )
+ text += postOfficeBox() + "\n";
+
+ text += locality() + QString(" ") + region();
+
+ if ( !postalCode().isEmpty() )
+ text += QString(", ") + postalCode();
+
+ text += "\n";
+
+ if ( !country().isEmpty() )
+ text += country() + "\n";
+
+ text += extended();
+
+
+ return text;
+ // **************************************************************
+
+ // FIXME: first check for iso-country-field and prefer that one
+ if ( !country().isEmpty() ) {
+ ciso = countryToISO( country() );
+ } else {
+ // fall back to our own country
+ ciso = KGlobal::locale()->country();
+ }
+ //qDebug("ciso %s ",ciso.latin1() );
+ KSimpleConfig entry( locate( "locale",
+ QString( "l10n/" ) + ciso + QString( "/entry.desktop" ) ) );
+ entry.setGroup( "KCM Locale" );
+
+ // decide whether this needs special business address formatting
+ if ( orgaName.isNull() ) {
+ addrTemplate = entry.readEntry( "AddressFormat" );
+ } else {
+ addrTemplate = entry.readEntry( "BusinessAddressFormat" );
+ if ( addrTemplate.isEmpty() )
+ addrTemplate = entry.readEntry( "AddressFormat" );
+ }
+
+ // in the case there's no format found at all, default to what we've always
+ // used:
+ if ( addrTemplate.isEmpty() ) {
+ qDebug("address format database incomplete****************** ");
+ kdWarning(5700) << "address format database incomplete "
+ << "(no format for locale " << ciso
+ << " found). Using default address formatting." << endl;
+ addrTemplate = "%0(%n\\n)%0(%cm\\n)%0(%s\\n)%0(PO BOX %p\\n)%0(%l%w%r)%,%z";
+ }
+
+ // scan
+ parseAddressTemplateSection( addrTemplate, ret, realName, orgaName );
+
+ // now add the country line if needed (formatting this time according to
+ // the rules of our own system country )
+ if ( !country().isEmpty() ) {
+ KSimpleConfig entry( locate( "locale", QString( "l10n/" )
+ + KGlobal::locale()->country() + QString( "/entry.desktop" ) ) );
+ entry.setGroup( "KCM Locale" );
+ QString cpos = entry.readEntry( "AddressCountryPosition" );
+ if ( "BELOW" == cpos || cpos.isEmpty() ) {
+ ret = ret + "\n\n" + country().upper();
+ } else if ( "below" == cpos ) {
+ ret = ret + "\n\n" + country();
+ } else if ( "ABOVE" == cpos ) {
+ ret = country().upper() + "\n\n" + ret;
+ } else if ( "above" == cpos ) {
+ ret = country() + "\n\n" + ret;
+ }
+ }
+
+ return ret;
+}
+
+bool Address::parseAddressTemplateSection( const QString &tsection,
+ QString &result, const QString &realName, const QString &orgaName ) const
+{
+ // This method first parses and substitutes any bracketed sections and
+ // after that replaces any tags with their values. If a bracketed section
+ // or a tag evaluate to zero, they are not just removed but replaced
+ // with a placeholder. This is because in the last step conditionals are
+ // resolved which depend on information about zero-evaluations.
+ result = tsection;
+ int stpos = 0;
+ bool ret = false;
+
+ // first check for brackets that have to be evaluated first
+ int fpos = result.find( KABC_FMTTAG_purgeempty, stpos );
+ while ( -1 != fpos ) {
+ int bpos1 = fpos + KABC_FMTTAG_purgeempty.length();
+ int bpos2;
+ // expect opening bracket and find next balanced closing bracket. If
+ // next char is no opening bracket, continue parsing (no valid tag)
+ if ( '(' == result[bpos1] ) {
+ bpos2 = findBalancedBracket( result, bpos1 );
+ if ( -1 != bpos2 ) {
+ // we have balanced brackets, recursively parse:
+ QString rplstr;
+ bool purge = !parseAddressTemplateSection( result.mid( bpos1+1,
+ bpos2-bpos1-1 ), rplstr,
+ realName, orgaName );
+ if ( purge ) {
+ // purge -> remove all
+ // replace with !_P_!, so conditional tags work later
+ result.replace( fpos, bpos2 - fpos + 1, "!_P_!" );
+ // leave stpos as it is
+ } else {
+ // no purge -> replace with recursively parsed string
+ result.replace( fpos, bpos2 - fpos + 1, rplstr );
+ ret = true;
+ stpos = fpos + rplstr.length();
+ }
+ } else {
+ // unbalanced brackets: keep on parsing (should not happen
+ // and will result in bad formatting)
+ stpos = bpos1;
+ }
+ }
+ fpos = result.find( KABC_FMTTAG_purgeempty, stpos );
+ }
+
+ // after sorting out all purge tags, we just search'n'replace the rest,
+ // keeping track of whether at least one tag evaluates to something.
+ // The following macro needs QString for R_FIELD
+ // It substitutes !_P_! for empty fields so conditional tags work later
+#define REPLTAG(R_TAG,R_FIELD) \
+ if ( result.contains(R_TAG, false) ) { \
+ QString rpl = R_FIELD.isEmpty() ? QString("!_P_!") : R_FIELD; \
+ result.replace( R_TAG, rpl ); \
+ if ( !R_FIELD.isEmpty() ) { \
+ ret = true; \
+ } \
+ }
+ REPLTAG( KABC_FMTTAG_realname, realName );
+ REPLTAG( KABC_FMTTAG_REALNAME, realName.upper() );
+ REPLTAG( KABC_FMTTAG_company, orgaName );
+ REPLTAG( KABC_FMTTAG_COMPANY, orgaName.upper() );
+ REPLTAG( KABC_FMTTAG_pobox, postOfficeBox() );
+ REPLTAG( KABC_FMTTAG_street, street() );
+ REPLTAG( KABC_FMTTAG_STREET, street().upper() );
+ REPLTAG( KABC_FMTTAG_zipcode, postalCode() );
+ REPLTAG( KABC_FMTTAG_location, locality() );
+ REPLTAG( KABC_FMTTAG_LOCATION, locality().upper() );
+ REPLTAG( KABC_FMTTAG_region, region() );
+ REPLTAG( KABC_FMTTAG_REGION, region().upper() );
+ result.replace( KABC_FMTTAG_newline, "\n" );
+#undef REPLTAG
+
+ // conditional comma
+ fpos = result.find( KABC_FMTTAG_condcomma, 0 );
+ while ( -1 != fpos ) {
+ QString str1 = result.mid( fpos - 5, 5 );
+ QString str2 = result.mid( fpos + 2, 5 );
+ if ( str1 != "!_P_!" && str2 != "!_P_!" ) {
+ result.replace( fpos, 2, ", " );
+ } else {
+ result.remove( fpos, 2 );
+ }
+ fpos = result.find( KABC_FMTTAG_condcomma, fpos );
+ }
+ // conditional whitespace
+ fpos = result.find( KABC_FMTTAG_condwhite, 0 );
+ while ( -1 != fpos ) {
+ QString str1 = result.mid( fpos - 5, 5 );
+ QString str2 = result.mid( fpos + 2, 5 );
+ if ( str1 != "!_P_!" && str2 != "!_P_!" ) {
+ result.replace( fpos, 2, " " );
+ } else {
+ result.remove( fpos, 2 );
+ }
+ fpos = result.find( KABC_FMTTAG_condwhite, fpos );
+ }
+
+ // remove purged:
+//US my QT version does not support remove. So lets do it the old fashioned way.
+//US result.remove( "!_P_!" );
+ int n = result.find("!_P_!");
+ if (n >= 0)
+ result.remove( n, 5 );
+
+ return ret;
+}
+
+int Address::findBalancedBracket( const QString &tsection, int pos ) const
+{
+ int balancecounter = 0;
+ for( unsigned int i = pos + 1; i < tsection.length(); i++ ) {
+ if ( ')' == tsection.at(i) && 0 == balancecounter ) {
+ // found end of brackets
+ return i;
+ } else
+ if ( '(' == tsection.at(i) ) {
+ // nested brackets
+ balancecounter++;
+ }
+ }
+ return -1;
+}
+
+QString Address::countryToISO( const QString &cname )
+{
+ // we search a map file for translations from country names to
+ // iso codes, storing caching things in a QMap for faster future
+ // access.
+/*US
+
+ QString isoCode = mISOMap[ cname ];
+ if ( !isoCode.isEmpty() )
+ return isoCode;
+
+ QString mapfile = KGlobal::dirs()->findResource( "data",
+ QString::fromLatin1( "kabc/countrytransl.map" ) );
+
+ QFile file( mapfile );
+ if ( file.open( IO_ReadOnly ) ) {
+ QTextStream s( &file );
+ QString strbuf = s.readLine();
+ while( !strbuf.isNull() ) {
+ if ( strbuf.startsWith( cname ) ) {
+ int index = strbuf.findRev('\t');
+ strbuf = strbuf.mid(index+1, 2);
+ file.close();
+ mISOMap[ cname ] = strbuf;
+ return strbuf;
+ }
+ strbuf = s.readLine();
+ }
+ file.close();
+ }
+*/
+ // fall back to system country
+ mISOMap[ cname ] = KGlobal::locale()->country();
+ return KGlobal::locale()->country();
+}
+
+QString Address::ISOtoCountry( const QString &ISOname )
+{
+/*US
+ // get country name from ISO country code (e.g. "no" -> i18n("Norway"))
+ QString mapfile = KGlobal::dirs()->findResource( "data",
+ QString::fromLatin1( "kabc/countrytransl.map" ) );
+
+kdWarning() << "MAPFILE : " << mapfile << endl;
+ QFile file( mapfile );
+ if ( file.open( IO_ReadOnly ) ) {
+ QTextStream s( &file );
+ QString searchStr = "\t" + ISOname.simplifyWhiteSpace().lower();
+kdWarning() << "Suche : " << searchStr << endl;
+ QString strbuf = s.readLine();
+ int pos;
+ while( !strbuf.isNull() ) {
+ if ( (pos=strbuf.find( searchStr )) != -1 ) {
+ file.close();
+ return i18n(strbuf.left(pos).utf8());
+ }
+ strbuf = s.readLine();
+ }
+ file.close();
+ }
+*/
+ return ISOname;
+}
+
+QDataStream &KABC::operator<<( QDataStream &s, const Address &addr )
+{
+ return s << addr.mId << addr.mType << addr.mPostOfficeBox <<
+ addr.mExtended << addr.mStreet << addr.mLocality <<
+ addr.mRegion << addr.mPostalCode << addr.mCountry <<
+ addr.mLabel;
+}
+
+QDataStream &KABC::operator>>( QDataStream &s, Address &addr )
+{
+ s >> addr.mId >> addr.mType >> addr.mPostOfficeBox >> addr.mExtended >>
+ addr.mStreet >> addr.mLocality >> addr.mRegion >>
+ addr.mPostalCode >> addr.mCountry >> addr.mLabel;
+
+ addr.mEmpty = false;
+
+ return s;
+}