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 "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
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
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
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
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
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"