addresseeview.cpp
00001 /* 00002 This file is part of libkdepim. 00003 00004 Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> 00005 00006 This library is free software; you can redistribute it and/or 00007 modify it under the terms of the GNU Library General Public 00008 License as published by the Free Software Foundation; either 00009 version 2 of the License, or (at your option) any later version. 00010 00011 This library is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 Library General Public License for more details. 00015 00016 You should have received a copy of the GNU Library General Public License 00017 along with this library; see the file COPYING.LIB. If not, write to 00018 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00019 Boston, MA 02110-1301, USA. 00020 */ 00021 00022 #include <tqbuffer.h> 00023 #include <tqimage.h> 00024 #include <tqpopupmenu.h> 00025 #include <tqurl.h> 00026 00027 #include <kabc/address.h> 00028 #include <kabc/addressee.h> 00029 #include <kabc/phonenumber.h> 00030 #include <kabc/resource.h> 00031 #include <kactionclasses.h> 00032 #include <kapplication.h> 00033 #include <kconfig.h> 00034 #include <kglobal.h> 00035 #include <kglobalsettings.h> 00036 #include <kiconloader.h> 00037 #include <kio/job.h> 00038 #include <klocale.h> 00039 #include <kmdcodec.h> 00040 #include <kmessagebox.h> 00041 #include <krun.h> 00042 #include <kstringhandler.h> 00043 #include <ktempfile.h> 00044 00045 #include <kdebug.h> 00046 00047 #include "addresseeview.h" 00048 #include "sendsmsdialog.h" 00049 #include "resourceabc.h" 00050 00051 using namespace KPIM; 00052 00053 AddresseeView::AddresseeView( TQWidget *parent, const char *name, 00054 KConfig *config ) 00055 : KTextBrowser( parent, name ), mDefaultConfig( false ), mImageJob( 0 ), 00056 mLinkMask( AddressLinks | EmailLinks | PhoneLinks | URLLinks | IMLinks | CustomFields ) 00057 { 00058 setWrapPolicy( TQTextEdit::AtWordBoundary ); 00059 setLinkUnderline( false ); 00060 setVScrollBarMode( TQScrollView::AlwaysOff ); 00061 setHScrollBarMode( TQScrollView::AlwaysOff ); 00062 00063 TQStyleSheet *sheet = styleSheet(); 00064 TQStyleSheetItem *link = sheet->item( "a" ); 00065 link->setColor( KGlobalSettings::linkColor() ); 00066 00067 connect( this, TQT_SIGNAL( mailClick( const TQString&, const TQString& ) ), 00068 this, TQT_SLOT( slotMailClicked( const TQString&, const TQString& ) ) ); 00069 connect( this, TQT_SIGNAL( urlClick( const TQString& ) ), 00070 this, TQT_SLOT( slotUrlClicked( const TQString& ) ) ); 00071 connect( this, TQT_SIGNAL( highlighted( const TQString& ) ), 00072 this, TQT_SLOT( slotHighlighted( const TQString& ) ) ); 00073 00074 setNotifyClick( true ); 00075 00076 mActionShowBirthday = new KToggleAction( i18n( "Show Birthday" ) ); 00077 mActionShowBirthday->setCheckedState( i18n( "Hide Birthday" ) ); 00078 mActionShowAddresses = new KToggleAction( i18n( "Show Postal Addresses" ) ); 00079 mActionShowAddresses->setCheckedState( i18n( "Hide Postal Addresses" ) ); 00080 mActionShowEmails = new KToggleAction( i18n( "Show Email Addresses" ) ); 00081 mActionShowEmails->setCheckedState( i18n( "Hide Email Addresses" ) ); 00082 mActionShowPhones = new KToggleAction( i18n( "Show Telephone Numbers" ) ); 00083 mActionShowPhones->setCheckedState( i18n( "Hide Telephone Numbers" ) ); 00084 mActionShowURLs = new KToggleAction( i18n( "Show Web Pages (URLs)" ) ); 00085 mActionShowURLs->setCheckedState( i18n( "Hide Web Pages (URLs)" ) ); 00086 mActionShowIMAddresses = new KToggleAction( i18n( "Show Instant Messaging Addresses" ) ); 00087 mActionShowIMAddresses->setCheckedState( i18n( "Hide Instant Messaging Addresses" ) ); 00088 mActionShowCustomFields = new KToggleAction( i18n( "Show Custom Fields" ) ); 00089 mActionShowCustomFields->setCheckedState( i18n( "Hide Custom Fields" ) ); 00090 00091 connect( mActionShowBirthday, TQT_SIGNAL( toggled( bool ) ), TQT_SLOT( configChanged() ) ); 00092 connect( mActionShowAddresses, TQT_SIGNAL( toggled( bool ) ), TQT_SLOT( configChanged() ) ); 00093 connect( mActionShowEmails, TQT_SIGNAL( toggled( bool ) ), TQT_SLOT( configChanged() ) ); 00094 connect( mActionShowPhones, TQT_SIGNAL( toggled( bool ) ), TQT_SLOT( configChanged() ) ); 00095 connect( mActionShowURLs, TQT_SIGNAL( toggled( bool ) ), TQT_SLOT( configChanged() ) ); 00096 connect( mActionShowIMAddresses, TQT_SIGNAL( toggled( bool ) ), TQT_SLOT( configChanged() ) ); 00097 connect( mActionShowCustomFields, TQT_SIGNAL( toggled( bool ) ), TQT_SLOT( configChanged() ) ); 00098 00099 if ( !config ) { 00100 mConfig = new KConfig( "kaddressbookrc" ); 00101 mDefaultConfig = true; 00102 } else 00103 mConfig = config; 00104 00105 load(); 00106 00107 // set up IMProxy to display contacts' IM presence and make connections to keep the display live 00108 mKIMProxy = ::KIMProxy::instance( kapp->dcopClient() ); 00109 connect( mKIMProxy, TQT_SIGNAL( sigContactPresenceChanged( const TQString& ) ), 00110 this, TQT_SLOT( slotPresenceChanged( const TQString& ) ) ); 00111 connect( mKIMProxy, TQT_SIGNAL( sigPresenceInfoExpired() ), 00112 this, TQT_SLOT( slotPresenceInfoExpired() ) ); 00113 } 00114 00115 AddresseeView::~AddresseeView() 00116 { 00117 if ( mDefaultConfig ) 00118 delete mConfig; 00119 mConfig = 0; 00120 00121 delete mActionShowBirthday; 00122 delete mActionShowAddresses; 00123 delete mActionShowEmails; 00124 delete mActionShowPhones; 00125 delete mActionShowURLs; 00126 delete mActionShowIMAddresses; 00127 delete mActionShowCustomFields; 00128 00129 mKIMProxy = 0; 00130 } 00131 00132 void AddresseeView::setAddressee( const KABC::Addressee& addr ) 00133 { 00134 mAddressee = addr; 00135 00136 if ( mImageJob ) { 00137 mImageJob->kill(); 00138 mImageJob = 0; 00139 } 00140 00141 mImageData.truncate( 0 ); 00142 00143 updateView(); 00144 } 00145 00146 void AddresseeView::enableLinks( int linkMask ) 00147 { 00148 mLinkMask = linkMask; 00149 } 00150 00151 TQString AddresseeView::vCardAsHTML( const KABC::Addressee& addr, ::KIMProxy *proxy, LinkMask linkMask, 00152 bool internalLoading, FieldMask fieldMask ) 00153 { 00154 TQString image = TQString( "contact_%1_image" ).arg( addr.uid() ); 00155 00156 // Style strings from Gentix; this is just an initial version. 00157 // 00158 // These will be substituted into various HTML strings with .arg(). 00159 // Search for @STYLE@ to find where. Note how we use %1 as a 00160 // placeholder where we fill in something else (in this case, 00161 // the global background color). 00162 // 00163 TQString backgroundColor = KGlobalSettings::alternateBackgroundColor().name(); 00164 TQString cellStyle = TQString::fromLatin1( 00165 "style=\"" 00166 "padding-right: 2px; " 00167 "border-right: #000 dashed 1px; " 00168 "background: %1;\"").arg(backgroundColor); 00169 TQString backgroundColor2 = KGlobalSettings::baseColor().name(); 00170 TQString cellStyle2 = TQString::fromLatin1( 00171 "style=\"" 00172 "padding-left: 2px; " 00173 "background: %1;\"").arg(backgroundColor2); 00174 TQString tableStyle = TQString::fromLatin1( 00175 "style=\"" 00176 "border: solid 1px; " 00177 "margin: 0em;\""); 00178 00179 // We'll be building a table to display the vCard in. 00180 // Each row of the table will be built using this string for its HTML. 00181 // 00182 TQString rowFmtStr = TQString::fromLatin1( 00183 "<tr>" 00184 "<td align=\"right\" valign=\"top\" width=\"30%\" "); // Tag unclosed 00185 rowFmtStr.append( cellStyle ); 00186 rowFmtStr.append( TQString::fromLatin1( 00187 ">" // Close tag 00188 "<b>%1</b>" 00189 "</td>" 00190 "<td align=\"left\" valign=\"top\" width=\"70%\" ") ); // Tag unclosed 00191 rowFmtStr.append( cellStyle2 ); 00192 rowFmtStr.append( TQString::fromLatin1( 00193 ">" // Close tag 00194 "%2" 00195 "</td>" 00196 "</tr>\n" 00197 ) ); 00198 00199 // Build the table's rows here 00200 TQString dynamicPart; 00201 00202 00203 if ( !internalLoading ) { 00204 KABC::Picture pic = addr.photo(); 00205 if ( pic.isIntern() && !pic.data().isNull() ) { 00206 image = pixmapAsDataUrl( pic.data() ); 00207 } else if ( !pic.url().isEmpty() ) { 00208 image = (pic.url().startsWith( "http://" ) || pic.url().startsWith( "https://" ) ? pic.url() : "http://" + pic.url()); 00209 } else { 00210 image = "file:" + KGlobal::iconLoader()->iconPath( "personal", KIcon::Desktop ); 00211 } 00212 } 00213 00214 if ( fieldMask & BirthdayFields ) { 00215 TQDate date = addr.birthday().date(); 00216 00217 if ( date.isValid() ) 00218 dynamicPart += rowFmtStr 00219 .arg( KABC::Addressee::birthdayLabel() ) 00220 .arg( KGlobal::locale()->formatDate( date, true ) ); 00221 } 00222 00223 if ( fieldMask & PhoneFields ) { 00224 KABC::PhoneNumber::List phones = addr.phoneNumbers(); 00225 KABC::PhoneNumber::List::ConstIterator phoneIt; 00226 for ( phoneIt = phones.begin(); phoneIt != phones.end(); ++phoneIt ) { 00227 TQString number = TQStyleSheet::escape( (*phoneIt).number() ); 00228 00229 TQString url; 00230 if ( (*phoneIt).type() & KABC::PhoneNumber::Fax ) 00231 url = TQString::fromLatin1( "fax:" ) + number; 00232 else 00233 url = TQString::fromLatin1( "phone:" ) + number; 00234 00235 if ( linkMask & PhoneLinks ) { 00236 TQString smsURL; 00237 if ( (*phoneIt).type() & KABC::PhoneNumber::Cell ) 00238 smsURL = TQString(" (<a href=\"sms:%1\">%2</a>)" ).arg( number ).arg( i18n( "SMS") ); 00239 00240 dynamicPart += rowFmtStr 00241 .arg( (*phoneIt).typeLabel().replace( " ", " " ) ) 00242 .arg( TQString::fromLatin1( "<a href=\"%1\">%2</a>%3" ).arg( url ).arg( number ).arg( smsURL ) ); 00243 } else { 00244 dynamicPart += rowFmtStr 00245 .arg( (*phoneIt).typeLabel().replace( " ", " " ) ) 00246 .arg( number ); 00247 } 00248 } 00249 } 00250 00251 if ( fieldMask & EmailFields ) { 00252 TQStringList emails = addr.emails(); 00253 TQStringList::ConstIterator emailIt; 00254 TQString type = i18n( "Email" ); 00255 for ( emailIt = emails.begin(); emailIt != emails.end(); ++emailIt ) { 00256 TQString fullEmail = addr.fullEmail( *emailIt ); 00257 TQUrl::encode( fullEmail ); 00258 00259 if ( linkMask & EmailLinks ) { 00260 dynamicPart += rowFmtStr.arg( type ) 00261 .arg( TQString::fromLatin1( "<a href=\"mailto:%1\">%2</a>" ) 00262 .arg( fullEmail, TQStyleSheet::escape( *emailIt ) ) ); 00263 } else { 00264 dynamicPart += rowFmtStr.arg( type ).arg( *emailIt ); 00265 } 00266 } 00267 } 00268 00269 if ( fieldMask & URLFields ) { 00270 if ( !addr.url().url().isEmpty() ) { 00271 TQString url; 00272 if ( linkMask & URLLinks ) { 00273 url = (addr.url().url().startsWith( "http://" ) || addr.url().url().startsWith( "https://" ) ? addr.url().prettyURL() : 00274 "http://" + addr.url().prettyURL()); 00275 url = KStringHandler::tagURLs( url ); 00276 } else { 00277 url = addr.url().prettyURL(); 00278 } 00279 dynamicPart += rowFmtStr.arg( i18n("Homepage") ).arg( url ); 00280 } 00281 00282 TQString blog = addr.custom( "KADDRESSBOOK", "BlogFeed" ); 00283 if ( !blog.isEmpty() ) { 00284 if ( linkMask & URLLinks ) { 00285 blog = KStringHandler::tagURLs( blog ); 00286 } 00287 dynamicPart += rowFmtStr.arg( i18n("Blog Feed") ).arg( blog ); 00288 } 00289 } 00290 00291 if ( fieldMask & AddressFields ) { 00292 KABC::Address::List addresses = addr.addresses(); 00293 KABC::Address::List::ConstIterator addrIt; 00294 for ( addrIt = addresses.begin(); addrIt != addresses.end(); ++addrIt ) { 00295 if ( (*addrIt).label().isEmpty() ) { 00296 TQString formattedAddress; 00297 00298 formattedAddress = TQStyleSheet::escape( (*addrIt).formattedAddress().stripWhiteSpace() ); 00299 formattedAddress = formattedAddress.replace( '\n', "<br>" ); 00300 00301 TQString link = "<a href=\"addr:" + (*addrIt).id() + "\">" + 00302 formattedAddress + "</a>"; 00303 00304 if ( linkMask & AddressLinks ) { 00305 dynamicPart += rowFmtStr 00306 .arg( KABC::Address::typeLabel( (*addrIt).type() ) ) 00307 .arg( link ); 00308 } else { 00309 dynamicPart += rowFmtStr 00310 .arg( KABC::Address::typeLabel( (*addrIt).type() ) ) 00311 .arg( formattedAddress ); 00312 } 00313 } else { 00314 TQString link = "<a href=\"addr:" + (*addrIt).id() + "\">" + 00315 (*addrIt).label().replace( '\n', "<br>" ) + "</a>"; 00316 00317 if ( linkMask & AddressLinks ) { 00318 dynamicPart += rowFmtStr 00319 .arg( KABC::Address::typeLabel( (*addrIt).type() ) ) 00320 .arg( link ); 00321 } else { 00322 dynamicPart += rowFmtStr 00323 .arg( KABC::Address::typeLabel( (*addrIt).type() ) ) 00324 .arg( (*addrIt).label().replace( '\n', "<br>" ) ); 00325 } 00326 } 00327 } 00328 } 00329 00330 TQString notes; 00331 if ( !addr.note().isEmpty() ) { 00332 // @STYLE@ - substitute the cell style in first, and append 00333 // the data afterwards (keeps us safe from possible % signs 00334 // in either one). 00335 notes = TQStyleSheet::escape( addr.note() ); 00336 notes = rowFmtStr.arg( i18n( "Notes" ) ).arg( notes.replace( '\n', "<br>" ) ) ; 00337 } 00338 00339 TQString customData; 00340 if ( fieldMask & CustomFields ) { 00341 static TQMap<TQString, TQString> titleMap; 00342 if ( titleMap.isEmpty() ) { 00343 titleMap.insert( "Department", i18n( "Department" ) ); 00344 titleMap.insert( "Profession", i18n( "Profession" ) ); 00345 titleMap.insert( "AssistantsName", i18n( "Assistant's Name" ) ); 00346 titleMap.insert( "ManagersName", i18n( "Manager's Name" ) ); 00347 titleMap.insert( "SpousesName", i18n( "Partner's Name" ) ); 00348 titleMap.insert( "Office", i18n( "Office" ) ); 00349 titleMap.insert( "Anniversary", i18n( "Anniversary" ) ); 00350 } 00351 00352 if ( !addr.customs().empty() ) { 00353 TQStringList customs = addr.customs(); 00354 TQStringList::Iterator it( customs.begin() ); 00355 const TQStringList::Iterator endIt( customs.end() ); 00356 for ( ; it != endIt; ++it ) { 00357 TQString customEntry = *it; 00358 if ( customEntry.startsWith ( "KADDRESSBOOK-" ) ) { 00359 customEntry.remove( "KADDRESSBOOK-X-" ); 00360 customEntry.remove( "KADDRESSBOOK-" ); 00361 00362 int pos = customEntry.find( ':' ); 00363 TQString key = customEntry.left( pos ); 00364 const TQString value = customEntry.mid( pos + 1 ); 00365 00366 // blog and im address is handled separated 00367 if ( key == "BlogFeed" || key == "IMAddress" ) 00368 continue; 00369 00370 const TQMap<TQString, TQString>::ConstIterator keyIt = titleMap.find( key ); 00371 if ( keyIt != titleMap.end() ) 00372 key = keyIt.data(); 00373 00374 customData += rowFmtStr.arg( key ).arg( TQStyleSheet::escape( value ) ) ; 00375 } 00376 } 00377 } 00378 } 00379 00380 TQString name( TQStyleSheet::escape( addr.realName() ) ); 00381 TQString role( TQStyleSheet::escape( addr.role() ) ); 00382 TQString organization( TQStyleSheet::escape( addr.organization() ) ); 00383 00384 if ( fieldMask & IMFields ) { 00385 00386 const TQString imAddress = addr.custom( "KADDRESSBOOK", "X-IMAddress" ); 00387 if ( !imAddress.isEmpty() ) { 00388 customData += rowFmtStr.arg( i18n( "IM Address" ) ).arg( TQStyleSheet::escape( imAddress ) ) ; 00389 } 00390 00391 if ( proxy ) { 00392 if ( proxy->isPresent( addr.uid() ) && proxy->presenceNumeric( addr.uid() ) > 0 ) { 00393 // set image source to either a TQMimeSourceFactory key or a data:/ URL 00394 TQString imgSrc; 00395 if ( internalLoading ) { 00396 imgSrc = TQString::fromLatin1( "im_status_%1_image").arg( addr.uid() ); 00397 TQMimeSourceFactory::defaultFactory()->setPixmap( imgSrc, proxy->presenceIcon( addr.uid() ) ); 00398 } else 00399 imgSrc = pixmapAsDataUrl( proxy->presenceIcon( addr.uid() ) ); 00400 00401 // make the status a link, if required 00402 TQString imStatus; 00403 if ( linkMask & IMLinks ) 00404 imStatus = TQString::fromLatin1( "<a href=\"im:\"><img src=\"%1\"> (%2)</a>" ); 00405 else 00406 imStatus = TQString::fromLatin1( "<img src=\"%1\"> (%2)" ); 00407 00408 // append our status to the rest of the dynamic part of the addressee 00409 dynamicPart += rowFmtStr 00410 .arg( i18n( "Presence" ) ) 00411 .arg( imStatus 00412 .arg( imgSrc ) 00413 .arg( proxy->presenceString( addr.uid() ) ) 00414 ); 00415 } 00416 } 00417 } 00418 00419 // @STYLE@ - construct the string by parts, substituting in 00420 // the styles first. There are lots of appends, but we need to 00421 // do it this way to avoid cases where the substituted string 00422 // contains %1 and the like. 00423 // 00424 TQString strAddr = TQString::fromLatin1( 00425 "<div align=\"center\">" 00426 "<table cellpadding=\"1\" cellspacing=\"0\" %1>" 00427 "<tr>").arg(tableStyle); 00428 00429 strAddr.append( TQString::fromLatin1( 00430 "<td align=\"right\" valign=\"top\" width=\"30%\" rowspan=\"3\" %2>") 00431 .arg( cellStyle ) ); 00432 strAddr.append( TQString::fromLatin1( 00433 "<img src=\"%1\" width=\"50\" vspace=\"1\">" // image 00434 "</td>") 00435 .arg( image ) ); 00436 strAddr.append( TQString::fromLatin1( 00437 "<td align=\"left\" width=\"70%\" %2>") 00438 .arg( cellStyle2 ) ); 00439 strAddr.append( TQString::fromLatin1( 00440 "<font size=\"+2\"><b>%2</b></font></td>" // name 00441 "</tr>") 00442 .arg( name ) ); 00443 strAddr.append( TQString::fromLatin1( 00444 "<tr>" 00445 "<td align=\"left\" width=\"70%\" %2>") 00446 .arg( cellStyle2 ) ); 00447 strAddr.append( TQString::fromLatin1( 00448 "%3</td>" // role 00449 "</tr>") 00450 .arg( role ) ); 00451 strAddr.append( TQString::fromLatin1( 00452 "<tr>" 00453 "<td align=\"left\" width=\"70%\" %2>") 00454 .arg( cellStyle2 ) ); 00455 strAddr.append( TQString::fromLatin1( 00456 "%4</td>" // organization 00457 "</tr>") 00458 .arg( organization ) ); 00459 strAddr.append( TQString::fromLatin1( 00460 "<tr><td %2>") 00461 .arg( cellStyle ) ); 00462 strAddr.append( TQString::fromLatin1( 00463 " </td><td %2> </td></tr>") 00464 .arg( cellStyle2 ) ); 00465 strAddr.append( dynamicPart ); 00466 strAddr.append( notes ); 00467 strAddr.append( customData ); 00468 strAddr.append( TQString::fromLatin1( "</table></div>\n" ) ); 00469 00470 if ( addr.resource() ) { 00471 TQString addrBookName = addr.resource()->resourceName(); 00472 ResourceABC *r = dynamic_cast<ResourceABC*>( addr.resource() ); 00473 if ( r && !r->subresources().isEmpty() ) { 00474 const TQString subRes = r->uidToResourceMap()[ addr.uid() ]; 00475 const TQString label = r->subresourceLabel( subRes ); 00476 if ( !label.isEmpty() ) 00477 addrBookName = label; 00478 } 00479 strAddr.append( i18n( "<p><b>Address book</b>: %1</p>" ).arg( addrBookName ) ); 00480 } 00481 return strAddr; 00482 } 00483 00484 TQString AddresseeView::pixmapAsDataUrl( const TQPixmap& pixmap ) 00485 { 00486 TQByteArray ba; 00487 TQBuffer buffer( ba ); 00488 buffer.open( IO_WriteOnly ); 00489 pixmap.save( &buffer, "PNG" ); 00490 TQString encoded( "data:image/png;base64," ); 00491 encoded.append( KCodecs::base64Encode( ba ) ); 00492 return encoded; 00493 } 00494 00495 void AddresseeView::updateView() 00496 { 00497 // clear view 00498 setText( TQString() ); 00499 00500 if ( mAddressee.isEmpty() ) 00501 return; 00502 00503 if ( mImageJob ) { 00504 mImageJob->kill(); 00505 mImageJob = 0; 00506 00507 mImageData.truncate( 0 ); 00508 } 00509 00510 int fieldMask = NoFields; 00511 if ( mActionShowBirthday->isChecked() ) 00512 fieldMask |= ( FieldMask )BirthdayFields; 00513 if ( mActionShowAddresses->isChecked() ) 00514 fieldMask |= AddressFields; 00515 if ( mActionShowEmails->isChecked() ) 00516 fieldMask |= EmailFields; 00517 if ( mActionShowPhones->isChecked() ) 00518 fieldMask |= PhoneFields; 00519 if ( mActionShowURLs->isChecked() ) 00520 fieldMask |= URLFields; 00521 if ( mActionShowIMAddresses->isChecked() ) 00522 fieldMask |= IMFields; 00523 if ( mActionShowCustomFields->isChecked() ) 00524 fieldMask |= CustomFields; 00525 00526 TQString strAddr = vCardAsHTML( mAddressee, mKIMProxy, (LinkMask)mLinkMask, 00527 true, (FieldMask)fieldMask ); 00528 00529 strAddr = TQString::fromLatin1( 00530 "<html>" 00531 "<body text=\"%1\" bgcolor=\"%2\">" // text and background color 00532 "%3" // dynamic part 00533 "</body>" 00534 "</html>" ) 00535 .arg( KGlobalSettings::textColor().name() ) 00536 .arg( KGlobalSettings::baseColor().name() ) 00537 .arg( strAddr ); 00538 00539 TQString imageURL = TQString( "contact_%1_image" ).arg( mAddressee.uid() ); 00540 00541 KABC::Picture picture = mAddressee.photo(); 00542 if ( picture.isIntern() && !picture.data().isNull() ) 00543 TQMimeSourceFactory::defaultFactory()->setImage( imageURL, picture.data() ); 00544 else { 00545 if ( !picture.url().isEmpty() ) { 00546 if ( mImageData.count() > 0 ) 00547 TQMimeSourceFactory::defaultFactory()->setImage( imageURL, TQImage(mImageData) ); 00548 else { 00549 mImageJob = KIO::get( KURL( picture.url() ), false, false ); 00550 connect( mImageJob, TQT_SIGNAL( data( KIO::Job*, const TQByteArray& ) ), 00551 this, TQT_SLOT( data( KIO::Job*, const TQByteArray& ) ) ); 00552 connect( mImageJob, TQT_SIGNAL( result( KIO::Job* ) ), 00553 this, TQT_SLOT( result( KIO::Job* ) ) ); 00554 } 00555 } else { 00556 TQMimeSourceFactory::defaultFactory()->setPixmap( imageURL, 00557 KGlobal::iconLoader()->loadIcon( "personal", KIcon::Desktop, 128 ) ); 00558 } 00559 } 00560 00561 // at last display it... 00562 setText( strAddr ); 00563 } 00564 00565 KABC::Addressee AddresseeView::addressee() const 00566 { 00567 return mAddressee; 00568 } 00569 00570 void AddresseeView::urlClicked( const TQString &url ) 00571 { 00572 kapp->invokeBrowser( url ); 00573 } 00574 00575 void AddresseeView::emailClicked( const TQString &email ) 00576 { 00577 if ( email.startsWith( "mailto:" ) ) 00578 kapp->invokeMailer( email.mid( 7 ), TQString() ); 00579 else 00580 kapp->invokeMailer( email, TQString() ); 00581 } 00582 00583 void AddresseeView::phoneNumberClicked( const TQString &number ) 00584 { 00585 KConfig config( "kaddressbookrc" ); 00586 config.setGroup( "General" ); 00587 TQString commandLine = config.readEntry( "PhoneHookApplication" ); 00588 00589 if ( commandLine.isEmpty() ) { 00590 KMessageBox::sorry( this, i18n( "There is no application set which could be executed. Please go to the settings dialog and configure one." ) ); 00591 return; 00592 } 00593 00594 commandLine.replace( "%N", number ); 00595 KRun::runCommand( commandLine ); 00596 } 00597 00598 void AddresseeView::smsTextClicked( const TQString &number ) 00599 { 00600 KConfig config( "kaddressbookrc" ); 00601 config.setGroup( "General" ); 00602 TQString commandLine = config.readEntry( "SMSHookApplication" ); 00603 00604 if ( commandLine.isEmpty() ) { 00605 KMessageBox::sorry( this, i18n( "There is no application set which could be executed. Please go to the settings dialog and configure one." ) ); 00606 return; 00607 } 00608 00609 SendSMSDialog dlg( mAddressee.realName(), this ); 00610 00611 if ( dlg.exec() ) 00612 sendSMS ( number, dlg.text() ); 00613 } 00614 00615 void AddresseeView::sendSMS( const TQString &number, const TQString &text ) 00616 { 00617 KConfig config( "kaddressbookrc" ); 00618 config.setGroup( "General" ); 00619 TQString commandLine = config.readEntry( "SMSHookApplication" ); 00620 00621 KTempFile file ; 00622 TQTextStream* stream = file.textStream(); 00623 *stream << text; 00624 file.close(); 00625 00626 commandLine.replace( "%N", number ); 00627 commandLine.replace( "%F", file.name() ); 00628 00629 KRun::runCommand( commandLine ); 00630 } 00631 00632 void AddresseeView::faxNumberClicked( const TQString &number ) 00633 { 00634 KConfig config( "kaddressbookrc" ); 00635 config.setGroup( "General" ); 00636 TQString commandLine = config.readEntry( "FaxHookApplication", "kdeprintfax --phone %N" ); 00637 00638 if ( commandLine.isEmpty() ) { 00639 KMessageBox::sorry( this, i18n( "There is no application set which could be executed. Please go to the settings dialog and configure one." ) ); 00640 return; 00641 } 00642 00643 commandLine.replace( "%N", number ); 00644 KRun::runCommand( commandLine ); 00645 } 00646 00647 void AddresseeView::imAddressClicked() 00648 { 00649 mKIMProxy->chatWithContact( mAddressee.uid() ); 00650 } 00651 00652 TQPopupMenu *AddresseeView::createPopupMenu( const TQPoint& ) 00653 { 00654 TQPopupMenu *menu = new TQPopupMenu( this ); 00655 mActionShowBirthday->plug( menu ); 00656 mActionShowAddresses->plug( menu ); 00657 mActionShowEmails->plug( menu ); 00658 mActionShowPhones->plug( menu ); 00659 mActionShowURLs->plug( menu ); 00660 mActionShowIMAddresses->plug( menu ); 00661 mActionShowCustomFields->plug( menu ); 00662 00663 return menu; 00664 } 00665 00666 void AddresseeView::slotMailClicked( const TQString&, const TQString &email ) 00667 { 00668 emailClicked( email ); 00669 } 00670 00671 void AddresseeView::slotUrlClicked( const TQString &url ) 00672 { 00673 if ( url.startsWith( "phone:" ) ) 00674 phoneNumberClicked( strippedNumber( url.mid( 8 ) ) ); 00675 else if ( url.startsWith( "sms:" ) ) 00676 smsTextClicked( strippedNumber( url.mid( 6 ) ) ); 00677 else if ( url.startsWith( "fax:" ) ) 00678 faxNumberClicked( strippedNumber( url.mid( 6 ) ) ); 00679 else if ( url.startsWith( "addr:" ) ) 00680 emit addressClicked( url.mid( 7 ) ); 00681 else if ( url.startsWith( "im:" ) ) 00682 imAddressClicked(); 00683 else 00684 urlClicked( url ); 00685 } 00686 00687 void AddresseeView::slotHighlighted( const TQString &link ) 00688 { 00689 if ( link.startsWith( "mailto:" ) ) { 00690 TQString email = link.mid( 7 ); 00691 00692 emit emailHighlighted( email ); 00693 emit highlightedMessage( i18n( "Send mail to '%1'" ).arg( email ) ); 00694 } else if ( link.startsWith( "phone:" ) ) { 00695 TQString number = link.mid( 8 ); 00696 00697 emit phoneNumberHighlighted( strippedNumber( number ) ); 00698 emit highlightedMessage( i18n( "Call number %1" ).arg( number ) ); 00699 } else if ( link.startsWith( "fax:" ) ) { 00700 TQString number = link.mid( 6 ); 00701 00702 emit faxNumberHighlighted( strippedNumber( number ) ); 00703 emit highlightedMessage( i18n( "Send fax to %1" ).arg( number ) ); 00704 } else if ( link.startsWith( "addr:" ) ) { 00705 emit highlightedMessage( i18n( "Show address on map" ) ); 00706 } else if ( link.startsWith( "sms:" ) ) { 00707 TQString number = link.mid( 6 ); 00708 emit highlightedMessage( i18n( "Send SMS to %1" ).arg( number ) ); 00709 } else if ( link.startsWith( "http:" ) || link.startsWith( "https:" ) ) { 00710 emit urlHighlighted( link ); 00711 emit highlightedMessage( i18n( "Open URL %1" ).arg( link ) ); 00712 } else if ( link.startsWith( "im:" ) ) { 00713 emit highlightedMessage( i18n( "Chat with %1" ).arg( mAddressee.realName() ) ); 00714 } else 00715 emit highlightedMessage( "" ); 00716 } 00717 00718 void AddresseeView::slotPresenceChanged( const TQString &uid ) 00719 { 00720 kdDebug() << k_funcinfo << " uid is: " << uid << " mAddressee is: " << mAddressee.uid() << endl; 00721 if ( uid == mAddressee.uid() ) 00722 updateView(); 00723 } 00724 00725 00726 void AddresseeView::slotPresenceInfoExpired() 00727 { 00728 updateView(); 00729 } 00730 00731 void AddresseeView::configChanged() 00732 { 00733 save(); 00734 updateView(); 00735 } 00736 00737 void AddresseeView::data( KIO::Job*, const TQByteArray &d ) 00738 { 00739 unsigned int oldSize = mImageData.size(); 00740 mImageData.resize( oldSize + d.size() ); 00741 memcpy( mImageData.data() + oldSize, d.data(), d.size() ); 00742 } 00743 00744 void AddresseeView::result( KIO::Job *job ) 00745 { 00746 mImageJob = 0; 00747 00748 if ( job->error() ) 00749 mImageData.truncate( 0 ); 00750 else 00751 updateView(); 00752 } 00753 00754 void AddresseeView::load() 00755 { 00756 mConfig->setGroup( "AddresseeViewSettings" ); 00757 mActionShowBirthday->setChecked( mConfig->readBoolEntry( "ShowBirthday", false ) ); 00758 mActionShowAddresses->setChecked( mConfig->readBoolEntry( "ShowAddresses", true ) ); 00759 mActionShowEmails->setChecked( mConfig->readBoolEntry( "ShowEmails", true ) ); 00760 mActionShowPhones->setChecked( mConfig->readBoolEntry( "ShowPhones", true ) ); 00761 mActionShowURLs->setChecked( mConfig->readBoolEntry( "ShowURLs", true ) ); 00762 mActionShowIMAddresses->setChecked( mConfig->readBoolEntry( "ShowIMAddresses", false ) ); 00763 mActionShowCustomFields->setChecked( mConfig->readBoolEntry( "ShowCustomFields", false ) ); 00764 } 00765 00766 void AddresseeView::save() 00767 { 00768 mConfig->setGroup( "AddresseeViewSettings" ); 00769 mConfig->writeEntry( "ShowBirthday", mActionShowBirthday->isChecked() ); 00770 mConfig->writeEntry( "ShowAddresses", mActionShowAddresses->isChecked() ); 00771 mConfig->writeEntry( "ShowEmails", mActionShowEmails->isChecked() ); 00772 mConfig->writeEntry( "ShowPhones", mActionShowPhones->isChecked() ); 00773 mConfig->writeEntry( "ShowURLs", mActionShowURLs->isChecked() ); 00774 mConfig->writeEntry( "ShowIMAddresses", mActionShowIMAddresses->isChecked() ); 00775 mConfig->writeEntry( "ShowCustomFields", mActionShowCustomFields->isChecked() ); 00776 mConfig->sync(); 00777 } 00778 00779 TQString AddresseeView::strippedNumber( const TQString &number ) 00780 { 00781 TQString retval; 00782 00783 for ( uint i = 0; i < number.length(); ++i ) { 00784 TQChar c = number[ i ]; 00785 if ( c.isDigit() || (((c == '*') || (c == '#') || (c == '+')) && (i == 0)) ) 00786 retval.append( c ); 00787 } 00788 00789 return retval; 00790 } 00791 00792 #include "addresseeview.moc"