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>
36 #include <QtCore/QRegExp>
38 using namespace Akonadi
;
40 class GrantleeContactFormatter::Private
43 Private( const QString
&templatePath
)
45 mEngine
= new Grantlee::Engine
;
47 mTemplateLoader
= Grantlee::FileSystemTemplateLoader::Ptr( new Grantlee::FileSystemTemplateLoader
);
48 mTemplateLoader
->setTemplateDirs( QStringList() << templatePath
);
49 mTemplateLoader
->setTheme( QLatin1String( "default" ) );
51 mEngine
->addTemplateLoader( mTemplateLoader
);
52 mSelfcontainedTemplate
= mEngine
->loadByName( "contact.html" );
53 if ( mSelfcontainedTemplate
->error() )
54 mErrorMessage
+= mSelfcontainedTemplate
->errorString();
56 mEmbeddableTemplate
= mEngine
->loadByName( "contact_embedded.html" );
57 if ( mEmbeddableTemplate
->error() )
58 mErrorMessage
+= mEmbeddableTemplate
->errorString();
66 QVector
<QObject
*> mObjects
;
67 Grantlee::Engine
*mEngine
;
68 Grantlee::FileSystemTemplateLoader::Ptr mTemplateLoader
;
69 Grantlee::Template mSelfcontainedTemplate
;
70 Grantlee::Template mEmbeddableTemplate
;
71 QString mErrorMessage
;
74 GrantleeContactFormatter::GrantleeContactFormatter( const QString
&templatePath
)
75 : d( new Private( templatePath
) )
79 GrantleeContactFormatter::~GrantleeContactFormatter()
84 inline static void setHashField( QVariantHash
&hash
, const QString
&name
, const QString
&value
)
86 if ( !value
.isEmpty() )
87 hash
.insert( name
, value
);
90 static QVariantHash
phoneNumberHash( const KABC::PhoneNumber
&phoneNumber
, int counter
)
92 QVariantHash numberObject
;
94 setHashField( numberObject
, QLatin1String( "type" ), phoneNumber
.typeLabel() );
95 setHashField( numberObject
, QLatin1String( "number" ), phoneNumber
.number() );
97 if ( !phoneNumber
.isEmpty() ) {
98 const QString url
= QString::fromLatin1( "<a href=\"phone:?index=%1\">%2</a>" ).arg( counter
).arg( phoneNumber
.number() );
99 numberObject
.insert( QLatin1String( "numberLink" ), url
);
101 if ( phoneNumber
.type() & KABC::PhoneNumber::Cell
) {
102 const QString url
= QString::fromLatin1( "<a href=\"sms:?index=%1\">(SMS)</a>" ).arg( counter
);
103 numberObject
.insert( QLatin1String( "smsLink" ), url
);
110 static QVariantHash
addressHash( const KABC::Address
&address
, int counter
)
112 QVariantHash addressObject
;
114 setHashField( addressObject
, QLatin1String( "type" ), KABC::Address::typeLabel( address
.type() ) );
115 setHashField( addressObject
, QLatin1String( "street" ), address
.street() );
116 setHashField( addressObject
, QLatin1String( "postOfficeBox" ), address
.postOfficeBox() );
117 setHashField( addressObject
, QLatin1String( "locality" ), address
.locality() );
118 setHashField( addressObject
, QLatin1String( "region" ), address
.region() );
119 setHashField( addressObject
, QLatin1String( "postalCode" ), address
.postalCode() );
120 setHashField( addressObject
, QLatin1String( "country" ), address
.country() );
121 setHashField( addressObject
, QLatin1String( "label" ), address
.label() );
122 setHashField( addressObject
, QLatin1String( "formattedAddress" ), address
.formattedAddress() );
124 QString formattedAddress
;
126 if ( address
.label().isEmpty() ) {
127 formattedAddress
= address
.formattedAddress().trimmed();
129 formattedAddress
= address
.label();
132 if ( !formattedAddress
.isEmpty() ) {
133 formattedAddress
= formattedAddress
.replace( QRegExp( "\n+" ), QLatin1String( "<br/>" ) );
135 const QString url
= QString::fromLatin1( "<a href=\"address:?index=%1\">%2</a>" ).arg( counter
).arg( formattedAddress
);
136 addressObject
.insert( "formattedAddressLink", url
);
139 return addressObject
;
142 QString
GrantleeContactFormatter::toHtml( HtmlForm form
) const
144 if ( !d
->mErrorMessage
.isEmpty() )
145 return d
->mErrorMessage
;
147 KABC::Addressee rawContact
;
148 const Akonadi::Item localItem
= item();
149 if ( localItem
.isValid() && localItem
.hasPayload
<KABC::Addressee
>() )
150 rawContact
= localItem
.payload
<KABC::Addressee
>();
152 rawContact
= contact();
154 if ( rawContact
.isEmpty() )
157 QVariantHash contactObject
;
160 setHashField( contactObject
, QLatin1String( "name" ), rawContact
.realName() );
161 setHashField( contactObject
, QLatin1String( "formattedName" ), rawContact
.formattedName() );
162 setHashField( contactObject
, QLatin1String( "prefix" ), rawContact
.prefix() );
163 setHashField( contactObject
, QLatin1String( "givenName" ), rawContact
.givenName() );
164 setHashField( contactObject
, QLatin1String( "additionalName" ), rawContact
.additionalName() );
165 setHashField( contactObject
, QLatin1String( "familyName" ), rawContact
.familyName() );
166 setHashField( contactObject
, QLatin1String( "suffix" ), rawContact
.suffix() );
167 setHashField( contactObject
, QLatin1String( "nickName" ), rawContact
.nickName() );
170 const QDate birthday
= rawContact
.birthday().date();
171 if ( birthday
.isValid() ) {
172 contactObject
.insert( QLatin1String( "birthday" ), KGlobal::locale()->formatDate( birthday
) );
174 const int years
= (birthday
.daysTo( QDate::currentDate() ) / 365);
175 contactObject
.insert( QLatin1String( "age" ), QString::number( years
) );
178 const QDate anniversary
= QDate::fromString( rawContact
.custom( QLatin1String( "KADDRESSBOOK" ), QLatin1String( "X-Anniversary" ) ), Qt::ISODate
);
179 if ( anniversary
.isValid() ) {
180 contactObject
.insert( QLatin1String( "anniversary" ), KGlobal::locale()->formatDate( anniversary
) );
184 contactObject
.insert( QLatin1String( "emails" ), rawContact
.emails() );
187 QVariantList phoneNumbers
;
189 foreach ( const KABC::PhoneNumber
&phoneNumber
, rawContact
.phoneNumbers() ) {
190 phoneNumbers
.append( phoneNumberHash( phoneNumber
, counter
) );
194 contactObject
.insert( QLatin1String( "phoneNumbers" ), phoneNumbers
);
197 if ( rawContact
.url().isValid() ) {
198 QString url
= rawContact
.url().url();
199 if ( !url
.startsWith( QLatin1String( "http://" ) ) && !url
.startsWith( QLatin1String( "https://" ) ) )
200 url
= QLatin1String( "http://" ) + url
;
202 url
= KStringHandler::tagUrls( url
);
203 contactObject
.insert( QLatin1String( "website" ), url
);
207 const QString blog
= rawContact
.custom( QLatin1String( "KADDRESSBOOK" ), QLatin1String( "BlogFeed" ) );
208 if ( !blog
.isEmpty() ) {
209 contactObject
.insert( QLatin1String( "blogUrl" ), KStringHandler::tagUrls( blog
) );
213 const QString addressBookName
= rawContact
.custom( QLatin1String( "KADDRESSBOOK" ), QLatin1String( "AddressBook" ) );
214 if ( !addressBookName
.isEmpty() ) {
215 contactObject
.insert( QLatin1String( "addressBookName" ), addressBookName
);
219 QVariantList addresses
;
221 foreach ( const KABC::Address
&address
, rawContact
.addresses() ) {
222 addresses
.append( addressHash( address
, counter
) );
226 contactObject
.insert( QLatin1String( "addresses" ), addresses
);
228 setHashField( contactObject
, QLatin1String( "mailer" ), rawContact
.mailer() );
229 setHashField( contactObject
, QLatin1String( "title" ), rawContact
.title() );
230 setHashField( contactObject
, QLatin1String( "role" ), rawContact
.role() );
231 setHashField( contactObject
, QLatin1String( "organization" ), rawContact
.organization() );
232 setHashField( contactObject
, QLatin1String( "department" ), rawContact
.department() );
233 setHashField( contactObject
, QLatin1String( "note" ), rawContact
.note() );
234 setHashField( contactObject
, QLatin1String( "profession" ), rawContact
.custom( QLatin1String( "KADDRESSBOOK" ), QLatin1String( "X-Profession" ) ) );
235 setHashField( contactObject
, QLatin1String( "office" ), rawContact
.custom( QLatin1String( "KADDRESSBOOK" ), QLatin1String( "X-Office" ) ) );
236 setHashField( contactObject
, QLatin1String( "manager" ), rawContact
.custom( QLatin1String( "KADDRESSBOOK" ), QLatin1String( "X-ManagersName" ) ) );
237 setHashField( contactObject
, QLatin1String( "assistant" ), rawContact
.custom( QLatin1String( "KADDRESSBOOK" ), QLatin1String( "X-AssistantsName" ) ) );
238 setHashField( contactObject
, QLatin1String( "spouse" ), rawContact
.custom( QLatin1String( "KADDRESSBOOK" ), QLatin1String( "X-SpousesName" ) ) );
239 setHashField( contactObject
, QLatin1String( "imAddress" ), rawContact
.custom( QLatin1String( "KADDRESSBOOK" ), QLatin1String( "X-IMAddress" ) ) );
243 QVariantList customFields
;
245 static QSet
<QString
> blacklistedKeys
;
246 if ( blacklistedKeys
.isEmpty() ) {
247 blacklistedKeys
.insert( QLatin1String( "CRYPTOPROTOPREF" ) );
248 blacklistedKeys
.insert( QLatin1String( "OPENPGPFP" ) );
249 blacklistedKeys
.insert( QLatin1String( "SMIMEFP" ) );
250 blacklistedKeys
.insert( QLatin1String( "CRYPTOSIGNPREF" ) );
251 blacklistedKeys
.insert( QLatin1String( "CRYPTOENCRYPTPREF" ) );
252 blacklistedKeys
.insert( QLatin1String( "Anniversary" ) );
253 blacklistedKeys
.insert( QLatin1String( "BlogFeed" ) );
254 blacklistedKeys
.insert( QLatin1String( "Profession" ) );
255 blacklistedKeys
.insert( QLatin1String( "Office" ) );
256 blacklistedKeys
.insert( QLatin1String( "ManagersName" ) );
257 blacklistedKeys
.insert( QLatin1String( "AssistantsName" ) );
258 blacklistedKeys
.insert( QLatin1String( "SpousesName" ) );
259 blacklistedKeys
.insert( QLatin1String( "IMAddress" ) );
260 blacklistedKeys
.insert( QLatin1String( "AddressBook" ) );
263 if ( !rawContact
.customs().empty() ) {
264 const QStringList customs
= rawContact
.customs();
265 foreach ( QString custom
, customs
) { //krazy:exclude=foreach
266 if ( custom
.startsWith( QLatin1String( "KADDRESSBOOK-" ) ) ) {
267 custom
.remove( QLatin1String( "KADDRESSBOOK-X-" ) );
268 custom
.remove( QLatin1String( "KADDRESSBOOK-" ) );
270 int pos
= custom
.indexOf( QLatin1Char( ':' ) );
271 QString key
= custom
.left( pos
);
272 QString value
= custom
.mid( pos
+ 1 );
274 if ( blacklistedKeys
.contains( key
) )
277 // check whether it is a custom local field
278 foreach ( const QVariantMap
&description
, customFieldDescriptions() ) {
279 if ( description
.value( QLatin1String( "key" ) ).toString() == key
) {
280 key
= description
.value( QLatin1String( "title" ) ).toString();
281 if ( description
.value( QLatin1String( "type" ) ) == QLatin1String( "boolean" ) ) {
282 if ( value
== QLatin1String( "true" ) )
283 value
= i18nc( "Boolean value", "yes" );
285 value
= i18nc( "Boolean value", "no" );
286 } else if ( description
.value( QLatin1String( "type" ) ) == QLatin1String( "date" ) ) {
287 const QDate date
= QDate::fromString( value
, Qt::ISODate
);
288 value
= KGlobal::locale()->formatDate( date
, KLocale::ShortDate
);
289 } else if ( description
.value( QLatin1String( "type" ) ) == QLatin1String( "time" ) ) {
290 const QTime time
= QTime::fromString( value
, Qt::ISODate
);
291 value
= KGlobal::locale()->formatTime( time
);
292 } else if ( description
.value( QLatin1String( "type" ) ) == QLatin1String( "datetime" ) ) {
293 const QDateTime dateTime
= QDateTime::fromString( value
, Qt::ISODate
);
294 value
= KGlobal::locale()->formatDateTime( dateTime
, KLocale::ShortDate
);
300 QVariantHash customFieldObject
;
301 customFieldObject
.insert( QLatin1String( "title" ), key
);
302 customFieldObject
.insert( QLatin1String( "value" ), value
);
304 customFields
.append( customFieldObject
);
309 contactObject
.insert( QLatin1String( "customFields" ), customFields
);
311 QVariantHash colorsObject
;
312 colorsObject
.insert( "linkColor", KColorScheme( QPalette::Active
, KColorScheme::View
).foreground().color().name() );
313 colorsObject
.insert( "textColor", KColorScheme( QPalette::Active
, KColorScheme::View
).foreground().color().name() );
314 colorsObject
.insert( "backgroundColor", KColorScheme( QPalette::Active
, KColorScheme::View
).background().color().name() );
316 QVariantHash mapping
;
317 mapping
.insert( "contact", contactObject
);
318 mapping
.insert( "colors", colorsObject
);
320 Grantlee::Context
context( mapping
);
322 if ( form
== SelfcontainedForm
)
323 return d
->mSelfcontainedTemplate
->render( &context
);
324 else if ( form
== EmbeddableForm
)
325 return d
->mEmbeddableTemplate
->render( &context
);