• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdepimlibs-4.9.4 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 <kstringhandler.h>
31 
32 #include <QtCore/QSet>
33 
34 using namespace Akonadi;
35 
36 class StandardContactFormatter::Private
37 {
38 public:
39  Private()
40  :displayQRcode(true)
41  {
42 
43  }
44 
45  bool displayQRcode;
46 };
47 
48 StandardContactFormatter::StandardContactFormatter()
49  : d( new Private() )
50 {
51 }
52 
53 StandardContactFormatter::~StandardContactFormatter()
54 {
55  delete d;
56 }
57 
58 static int contactAge( const QDate &date )
59 {
60  QDate now = QDate::currentDate();
61  int age = now.year() - date.year();
62  if ( date > now.addYears( -age ) ) {
63  age--;
64  }
65  return age;
66 }
67 
68 QString StandardContactFormatter::toHtml( HtmlForm form ) const
69 {
70  KABC::Addressee rawContact;
71  const Akonadi::Item localItem = item();
72  if ( localItem.isValid() && localItem.hasPayload<KABC::Addressee>() )
73  rawContact = localItem.payload<KABC::Addressee>();
74  else
75  rawContact = contact();
76 
77  if ( rawContact.isEmpty() )
78  return QString();
79 
80  // We'll be building a table to display the vCard in.
81  // Each row of the table will be built using this string for its HTML.
82 
83  QString rowFmtStr = QString::fromLatin1(
84  "<tr>"
85  "<td align=\"right\" valign=\"top\" width=\"30%\"><b><font color=\"grey\">%1</font></b></td>\n"
86  "<td align=\"left\" valign=\"top\" width=\"70%\"><font>%2</font></td>\n"
87  "</tr>\n"
88  );
89 
90  // Build the table's rows here
91  QString dynamicPart;
92 
93  // Birthday
94  const QDate date = rawContact.birthday().date();
95  const int years = contactAge( date );
96 
97  if ( date.isValid() )
98  dynamicPart += rowFmtStr
99  .arg( KABC::Addressee::birthdayLabel() )
100  .arg( KGlobal::locale()->formatDate( date ) +
101  QLatin1String( "&nbsp;&nbsp;" ) + i18np( "(One year old)", "(%1 years old)", years ) );
102 
103  // Phone Numbers
104  int counter = 0;
105  foreach ( const KABC::PhoneNumber &number, rawContact.phoneNumbers() ) {
106 
107  QString url;
108  if ( number.type() & KABC::PhoneNumber::Cell )
109  url = QString::fromLatin1( "<a href=\"phone:?index=%1\">%2</a> (<a href=\"sms:?index=%1\">SMS</a>)" ).arg( counter ).arg( number.number() );
110  else
111  url = QString::fromLatin1( "<a href=\"phone:?index=%1\">%2</a>" ).arg( counter ).arg( number.number() );
112 
113  counter++;
114 
115  dynamicPart += rowFmtStr
116  .arg( number.typeLabel().replace( QLatin1String( " " ), QLatin1String( "&nbsp;" ) ) )
117  .arg( url );
118  }
119 
120  // EMails
121  foreach ( const QString &email, rawContact.emails() ) {
122  QString type = i18nc( "a contact's email address", "Email" );
123 
124  const QString fullEmail = QString::fromLatin1( KUrl::toPercentEncoding( rawContact.fullEmail( email ) ) );
125 
126  dynamicPart += rowFmtStr.arg( type )
127  .arg( QString::fromLatin1( "<a href=\"mailto:%1\">%2</a>" )
128  .arg( fullEmail, email ) );
129  }
130 
131  // Homepage
132  if ( rawContact.url().isValid() ) {
133  QString url = rawContact.url().url();
134  if ( !url.startsWith( QLatin1String( "http://" ) ) && !url.startsWith( QLatin1String( "https://" ) ) )
135  url = QLatin1String( "http://" ) + url;
136 
137  url = KStringHandler::tagUrls( url );
138  dynamicPart += rowFmtStr.arg( i18n( "Homepage" ) ).arg( url );
139  }
140 
141  // Blog Feed
142  const QString blog = rawContact.custom( QLatin1String( "KADDRESSBOOK" ), QLatin1String( "BlogFeed" ) );
143  if ( !blog.isEmpty() )
144  dynamicPart += rowFmtStr.arg( i18n( "Blog Feed" ) ).arg( KStringHandler::tagUrls( blog ) );
145 
146  // Addresses
147  counter = 0;
148  foreach ( const KABC::Address &address, rawContact.addresses() ) {
149  QString formattedAddress;
150 
151  if ( address.label().isEmpty() ) {
152  formattedAddress = address.formattedAddress().trimmed();
153  } else {
154  formattedAddress = address.label();
155  }
156 
157  formattedAddress = formattedAddress.replace( QLatin1Char( '\n' ), QLatin1String( "<br>" ) );
158 
159  const QString url = QString::fromLatin1( "%1 <a href=\"address:?index=%2\"><img src=\"map_icon\" alt=\"%3\"/></a>" )
160  .arg( formattedAddress )
161  .arg( counter )
162  .arg( i18n( "Show address on map" ) );
163  counter++;
164 
165  dynamicPart += rowFmtStr
166  .arg( KABC::Address::typeLabel( address.type() ) )
167  .arg( url );
168  }
169 
170  // Note
171  QString notes;
172  if ( !rawContact.note().isEmpty() )
173  notes = rowFmtStr.arg( i18n( "Notes" ) ).arg( rawContact.note().replace( QLatin1Char( '\n' ), QLatin1String( "<br>" ) ) ) ;
174 
175  // Custom Data
176  QString customData;
177  static QMap<QString, QString> titleMap;
178  if ( titleMap.isEmpty() ) {
179  titleMap.insert( QLatin1String( "Department" ), i18n( "Department" ) );
180  titleMap.insert( QLatin1String( "Profession" ), i18n( "Profession" ) );
181  titleMap.insert( QLatin1String( "AssistantsName" ), i18n( "Assistant's Name" ) );
182  titleMap.insert( QLatin1String( "ManagersName" ), i18n( "Manager's Name" ) );
183  titleMap.insert( QLatin1String( "SpousesName" ), i18nc( "Wife/Husband/...", "Partner's Name" ) );
184  titleMap.insert( QLatin1String( "Office" ), i18n( "Office" ) );
185  titleMap.insert( QLatin1String( "IMAddress" ), i18n( "IM Address" ) );
186  titleMap.insert( QLatin1String( "Anniversary" ), i18n( "Anniversary" ) );
187  titleMap.insert( QLatin1String( "AddressBook" ), i18n( "Address Book" ) );
188  }
189 
190  static QSet<QString> blacklistedKeys;
191  if ( blacklistedKeys.isEmpty() ) {
192  blacklistedKeys.insert( QLatin1String( "CRYPTOPROTOPREF" ) );
193  blacklistedKeys.insert( QLatin1String( "OPENPGPFP" ) );
194  blacklistedKeys.insert( QLatin1String( "SMIMEFP" ) );
195  blacklistedKeys.insert( QLatin1String( "CRYPTOSIGNPREF" ) );
196  blacklistedKeys.insert( QLatin1String( "CRYPTOENCRYPTPREF" ) );
197  blacklistedKeys.insert( QLatin1String( "MailPreferedFormatting" ) );
198  blacklistedKeys.insert( QLatin1String( "MailAllowToRemoteContent") );
199  }
200 
201  if ( !rawContact.customs().empty() ) {
202  const QStringList customs = rawContact.customs();
203  foreach ( QString custom, customs ) { //krazy:exclude=foreach
204  if ( custom.startsWith( QLatin1String( "KADDRESSBOOK-" ) ) ) {
205  custom.remove( QLatin1String( "KADDRESSBOOK-X-" ) );
206  custom.remove( QLatin1String( "KADDRESSBOOK-" ) );
207 
208  int pos = custom.indexOf( QLatin1Char( ':' ) );
209  QString key = custom.left( pos );
210  QString value = custom.mid( pos + 1 );
211 
212  // convert anniversary correctly
213  if ( key == QLatin1String( "Anniversary" ) || key == QLatin1String( "ANNIVERSARY" ) ) {
214  const QDateTime dateTime = QDateTime::fromString( value, Qt::ISODate );
215  value = KGlobal::locale()->formatDate( dateTime.date() );
216  }
217 
218  // blog is handled separated
219  else if ( key == QLatin1String( "BlogFeed" ) )
220  continue;
221 
222  else if ( blacklistedKeys.contains( key ) )
223  continue;
224 
225  // check whether we have a mapping for the title
226  const QMap<QString, QString>::ConstIterator keyIt = titleMap.constFind( key );
227  if ( keyIt != titleMap.constEnd() ) {
228  key = keyIt.value();
229  } else {
230  // check whether it is a custom local field
231  foreach ( const QVariantMap &description, customFieldDescriptions() ) {
232  if ( description.value( QLatin1String( "key" ) ).toString() == key ) {
233  key = description.value( QLatin1String( "title" ) ).toString();
234  if ( description.value( QLatin1String( "type" ) ) == QLatin1String( "boolean" ) ) {
235  if ( value == QLatin1String( "true" ) )
236  value = i18nc( "Boolean value", "yes" );
237  else
238  value = i18nc( "Boolean value", "no" );
239  } else if ( description.value( QLatin1String( "type" ) ) == QLatin1String( "date" ) ) {
240  const QDate date = QDate::fromString( value, Qt::ISODate );
241  value = KGlobal::locale()->formatDate( date, KLocale::ShortDate );
242  } else if ( description.value( QLatin1String( "type" ) ) == QLatin1String( "time" ) ) {
243  const QTime time = QTime::fromString( value, Qt::ISODate );
244  value = KGlobal::locale()->formatTime( time );
245  } else if ( description.value( QLatin1String( "type" ) ) == QLatin1String( "datetime" ) ) {
246  const QDateTime dateTime = QDateTime::fromString( value, Qt::ISODate );
247  value = KGlobal::locale()->formatDateTime( dateTime, KLocale::ShortDate );
248  }
249  break;
250  }
251  }
252  }
253 
254  customData += rowFmtStr.arg( key ).arg( value ) ;
255  }
256  }
257  }
258 
259  // Assemble all parts
260  QString role = rawContact.title();
261  if ( role.isEmpty() )
262  role = rawContact.role();
263  if ( role.isEmpty() )
264  role = rawContact.custom( QLatin1String( "KADDRESSBOOK" ), QLatin1String( "X-Profession" ) );
265 
266  QString strAddr = QString::fromLatin1(
267  "<div align=\"center\">"
268  "<table cellpadding=\"3\" cellspacing=\"0\">"
269  "<tr>"
270  "<td align=\"right\" valign=\"top\" width=\"30%\" rowspan=\"3\">"
271  "<img src=\"%1\" width=\"100\" vspace=\"1\">" // image
272  "</td>"
273  "<td align=\"left\" width=\"70%\"><font size=\"+2\"><b>%2</b></font></td>" // name
274  "</tr>"
275  "<tr>"
276  "<td align=\"left\" width=\"70%\">%3</td>" // role
277  "</tr>"
278  "<tr>"
279  "<td align=\"left\" width=\"70%\">%4</td>" // organization
280  "</tr>")
281  .arg( QLatin1String( "contact_photo" ) )
282  .arg( rawContact.realName() )
283  .arg( role )
284  .arg( rawContact.organization() );
285 
286  strAddr.append( dynamicPart );
287  strAddr.append( notes );
288  strAddr.append( customData );
289  strAddr.append( QString::fromLatin1( "</table>" ) );
290 
291 #ifdef HAVE_PRISON
292  if(d->displayQRcode) {
293  KConfig config( QLatin1String( "akonadi_contactrc" ) );
294  KConfigGroup group( &config, QLatin1String( "View" ) );
295  if ( group.readEntry( "QRCodes", true ) ) {
296  strAddr.append( QString::fromLatin1(
297  "<p align=\"center\">"
298  "<img src=\"%1\" vspace=\"1\">"
299  "<img src=\"%2\" vspace=\"1\">"
300  "</p>"
301  )
302  .arg( QLatin1String( "datamatrix" ) )
303  .arg( QLatin1String( "qrcode" ) ) );
304  }
305  }
306 #endif // HAVE_PRISON
307 
308  strAddr.append( QString::fromLatin1( "</div>\n" ) );
309 
310  if ( form == EmbeddableForm )
311  return strAddr;
312 
313  const QString document = QString::fromLatin1(
314  "<html>"
315  "<head>"
316  " <style type=\"text/css\">"
317  " a {text-decoration:none; color:%1}"
318  " </style>"
319  "</head>"
320  "<body text=\"%1\" bgcolor=\"%2\">" // text and background color
321  "%3" // contact part
322  "</body>"
323  "</html>" )
324  .arg( KColorScheme( QPalette::Active, KColorScheme::View ).foreground().color().name() )
325  .arg( KColorScheme( QPalette::Active, KColorScheme::View ).background().color().name() )
326  .arg( strAddr );
327 
328  return document;
329 }
330 
331 void StandardContactFormatter::setDisplayQRCode( bool show )
332 {
333  d->displayQRcode = show;
334 }
335 
336 bool StandardContactFormatter::displayQRCode() const
337 {
338  return d->displayQRcode;
339 }
340 
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Tue Dec 11 2012 12:14:35 by doxygen 1.8.1.2 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
  • Modules
  • Related Pages

kdepimlibs-4.9.4 API Reference

Skip menu "kdepimlibs-4.9.4 API Reference"
  • akonadi
  •   contact
  •   kmime
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  •   richtextbuilders
  • 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