akonadi
contactviewer.cpp
00001 /* 00002 This file is part of Akonadi Contact. 00003 00004 Copyright (c) 2009 Tobias Koenig <tokoe@kde.org> 00005 00006 This library is free software; you can redistribute it and/or modify it 00007 under the terms of the GNU Library General Public License as published by 00008 the Free Software Foundation; either version 2 of the License, or (at your 00009 option) any later version. 00010 00011 This library is distributed in the hope that it will be useful, but WITHOUT 00012 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00013 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 00014 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 the 00018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 00019 02110-1301, USA. 00020 */ 00021 00022 #include "contactviewer.h" 00023 00024 #include "contactmetadata_p.h" 00025 #include "contactmetadataattribute_p.h" 00026 #include "customfieldmanager_p.h" 00027 #include "standardcontactformatter.h" 00028 #include "textbrowser_p.h" 00029 00030 #include <akonadi/collection.h> 00031 #include <akonadi/collectionfetchjob.h> 00032 #include <akonadi/entitydisplayattribute.h> 00033 #include <akonadi/item.h> 00034 #include <akonadi/itemfetchscope.h> 00035 #include <kabc/addressee.h> 00036 #include <kcolorscheme.h> 00037 #include <kglobal.h> 00038 #include <kicon.h> 00039 #include <klocale.h> 00040 #include <kstringhandler.h> 00041 00042 #include <QtGui/QVBoxLayout> 00043 00044 using namespace Akonadi; 00045 00046 class ContactViewer::Private 00047 { 00048 public: 00049 Private( ContactViewer *parent ) 00050 : mParent( parent ), mParentCollectionFetchJob( 0 ) 00051 { 00052 mStandardContactFormatter = new StandardContactFormatter; 00053 mContactFormatter = mStandardContactFormatter; 00054 } 00055 00056 ~Private() 00057 { 00058 delete mStandardContactFormatter; 00059 } 00060 00061 void updateView( const QVariantList &localCustomFieldDescriptions = QVariantList(), const QString &addressBookName = QString() ) 00062 { 00063 static QPixmap defaultPixmap = KIcon( QLatin1String( "user-identity" ) ).pixmap( QSize( 100, 100 ) ); 00064 00065 mParent->setWindowTitle( i18n( "Contact %1", mCurrentContact.assembledName() ) ); 00066 00067 if ( mCurrentContact.photo().isIntern() ) { 00068 mBrowser->document()->addResource( QTextDocument::ImageResource, 00069 QUrl( QLatin1String( "contact_photo" ) ), 00070 mCurrentContact.photo().data() ); 00071 } else { 00072 mBrowser->document()->addResource( QTextDocument::ImageResource, 00073 QUrl( QLatin1String( "contact_photo" ) ), 00074 defaultPixmap ); 00075 } 00076 00077 // merge local and global custom field descriptions 00078 QList<QVariantMap> customFieldDescriptions; 00079 foreach ( const QVariant &entry, localCustomFieldDescriptions ) 00080 customFieldDescriptions << entry.toMap(); 00081 00082 const CustomField::List globalCustomFields = CustomFieldManager::globalCustomFieldDescriptions(); 00083 foreach ( const CustomField &field, globalCustomFields ) { 00084 QVariantMap description; 00085 description.insert( QLatin1String( "key" ), field.key() ); 00086 description.insert( QLatin1String( "title" ), field.title() ); 00087 00088 customFieldDescriptions << description; 00089 } 00090 00091 KABC::Addressee contact( mCurrentContact ); 00092 if ( !addressBookName.isEmpty() ) { 00093 contact.insertCustom( QLatin1String( "KADDRESSBOOK" ), QLatin1String( "AddressBook" ), addressBookName ); 00094 } 00095 00096 mContactFormatter->setContact( contact ); 00097 mContactFormatter->setCustomFieldDescriptions( customFieldDescriptions ); 00098 00099 mBrowser->setHtml( mContactFormatter->toHtml() ); 00100 } 00101 00102 void slotMailClicked( const QString&, const QString &email ) 00103 { 00104 QString name, address; 00105 00106 // remove the 'mailto:' and split into name and email address 00107 KABC::Addressee::parseEmailAddress( email.mid( 7 ), name, address ); 00108 00109 emit mParent->emailClicked( name, address ); 00110 } 00111 00112 void slotUrlClicked( const QString &urlString ) 00113 { 00114 KUrl url( urlString ); 00115 00116 if ( url.scheme() == QLatin1String( "http" ) || 00117 url.scheme() == QLatin1String( "https" ) ) { 00118 emit mParent->urlClicked( url ); 00119 } else if ( url.scheme() == QLatin1String( "phone" ) ) { 00120 const int pos = url.queryItemValue( QLatin1String( "index" ) ).toInt(); 00121 00122 const KABC::PhoneNumber::List numbers = mCurrentContact.phoneNumbers(); 00123 if ( pos < numbers.count() ) { 00124 emit mParent->phoneNumberClicked( numbers.at( pos ) ); 00125 } 00126 } else if ( url.scheme() == QLatin1String( "sms" ) ) { 00127 const int pos = url.queryItemValue( QLatin1String( "index" ) ).toInt(); 00128 00129 const KABC::PhoneNumber::List numbers = mCurrentContact.phoneNumbers(); 00130 if ( pos < numbers.count() ) { 00131 emit mParent->smsClicked( numbers.at( pos ) ); 00132 } 00133 } else if ( url.scheme() == QLatin1String( "address" ) ) { 00134 const int pos = url.queryItemValue( QLatin1String( "index" ) ).toInt(); 00135 00136 const KABC::Address::List addresses = mCurrentContact.addresses(); 00137 if ( pos < addresses.count() ) { 00138 emit mParent->addressClicked( addresses.at( pos ) ); 00139 } 00140 } 00141 } 00142 00143 void slotParentCollectionFetched( KJob *job ) 00144 { 00145 mParentCollectionFetchJob = 0; 00146 00147 QString addressBookName; 00148 00149 if ( !job->error() ) { 00150 CollectionFetchJob *fetchJob = qobject_cast<CollectionFetchJob*>( job ); 00151 if ( !fetchJob->collections().isEmpty() ) { 00152 const Collection collection = fetchJob->collections().first(); 00153 if ( collection.hasAttribute<EntityDisplayAttribute>() ) 00154 addressBookName = collection.attribute<EntityDisplayAttribute>()->displayName(); 00155 else 00156 addressBookName = collection.name(); 00157 } 00158 } 00159 00160 // load the local meta data of the item 00161 ContactMetaData metaData; 00162 metaData.load( mCurrentItem ); 00163 00164 updateView( metaData.customFieldDescriptions(), addressBookName ); 00165 } 00166 00167 ContactViewer *mParent; 00168 TextBrowser *mBrowser; 00169 KABC::Addressee mCurrentContact; 00170 Item mCurrentItem; 00171 AbstractContactFormatter *mContactFormatter; 00172 AbstractContactFormatter *mStandardContactFormatter; 00173 CollectionFetchJob *mParentCollectionFetchJob; 00174 }; 00175 00176 ContactViewer::ContactViewer( QWidget *parent ) 00177 : QWidget( parent ), d( new Private( this ) ) 00178 { 00179 QVBoxLayout *layout = new QVBoxLayout( this ); 00180 layout->setMargin( 0 ); 00181 00182 d->mBrowser = new TextBrowser; 00183 d->mBrowser->setNotifyClick( true ); 00184 00185 connect( d->mBrowser, SIGNAL( mailClick( const QString&, const QString& ) ), 00186 this, SLOT( slotMailClicked( const QString&, const QString& ) ) ); 00187 connect( d->mBrowser, SIGNAL( urlClick( const QString& ) ), 00188 this, SLOT( slotUrlClicked( const QString& ) ) ); 00189 00190 layout->addWidget( d->mBrowser ); 00191 00192 // always fetch full payload for contacts 00193 fetchScope().fetchFullPayload(); 00194 fetchScope().fetchAttribute<ContactMetaDataAttribute>(); 00195 fetchScope().setAncestorRetrieval( ItemFetchScope::Parent ); 00196 } 00197 00198 ContactViewer::~ContactViewer() 00199 { 00200 delete d; 00201 } 00202 00203 Akonadi::Item ContactViewer::contact() const 00204 { 00205 return ItemMonitor::item(); 00206 } 00207 00208 KABC::Addressee ContactViewer::rawContact() const 00209 { 00210 return d->mCurrentContact; 00211 } 00212 00213 void ContactViewer::setContactFormatter( AbstractContactFormatter *formatter ) 00214 { 00215 if ( formatter == 0 ) 00216 d->mContactFormatter = d->mStandardContactFormatter; 00217 else 00218 d->mContactFormatter = formatter; 00219 } 00220 00221 void ContactViewer::setContact( const Akonadi::Item &contact ) 00222 { 00223 ItemMonitor::setItem( contact ); 00224 } 00225 00226 void ContactViewer::setRawContact( const KABC::Addressee &contact ) 00227 { 00228 d->mCurrentContact = contact; 00229 00230 d->updateView(); 00231 } 00232 00233 void ContactViewer::itemChanged( const Item &contactItem ) 00234 { 00235 if ( !contactItem.hasPayload<KABC::Addressee>() ) 00236 return; 00237 00238 d->mCurrentItem = contactItem; 00239 d->mCurrentContact = contactItem.payload<KABC::Addressee>(); 00240 00241 // stop any running fetch job 00242 if ( d->mParentCollectionFetchJob ) { 00243 disconnect( d->mParentCollectionFetchJob, SIGNAL( result( KJob* ) ), this, SLOT( slotParentCollectionFetched( KJob* ) ) ); 00244 delete d->mParentCollectionFetchJob; 00245 d->mParentCollectionFetchJob = 0; 00246 } 00247 00248 d->mParentCollectionFetchJob = new CollectionFetchJob( contactItem.parentCollection(), CollectionFetchJob::Base, this ); 00249 connect( d->mParentCollectionFetchJob, SIGNAL( result( KJob* ) ), SLOT( slotParentCollectionFetched( KJob* ) ) ); 00250 } 00251 00252 void ContactViewer::itemRemoved() 00253 { 00254 d->mBrowser->clear(); 00255 } 00256 00257 #include "contactviewer.moc"