00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
#include "address.h"
00022
00023
#include <kapplication.h>
00024
#include <kdebug.h>
00025
#include <klocale.h>
00026
#include <ksimpleconfig.h>
00027
#include <kstandarddirs.h>
00028
#include <kstaticdeleter.h>
00029
00030
#include <qfile.h>
00031
00032
using namespace KABC;
00033
00034
QMap<QString, QString> *Address::mISOMap = 0;
00035
static KStaticDeleter< QMap<QString, QString> > isoMapDeleter;
00036
00037 Address::Address() :
00038 mEmpty( true ), mType( 0 )
00039 {
00040 mId = KApplication::randomString( 10 );
00041 }
00042
00043 Address::Address(
int type ) :
00044 mEmpty( true ), mType( type )
00045 {
00046 mId = KApplication::randomString( 10 );
00047 }
00048
00049
bool Address::operator==(
const Address &a )
const
00050
{
00051
if ( mPostOfficeBox != a.
mPostOfficeBox )
return false;
00052
if ( mExtended != a.
mExtended )
return false;
00053
if ( mStreet != a.
mStreet )
return false;
00054
if ( mLocality != a.
mLocality )
return false;
00055
if ( mRegion != a.
mRegion )
return false;
00056
if ( mPostalCode != a.
mPostalCode )
return false;
00057
if ( mCountry != a.
mCountry )
return false;
00058
if ( mLabel != a.
mLabel )
return false;
00059
00060
return true;
00061 }
00062
00063
bool Address::operator!=(
const Address &a )
const
00064
{
00065
return !( a == *
this );
00066 }
00067
00068 bool Address::isEmpty()
const
00069
{
00070
if ( mPostOfficeBox.
isEmpty() &&
00071 mExtended.
isEmpty() &&
00072 mStreet.
isEmpty() &&
00073 mLocality.
isEmpty() &&
00074 mRegion.
isEmpty() &&
00075 mPostalCode.
isEmpty() &&
00076 mCountry.
isEmpty() &&
00077 mLabel.
isEmpty() ) {
00078
return true;
00079 }
00080
return false;
00081 }
00082
00083 void Address::clear()
00084 {
00085 *
this =
Address();
00086 }
00087
00088 void Address::setId(
const QString &
id )
00089 {
00090 mEmpty =
false;
00091
00092 mId =
id;
00093 }
00094
00095
QString Address::id()
const
00096
{
00097
return mId;
00098 }
00099
00100 void Address::setType(
int type )
00101 {
00102 mEmpty =
false;
00103
00104 mType = type;
00105 }
00106
00107 int Address::type()
const
00108
{
00109
return mType;
00110 }
00111
00112 QString Address::typeLabel()
const
00113
{
00114
QString label;
00115
bool first =
true;
00116
00117
const TypeList list =
typeList();
00118
00119 TypeList::ConstIterator it;
00120
for ( it = list.
begin(); it != list.
end(); ++it ) {
00121
if ( (
type() & (*it) ) && ( (*it) != Pref ) ) {
00122 label.
append( ( first ?
"" :
"/" ) +
typeLabel( *it ) );
00123
if ( first )
00124 first =
false;
00125 }
00126 }
00127
00128
return label;
00129 }
00130
00131 void Address::setPostOfficeBox(
const QString &s )
00132 {
00133 mEmpty =
false;
00134
00135 mPostOfficeBox = s;
00136 }
00137
00138 QString Address::postOfficeBox()
const
00139
{
00140
return mPostOfficeBox;
00141 }
00142
00143 QString Address::postOfficeBoxLabel()
00144 {
00145
return i18n(
"Post Office Box");
00146 }
00147
00148
00149 void Address::setExtended(
const QString &s )
00150 {
00151 mEmpty =
false;
00152
00153 mExtended = s;
00154 }
00155
00156 QString Address::extended()
const
00157
{
00158
return mExtended;
00159 }
00160
00161 QString Address::extendedLabel()
00162 {
00163
return i18n(
"Extended Address Information");
00164 }
00165
00166
00167 void Address::setStreet(
const QString &s )
00168 {
00169 mEmpty =
false;
00170
00171 mStreet = s;
00172 }
00173
00174 QString Address::street()
const
00175
{
00176
return mStreet;
00177 }
00178
00179 QString Address::streetLabel()
00180 {
00181
return i18n(
"Street");
00182 }
00183
00184
00185 void Address::setLocality(
const QString &s )
00186 {
00187 mEmpty =
false;
00188
00189 mLocality = s;
00190 }
00191
00192 QString Address::locality()
const
00193
{
00194
return mLocality;
00195 }
00196
00197 QString Address::localityLabel()
00198 {
00199
return i18n(
"Locality");
00200 }
00201
00202
00203 void Address::setRegion(
const QString &s )
00204 {
00205 mEmpty =
false;
00206
00207 mRegion = s;
00208 }
00209
00210 QString Address::region()
const
00211
{
00212
return mRegion;
00213 }
00214
00215 QString Address::regionLabel()
00216 {
00217
return i18n(
"Region");
00218 }
00219
00220
00221 void Address::setPostalCode(
const QString &s )
00222 {
00223 mEmpty =
false;
00224
00225 mPostalCode = s;
00226 }
00227
00228 QString Address::postalCode()
const
00229
{
00230
return mPostalCode;
00231 }
00232
00233 QString Address::postalCodeLabel()
00234 {
00235
return i18n(
"Postal Code");
00236 }
00237
00238
00239 void Address::setCountry(
const QString &s )
00240 {
00241 mEmpty =
false;
00242
00243 mCountry = s;
00244 }
00245
00246 QString Address::country()
const
00247
{
00248
return mCountry;
00249 }
00250
00251 QString Address::countryLabel()
00252 {
00253
return i18n(
"Country");
00254 }
00255
00256
00257 void Address::setLabel(
const QString &s )
00258 {
00259 mEmpty =
false;
00260
00261 mLabel = s;
00262 }
00263
00264 QString Address::label()
const
00265
{
00266
return mLabel;
00267 }
00268
00269 QString Address::labelLabel()
00270 {
00271
return i18n(
"Delivery Label");
00272 }
00273
00274 Address::TypeList Address::typeList()
00275 {
00276
static TypeList list;
00277
00278
if ( list.
isEmpty() )
00279 list << Dom << Intl << Postal << Parcel << Home << Work << Pref;
00280
00281
return list;
00282 }
00283
00284 QString Address::typeLabel(
int type )
00285 {
00286
if ( type & Pref )
00287
return i18n(
"Preferred address",
"Preferred" );
00288
00289
switch ( type ) {
00290
case Dom:
00291
return i18n(
"Domestic");
00292
break;
00293
case Intl:
00294
return i18n(
"International");
00295
break;
00296
case Postal:
00297
return i18n(
"Postal");
00298
break;
00299
case Parcel:
00300
return i18n(
"Parcel");
00301
break;
00302
case Home:
00303
return i18n(
"Home Address",
"Home");
00304
break;
00305
case Work:
00306
return i18n(
"Work Address",
"Work");
00307
break;
00308
case Pref:
00309
return i18n(
"Preferred Address");
00310
break;
00311
default:
00312
return i18n(
"Other");
00313
break;
00314 }
00315 }
00316
00317 void Address::dump()
const
00318
{
00319
kdDebug(5700) <<
" Address {" <<
endl;
00320
kdDebug(5700) <<
" Id: " << id() <<
endl;
00321
kdDebug(5700) <<
" Extended: " <<
extended() <<
endl;
00322
kdDebug(5700) <<
" Street: " <<
street() <<
endl;
00323
kdDebug(5700) <<
" Postal Code: " <<
postalCode() <<
endl;
00324
kdDebug(5700) <<
" Locality: " <<
locality() <<
endl;
00325
kdDebug(5700) <<
" }" <<
endl;
00326 }
00327
00328
00329 QString Address::formattedAddress(
const QString &realName,
00330
const QString &orgaName )
const
00331
{
00332
QString ciso;
00333
QString addrTemplate;
00334
QString ret;
00335
00336
00337
if ( !
country().
isEmpty() ) {
00338 ciso =
countryToISO(
country() );
00339 }
else {
00340
00341 ciso =
KGlobal::locale()->
country();
00342 }
00343
KSimpleConfig entry(
locate(
"locale",
00344
QString(
"l10n/" ) + ciso +
QString(
"/entry.desktop" ) ) );
00345 entry.
setGroup(
"KCM Locale" );
00346
00347
00348
if ( orgaName.
isNull() ) {
00349 addrTemplate = entry.
readEntry(
"AddressFormat" );
00350 }
else {
00351 addrTemplate = entry.
readEntry(
"BusinessAddressFormat" );
00352
if ( addrTemplate.
isEmpty() )
00353 addrTemplate = entry.
readEntry(
"AddressFormat" );
00354 }
00355
00356
00357
00358
if ( addrTemplate.
isEmpty() ) {
00359
kdWarning(5700) <<
"address format database incomplete "
00360 <<
"(no format for locale " << ciso
00361 <<
" found). Using default address formatting." <<
endl;
00362 addrTemplate =
"%0(%n\\n)%0(%cm\\n)%0(%s\\n)%0(PO BOX %p\\n)%0(%l%w%r)%,%z";
00363 }
00364
00365
00366 parseAddressTemplateSection( addrTemplate, ret, realName, orgaName );
00367
00368
00369
00370
if ( !
country().
isEmpty() ) {
00371
KSimpleConfig entry(
locate(
"locale",
QString(
"l10n/" )
00372 + KGlobal::locale()->
country() +
QString(
"/entry.desktop" ) ) );
00373 entry.
setGroup(
"KCM Locale" );
00374
QString cpos = entry.
readEntry(
"AddressCountryPosition" );
00375
if (
"BELOW" == cpos || cpos.
isEmpty() ) {
00376 ret = ret +
"\n\n" +
country().
upper();
00377 }
else if (
"below" == cpos ) {
00378 ret = ret +
"\n\n" +
country();
00379 }
else if (
"ABOVE" == cpos ) {
00380 ret =
country().
upper() +
"\n\n" + ret;
00381 }
else if (
"above" == cpos ) {
00382 ret =
country() +
"\n\n" + ret;
00383 }
00384 }
00385
00386
return ret;
00387 }
00388
00389
bool Address::parseAddressTemplateSection(
const QString &tsection,
00390
QString &result,
const QString &realName,
const QString &orgaName )
const
00391
{
00392
00393
00394
00395
00396
00397 result = tsection;
00398
int stpos = 0;
00399
bool ret =
false;
00400
00401
00402
int fpos = result.
find( KABC_FMTTAG_purgeempty, stpos );
00403
while ( -1 != fpos ) {
00404
int bpos1 = fpos + KABC_FMTTAG_purgeempty.length();
00405
int bpos2;
00406
00407
00408
if (
'(' == result[bpos1] ) {
00409 bpos2 = findBalancedBracket( result, bpos1 );
00410
if ( -1 != bpos2 ) {
00411
00412
QString rplstr;
00413
bool purge = !parseAddressTemplateSection( result.
mid( bpos1+1,
00414 bpos2-bpos1-1 ), rplstr,
00415 realName, orgaName );
00416
if ( purge ) {
00417
00418
00419 result.
replace( fpos, bpos2 - fpos + 1,
"!_P_!" );
00420
00421 }
else {
00422
00423 result.
replace( fpos, bpos2 - fpos + 1, rplstr );
00424 ret =
true;
00425 stpos = fpos + rplstr.
length();
00426 }
00427 }
else {
00428
00429
00430 stpos = bpos1;
00431 }
00432 }
00433 fpos = result.
find( KABC_FMTTAG_purgeempty, stpos );
00434 }
00435
00436
00437
00438
00439
00440
#define REPLTAG(R_TAG,R_FIELD) \
00441
if ( result.find(R_TAG, false) != -1 ) { \
00442
QString rpl = R_FIELD.isEmpty() ? QString("!_P_!") : R_FIELD; \
00443
result.replace( R_TAG, rpl ); \
00444
if ( !R_FIELD.isEmpty() ) { \
00445
ret = true; \
00446
} \
00447
}
00448
REPLTAG( KABC_FMTTAG_realname, realName );
00449 REPLTAG( KABC_FMTTAG_REALNAME, realName.
upper() );
00450 REPLTAG( KABC_FMTTAG_company, orgaName );
00451 REPLTAG( KABC_FMTTAG_COMPANY, orgaName.
upper() );
00452 REPLTAG( KABC_FMTTAG_pobox,
postOfficeBox() );
00453 REPLTAG( KABC_FMTTAG_street,
street() );
00454 REPLTAG( KABC_FMTTAG_STREET,
street().upper() );
00455 REPLTAG( KABC_FMTTAG_zipcode,
postalCode() );
00456 REPLTAG( KABC_FMTTAG_location,
locality() );
00457 REPLTAG( KABC_FMTTAG_LOCATION,
locality().upper() );
00458 REPLTAG( KABC_FMTTAG_region,
region() );
00459 REPLTAG( KABC_FMTTAG_REGION,
region().upper() );
00460 result.
replace( KABC_FMTTAG_newline,
"\n" );
00461
#undef REPLTAG
00462
00463
00464 fpos = result.
find( KABC_FMTTAG_condcomma, 0 );
00465
while ( -1 != fpos ) {
00466
QString str1 = result.
mid( fpos - 5, 5 );
00467
QString str2 = result.
mid( fpos + 2, 5 );
00468
if ( str1 !=
"!_P_!" && str2 !=
"!_P_!" ) {
00469 result.
replace( fpos, 2,
", " );
00470 }
else {
00471 result.
remove( fpos, 2 );
00472 }
00473 fpos = result.
find( KABC_FMTTAG_condcomma, fpos );
00474 }
00475
00476 fpos = result.
find( KABC_FMTTAG_condwhite, 0 );
00477
while ( -1 != fpos ) {
00478
QString str1 = result.
mid( fpos - 5, 5 );
00479
QString str2 = result.
mid( fpos + 2, 5 );
00480
if ( str1 !=
"!_P_!" && str2 !=
"!_P_!" ) {
00481 result.
replace( fpos, 2,
" " );
00482 }
else {
00483 result.
remove( fpos, 2 );
00484 }
00485 fpos = result.
find( KABC_FMTTAG_condwhite, fpos );
00486 }
00487
00488
00489 result.
remove(
"!_P_!" );
00490
00491
return ret;
00492 }
00493
00494
int Address::findBalancedBracket(
const QString &tsection,
int pos )
const
00495
{
00496
int balancecounter = 0;
00497
for(
unsigned int i = pos + 1; i < tsection.
length(); i++ ) {
00498
if (
')' == tsection[i] && 0 == balancecounter ) {
00499
00500
return i;
00501 }
else
00502
if (
'(' == tsection[i] ) {
00503
00504 balancecounter++;
00505 }
00506 }
00507
return -1;
00508 }
00509
00510 QString Address::countryToISO(
const QString &cname )
00511 {
00512
00513
00514
00515
if ( !mISOMap )
00516 isoMapDeleter.setObject( mISOMap,
new QMap<QString, QString>() );
00517
00518 QMap<QString, QString>::ConstIterator it;
00519 it = mISOMap->
find( cname );
00520
if ( it != mISOMap->
end() )
00521
return it.data();
00522
00523
QString mapfile =
KGlobal::dirs()->
findResource(
"data",
00524 QString::fromLatin1(
"kabc/countrytransl.map" ) );
00525
00526
QFile file( mapfile );
00527
if ( file.
open( IO_ReadOnly ) ) {
00528
QTextStream s( &file );
00529
QString strbuf = s.
readLine();
00530
while( !strbuf.
isNull() ) {
00531
QStringList countryInfo = QStringList::split(
'\t', strbuf,
true );
00532
if ( countryInfo[ 0 ] == cname ) {
00533 file.
close();
00534 mISOMap->
insert( cname, countryInfo[ 1 ] );
00535
return countryInfo[ 1 ];
00536 }
00537 strbuf = s.
readLine();
00538 }
00539 file.
close();
00540 }
00541
00542
00543 mISOMap->
insert( cname, KGlobal::locale()->
country() );
00544
return KGlobal::locale()->
country();
00545 }
00546
00547 QString Address::ISOtoCountry(
const QString &ISOname )
00548 {
00549
00550
if ( ISOname.
simplifyWhiteSpace().isEmpty() )
00551
return QString::null;
00552
00553
QString mapfile =
KGlobal::dirs()->
findResource(
"data",
00554 QString::fromLatin1(
"kabc/countrytransl.map" ) );
00555
00556
QFile file( mapfile );
00557
if ( file.
open( IO_ReadOnly ) ) {
00558
QTextStream s( &file );
00559
QString searchStr =
"\t" + ISOname.
simplifyWhiteSpace().lower();
00560
QString strbuf = s.
readLine();
00561
int pos;
00562
while ( !strbuf.
isNull() ) {
00563
if ( (pos = strbuf.
find( searchStr )) != -1 ) {
00564 file.
close();
00565
return i18n( strbuf.
left( pos ).utf8() );
00566 }
00567 strbuf = s.
readLine();
00568 }
00569 file.
close();
00570 }
00571
00572
return ISOname;
00573 }
00574
00575
QDataStream &KABC::operator<<(
QDataStream &s,
const Address &addr )
00576 {
00577
return s << addr.
mId << addr.
mType << addr.
mPostOfficeBox <<
00578 addr.
mExtended << addr.
mStreet << addr.
mLocality <<
00579 addr.
mRegion << addr.
mPostalCode << addr.
mCountry <<
00580 addr.
mLabel;
00581 }
00582
00583
QDataStream &KABC::operator>>(
QDataStream &s,
Address &addr )
00584 {
00585 s >> addr.
mId >> addr.
mType >> addr.
mPostOfficeBox >> addr.
mExtended >>
00586 addr.
mStreet >> addr.
mLocality >> addr.
mRegion >>
00587 addr.
mPostalCode >> addr.
mCountry >> addr.
mLabel;
00588
00589 addr.
mEmpty =
false;
00590
00591
return s;
00592 }