kde-playground/kdepimlibs/akonadi/contact/contactviewer.cpp
2015-04-14 21:49:29 +00:00

312 lines
11 KiB
C++

/*
This file is part of Akonadi Contact.
Copyright (c) 2009 Tobias Koenig <tokoe@kde.org>
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#include "contactviewer.h"
#include "contactmetadata_p.h"
#include "contactmetadataattribute_p.h"
#include "customfieldmanager_p.h"
#include "standardcontactformatter.h"
#include "textbrowser_p.h"
#include "editor/im/improtocols.h"
#include <akonadi/collection.h>
#include <akonadi/collectionfetchjob.h>
#include <akonadi/entitydisplayattribute.h>
#include <akonadi/item.h>
#include <akonadi/itemfetchscope.h>
#include <kabc/addressee.h>
#include <kcolorscheme.h>
#include <kconfiggroup.h>
#include <kglobal.h>
#include <kicon.h>
#include <klocalizedstring.h>
#include <kstringhandler.h>
#include <QVBoxLayout>
#ifdef HAVE_PRISON
#include <prison/QRCodeBarcode>
#include <prison/DataMatrixBarcode>
#include <kabc/vcardconverter.h>
#endif // HAVE_PRISON
using namespace Akonadi;
class ContactViewer::Private
{
public:
Private( ContactViewer *parent )
: mParent( parent ), mParentCollectionFetchJob( 0 )
{
mStandardContactFormatter = new StandardContactFormatter;
mContactFormatter = mStandardContactFormatter;
#ifdef HAVE_PRISON
mQRCode = new prison::QRCodeBarcode();
mDataMatrix = new prison::DataMatrixBarcode();
#endif // HAVE_PRISON
}
~Private()
{
delete mStandardContactFormatter;
#ifdef HAVE_PRISON
delete mQRCode;
delete mDataMatrix;
#endif // HAVE_PRISON
}
void updateView( const QVariantList &localCustomFieldDescriptions = QVariantList(), const QString &addressBookName = QString() )
{
static QPixmap defaultPixmap = KIcon( QLatin1String( "user-identity" ) ).pixmap( QSize( 100, 100 ) );
mParent->setWindowTitle( i18n( "Contact %1", mCurrentContact.assembledName() ) );
if ( mCurrentContact.photo().isIntern() ) {
mBrowser->document()->addResource( QTextDocument::ImageResource,
QUrl( QLatin1String( "contact_photo" ) ),
mCurrentContact.photo().data() );
} else {
mBrowser->document()->addResource( QTextDocument::ImageResource,
QUrl( QLatin1String( "contact_photo" ) ),
defaultPixmap );
}
if ( mCurrentContact.logo().isIntern() ) {
mBrowser->document()->addResource( QTextDocument::ImageResource,
QUrl( QLatin1String( "contact_logo" ) ),
mCurrentContact.logo().data() );
}
mBrowser->document()->addResource( QTextDocument::ImageResource,
QUrl( QLatin1String( "map_icon" ) ),
KIcon( QLatin1String( "document-open-remote" ) ).pixmap( QSize( 16, 16 ) ) );
mBrowser->document()->addResource( QTextDocument::ImageResource,
QUrl( QLatin1String( "sms_icon" ) ),
KIcon( IMProtocols::self()->icon( QString::fromLatin1( "messaging/sms" ) ) ).pixmap( QSize( 16, 16 ) ) );
#ifdef HAVE_PRISON
KConfig config( QLatin1String( "akonadi_contactrc" ) );
KConfigGroup group( &config, QLatin1String( "View" ) );
if ( group.readEntry( "QRCodes", true ) ) {
KABC::VCardConverter converter;
KABC::Addressee addr( mCurrentContact );
addr.setPhoto( KABC::Picture() );
addr.setLogo( KABC::Picture() );
const QString data = QString::fromUtf8( converter.createVCard( addr ) );
mQRCode->setData( data );
mDataMatrix->setData( data );
mBrowser->document()->addResource( QTextDocument::ImageResource,
QUrl( QLatin1String( "qrcode" ) ),
mQRCode->toImage( QSizeF( 50, 50 ) ) );
mBrowser->document()->addResource( QTextDocument::ImageResource,
QUrl( QLatin1String( "datamatrix" ) ),
mDataMatrix->toImage( QSizeF( 50, 50 ) ) );
}
#endif // HAVE_PRISON
// merge local and global custom field descriptions
QList<QVariantMap> customFieldDescriptions;
foreach ( const QVariant &entry, localCustomFieldDescriptions ) {
customFieldDescriptions << entry.toMap();
}
const CustomField::List globalCustomFields = CustomFieldManager::globalCustomFieldDescriptions();
foreach ( const CustomField &field, globalCustomFields ) {
QVariantMap description;
description.insert( QLatin1String( "key" ), field.key() );
description.insert( QLatin1String( "title" ), field.title() );
customFieldDescriptions << description;
}
KABC::Addressee contact( mCurrentContact );
if ( !addressBookName.isEmpty() ) {
contact.insertCustom( QLatin1String( "KADDRESSBOOK" ), QLatin1String( "AddressBook" ), addressBookName );
}
mContactFormatter->setContact( contact );
mContactFormatter->setCustomFieldDescriptions( customFieldDescriptions );
mBrowser->setHtml( mContactFormatter->toHtml() );
}
void slotMailClicked( const QString&, const QString &email )
{
QString name, address;
// remove the 'mailto:' and split into name and email address
KABC::Addressee::parseEmailAddress( email.mid( 7 ), name, address );
emit mParent->emailClicked( name, address );
}
void slotUrlClicked( const QString &urlString )
{
KUrl url( urlString );
const QString urlScheme( url.scheme() );
if ( urlScheme == QLatin1String( "http" ) ||
urlScheme == QLatin1String( "https" ) ) {
emit mParent->urlClicked( url );
} else if ( urlScheme == QLatin1String( "phone" ) ) {
const int pos = url.queryItemValue( QLatin1String( "index" ) ).toInt();
const KABC::PhoneNumber::List numbers = mCurrentContact.phoneNumbers();
if ( pos < numbers.count() ) {
emit mParent->phoneNumberClicked( numbers.at( pos ) );
}
} else if ( urlScheme == QLatin1String( "sms" ) ) {
const int pos = url.queryItemValue( QLatin1String( "index" ) ).toInt();
const KABC::PhoneNumber::List numbers = mCurrentContact.phoneNumbers();
if ( pos < numbers.count() ) {
emit mParent->smsClicked( numbers.at( pos ) );
}
} else if ( urlScheme == QLatin1String( "address" ) ) {
const int pos = url.queryItemValue( QLatin1String( "index" ) ).toInt();
const KABC::Address::List addresses = mCurrentContact.addresses();
if ( pos < addresses.count() ) {
emit mParent->addressClicked( addresses.at( pos ) );
}
}
}
void slotParentCollectionFetched( KJob *job )
{
mParentCollectionFetchJob = 0;
QString addressBookName;
if ( !job->error() ) {
CollectionFetchJob *fetchJob = qobject_cast<CollectionFetchJob*>( job );
if ( !fetchJob->collections().isEmpty() ) {
const Collection collection = fetchJob->collections().first();
addressBookName = collection.displayName();
}
}
// load the local meta data of the item
ContactMetaData metaData;
metaData.load( mCurrentItem );
updateView( metaData.customFieldDescriptions(), addressBookName );
}
ContactViewer *mParent;
TextBrowser *mBrowser;
KABC::Addressee mCurrentContact;
Item mCurrentItem;
AbstractContactFormatter *mContactFormatter;
AbstractContactFormatter *mStandardContactFormatter;
CollectionFetchJob *mParentCollectionFetchJob;
#ifdef HAVE_PRISON
prison::AbstractBarcode* mQRCode;
prison::AbstractBarcode* mDataMatrix;
#endif // HAVE_PRISON
};
ContactViewer::ContactViewer( QWidget *parent )
: QWidget( parent ), d( new Private( this ) )
{
QVBoxLayout *layout = new QVBoxLayout( this );
layout->setMargin( 0 );
d->mBrowser = new TextBrowser;
d->mBrowser->setNotifyClick( true );
connect( d->mBrowser, SIGNAL(mailClick(QString,QString)),
this, SLOT(slotMailClicked(QString,QString)) );
connect( d->mBrowser, SIGNAL(urlClick(QString)),
this, SLOT(slotUrlClicked(QString)) );
layout->addWidget( d->mBrowser );
// always fetch full payload for contacts
fetchScope().fetchFullPayload();
fetchScope().fetchAttribute<ContactMetaDataAttribute>();
fetchScope().setAncestorRetrieval( ItemFetchScope::Parent );
}
ContactViewer::~ContactViewer()
{
delete d;
}
Akonadi::Item ContactViewer::contact() const
{
return ItemMonitor::item();
}
KABC::Addressee ContactViewer::rawContact() const
{
return d->mCurrentContact;
}
void ContactViewer::setContactFormatter( AbstractContactFormatter *formatter )
{
if ( formatter == 0 ) {
d->mContactFormatter = d->mStandardContactFormatter;
} else {
d->mContactFormatter = formatter;
}
}
void ContactViewer::setContact( const Akonadi::Item &contact )
{
ItemMonitor::setItem( contact );
}
void ContactViewer::setRawContact( const KABC::Addressee &contact )
{
d->mCurrentContact = contact;
d->updateView();
}
void ContactViewer::itemChanged( const Item &contactItem )
{
if ( !contactItem.hasPayload<KABC::Addressee>() ) {
return;
}
d->mCurrentItem = contactItem;
d->mCurrentContact = contactItem.payload<KABC::Addressee>();
// stop any running fetch job
if ( d->mParentCollectionFetchJob ) {
disconnect( d->mParentCollectionFetchJob, SIGNAL(result(KJob*)), this, SLOT(slotParentCollectionFetched(KJob*)) );
delete d->mParentCollectionFetchJob;
d->mParentCollectionFetchJob = 0;
}
d->mParentCollectionFetchJob = new CollectionFetchJob( contactItem.parentCollection(), CollectionFetchJob::Base, this );
connect( d->mParentCollectionFetchJob, SIGNAL(result(KJob*)), SLOT(slotParentCollectionFetched(KJob*)) );
}
void ContactViewer::itemRemoved()
{
d->mBrowser->clear();
}
#include "moc_contactviewer.cpp"