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 mContactFormatter = new StandardContactFormatter;
00053 }
00054
00055 ~Private()
00056 {
00057 delete mContactFormatter;
00058 }
00059
00060 void updateView( const QVariantList &localCustomFieldDescriptions = QVariantList(), const QString &addressBookName = QString() )
00061 {
00062 static QPixmap defaultPixmap = KIcon( QLatin1String( "user-identity" ) ).pixmap( QSize( 100, 100 ) );
00063
00064 mParent->setWindowTitle( i18n( "Contact %1", mCurrentContact.assembledName() ) );
00065
00066 if ( mCurrentContact.photo().isIntern() ) {
00067 mBrowser->document()->addResource( QTextDocument::ImageResource,
00068 QUrl( QLatin1String( "contact_photo" ) ),
00069 mCurrentContact.photo().data() );
00070 } else {
00071 mBrowser->document()->addResource( QTextDocument::ImageResource,
00072 QUrl( QLatin1String( "contact_photo" ) ),
00073 defaultPixmap );
00074 }
00075
00076
00077 QList<QVariantMap> customFieldDescriptions;
00078 foreach ( const QVariant &entry, localCustomFieldDescriptions )
00079 customFieldDescriptions << entry.toMap();
00080
00081 const CustomField::List globalCustomFields = CustomFieldManager::globalCustomFieldDescriptions();
00082 foreach ( const CustomField &field, globalCustomFields ) {
00083 QVariantMap description;
00084 description.insert( QLatin1String( "key" ), field.key() );
00085 description.insert( QLatin1String( "title" ), field.title() );
00086
00087 customFieldDescriptions << description;
00088 }
00089
00090 KABC::Addressee contact( mCurrentContact );
00091 if ( !addressBookName.isEmpty() ) {
00092 contact.insertCustom( QLatin1String( "KADDRESSBOOK" ), QLatin1String( "AddressBook" ), addressBookName );
00093 }
00094
00095 mContactFormatter->setContact( contact );
00096 mContactFormatter->setCustomFieldDescriptions( customFieldDescriptions );
00097
00098 mBrowser->setHtml( mContactFormatter->toHtml() );
00099 }
00100
00101 void slotMailClicked( const QString&, const QString &email )
00102 {
00103 QString name, address;
00104
00105
00106 KABC::Addressee::parseEmailAddress( email.mid( 7 ), name, address );
00107
00108 emit mParent->emailClicked( name, address );
00109 }
00110
00111 void slotUrlClicked( const QString &urlString )
00112 {
00113 KUrl url( urlString );
00114
00115 if ( url.scheme() == QLatin1String( "http" ) ||
00116 url.scheme() == QLatin1String( "https" ) ) {
00117 emit mParent->urlClicked( url );
00118 } else if ( url.scheme() == QLatin1String( "phone" ) ) {
00119 const int pos = url.queryItemValue( QLatin1String( "index" ) ).toInt();
00120
00121 const KABC::PhoneNumber::List numbers = mCurrentContact.phoneNumbers();
00122 if ( pos < numbers.count() ) {
00123 emit mParent->phoneNumberClicked( numbers.at( pos ) );
00124 }
00125 } else if ( url.scheme() == QLatin1String( "address" ) ) {
00126 const int pos = url.queryItemValue( QLatin1String( "index" ) ).toInt();
00127
00128 const KABC::Address::List addresses = mCurrentContact.addresses();
00129 if ( pos < addresses.count() ) {
00130 emit mParent->addressClicked( addresses.at( pos ) );
00131 }
00132 }
00133 }
00134
00135 void slotParentCollectionFetched( KJob *job )
00136 {
00137 mParentCollectionFetchJob = 0;
00138
00139 QString addressBookName;
00140
00141 if ( !job->error() ) {
00142 CollectionFetchJob *fetchJob = qobject_cast<CollectionFetchJob*>( job );
00143 if ( !fetchJob->collections().isEmpty() ) {
00144 const Collection collection = fetchJob->collections().first();
00145 if ( collection.hasAttribute<EntityDisplayAttribute>() )
00146 addressBookName = collection.attribute<EntityDisplayAttribute>()->displayName();
00147 else
00148 addressBookName = collection.name();
00149 }
00150 }
00151
00152
00153 ContactMetaData metaData;
00154 metaData.load( mCurrentItem );
00155
00156 updateView( metaData.customFieldDescriptions(), addressBookName );
00157 }
00158
00159 ContactViewer *mParent;
00160 TextBrowser *mBrowser;
00161 KABC::Addressee mCurrentContact;
00162 Item mCurrentItem;
00163 AbstractContactFormatter *mContactFormatter;
00164 CollectionFetchJob *mParentCollectionFetchJob;
00165 };
00166
00167 ContactViewer::ContactViewer( QWidget *parent )
00168 : QWidget( parent ), d( new Private( this ) )
00169 {
00170 QVBoxLayout *layout = new QVBoxLayout( this );
00171 layout->setMargin( 0 );
00172
00173 d->mBrowser = new TextBrowser;
00174 d->mBrowser->setNotifyClick( true );
00175
00176 connect( d->mBrowser, SIGNAL( mailClick( const QString&, const QString& ) ),
00177 this, SLOT( slotMailClicked( const QString&, const QString& ) ) );
00178 connect( d->mBrowser, SIGNAL( urlClick( const QString& ) ),
00179 this, SLOT( slotUrlClicked( const QString& ) ) );
00180
00181 layout->addWidget( d->mBrowser );
00182
00183
00184 fetchScope().fetchFullPayload();
00185 fetchScope().fetchAttribute<ContactMetaDataAttribute>();
00186 fetchScope().setAncestorRetrieval( ItemFetchScope::Parent );
00187 }
00188
00189 ContactViewer::~ContactViewer()
00190 {
00191 delete d;
00192 }
00193
00194 Akonadi::Item ContactViewer::contact() const
00195 {
00196 return ItemMonitor::item();
00197 }
00198
00199 KABC::Addressee ContactViewer::rawContact() const
00200 {
00201 return d->mCurrentContact;
00202 }
00203
00204 void ContactViewer::setContact( const Akonadi::Item &contact )
00205 {
00206 ItemMonitor::setItem( contact );
00207 }
00208
00209 void ContactViewer::setRawContact( const KABC::Addressee &contact )
00210 {
00211 d->mCurrentContact = contact;
00212
00213 d->updateView();
00214 }
00215
00216 void ContactViewer::itemChanged( const Item &contactItem )
00217 {
00218 if ( !contactItem.hasPayload<KABC::Addressee>() )
00219 return;
00220
00221 d->mCurrentItem = contactItem;
00222 d->mCurrentContact = contactItem.payload<KABC::Addressee>();
00223
00224
00225 if ( d->mParentCollectionFetchJob ) {
00226 disconnect( d->mParentCollectionFetchJob, SIGNAL( result( KJob* ) ), this, SLOT( slotParentCollectionFetched( KJob* ) ) );
00227 delete d->mParentCollectionFetchJob;
00228 d->mParentCollectionFetchJob = 0;
00229 }
00230
00231 d->mParentCollectionFetchJob = new CollectionFetchJob( contactItem.parentCollection(), CollectionFetchJob::Base, this );
00232 connect( d->mParentCollectionFetchJob, SIGNAL( result( KJob* ) ), SLOT( slotParentCollectionFetched( KJob* ) ) );
00233 }
00234
00235 void ContactViewer::itemRemoved()
00236 {
00237 d->mBrowser->clear();
00238 }
00239
00240 #include "contactviewer.moc"