• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdepimlibs-4.14.10 API Reference
  • KDE Home
  • Contact Us
 

akonadi

  • akonadi
  • contact
standardcontactformatter.cpp
1/*
2 This file is part of Akonadi Contact.
3
4 Copyright (c) 2010 Tobias Koenig <tokoe@kde.org>
5
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.
10
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.
15
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
19 02110-1301, USA.
20*/
21
22#include "standardcontactformatter.h"
23
24#include <akonadi/item.h>
25#include <kabc/addressee.h>
26#include <kcolorscheme.h>
27#include <kconfiggroup.h>
28#include <kglobal.h>
29#include <klocale.h>
30#include <klocalizedstring.h>
31#include <kstringhandler.h>
32
33#include <QtCore/QSet>
34#include <QTextDocument>
35
36using namespace Akonadi;
37
38class StandardContactFormatter::Private
39{
40public:
41 Private()
42 :displayQRcode(true)
43 {
44
45 }
46
47 bool displayQRcode;
48};
49
50StandardContactFormatter::StandardContactFormatter()
51 : d( new Private() )
52{
53}
54
55StandardContactFormatter::~StandardContactFormatter()
56{
57 delete d;
58}
59
60static int contactAge( const QDate &date )
61{
62 QDate now = QDate::currentDate();
63 int age = now.year() - date.year();
64 if ( date > now.addYears( -age ) ) {
65 age--;
66 }
67 return age;
68}
69
70QString StandardContactFormatter::toHtml( HtmlForm form ) const
71{
72 KABC::Addressee rawContact;
73 const Akonadi::Item localItem = item();
74 if ( localItem.isValid() && localItem.hasPayload<KABC::Addressee>() ) {
75 rawContact = localItem.payload<KABC::Addressee>();
76 } else {
77 rawContact = contact();
78 }
79
80 if ( rawContact.isEmpty() ) {
81 return QString();
82 }
83
84 // We'll be building a table to display the vCard in.
85 // Each row of the table will be built using one of these strings for its HTML.
86
87 // single data item:
88 // %1 is the item name
89 // %2 is the item value
90 QString rowFmtStr1 = QString::fromLatin1(
91 "<tr valign=\"top\">"
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"
94 "</tr>\n"
95 );
96
97 // data item plus additional icon(s):
98 // %1 is the item name
99 // %2 is the item value
100 // %3 is the icon(s), each as a HTML <a><img> tag
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"
106 "</tr>\n"
107 );
108
109 // Build the table's rows here
110 QString dynamicPart;
111
112 // Birthday
113 const QDate date = rawContact.birthday().date();
114 const int years = contactAge( date );
115
116 if ( date.isValid() ) {
117 dynamicPart += rowFmtStr1
118 .arg( KABC::Addressee::birthdayLabel() )
119 .arg( KGlobal::locale()->formatDate( date ) +
120 QLatin1String( "&nbsp;&nbsp;" ) + i18np( "(One year old)", "(%1 years old)", years ) );
121 }
122
123 // Phone Numbers
124 int counter = 0;
125 foreach ( const KABC::PhoneNumber &number, rawContact.phoneNumbers() ) {
126
127 QString dispLabel = number.typeLabel().replace( QLatin1String( " " ), QLatin1String( "&nbsp;" ) );
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\"/>")
131 .arg( counter )
132 .arg( i18nc( "@info:tooltip", "Send SMS" ) );
133 dynamicPart += rowFmtStr2
134 .arg( dispLabel )
135 .arg( dispValue )
136 .arg( dispIcon );
137 } else {
138 dynamicPart += rowFmtStr1
139 .arg( dispLabel )
140 .arg( dispValue );
141 }
142
143 ++counter;
144 }
145
146 // EMails
147 foreach ( const QString &email, rawContact.emails() ) {
148 const QString type = i18nc( "a contact's email address", "Email" );
149
150 const QString fullEmail = QString::fromLatin1( KUrl::toPercentEncoding( rawContact.fullEmail( email ) ) );
151
152 dynamicPart += rowFmtStr1.arg( type )
153 .arg( QString::fromLatin1( "<a href=\"mailto:%1\">%2</a>" )
154 .arg( fullEmail, email ) );
155 }
156
157 // Homepage
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;
162 }
163
164 url = KStringHandler::tagUrls( Qt::escape( url ) );
165 dynamicPart += rowFmtStr1.arg( i18n( "Homepage" ) ).arg( url );
166 }
167
168 // Blog Feed
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 ) ) );
172 }
173
174 // Addresses
175 counter = 0;
176 foreach ( const KABC::Address &address, rawContact.addresses() ) {
177 QString formattedAddress;
178
179 if ( address.label().isEmpty() ) {
180 formattedAddress = Qt::escape( address.formattedAddress().trimmed() );
181 } else {
182 formattedAddress = Qt::escape( address.label() );
183 }
184
185 formattedAddress = formattedAddress.replace( QRegExp( QLatin1String( "\n+" ) ), QLatin1String( "<br>" ) );
186
187 const QString url = QString::fromLatin1( "<a href=\"address:?index=%1\" title=\"%2\"><img src=\"map_icon\" alt=\"%2\"/></a>" )
188 .arg( counter )
189 .arg( i18nc( "@info:tooltip", "Show address on map" ) );
190 counter++;
191
192 dynamicPart += rowFmtStr2
193 .arg( KABC::Address::typeLabel( address.type() ) )
194 .arg( formattedAddress )
195 .arg( url );
196 }
197
198 // Note
199 QString notes;
200 if ( !rawContact.note().isEmpty() ) {
201 notes = rowFmtStr1.arg( i18n( "Notes" ) ).arg( Qt::escape( rawContact.note() ).replace( QLatin1Char( '\n' ), QLatin1String( "<br>" ) ) ) ;
202 }
203
204 // Custom Data
205 QString customData;
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" ) );
217 }
218
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" ) );
228 }
229
230 if ( !rawContact.customs().empty() ) {
231 const QStringList customs = rawContact.customs();
232 foreach ( QString custom, customs ) { //krazy:exclude=foreach
233 if ( custom.startsWith( QLatin1String( "KADDRESSBOOK-" ) ) ) {
234 custom.remove( QLatin1String( "KADDRESSBOOK-X-" ) );
235 custom.remove( QLatin1String( "KADDRESSBOOK-" ) );
236
237 int pos = custom.indexOf( QLatin1Char( ':' ) );
238 QString key = custom.left( pos );
239 QString value = custom.mid( pos + 1 );
240
241 // convert anniversary correctly
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" ) ) { // blog is handled separated
246 continue;
247 } else if ( blacklistedKeys.contains( key ) ) {
248 continue;
249 }
250
251 // check whether we have a mapping for the title
252 const QMap<QString, QString>::ConstIterator keyIt = titleMap.constFind( key );
253 bool needToEscape = true;
254 if ( keyIt != titleMap.constEnd() ) {
255 key = keyIt.value();
256 } else {
257 // check whether it is a custom local field
258 foreach ( const QVariantMap &description, customFieldDescriptions() ) {
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" );
265 } else {
266 value = i18nc( "Boolean value", "no" );
267 }
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;
280 }
281
282 break;
283 }
284 }
285 }
286 if (needToEscape)
287 value = Qt::escape( value );
288 customData += rowFmtStr1.arg( key ).arg( value );
289 }
290 }
291 }
292
293 // Assemble all parts
294 QString role = rawContact.title();
295 if ( role.isEmpty() ) {
296 role = rawContact.role();
297 }
298 if ( role.isEmpty() ) {
299 role = rawContact.custom( QLatin1String( "KADDRESSBOOK" ), QLatin1String( "X-Profession" ) );
300 }
301
302 QString strAddr = QString::fromLatin1(
303 "<div align=\"center\">"
304 "<table cellpadding=\"3\" cellspacing=\"1\">"
305 "<tr>"
306 "<td align=\"right\" valign=\"top\" width=\"30%\" rowspan=\"3\">"
307 "<img src=\"%1\" width=\"100\" vspace=\"1\">" // image
308 "</td>"
309 "<td colspan=\"2\" align=\"left\" width=\"70%\"><font size=\"+2\"><b>%2</b></font></td>" // name
310 "</tr>"
311 "<tr>"
312 "<td colspan=\"2\" align=\"left\" width=\"70%\">%3</td>" // role
313 "</tr>"
314 "<tr>"
315 "<td colspan=\"2\" align=\"left\" width=\"70%\">%4</td>" // organization
316 "</tr>")
317 .arg( QLatin1String( "contact_photo" ) )
318 .arg( Qt::escape( rawContact.realName() ) )
319 .arg( Qt::escape( role ) )
320 .arg( Qt::escape( rawContact.organization() ) );
321
322 strAddr.append( dynamicPart );
323 strAddr.append( notes );
324 strAddr.append( customData );
325 strAddr.append( QString::fromLatin1( "</table>" ) );
326
327#ifdef HAVE_PRISON
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\">"
336 "</p>"
337 )
338 .arg( QLatin1String( "datamatrix" ) )
339 .arg( QLatin1String( "qrcode" ) ) );
340 }
341 }
342#endif // HAVE_PRISON
343
344 strAddr.append( QString::fromLatin1( "</div>\n" ) );
345
346 if ( form == EmbeddableForm ) {
347 return strAddr;
348 }
349
350 const QString document = QString::fromLatin1(
351 "<html>"
352 "<head>"
353 " <style type=\"text/css\">"
354 " a {text-decoration:none; color:%1}"
355 " </style>"
356 "</head>"
357 "<body text=\"%1\" bgcolor=\"%2\">" // text and background color
358 "%3" // contact part
359 "</body>"
360 "</html>" )
361 .arg( KColorScheme( QPalette::Active, KColorScheme::View ).foreground().color().name() )
362 .arg( KColorScheme( QPalette::Active, KColorScheme::View ).background().color().name() )
363 .arg( strAddr );
364
365 return document;
366}
367
368void StandardContactFormatter::setDisplayQRCode( bool show )
369{
370 d->displayQRcode = show;
371}
372
373bool StandardContactFormatter::displayQRCode() const
374{
375 return d->displayQRcode;
376}
377
Akonadi::AbstractContactFormatter::item
Akonadi::Item item() const
Returns the item who's payload will be formatted.
Definition abstractcontactformatter.cpp:62
Akonadi::AbstractContactFormatter::customFieldDescriptions
QList< QVariantMap > customFieldDescriptions() const
Returns the custom field descriptions that will be used.
Definition abstractcontactformatter.cpp:72
Akonadi::AbstractContactFormatter::contact
KABC::Addressee contact() const
Returns the contact that will be formatted.
Definition abstractcontactformatter.cpp:52
Akonadi::AbstractContactFormatter::HtmlForm
HtmlForm
Describes the form of the HTML that is created.
Definition abstractcontactformatter.h:52
Akonadi::AbstractContactFormatter::EmbeddableForm
@ EmbeddableForm
Creates a div HTML element that can be embedded.
Definition abstractcontactformatter.h:54
Akonadi::StandardContactFormatter::~StandardContactFormatter
virtual ~StandardContactFormatter()
Destroys the standard contact formatter.
Definition standardcontactformatter.cpp:55
Akonadi::StandardContactFormatter::StandardContactFormatter
StandardContactFormatter()
Creates a new standard contact formatter.
Definition standardcontactformatter.cpp:50
Akonadi::StandardContactFormatter::toHtml
virtual QString toHtml(HtmlForm form=SelfcontainedForm) const
Returns the contact formatted as HTML.
Definition standardcontactformatter.cpp:70
Akonadi
FreeBusyManager::Singleton.
Definition actionstatemanager_p.h:28
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Wed Jan 24 2024 00:00:00 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

akonadi

Skip menu "akonadi"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • Related Pages

kdepimlibs-4.14.10 API Reference

Skip menu "kdepimlibs-4.14.10 API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal