00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "contactviewer.h"
00023
00024 #include "textbrowser_p.h"
00025
00026 #include <akonadi/item.h>
00027 #include <akonadi/itemfetchscope.h>
00028 #include <kabc/addressee.h>
00029 #include <kcolorscheme.h>
00030 #include <kglobal.h>
00031 #include <kicon.h>
00032 #include <klocale.h>
00033 #include <kstringhandler.h>
00034
00035 #include <QtGui/QVBoxLayout>
00036
00037 using namespace Akonadi;
00038
00039 static QString contactAsHtml( const KABC::Addressee &contact );
00040
00041 class ContactViewer::Private
00042 {
00043 public:
00044 Private( ContactViewer *parent )
00045 : mParent( parent )
00046 {
00047 }
00048
00049 void slotMailClicked( const QString&, const QString &email )
00050 {
00051 QString name, address;
00052
00053
00054 KABC::Addressee::parseEmailAddress( email.mid( 7 ), name, address );
00055
00056 emit mParent->emailClicked( name, address );
00057 }
00058
00059 void slotUrlClicked( const QString &urlString )
00060 {
00061 KUrl url( urlString );
00062
00063 if ( url.scheme() == QLatin1String( "http" ) ||
00064 url.scheme() == QLatin1String( "https" ) ) {
00065 emit mParent->urlClicked( url );
00066 } else if ( url.scheme() == QLatin1String( "phone" ) ) {
00067 const int pos = url.queryItemValue( QLatin1String( "index" ) ).toInt();
00068
00069 const KABC::PhoneNumber::List numbers = mCurrentContact.phoneNumbers();
00070 if ( pos < numbers.count() ) {
00071 emit mParent->phoneNumberClicked( numbers.at( pos ) );
00072 }
00073 } else if ( url.scheme() == QLatin1String( "address" ) ) {
00074 const int pos = url.queryItemValue( QLatin1String( "index" ) ).toInt();
00075
00076 const KABC::Address::List addresses = mCurrentContact.addresses();
00077 if ( pos < addresses.count() ) {
00078 emit mParent->addressClicked( addresses.at( pos ) );
00079 }
00080 }
00081 }
00082
00083 ContactViewer *mParent;
00084 TextBrowser *mBrowser;
00085 KABC::Addressee mCurrentContact;
00086 };
00087
00088 ContactViewer::ContactViewer( QWidget *parent )
00089 : QWidget( parent ), d( new Private( this ) )
00090 {
00091 QVBoxLayout *layout = new QVBoxLayout( this );
00092 layout->setMargin( 0 );
00093
00094 d->mBrowser = new TextBrowser;
00095 d->mBrowser->setNotifyClick( true );
00096
00097 connect( d->mBrowser, SIGNAL( mailClick( const QString&, const QString& ) ),
00098 this, SLOT( slotMailClicked( const QString&, const QString& ) ) );
00099 connect( d->mBrowser, SIGNAL( urlClick( const QString& ) ),
00100 this, SLOT( slotUrlClicked( const QString& ) ) );
00101
00102 layout->addWidget( d->mBrowser );
00103
00104
00105 fetchScope().fetchFullPayload();
00106 }
00107
00108 ContactViewer::~ContactViewer()
00109 {
00110 delete d;
00111 }
00112
00113 Akonadi::Item ContactViewer::contact() const
00114 {
00115 return ItemMonitor::item();
00116 }
00117
00118 void ContactViewer::setContact( const Akonadi::Item &contact )
00119 {
00120 ItemMonitor::setItem( contact );
00121 }
00122
00123 void ContactViewer::itemChanged( const Item &contactItem )
00124 {
00125 if ( !contactItem.hasPayload<KABC::Addressee>() )
00126 return;
00127
00128 static QPixmap defaultPixmap = KIcon( QLatin1String( "x-office-contact" ) ).pixmap( QSize( 100, 140 ) );
00129
00130 d->mCurrentContact = contactItem.payload<KABC::Addressee>();
00131
00132 setWindowTitle( i18n( "Contact %1", d->mCurrentContact.assembledName() ) );
00133
00134 if ( d->mCurrentContact.photo().isIntern() ) {
00135 d->mBrowser->document()->addResource( QTextDocument::ImageResource,
00136 QUrl( QLatin1String( "contact_photo" ) ),
00137 d->mCurrentContact.photo().data() );
00138 } else {
00139 d->mBrowser->document()->addResource( QTextDocument::ImageResource,
00140 QUrl( QLatin1String( "contact_photo" ) ),
00141 defaultPixmap );
00142 }
00143
00144 d->mBrowser->setHtml( contactAsHtml( d->mCurrentContact ) );
00145 }
00146
00147 void ContactViewer::itemRemoved()
00148 {
00149 d->mBrowser->clear();
00150 }
00151
00152 static QString contactAsHtml( const KABC::Addressee &contact )
00153 {
00154
00155
00156
00157 QString rowFmtStr = QString::fromLatin1(
00158 "<tr>"
00159 "<td align=\"right\" valign=\"top\" width=\"30%\"><b><font size=\"-1\" color=\"grey\">%1</font></b></td>\n"
00160 "<td align=\"left\" valign=\"top\" width=\"70%\"><font size=\"-1\">%2</font></td>\n"
00161 "</tr>\n"
00162 );
00163
00164
00165 QString dynamicPart;
00166
00167
00168 const QDate date = contact.birthday().date();
00169
00170 if ( date.isValid() )
00171 dynamicPart += rowFmtStr
00172 .arg( KABC::Addressee::birthdayLabel() )
00173 .arg( KGlobal::locale()->formatDate( date, KLocale::ShortDate ) );
00174
00175
00176 int counter = 0;
00177 foreach ( const KABC::PhoneNumber &number, contact.phoneNumbers() ) {
00178 const QString url = QString::fromLatin1( "<a href=\"phone:?index=%1\">%2</a>" ).arg( counter ).arg( number.number() );
00179 counter++;
00180
00181 dynamicPart += rowFmtStr
00182 .arg( KABC::PhoneNumber::typeLabel( number.type() ).replace( QLatin1String( " " ), QLatin1String( " " ) ) )
00183 .arg( url );
00184 }
00185
00186
00187 foreach ( const QString &email, contact.emails() ) {
00188 QString type = i18nc( "a contact's email address", "Email" );
00189
00190 const QString fullEmail = QString::fromLatin1( KUrl::toPercentEncoding( contact.fullEmail( email ) ) );
00191
00192 dynamicPart += rowFmtStr.arg( type )
00193 .arg( QString::fromLatin1( "<a href=\"mailto:%1\">%2</a>" )
00194 .arg( fullEmail, email ) );
00195 }
00196
00197
00198 if ( contact.url().isValid() ) {
00199 QString url = contact.url().url();
00200 if ( !url.startsWith( QLatin1String( "http://" ) ) && !url.startsWith( QLatin1String( "https://" ) ) )
00201 url = QLatin1String( "http://" ) + url;
00202
00203 url = KStringHandler::tagUrls( url );
00204 dynamicPart += rowFmtStr.arg( i18n( "Homepage" ) ).arg( url );
00205 }
00206
00207
00208 const QString blog = contact.custom( QLatin1String( "KADDRESSBOOK" ), QLatin1String( "BlogFeed" ) );
00209 if ( !blog.isEmpty() )
00210 dynamicPart += rowFmtStr.arg( i18n( "Blog Feed" ) ).arg( KStringHandler::tagUrls( blog ) );
00211
00212
00213 counter = 0;
00214 foreach ( const KABC::Address &address, contact.addresses() ) {
00215 QString formattedAddress;
00216
00217 if ( address.label().isEmpty() ) {
00218 formattedAddress = address.formattedAddress().trimmed();
00219 } else {
00220 formattedAddress = address.label();
00221 }
00222
00223 formattedAddress = formattedAddress.replace( QLatin1Char( '\n' ), QLatin1String( "<br>" ) );
00224
00225 const QString url = QString::fromLatin1( "<a href=\"address:?index=%1\">%2</a>" ).arg( counter).arg( formattedAddress );
00226 counter++;
00227
00228 dynamicPart += rowFmtStr
00229 .arg( KABC::Address::typeLabel( address.type() ) )
00230 .arg( url );
00231 }
00232
00233
00234 QString notes;
00235 if ( !contact.note().isEmpty() )
00236 notes = rowFmtStr.arg( i18n( "Notes" ) ).arg( contact.note().replace( QLatin1Char( '\n' ), QLatin1String( "<br>" ) ) ) ;
00237
00238
00239 QString customData;
00240 static QMap<QString, QString> titleMap;
00241 if ( titleMap.isEmpty() ) {
00242 titleMap.insert( QLatin1String( "Department" ), i18n( "Department" ) );
00243 titleMap.insert( QLatin1String( "Profession" ), i18n( "Profession" ) );
00244 titleMap.insert( QLatin1String( "AssistantsName" ), i18n( "Assistant's Name" ) );
00245 titleMap.insert( QLatin1String( "ManagersName" ), i18n( "Manager's Name" ) );
00246 titleMap.insert( QLatin1String( "SpousesName" ), i18nc( "Wife/Husband/...", "Partner's Name" ) );
00247 titleMap.insert( QLatin1String( "Office" ), i18n( "Office" ) );
00248 titleMap.insert( QLatin1String( "IMAddress" ), i18n( "IM Address" ) );
00249 titleMap.insert( QLatin1String( "Anniversary" ), i18n( "Anniversary" ) );
00250 }
00251
00252 static QSet<QString> blacklistedKeys;
00253 if ( blacklistedKeys.isEmpty() ) {
00254 blacklistedKeys.insert( QLatin1String( "CRYPTOPROTOPREF" ) );
00255 blacklistedKeys.insert( QLatin1String( "OPENPGPFP" ) );
00256 blacklistedKeys.insert( QLatin1String( "SMIMEFP" ) );
00257 blacklistedKeys.insert( QLatin1String( "CRYPTOSIGNPREF" ) );
00258 blacklistedKeys.insert( QLatin1String( "CRYPTOENCRYPTPREF" ) );
00259 }
00260
00261 if ( !contact.customs().empty() ) {
00262 const QStringList customs = contact.customs();
00263 foreach ( QString custom, customs ) {
00264 if ( custom.startsWith( QLatin1String( "KADDRESSBOOK-" ) ) ) {
00265 custom.remove( QLatin1String( "KADDRESSBOOK-X-" ) );
00266 custom.remove( QLatin1String( "KADDRESSBOOK-" ) );
00267
00268 int pos = custom.indexOf( QLatin1Char( ':' ) );
00269 QString key = custom.left( pos );
00270 QString value = custom.mid( pos + 1 );
00271
00272
00273 if ( key == QLatin1String( "Anniversary" ) ) {
00274 const QDateTime dateTime = QDateTime::fromString( value, Qt::ISODate );
00275 value = KGlobal::locale()->formatDate( dateTime.date(), KLocale::ShortDate );
00276 }
00277
00278
00279 if ( key == QLatin1String( "BlogFeed" ) )
00280 continue;
00281
00282 if ( blacklistedKeys.contains( key ) )
00283 continue;
00284
00285 const QMap<QString, QString>::ConstIterator keyIt = titleMap.constFind( key );
00286 if ( keyIt != titleMap.constEnd() )
00287 key = keyIt.value();
00288
00289 customData += rowFmtStr.arg( key ).arg( value ) ;
00290 }
00291 }
00292 }
00293
00294
00295 QString role = contact.title();
00296 if ( role.isEmpty() )
00297 role = contact.role();
00298 if ( role.isEmpty() )
00299 role = contact.custom( QLatin1String( "KADDRESSBOOK" ), QLatin1String( "X-Profession" ) );
00300
00301 QString strAddr = QString::fromLatin1(
00302 "<div align=\"center\">"
00303 "<table cellpadding=\"3\" cellspacing=\"0\">"
00304 "<tr>"
00305 "<td align=\"right\" valign=\"top\" width=\"30%\" rowspan=\"3\">"
00306 "<img src=\"%1\" width=\"100\" vspace=\"1\">"
00307 "</td>"
00308 "<td align=\"left\" width=\"70%\"><font size=\"+2\"><b>%2</b></font></td>"
00309 "</tr>"
00310 "<tr>"
00311 "<td align=\"left\" width=\"70%\">%3</td>"
00312 "</tr>"
00313 "<tr>"
00314 "<td align=\"left\" width=\"70%\">%4</td>"
00315 "</tr>")
00316 .arg( QLatin1String( "contact_photo" ) )
00317 .arg( contact.realName() )
00318 .arg( role )
00319 .arg( contact.organization() );
00320
00321 strAddr.append( dynamicPart );
00322 strAddr.append( notes );
00323 strAddr.append( customData );
00324 strAddr.append( QString::fromLatin1( "</table></div>\n" ) );
00325
00326 const QString document = QString::fromLatin1(
00327 "<html>"
00328 "<head>"
00329 " <style type=\"text/css\">"
00330 " a {text-decoration:none; color:%1}"
00331 " </style>"
00332 "</head>"
00333 "<body text=\"%1\" bgcolor=\"%2\">"
00334 "%3"
00335 "</body>"
00336 "</html>" )
00337 .arg( KColorScheme( QPalette::Active, KColorScheme::View ).foreground().color().name() )
00338 .arg( KColorScheme( QPalette::Active, KColorScheme::View ).background().color().name() )
00339 .arg( strAddr );
00340
00341 return document;
00342 }
00343
00344 #include "contactviewer.moc"