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 );