27 #include <kstandarddirs.h>
28 #include <kconfiggroup.h>
30 #include <QtCore/QFile>
31 #include <QtCore/QMap>
32 #include <QtCore/QTextStream>
33 #include <QtCore/QSharedData>
38 #define KABC_FMTTAG_realname QString::fromLatin1("%n")
39 #define KABC_FMTTAG_REALNAME QString::fromLatin1("%N")
40 #define KABC_FMTTAG_company QString::fromLatin1("%cm")
41 #define KABC_FMTTAG_COMPANY QString::fromLatin1("%CM")
42 #define KABC_FMTTAG_pobox QString::fromLatin1("%p")
43 #define KABC_FMTTAG_street QString::fromLatin1("%s")
44 #define KABC_FMTTAG_STREET QString::fromLatin1("%S")
45 #define KABC_FMTTAG_zipcode QString::fromLatin1("%z")
46 #define KABC_FMTTAG_location QString::fromLatin1("%l")
47 #define KABC_FMTTAG_LOCATION QString::fromLatin1("%L")
48 #define KABC_FMTTAG_region QString::fromLatin1("%r")
49 #define KABC_FMTTAG_REGION QString::fromLatin1("%R")
50 #define KABC_FMTTAG_newline QString::fromLatin1("\\n")
51 #define KABC_FMTTAG_condcomma QString::fromLatin1("%,")
52 #define KABC_FMTTAG_condwhite QString::fromLatin1("%w")
53 #define KABC_FMTTAG_purgeempty QString::fromLatin1("%0")
60 static int findBalancedBracket(
const QString &tsection,
int pos )
62 int balancecounter = 0;
63 for (
int i = pos + 1; i < tsection.length(); ++i ) {
64 if ( QLatin1Char(
')' ) == tsection[i] && 0 == balancecounter ) {
68 if ( QLatin1Char(
'(' ) == tsection[i] ) {
83 static bool parseAddressTemplateSection(
const QString &tsection, QString &result,
84 const QString &realName,
const QString &orgaName,
97 int fpos = result.indexOf( KABC_FMTTAG_purgeempty, stpos );
98 while ( -1 != fpos ) {
99 int bpos1 = fpos + KABC_FMTTAG_purgeempty.length();
103 if ( QLatin1Char(
'(' ) == result[bpos1] ) {
104 bpos2 = findBalancedBracket( result, bpos1 );
108 bool purge = !parseAddressTemplateSection( result.mid( bpos1+1,
109 bpos2-bpos1-1 ), rplstr,
110 realName, orgaName, address );
114 result.replace( fpos, bpos2 - fpos + 1, QLatin1String(
"!_P_!" ) );
118 result.replace( fpos, bpos2 - fpos + 1, rplstr );
120 stpos = fpos + rplstr.length();
128 fpos = result.indexOf( KABC_FMTTAG_purgeempty, stpos );
135 #define REPLTAG(R_TAG,R_FIELD) \
136 if ( result.indexOf( R_TAG, false ) != -1 ) { \
137 QString rpl = R_FIELD.isEmpty() ? QLatin1String( "!_P_!" ) : R_FIELD; \
138 result.replace( R_TAG, rpl ); \
139 if ( !R_FIELD.isEmpty() ) { \
143 REPLTAG( KABC_FMTTAG_realname, realName );
144 REPLTAG( KABC_FMTTAG_REALNAME, realName.toUpper() );
145 REPLTAG( KABC_FMTTAG_company, orgaName );
146 REPLTAG( KABC_FMTTAG_COMPANY, orgaName.toUpper() );
148 REPLTAG( KABC_FMTTAG_street, address.
street() );
149 REPLTAG( KABC_FMTTAG_STREET, address.
street().toUpper() );
150 REPLTAG( KABC_FMTTAG_zipcode, address.
postalCode() );
151 REPLTAG( KABC_FMTTAG_location, address.
locality() );
152 REPLTAG( KABC_FMTTAG_LOCATION, address.
locality().toUpper() );
153 REPLTAG( KABC_FMTTAG_region, address.
region() );
154 REPLTAG( KABC_FMTTAG_REGION, address.
region().toUpper() );
155 result.replace( KABC_FMTTAG_newline, QLatin1String(
"\n" ) );
159 fpos = result.indexOf( KABC_FMTTAG_condcomma, 0 );
160 while ( -1 != fpos ) {
161 const QString str1 = result.mid( fpos - 5, 5 );
162 const QString str2 = result.mid( fpos + 2, 5 );
163 if ( str1 != QLatin1String(
"!_P_!" ) && str2 != QLatin1String(
"!_P_!" ) ) {
164 result.replace( fpos, 2, QLatin1String(
", " ) );
166 result.remove( fpos, 2 );
168 fpos = result.indexOf( KABC_FMTTAG_condcomma, fpos );
171 fpos = result.indexOf( KABC_FMTTAG_condwhite, 0 );
172 while ( -1 != fpos ) {
173 const QString str1 = result.mid( fpos - 5, 5 );
174 const QString str2 = result.mid( fpos + 2, 5 );
175 if ( str1 != QLatin1String(
"!_P_!" ) && str2 != QLatin1String(
"!_P_!" ) ) {
176 result.replace( fpos, 2, QLatin1String(
" " ) );
178 result.remove( fpos, 2 );
180 fpos = result.indexOf( KABC_FMTTAG_condwhite, fpos );
184 result.remove( QLatin1String(
"!_P_!" ) );
189 class Address::Private :
public QSharedData
193 : mEmpty( true ), mType( 0 )
195 mId = KRandom::randomString( 10 );
198 Private(
const Private &other )
199 : QSharedData( other )
201 mEmpty = other.mEmpty;
205 mPostOfficeBox = other.mPostOfficeBox;
206 mExtended = other.mExtended;
207 mStreet = other.mStreet;
208 mLocality = other.mLocality;
209 mRegion = other.mRegion;
210 mPostalCode = other.mPostalCode;
211 mCountry = other.mCountry;
212 mLabel = other.mLabel;
219 QString mPostOfficeBox;
251 if (
this != &other ) {
260 if ( d->mId != other.d->mId ) {
263 if ( d->mType != other.d->mType ) {
266 if ( d->mPostOfficeBox != other.d->mPostOfficeBox ) {
269 if ( d->mExtended != other.d->mExtended ) {
272 if ( d->mStreet != other.d->mStreet ) {
275 if ( d->mLocality != other.d->mLocality ) {
278 if ( d->mRegion != other.d->mRegion ) {
281 if ( d->mPostalCode != other.d->mPostalCode ) {
284 if ( d->mCountry != other.d->mCountry ) {
287 if ( d->mLabel != other.d->mLabel ) {
296 return !( a == *this );
338 TypeList::ConstIterator it;
339 for ( it = list.begin(); it != list.end(); ++it ) {
340 if ( (
type() & ( *it ) ) && ( ( *it ) !=
Pref ) ) {
342 label.append( QLatin1Char(
'/' ) );
362 return d->mPostOfficeBox;
367 return i18n(
"Post Office Box" );
383 return i18n(
"Extended Address Information" );
399 return i18n(
"Street" );
415 return i18n(
"Locality" );
431 return i18n(
"Region" );
442 return d->mPostalCode;
447 return i18n(
"Postal Code" );
463 return i18n(
"Country" );
479 return i18n(
"Delivery Label" );
486 if ( list.isEmpty() ) {
496 return i18nc(
"Preferred address",
"Preferred" );
501 return i18nc(
"Address is in home country",
"Domestic" );
504 return i18nc(
"Address is not in home country",
"International" );
507 return i18nc(
"Address for delivering letters",
"Postal" );
510 return i18nc(
"Address for delivering packages",
"Parcel" );
513 return i18nc(
"Home Address",
"Home" );
516 return i18nc(
"Work Address",
"Work" );
519 return i18n(
"Preferred Address" );
522 return i18nc(
"another type of address",
"Other" );
531 str += QLatin1String(
"Address {\n" );
532 str += QString::fromLatin1(
" IsEmpty: %1\n" ).
533 arg( d->mEmpty ? QLatin1String(
"true" ) : QLatin1String(
"false" ) );
534 str += QString::fromLatin1(
" Id: %1\n" ).arg( d->mId );
535 str += QString::fromLatin1(
" Type: %1\n" ).arg(
typeLabel( d->mType ) );
536 str += QString::fromLatin1(
" Post office box: %1\n" ).arg( d->mPostOfficeBox );
537 str += QString::fromLatin1(
" Extended: %1\n" ).arg( d->mExtended );
538 str += QString::fromLatin1(
" Street: %1\n" ).arg( d->mStreet );
539 str += QString::fromLatin1(
" Locality: %1\n" ).arg( d->mLocality );
540 str += QString::fromLatin1(
" Region: %1\n" ).arg( d->mRegion );
541 str += QString::fromLatin1(
" Postal code: %1\n" ).arg( d->mPostalCode );
542 str += QString::fromLatin1(
" Country: %1\n" ).arg( d->mCountry );
543 str += QString::fromLatin1(
" Label: %1\n" ).arg( d->mLabel );
544 str += QLatin1String(
"}\n" );
550 const QString &orgaName )
const
553 QString addrTemplate;
561 ciso = KGlobal::locale()->country();
563 KConfig entry( KStandardDirs::locate(
"locale",
564 QLatin1String(
"l10n/" ) + ciso + QLatin1String(
"/entry.desktop" ) ) );
566 KConfigGroup group = entry.group(
"KCM Locale" );
568 if ( orgaName.isEmpty() ) {
569 addrTemplate = group.readEntry(
"AddressFormat" );
571 addrTemplate = group.readEntry(
"BusinessAddressFormat" );
572 if ( addrTemplate.isEmpty() ) {
573 addrTemplate = group.readEntry(
"AddressFormat" );
579 if ( addrTemplate.isEmpty() ) {
580 kWarning( 5700 ) <<
"address format database incomplete"
581 <<
"(no format for locale" << ciso
582 <<
"found). Using default address formatting.";
583 addrTemplate = QLatin1String(
"%0(%n\\n)%0(%cm\\n)%0(%s\\n)%0(PO BOX %p\\n)%0(%l%w%r)%,%z" );
587 parseAddressTemplateSection( addrTemplate, ret, realName, orgaName, *
this );
592 KConfig entry( KStandardDirs::locate(
"locale", QLatin1String(
"l10n/" ) +
594 QLatin1String(
"/entry.desktop" ) ) );
595 KConfigGroup group = entry.group(
"KCM Locale" );
596 QString cpos = group.readEntry(
"AddressCountryPosition" );
597 if ( QLatin1String(
"BELOW" ) == cpos || cpos.isEmpty() ) {
598 ret = ret + QLatin1String(
"\n\n" ) +
country().toUpper();
599 }
else if ( QLatin1String(
"below" ) == cpos ) {
600 ret = ret + QLatin1String(
"\n\n" ) +
country();
601 }
else if ( QLatin1String(
"ABOVE" ) == cpos ) {
602 ret =
country().toUpper() + QLatin1String(
"\n\n" ) + ret;
603 }
else if ( QLatin1String(
"above" ) == cpos ) {
604 ret =
country() + QLatin1String(
"\n\n" ) + ret;
616 typedef QMap<QString, QString> stringMap;
617 K_GLOBAL_STATIC( stringMap, sISOMap )
619 QMap<QString, QString>::ConstIterator it;
620 it = sISOMap->constFind( cname );
621 if ( it != sISOMap->constEnd() ) {
625 QString mapfile = KGlobal::dirs()->findResource(
"data",
626 QLatin1String(
"kabc/countrytransl.map" ) );
628 QFile file( mapfile );
629 if ( file.open( QIODevice::ReadOnly ) ) {
630 QTextStream s( &file );
631 QString strbuf = s.readLine();
632 while ( !strbuf.isEmpty() ) {
633 QStringList countryInfo = strbuf.split( QLatin1Char(
'\t' ), QString::KeepEmptyParts );
634 if ( countryInfo[ 0 ] == cname ) {
636 sISOMap->insert( cname, countryInfo[ 1 ] );
637 return countryInfo[ 1 ];
639 strbuf = s.readLine();
645 sISOMap->insert( cname, KGlobal::locale()->
country() );
646 return KGlobal::locale()->country();
652 if ( ISOname.simplified().isEmpty() ) {
656 QString mapfile = KGlobal::dirs()->findResource(
"data",
657 QLatin1String(
"kabc/countrytransl.map" ) );
659 QFile file( mapfile );
660 if ( file.open( QIODevice::ReadOnly ) ) {
661 QTextStream s( &file );
662 QString searchStr = QLatin1Char(
'\t' ) + ISOname.simplified().toLower();
663 QString strbuf = s.readLine();
665 while ( !strbuf.isEmpty() ) {
666 if ( ( pos = strbuf.indexOf( searchStr ) ) != -1 ) {
668 return i18n( strbuf.left( pos ).toUtf8() );
670 strbuf = s.readLine();
678 QDataStream &KABC::operator<<( QDataStream &s,
const Address &addr )
680 return s << addr.d->mId << (uint)addr.d->mType << addr.d->mPostOfficeBox
681 << addr.d->mExtended << addr.d->mStreet << addr.d->mLocality
682 << addr.d->mRegion << addr.d->mPostalCode << addr.d->mCountry
683 << addr.d->mLabel << addr.d->mEmpty;
686 QDataStream &KABC::operator>>( QDataStream &s,
Address &addr )
689 s >> addr.d->mId >> type >> addr.d->mPostOfficeBox >> addr.d->mExtended
690 >> addr.d->mStreet >> addr.d->mLocality >> addr.d->mRegion
691 >> addr.d->mPostalCode >> addr.d->mCountry >> addr.d->mLabel
694 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.