2
This file is part of Akonadi Contact.
4
Copyright (c) 2010 Tobias Koenig <tokoe@kde.org>
6
This library is free software; you can redistribute it and/or modify it
7
under the terms of the GNU Library General Public License as published by
8
the Free Software Foundation; either version 2 of the License, or (at your
9
option) any later version.
11
This library is distributed in the hope that it will be useful, but WITHOUT
12
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
14
License for more details.
16
You should have received a copy of the GNU Library General Public License
17
along with this library; see the file COPYING.LIB. If not, write to the
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22
#include "grantleecontactformatter.h"
24
#include <grantlee/context.h>
25
#include <grantlee/engine.h>
26
#include <grantlee/templateloader.h>
28
#include <akonadi/item.h>
29
#include <kabc/addressee.h>
30
#include <kcolorscheme.h>
33
#include <kstringhandler.h>
35
#include <QtCore/QSet>
37
using namespace Akonadi;
39
class GrantleeContactFormatter::Private
42
Private( const QString &templatePath )
44
mEngine = new Grantlee::Engine;
46
mTemplateLoader = Grantlee::FileSystemTemplateLoader::Ptr( new Grantlee::FileSystemTemplateLoader );
47
mTemplateLoader->setTemplateDirs( QStringList() << templatePath );
48
mTemplateLoader->setTheme( QLatin1String( "default" ) );
50
mEngine->addTemplateLoader( mTemplateLoader );
51
mSelfcontainedTemplate = mEngine->loadByName( "contact.html" );
52
if ( mSelfcontainedTemplate->error() )
53
mErrorMessage += mSelfcontainedTemplate->errorString();
55
mEmbeddableTemplate = mEngine->loadByName( "contact_embedded.html" );
56
if ( mEmbeddableTemplate->error() )
57
mErrorMessage += mEmbeddableTemplate->errorString();
65
QVector<QObject*> mObjects;
66
Grantlee::Engine *mEngine;
67
Grantlee::FileSystemTemplateLoader::Ptr mTemplateLoader;
68
Grantlee::Template mSelfcontainedTemplate;
69
Grantlee::Template mEmbeddableTemplate;
70
QString mErrorMessage;
73
GrantleeContactFormatter::GrantleeContactFormatter( const QString &templatePath )
74
: d( new Private( templatePath ) )
78
GrantleeContactFormatter::~GrantleeContactFormatter()
83
inline static void setHashField( QVariantHash &hash, const QString &name, const QString &value )
85
if ( !value.isEmpty() )
86
hash.insert( name, value );
89
static QVariantHash phoneNumberHash( const KABC::PhoneNumber &phoneNumber, int counter )
91
QVariantHash numberObject;
93
setHashField( numberObject, QLatin1String( "type" ), phoneNumber.typeLabel() );
94
setHashField( numberObject, QLatin1String( "number" ), phoneNumber.number() );
96
if ( !phoneNumber.isEmpty() ) {
97
const QString url = QString::fromLatin1( "<a href=\"phone:?index=%1\">%2</a>" ).arg( counter ).arg( phoneNumber.number() );
98
numberObject.insert( QLatin1String( "numberLink" ), url );
100
if ( phoneNumber.type() & KABC::PhoneNumber::Cell ) {
101
const QString url = QString::fromLatin1( "<a href=\"sms:?index=%1\">(SMS)</a>" ).arg( counter );
102
numberObject.insert( QLatin1String( "smsLink" ), url );
109
static QVariantHash addressHash( const KABC::Address &address, int counter )
111
QVariantHash addressObject;
113
setHashField( addressObject, QLatin1String( "type" ), KABC::Address::typeLabel( address.type() ) );
114
setHashField( addressObject, QLatin1String( "street" ), address.street() );
115
setHashField( addressObject, QLatin1String( "postOfficeBox" ), address.postOfficeBox() );
116
setHashField( addressObject, QLatin1String( "locality" ), address.locality() );
117
setHashField( addressObject, QLatin1String( "region" ), address.region() );
118
setHashField( addressObject, QLatin1String( "postalCode" ), address.postalCode() );
119
setHashField( addressObject, QLatin1String( "country" ), address.country() );
120
setHashField( addressObject, QLatin1String( "label" ), address.label() );
121
setHashField( addressObject, QLatin1String( "formattedAddress" ), address.formattedAddress() );
123
QString formattedAddress;
125
if ( address.label().isEmpty() ) {
126
formattedAddress = address.formattedAddress().trimmed();
128
formattedAddress = address.label();
131
if ( !formattedAddress.isEmpty() ) {
132
formattedAddress = formattedAddress.replace( QLatin1Char( '\n' ), QLatin1String( "<br/>" ) );
134
const QString url = QString::fromLatin1( "<a href=\"address:?index=%1\">%2</a>" ).arg( counter).arg( formattedAddress );
135
addressObject.insert( "formattedAddressLink", url );
138
return addressObject;
141
QString GrantleeContactFormatter::toHtml( HtmlForm form ) const
143
if ( !d->mErrorMessage.isEmpty() )
144
return d->mErrorMessage;
146
KABC::Addressee rawContact;
147
const Akonadi::Item localItem = item();
148
if ( localItem.isValid() && localItem.hasPayload<KABC::Addressee>() )
149
rawContact = localItem.payload<KABC::Addressee>();
151
rawContact = contact();
153
if ( rawContact.isEmpty() )
156
QVariantHash contactObject;
159
setHashField( contactObject, QLatin1String( "name" ), rawContact.realName() );
160
setHashField( contactObject, QLatin1String( "formattedName" ), rawContact.formattedName() );
161
setHashField( contactObject, QLatin1String( "prefix" ), rawContact.prefix() );
162
setHashField( contactObject, QLatin1String( "givenName" ), rawContact.givenName() );
163
setHashField( contactObject, QLatin1String( "additionalName" ), rawContact.additionalName() );
164
setHashField( contactObject, QLatin1String( "familyName" ), rawContact.familyName() );
165
setHashField( contactObject, QLatin1String( "suffix" ), rawContact.suffix() );
166
setHashField( contactObject, QLatin1String( "nickName" ), rawContact.nickName() );
169
const QDate birthday = rawContact.birthday().date();
170
if ( birthday.isValid() ) {
171
contactObject.insert( QLatin1String( "birthday" ), KGlobal::locale()->formatDate( birthday ) );
173
const int years = (birthday.daysTo( QDate::currentDate() ) / 365);
174
contactObject.insert( QLatin1String( "age" ), QString::number( years ) );
177
const QDate anniversary = QDate::fromString( rawContact.custom( QLatin1String( "KADDRESSBOOK" ), QLatin1String( "X-Anniversary" ) ), Qt::ISODate );
178
if ( anniversary.isValid() ) {
179
contactObject.insert( QLatin1String( "anniversary" ), KGlobal::locale()->formatDate( anniversary ) );
183
contactObject.insert( QLatin1String( "emails" ), rawContact.emails() );
186
QVariantList phoneNumbers;
188
foreach ( const KABC::PhoneNumber &phoneNumber, rawContact.phoneNumbers() ) {
189
phoneNumbers.append( phoneNumberHash( phoneNumber, counter ) );
193
contactObject.insert( QLatin1String( "phoneNumbers" ), phoneNumbers );
196
if ( rawContact.url().isValid() ) {
197
QString url = rawContact.url().url();
198
if ( !url.startsWith( QLatin1String( "http://" ) ) && !url.startsWith( QLatin1String( "https://" ) ) )
199
url = QLatin1String( "http://" ) + url;
201
url = KStringHandler::tagUrls( url );
202
contactObject.insert( QLatin1String( "website" ), url );
206
const QString blog = rawContact.custom( QLatin1String( "KADDRESSBOOK" ), QLatin1String( "BlogFeed" ) );
207
if ( !blog.isEmpty() ) {
208
contactObject.insert( QLatin1String( "blogUrl" ), KStringHandler::tagUrls( blog ) );
212
const QString addressBookName = rawContact.custom( QLatin1String( "KADDRESSBOOK" ), QLatin1String( "AddressBook" ) );
213
if ( !addressBookName.isEmpty() ) {
214
contactObject.insert( QLatin1String( "addressBookName" ), addressBookName );
218
QVariantList addresses;
220
foreach ( const KABC::Address &address, rawContact.addresses() ) {
221
addresses.append( addressHash( address, counter ) );
225
contactObject.insert( QLatin1String( "addresses" ), addresses );
227
setHashField( contactObject, QLatin1String( "mailer" ), rawContact.mailer() );
228
setHashField( contactObject, QLatin1String( "title" ), rawContact.title() );
229
setHashField( contactObject, QLatin1String( "role" ), rawContact.role() );
230
setHashField( contactObject, QLatin1String( "organization" ), rawContact.organization() );
231
setHashField( contactObject, QLatin1String( "department" ), rawContact.department() );
232
setHashField( contactObject, QLatin1String( "note" ), rawContact.note() );
233
setHashField( contactObject, QLatin1String( "profession" ), rawContact.custom( QLatin1String( "KADDRESSBOOK" ), QLatin1String( "X-Profession" ) ) );
234
setHashField( contactObject, QLatin1String( "office" ), rawContact.custom( QLatin1String( "KADDRESSBOOK" ), QLatin1String( "X-Office" ) ) );
235
setHashField( contactObject, QLatin1String( "manager" ), rawContact.custom( QLatin1String( "KADDRESSBOOK" ), QLatin1String( "X-ManagersName" ) ) );
236
setHashField( contactObject, QLatin1String( "assistant" ), rawContact.custom( QLatin1String( "KADDRESSBOOK" ), QLatin1String( "X-AssistantsName" ) ) );
237
setHashField( contactObject, QLatin1String( "spouse" ), rawContact.custom( QLatin1String( "KADDRESSBOOK" ), QLatin1String( "X-SpousesName" ) ) );
238
setHashField( contactObject, QLatin1String( "imAddress" ), rawContact.custom( QLatin1String( "KADDRESSBOOK" ), QLatin1String( "X-IMAddress" ) ) );
242
QVariantList customFields;
244
static QSet<QString> blacklistedKeys;
245
if ( blacklistedKeys.isEmpty() ) {
246
blacklistedKeys.insert( QLatin1String( "CRYPTOPROTOPREF" ) );
247
blacklistedKeys.insert( QLatin1String( "OPENPGPFP" ) );
248
blacklistedKeys.insert( QLatin1String( "SMIMEFP" ) );
249
blacklistedKeys.insert( QLatin1String( "CRYPTOSIGNPREF" ) );
250
blacklistedKeys.insert( QLatin1String( "CRYPTOENCRYPTPREF" ) );
251
blacklistedKeys.insert( QLatin1String( "Anniversary" ) );
252
blacklistedKeys.insert( QLatin1String( "BlogFeed" ) );
253
blacklistedKeys.insert( QLatin1String( "Profession" ) );
254
blacklistedKeys.insert( QLatin1String( "Office" ) );
255
blacklistedKeys.insert( QLatin1String( "ManagersName" ) );
256
blacklistedKeys.insert( QLatin1String( "AssistantsName" ) );
257
blacklistedKeys.insert( QLatin1String( "SpousesName" ) );
258
blacklistedKeys.insert( QLatin1String( "IMAddress" ) );
259
blacklistedKeys.insert( QLatin1String( "AddressBook" ) );
262
if ( !rawContact.customs().empty() ) {
263
const QStringList customs = rawContact.customs();
264
foreach ( QString custom, customs ) { //krazy:exclude=foreach
265
if ( custom.startsWith( QLatin1String( "KADDRESSBOOK-" ) ) ) {
266
custom.remove( QLatin1String( "KADDRESSBOOK-X-" ) );
267
custom.remove( QLatin1String( "KADDRESSBOOK-" ) );
269
int pos = custom.indexOf( QLatin1Char( ':' ) );
270
QString key = custom.left( pos );
271
QString value = custom.mid( pos + 1 );
273
if ( blacklistedKeys.contains( key ) )
276
// check whether it is a custom local field
277
foreach ( const QVariantMap &description, customFieldDescriptions() ) {
278
if ( description.value( QLatin1String( "key" ) ).toString() == key ) {
279
key = description.value( QLatin1String( "title" ) ).toString();
280
if ( description.value( QLatin1String( "type" ) ) == QLatin1String( "boolean" ) ) {
281
if ( value == QLatin1String( "true" ) )
282
value = i18nc( "Boolean value", "yes" );
284
value = i18nc( "Boolean value", "no" );
285
} else if ( description.value( QLatin1String( "type" ) ) == QLatin1String( "date" ) ) {
286
const QDate date = QDate::fromString( value, Qt::ISODate );
287
value = KGlobal::locale()->formatDate( date, KLocale::ShortDate );
288
} else if ( description.value( QLatin1String( "type" ) ) == QLatin1String( "time" ) ) {
289
const QTime time = QTime::fromString( value, Qt::ISODate );
290
value = KGlobal::locale()->formatTime( time );
291
} else if ( description.value( QLatin1String( "type" ) ) == QLatin1String( "datetime" ) ) {
292
const QDateTime dateTime = QDateTime::fromString( value, Qt::ISODate );
293
value = KGlobal::locale()->formatDateTime( dateTime, KLocale::ShortDate );
299
QVariantHash customFieldObject;
300
customFieldObject.insert( QLatin1String( "title" ), key );
301
customFieldObject.insert( QLatin1String( "value" ), value );
303
customFields.append( customFieldObject );
308
contactObject.insert( QLatin1String( "customFields" ), customFields );
310
QVariantHash colorsObject;
311
colorsObject.insert( "linkColor", KColorScheme( QPalette::Active, KColorScheme::View ).foreground().color().name() );
312
colorsObject.insert( "textColor", KColorScheme( QPalette::Active, KColorScheme::View ).foreground().color().name() );
313
colorsObject.insert( "backgroundColor", KColorScheme( QPalette::Active, KColorScheme::View ).background().color().name() );
315
QVariantHash mapping;
316
mapping.insert( "contact", contactObject );
317
mapping.insert( "colors", colorsObject );
319
Grantlee::Context context( mapping );
321
if ( form == SelfcontainedForm )
322
return d->mSelfcontainedTemplate->render( &context );
323
else if ( form == EmbeddableForm )
324
return d->mEmbeddableTemplate->render( &context );