libkdepim

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