27 #include <klocalizedstring.h>
29 #include <kstandarddirs.h>
30 #include <kconfiggroup.h>
32 #include <QtCore/QFile>
33 #include <QtCore/QMap>
34 #include <QtCore/QTextStream>
35 #include <QtCore/QSharedData>
40 #define KABC_FMTTAG_realname QString::fromLatin1("%n")
41 #define KABC_FMTTAG_REALNAME QString::fromLatin1("%N")
42 #define KABC_FMTTAG_company QString::fromLatin1("%cm")
43 #define KABC_FMTTAG_COMPANY QString::fromLatin1("%CM")
44 #define KABC_FMTTAG_pobox QString::fromLatin1("%p")
45 #define KABC_FMTTAG_street QString::fromLatin1("%s")
46 #define KABC_FMTTAG_STREET QString::fromLatin1("%S")
47 #define KABC_FMTTAG_zipcode QString::fromLatin1("%z")
48 #define KABC_FMTTAG_location QString::fromLatin1("%l")
49 #define KABC_FMTTAG_LOCATION QString::fromLatin1("%L")
50 #define KABC_FMTTAG_region QString::fromLatin1("%r")
51 #define KABC_FMTTAG_REGION QString::fromLatin1("%R")
52 #define KABC_FMTTAG_newline QString::fromLatin1("\\n")
53 #define KABC_FMTTAG_condcomma QString::fromLatin1("%,")
54 #define KABC_FMTTAG_condwhite QString::fromLatin1("%w")
55 #define KABC_FMTTAG_purgeempty QString::fromLatin1("%0")
62 static int findBalancedBracket(
const QString &tsection,
int pos )
64 int balancecounter = 0;
65 for (
int i = pos + 1; i < tsection.length(); ++i ) {
66 if ( QLatin1Char(
')' ) == tsection[i] && 0 == balancecounter ) {
70 if ( QLatin1Char(
'(' ) == tsection[i] ) {
85 static bool parseAddressTemplateSection(
const QString &tsection, QString &result,
86 const QString &realName,
const QString &orgaName,
99 int fpos = result.indexOf( KABC_FMTTAG_purgeempty, stpos );
100 while ( -1 != fpos ) {
101 int bpos1 = fpos + KABC_FMTTAG_purgeempty.length();
105 if ( QLatin1Char(
'(' ) == result[bpos1] ) {
106 bpos2 = findBalancedBracket( result, bpos1 );
110 bool purge = !parseAddressTemplateSection( result.mid( bpos1+1,
111 bpos2-bpos1-1 ), rplstr,
112 realName, orgaName, address );
116 result.replace( fpos, bpos2 - fpos + 1, QLatin1String(
"!_P_!" ) );
120 result.replace( fpos, bpos2 - fpos + 1, rplstr );
122 stpos = fpos + rplstr.length();
130 fpos = result.indexOf( KABC_FMTTAG_purgeempty, stpos );
137 #define REPLTAG(R_TAG,R_FIELD) \
138 if ( result.indexOf( R_TAG, false ) != -1 ) { \
139 QString rpl = R_FIELD.isEmpty() ? QLatin1String( "!_P_!" ) : R_FIELD; \
140 result.replace( R_TAG, rpl ); \
141 if ( !R_FIELD.isEmpty() ) { \
145 REPLTAG( KABC_FMTTAG_realname, realName );
146 REPLTAG( KABC_FMTTAG_REALNAME, realName.toUpper() );
147 REPLTAG( KABC_FMTTAG_company, orgaName );
148 REPLTAG( KABC_FMTTAG_COMPANY, orgaName.toUpper() );
150 REPLTAG( KABC_FMTTAG_street, address.
street() );
151 REPLTAG( KABC_FMTTAG_STREET, address.
street().toUpper() );
152 REPLTAG( KABC_FMTTAG_zipcode, address.
postalCode() );
153 REPLTAG( KABC_FMTTAG_location, address.
locality() );
154 REPLTAG( KABC_FMTTAG_LOCATION, address.
locality().toUpper() );
155 REPLTAG( KABC_FMTTAG_region, address.
region() );
156 REPLTAG( KABC_FMTTAG_REGION, address.
region().toUpper() );
157 result.replace( KABC_FMTTAG_newline, QLatin1String(
"\n" ) );
161 fpos = result.indexOf( KABC_FMTTAG_condcomma, 0 );
162 while ( -1 != fpos ) {
163 const QString str1 = result.mid( fpos - 5, 5 );
164 const QString str2 = result.mid( fpos + 2, 5 );
165 if ( str1 != QLatin1String(
"!_P_!" ) && str2 != QLatin1String(
"!_P_!" ) ) {
166 result.replace( fpos, 2, QLatin1String(
", " ) );
168 result.remove( fpos, 2 );
170 fpos = result.indexOf( KABC_FMTTAG_condcomma, fpos );
173 fpos = result.indexOf( KABC_FMTTAG_condwhite, 0 );
174 while ( -1 != fpos ) {
175 const QString str1 = result.mid( fpos - 5, 5 );
176 const QString str2 = result.mid( fpos + 2, 5 );
177 if ( str1 != QLatin1String(
"!_P_!" ) && str2 != QLatin1String(
"!_P_!" ) ) {
178 result.replace( fpos, 2, QLatin1String(
" " ) );
180 result.remove( fpos, 2 );
182 fpos = result.indexOf( KABC_FMTTAG_condwhite, fpos );
186 result.remove( QLatin1String(
"!_P_!" ) );
191 class Address::Private :
public QSharedData
195 : mEmpty( true ), mType( 0 )
197 mId = KRandom::randomString( 10 );
200 Private(
const Private &other )
201 : QSharedData( other )
203 mEmpty = other.mEmpty;
207 mPostOfficeBox = other.mPostOfficeBox;
208 mExtended = other.mExtended;
209 mStreet = other.mStreet;
210 mLocality = other.mLocality;
211 mRegion = other.mRegion;
212 mPostalCode = other.mPostalCode;
213 mCountry = other.mCountry;
214 mLabel = other.mLabel;
221 QString mPostOfficeBox;
253 if (
this != &other ) {
262 if ( d->mId != other.d->mId ) {
265 if ( d->mType != other.d->mType ) {
268 if ( d->mPostOfficeBox != other.d->mPostOfficeBox ) {
271 if ( d->mExtended != other.d->mExtended ) {
274 if ( d->mStreet != other.d->mStreet ) {
277 if ( d->mLocality != other.d->mLocality ) {
280 if ( d->mRegion != other.d->mRegion ) {
283 if ( d->mPostalCode != other.d->mPostalCode ) {
286 if ( d->mCountry != other.d->mCountry ) {
289 if ( d->mLabel != other.d->mLabel ) {
298 return !( a == *this );
340 TypeList::ConstIterator it;
341 for ( it = list.begin(); it != list.end(); ++it ) {
342 if ( (
type() & ( *it ) ) && ( ( *it ) !=
Pref ) ) {
344 label.append( QLatin1Char(
'/' ) );
364 return d->mPostOfficeBox;
369 return i18n(
"Post Office Box" );
385 return i18n(
"Extended Address Information" );
401 return i18n(
"Street" );
417 return i18n(
"Locality" );
433 return i18n(
"Region" );
444 return d->mPostalCode;
449 return i18n(
"Postal Code" );
465 return i18n(
"Country" );
481 return i18n(
"Delivery Label" );
488 if ( list.isEmpty() ) {
498 return i18nc(
"Preferred address",
"Preferred" );
503 return i18nc(
"Address is in home country",
"Domestic" );
506 return i18nc(
"Address is not in home country",
"International" );
509 return i18nc(
"Address for delivering letters",
"Postal" );
512 return i18nc(
"Address for delivering packages",
"Parcel" );
515 return i18nc(
"Home Address",
"Home" );
518 return i18nc(
"Work Address",
"Work" );
521 return i18n(
"Preferred Address" );
524 return i18nc(
"another type of address",
"Other" );
533 str += QLatin1String(
"Address {\n" );
534 str += QString::fromLatin1(
" IsEmpty: %1\n" ).
535 arg( d->mEmpty ? QLatin1String(
"true" ) : QLatin1String(
"false" ) );
536 str += QString::fromLatin1(
" Id: %1\n" ).arg( d->mId );
537 str += QString::fromLatin1(
" Type: %1\n" ).arg(
typeLabel( d->mType ) );
538 str += QString::fromLatin1(
" Post office box: %1\n" ).arg( d->mPostOfficeBox );
539 str += QString::fromLatin1(
" Extended: %1\n" ).arg( d->mExtended );
540 str += QString::fromLatin1(
" Street: %1\n" ).arg( d->mStreet );
541 str += QString::fromLatin1(
" Locality: %1\n" ).arg( d->mLocality );
542 str += QString::fromLatin1(
" Region: %1\n" ).arg( d->mRegion );
543 str += QString::fromLatin1(
" Postal code: %1\n" ).arg( d->mPostalCode );
544 str += QString::fromLatin1(
" Country: %1\n" ).arg( d->mCountry );
545 str += QString::fromLatin1(
" Label: %1\n" ).arg( d->mLabel );
546 str += QLatin1String(
"}\n" );
552 const QString &orgaName )
const
555 QString addrTemplate;
563 ciso = KGlobal::locale()->country();
565 KConfig entry( KStandardDirs::locate(
"locale",
566 QLatin1String(
"l10n/" ) + ciso + QLatin1String(
"/entry.desktop" ) ) );
568 KConfigGroup group = entry.group(
"KCM Locale" );
570 if ( orgaName.isEmpty() ) {
571 addrTemplate = group.readEntry(
"AddressFormat" );
573 addrTemplate = group.readEntry(
"BusinessAddressFormat" );
574 if ( addrTemplate.isEmpty() ) {
575 addrTemplate = group.readEntry(
"AddressFormat" );
581 if ( addrTemplate.isEmpty() ) {
582 kWarning( 5700 ) <<
"address format database incomplete"
583 <<
"(no format for locale" << ciso
584 <<
"found). Using default address formatting.";
585 addrTemplate = QLatin1String(
"%0(%n\\n)%0(%cm\\n)%0(%s\\n)%0(PO BOX %p\\n)%0(%l%w%r)%,%z" );
589 parseAddressTemplateSection( addrTemplate, ret, realName, orgaName, *
this );
594 KConfig entry( KStandardDirs::locate(
"locale", QLatin1String(
"l10n/" ) +
596 QLatin1String(
"/entry.desktop" ) ) );
597 KConfigGroup group = entry.group(
"KCM Locale" );
598 QString cpos = group.readEntry(
"AddressCountryPosition" );
599 if ( QLatin1String(
"BELOW" ) == cpos || cpos.isEmpty() ) {
600 ret = ret + QLatin1String(
"\n\n" ) +
country().toUpper();
601 }
else if ( QLatin1String(
"below" ) == cpos ) {
602 ret = ret + QLatin1String(
"\n\n" ) +
country();
603 }
else if ( QLatin1String(
"ABOVE" ) == cpos ) {
604 ret =
country().toUpper() + QLatin1String(
"\n\n" ) + ret;
605 }
else if ( QLatin1String(
"above" ) == cpos ) {
606 ret =
country() + QLatin1String(
"\n\n" ) + ret;
618 typedef QMap<QString, QString> stringMap;
619 K_GLOBAL_STATIC( stringMap, sISOMap )
621 QMap<QString, QString>::ConstIterator it;
622 it = sISOMap->constFind( cname );
623 if ( it != sISOMap->constEnd() ) {
627 QString mapfile = KGlobal::dirs()->findResource(
"data",
628 QLatin1String(
"kabc/countrytransl.map" ) );
630 QFile file( mapfile );
631 if ( file.open( QIODevice::ReadOnly ) ) {
632 QTextStream s( &file );
633 QString strbuf = s.readLine();
634 while ( !strbuf.isEmpty() ) {
635 QStringList countryInfo = strbuf.split( QLatin1Char(
'\t' ), QString::KeepEmptyParts );
636 if ( countryInfo[ 0 ] == cname ) {
638 sISOMap->insert( cname, countryInfo[ 1 ] );
639 return countryInfo[ 1 ];
641 strbuf = s.readLine();
647 sISOMap->insert( cname, KGlobal::locale()->
country() );
648 return KGlobal::locale()->country();
654 if ( ISOname.simplified().isEmpty() ) {
658 QString mapfile = KGlobal::dirs()->findResource(
"data",
659 QLatin1String(
"kabc/countrytransl.map" ) );
661 QFile file( mapfile );
662 if ( file.open( QIODevice::ReadOnly ) ) {
663 QTextStream s( &file );
664 QString searchStr = QLatin1Char(
'\t' ) + ISOname.simplified().toLower();
665 QString strbuf = s.readLine();
667 while ( !strbuf.isEmpty() ) {
668 if ( ( pos = strbuf.indexOf( searchStr ) ) != -1 ) {
670 return i18n( strbuf.left( pos ).toUtf8() );
672 strbuf = s.readLine();
680 QDataStream &KABC::operator<<( QDataStream &s,
const Address &addr )
682 return s << addr.d->mId << (uint)addr.d->mType << addr.d->mPostOfficeBox
683 << addr.d->mExtended << addr.d->mStreet << addr.d->mLocality
684 << addr.d->mRegion << addr.d->mPostalCode << addr.d->mCountry
685 << addr.d->mLabel << addr.d->mEmpty;
688 QDataStream &KABC::operator>>( QDataStream &s,
Address &addr )
691 s >> addr.d->mId >> type >> addr.d->mPostOfficeBox >> addr.d->mExtended
692 >> addr.d->mStreet >> addr.d->mLocality >> addr.d->mRegion
693 >> addr.d->mPostalCode >> addr.d->mCountry >> addr.d->mLabel
696 addr.d->mType = Address::Type( type );
void setType(Type type)
Sets the type of address.
static QString streetLabel()
Returns the translated label for street field.
Postal address information.
QString street() const
Returns the street.
~Address()
Destroys the address.
bool operator==(const Address &addr) const
Equality operator.
void setStreet(const QString &street)
Sets the street (including house number).
static QString localityLabel()
Returns the translated label for locality field.
void setId(const QString &identifier)
Sets the unique identifier.
Address & operator=(const Address &addr)
Assignment operator.
QString postalCode() const
Returns the postal code.
Type type() const
Returns the type of address.
QString formattedAddress(const QString &realName=QString(), const QString &orgaName=QString()) const
Returns this address formatted according to the country-specific address formatting rules...
QString country() const
Returns the country.
QString typeLabel() const
Returns a translated string of all types the address has.
static QString postalCodeLabel()
Returns the translated label for postal code field.
static QString ISOtoCountry(const QString &ISOname)
Returns a localized country name for a ISO code.
static QString regionLabel()
Returns the translated label for region field.
static QString extendedLabel()
Returns the translated label for extended field.
void clear()
Clears all entries of the address.
bool operator!=(const Address &addr) const
Not-equal operator.
void setPostOfficeBox(const QString &postOfficeBox)
Sets the post office box.
QString id() const
Returns the unique identifier.
static QString postOfficeBoxLabel()
Returns the translated label for post office box field.
void setRegion(const QString ®ion)
Sets the region, e.g.
static QString countryLabel()
Returns the translated label for country field.
QList< TypeFlag > TypeList
List of address types.
QString toString() const
Returns a string representation of the address.
void setLabel(const QString &label)
Sets the delivery label.
static QString countryToISO(const QString &cname)
Returns ISO code for a localized country name.
void setCountry(const QString &country)
Sets the country.
QString locality() const
Returns the locality.
QString region() const
Returns the region.
QString extended() const
Returns the extended address information.
void setLocality(const QString &locality)
Sets the locality, e.g.
static TypeList typeList()
Returns the list of available types.
void setPostalCode(const QString &code)
Sets the postal code.
void setExtended(const QString &extended)
Sets the extended address information.
static QString labelLabel()
Returns the translated label for delivery label field.
QString label() const
Returns the delivery label.
bool isEmpty() const
Returns true, if the address is empty.
QString postOfficeBox() const
Returns the post office box.
Address()
Creates an empty address.