22 #include "standardcontactformatter.h"
24 #include <akonadi/item.h>
25 #include <kabc/addressee.h>
26 #include <kcolorscheme.h>
27 #include <kconfiggroup.h>
30 #include <klocalizedstring.h>
31 #include <kstringhandler.h>
33 #include <QtCore/QSet>
34 #include <QTextDocument>
36 using namespace Akonadi;
38 class StandardContactFormatter::Private
60 static int contactAge(
const QDate &date )
62 QDate now = QDate::currentDate();
63 int age = now.year() - date.year();
64 if ( date > now.addYears( -age ) ) {
72 KABC::Addressee rawContact;
73 const Akonadi::Item localItem =
item();
74 if ( localItem.isValid() && localItem.hasPayload<KABC::Addressee>() ) {
75 rawContact = localItem.payload<KABC::Addressee>();
80 if ( rawContact.isEmpty() ) {
90 QString rowFmtStr1 = QString::fromLatin1(
92 "<td align=\"right\" valign=\"top\" width=\"30%\"><b><font color=\"grey\">%1</font></b></td>\n"
93 "<td colspan=\"2\" align=\"left\" valign=\"top\" width=\"70%\"><font>%2</font></td>\n"
101 QString rowFmtStr2 = QString::fromLatin1(
102 "<tr valign=\"top\">"
103 "<td align=\"right\" valign=\"top\" width=\"30%\"><b><font color=\"grey\">%1</font></b></td>\n"
104 "<td align=\"left\" valign=\"top\"><font>%2</font></td>\n"
105 "<td align=\"left\" valign=\"top\">%3</td>\n"
113 const QDate date = rawContact.birthday().date();
114 const int years = contactAge( date );
116 if ( date.isValid() ) {
117 dynamicPart += rowFmtStr1
118 .arg( KABC::Addressee::birthdayLabel() )
119 .arg( KGlobal::locale()->formatDate( date ) +
120 QLatin1String(
" " ) + i18np(
"(One year old)",
"(%1 years old)", years ) );
125 foreach (
const KABC::PhoneNumber &number, rawContact.phoneNumbers() ) {
127 QString dispLabel = number.typeLabel().replace( QLatin1String(
" " ), QLatin1String(
" " ) );
128 QString dispValue = QString::fromLatin1(
"<a href=\"phone:?index=%1\">%2</a>" ).arg( counter ).arg( Qt::escape( number.number() ) );
129 if ( number.type() & KABC::PhoneNumber::Cell ) {
130 QString dispIcon = QString::fromLatin1(
"<a href=\"sms:?index=%1\" title=\"%2\"><img src=\"sms_icon\" align=\"top\"/>")
132 .arg( i18nc(
"@info:tooltip",
"Send SMS" ) );
133 dynamicPart += rowFmtStr2
138 dynamicPart += rowFmtStr1
147 foreach (
const QString &email, rawContact.emails() ) {
148 const QString type = i18nc(
"a contact's email address",
"Email" );
150 const QString fullEmail = QString::fromLatin1( KUrl::toPercentEncoding( rawContact.fullEmail( email ) ) );
152 dynamicPart += rowFmtStr1.arg( type )
153 .arg( QString::fromLatin1(
"<a href=\"mailto:%1\">%2</a>" )
154 .arg( fullEmail, email ) );
158 if ( rawContact.url().isValid() ) {
159 QString url = rawContact.url().url();
160 if ( !url.startsWith( QLatin1String(
"http://" ) ) && !url.startsWith( QLatin1String(
"https://" ) ) ) {
161 url = QLatin1String(
"http://" ) + url;
164 url = KStringHandler::tagUrls( Qt::escape( url ) );
165 dynamicPart += rowFmtStr1.arg( i18n(
"Homepage" ) ).arg( url );
169 const QString blog = rawContact.custom( QLatin1String(
"KADDRESSBOOK" ), QLatin1String(
"BlogFeed" ) );
170 if ( !blog.isEmpty() ) {
171 dynamicPart += rowFmtStr1.arg( i18n(
"Blog Feed" ) ).arg( KStringHandler::tagUrls( Qt::escape( blog ) ) );
176 foreach (
const KABC::Address &address, rawContact.addresses() ) {
177 QString formattedAddress;
179 if ( address.label().isEmpty() ) {
180 formattedAddress = Qt::escape( address.formattedAddress().trimmed() );
182 formattedAddress = Qt::escape( address.label() );
185 formattedAddress = formattedAddress.replace( QRegExp( QLatin1String(
"\n+" ) ), QLatin1String(
"<br>" ) );
187 const QString url = QString::fromLatin1(
"<a href=\"address:?index=%1\" title=\"%2\"><img src=\"map_icon\" alt=\"%2\"/></a>" )
189 .arg( i18nc(
"@info:tooltip",
"Show address on map" ) );
192 dynamicPart += rowFmtStr2
193 .arg( KABC::Address::typeLabel( address.type() ) )
194 .arg( formattedAddress )
200 if ( !rawContact.note().isEmpty() ) {
201 notes = rowFmtStr1.arg( i18n(
"Notes" ) ).arg( Qt::escape( rawContact.note() ).replace( QLatin1Char(
'\n' ), QLatin1String(
"<br>" ) ) ) ;
206 static QMap<QString, QString> titleMap;
207 if ( titleMap.isEmpty() ) {
208 titleMap.insert( QLatin1String(
"Department" ), i18n(
"Department" ) );
209 titleMap.insert( QLatin1String(
"Profession" ), i18n(
"Profession" ) );
210 titleMap.insert( QLatin1String(
"AssistantsName" ), i18n(
"Assistant's Name" ) );
211 titleMap.insert( QLatin1String(
"ManagersName" ), i18n(
"Manager's Name" ) );
212 titleMap.insert( QLatin1String(
"SpousesName" ), i18nc(
"Wife/Husband/...",
"Partner's Name" ) );
213 titleMap.insert( QLatin1String(
"Office" ), i18n(
"Office" ) );
214 titleMap.insert( QLatin1String(
"IMAddress" ), i18n(
"IM Address" ) );
215 titleMap.insert( QLatin1String(
"Anniversary" ), i18n(
"Anniversary" ) );
216 titleMap.insert( QLatin1String(
"AddressBook" ), i18n(
"Address Book" ) );
219 static QSet<QString> blacklistedKeys;
220 if ( blacklistedKeys.isEmpty() ) {
221 blacklistedKeys.insert( QLatin1String(
"CRYPTOPROTOPREF" ) );
222 blacklistedKeys.insert( QLatin1String(
"OPENPGPFP" ) );
223 blacklistedKeys.insert( QLatin1String(
"SMIMEFP" ) );
224 blacklistedKeys.insert( QLatin1String(
"CRYPTOSIGNPREF" ) );
225 blacklistedKeys.insert( QLatin1String(
"CRYPTOENCRYPTPREF" ) );
226 blacklistedKeys.insert( QLatin1String(
"MailPreferedFormatting" ) );
227 blacklistedKeys.insert( QLatin1String(
"MailAllowToRemoteContent" ) );
230 if ( !rawContact.customs().empty() ) {
231 const QStringList customs = rawContact.customs();
232 foreach ( QString custom, customs ) {
233 if ( custom.startsWith( QLatin1String(
"KADDRESSBOOK-" ) ) ) {
234 custom.remove( QLatin1String(
"KADDRESSBOOK-X-" ) );
235 custom.remove( QLatin1String(
"KADDRESSBOOK-" ) );
237 int pos = custom.indexOf( QLatin1Char(
':' ) );
238 QString key = custom.left( pos );
239 QString value = custom.mid( pos + 1 );
242 if ( key == QLatin1String(
"Anniversary" ) || key == QLatin1String(
"ANNIVERSARY" ) ) {
243 const QDateTime dateTime = QDateTime::fromString( value, Qt::ISODate );
244 value = KGlobal::locale()->formatDate( dateTime.date() );
245 }
else if ( key == QLatin1String(
"BlogFeed" ) ) {
247 }
else if ( blacklistedKeys.contains( key ) ) {
252 const QMap<QString, QString>::ConstIterator keyIt = titleMap.constFind( key );
253 bool needToEscape =
true;
254 if ( keyIt != titleMap.constEnd() ) {
259 if ( description.value( QLatin1String(
"key" ) ).toString() == key ) {
260 key = description.value( QLatin1String(
"title" ) ).toString();
261 const QString descriptionType = description.value( QLatin1String(
"type" ) ).toString();
262 if ( descriptionType == QLatin1String(
"boolean" ) ) {
263 if ( value == QLatin1String(
"true" ) ) {
264 value = i18nc(
"Boolean value",
"yes" );
266 value = i18nc(
"Boolean value",
"no" );
268 }
else if ( descriptionType == QLatin1String(
"date" ) ) {
269 const QDate date = QDate::fromString( value, Qt::ISODate );
270 value = KGlobal::locale()->formatDate( date, KLocale::ShortDate );
271 }
else if ( descriptionType == QLatin1String(
"time" ) ) {
272 const QTime time = QTime::fromString( value, Qt::ISODate );
273 value = KGlobal::locale()->formatTime( time );
274 }
else if ( descriptionType == QLatin1String(
"datetime" ) ) {
275 const QDateTime dateTime = QDateTime::fromString( value, Qt::ISODate );
276 value = KGlobal::locale()->formatDateTime( dateTime, KLocale::ShortDate );
277 }
else if ( descriptionType == QLatin1String(
"url") ) {
278 value = KStringHandler::tagUrls( Qt::escape(value) );
279 needToEscape =
false;
287 value = Qt::escape( value );
288 customData += rowFmtStr1.arg( key ).arg( value );
294 QString role = rawContact.title();
295 if ( role.isEmpty() ) {
296 role = rawContact.role();
298 if ( role.isEmpty() ) {
299 role = rawContact.custom( QLatin1String(
"KADDRESSBOOK" ), QLatin1String(
"X-Profession" ) );
302 QString strAddr = QString::fromLatin1(
303 "<div align=\"center\">"
304 "<table cellpadding=\"3\" cellspacing=\"1\">"
306 "<td align=\"right\" valign=\"top\" width=\"30%\" rowspan=\"3\">"
307 "<img src=\"%1\" width=\"100\" vspace=\"1\">"
309 "<td colspan=\"2\" align=\"left\" width=\"70%\"><font size=\"+2\"><b>%2</b></font></td>"
312 "<td colspan=\"2\" align=\"left\" width=\"70%\">%3</td>"
315 "<td colspan=\"2\" align=\"left\" width=\"70%\">%4</td>"
317 .arg( QLatin1String(
"contact_photo" ) )
318 .arg( Qt::escape( rawContact.realName() ) )
319 .arg( Qt::escape( role ) )
320 .arg( Qt::escape( rawContact.organization() ) );
322 strAddr.append( dynamicPart );
323 strAddr.append( notes );
324 strAddr.append( customData );
325 strAddr.append( QString::fromLatin1(
"</table>" ) );
328 if (d->displayQRcode) {
329 KConfig config( QLatin1String(
"akonadi_contactrc" ) );
330 KConfigGroup group( &config, QLatin1String(
"View" ) );
331 if ( group.readEntry(
"QRCodes",
true ) ) {
332 strAddr.append( QString::fromLatin1(
333 "<p align=\"center\">"
334 "<img src=\"%1\" vspace=\"1\">"
335 "<img src=\"%2\" vspace=\"1\">"
338 .arg( QLatin1String(
"datamatrix" ) )
339 .arg( QLatin1String(
"qrcode" ) ) );
342 #endif // HAVE_PRISON
344 strAddr.append( QString::fromLatin1(
"</div>\n" ) );
350 const QString document = QString::fromLatin1(
353 " <style type=\"text/css\">"
354 " a {text-decoration:none; color:%1}"
357 "<body text=\"%1\" bgcolor=\"%2\">"
361 .arg( KColorScheme( QPalette::Active, KColorScheme::View ).foreground().color().name() )
362 .arg( KColorScheme( QPalette::Active, KColorScheme::View ).background().color().name() )
368 void StandardContactFormatter::setDisplayQRCode(
bool show )
370 d->displayQRcode = show;
373 bool StandardContactFormatter::displayQRCode()
const
375 return d->displayQRcode;