/* This file is part of Akonadi Contact. Copyright (c) 2010 Tobias Koenig This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "standardcontactformatter.h" #include #include #include #include #include #include #include #include #include #include using namespace Akonadi; class StandardContactFormatter::Private { public: Private() :displayQRcode(true) { } bool displayQRcode; }; StandardContactFormatter::StandardContactFormatter() : d( new Private() ) { } StandardContactFormatter::~StandardContactFormatter() { delete d; } static int contactAge( const QDate &date ) { QDate now = QDate::currentDate(); int age = now.year() - date.year(); if ( date > now.addYears( -age ) ) { age--; } return age; } QString StandardContactFormatter::toHtml( HtmlForm form ) const { KABC::Addressee rawContact; const Akonadi::Item localItem = item(); if ( localItem.isValid() && localItem.hasPayload() ) { rawContact = localItem.payload(); } else { rawContact = contact(); } if ( rawContact.isEmpty() ) { return QString(); } // We'll be building a table to display the vCard in. // Each row of the table will be built using one of these strings for its HTML. // single data item: // %1 is the item name // %2 is the item value QString rowFmtStr1 = QString::fromLatin1( "" "%1\n" "%2\n" "\n" ); // data item plus additional icon(s): // %1 is the item name // %2 is the item value // %3 is the icon(s), each as a HTML tag QString rowFmtStr2 = QString::fromLatin1( "" "%1\n" "%2\n" "%3\n" "\n" ); // Build the table's rows here QString dynamicPart; // Birthday const QDate date = rawContact.birthday().date(); const int years = contactAge( date ); if ( date.isValid() ) { dynamicPart += rowFmtStr1 .arg( KABC::Addressee::birthdayLabel() ) .arg( KGlobal::locale()->formatDate( date ) + QLatin1String( "  " ) + i18np( "(One year old)", "(%1 years old)", years ) ); } // Phone Numbers int counter = 0; foreach ( const KABC::PhoneNumber &number, rawContact.phoneNumbers() ) { QString dispLabel = number.typeLabel().replace( QLatin1String( " " ), QLatin1String( " " ) ); QString dispValue = QString::fromLatin1( "%2" ).arg( counter ).arg( Qt::escape( number.number() ) ); if ( number.type() & KABC::PhoneNumber::Cell ) { QString dispIcon = QString::fromLatin1( "") .arg( counter ) .arg( i18nc( "@info:tooltip", "Send SMS" ) ); dynamicPart += rowFmtStr2 .arg( dispLabel ) .arg( dispValue ) .arg( dispIcon ); } else { dynamicPart += rowFmtStr1 .arg( dispLabel ) .arg( dispValue ); } ++counter; } // EMails foreach ( const QString &email, rawContact.emails() ) { const QString type = i18nc( "a contact's email address", "Email" ); const QString fullEmail = QString::fromLatin1( KUrl::toPercentEncoding( rawContact.fullEmail( email ) ) ); dynamicPart += rowFmtStr1.arg( type ) .arg( QString::fromLatin1( "%2" ) .arg( fullEmail, email ) ); } // Homepage if ( rawContact.url().isValid() ) { QString url = rawContact.url().url(); if ( !url.startsWith( QLatin1String( "http://" ) ) && !url.startsWith( QLatin1String( "https://" ) ) ) { url = QLatin1String( "http://" ) + url; } url = KStringHandler::tagUrls( Qt::escape( url ) ); dynamicPart += rowFmtStr1.arg( i18n( "Homepage" ) ).arg( url ); } // Blog Feed const QString blog = rawContact.custom( QLatin1String( "KADDRESSBOOK" ), QLatin1String( "BlogFeed" ) ); if ( !blog.isEmpty() ) { dynamicPart += rowFmtStr1.arg( i18n( "Blog Feed" ) ).arg( KStringHandler::tagUrls( Qt::escape( blog ) ) ); } // Addresses counter = 0; foreach ( const KABC::Address &address, rawContact.addresses() ) { QString formattedAddress; if ( address.label().isEmpty() ) { formattedAddress = Qt::escape( address.formattedAddress().trimmed() ); } else { formattedAddress = Qt::escape( address.label() ); } formattedAddress = formattedAddress.replace( QRegExp( QLatin1String( "\n+" ) ), QLatin1String( "
" ) ); const QString url = QString::fromLatin1( "\"%2\"/" ) .arg( counter ) .arg( i18nc( "@info:tooltip", "Show address on map" ) ); counter++; dynamicPart += rowFmtStr2 .arg( KABC::Address::typeLabel( address.type() ) ) .arg( formattedAddress ) .arg( url ); } // Note QString notes; if ( !rawContact.note().isEmpty() ) { notes = rowFmtStr1.arg( i18n( "Notes" ) ).arg( Qt::escape( rawContact.note() ).replace( QLatin1Char( '\n' ), QLatin1String( "
" ) ) ) ; } // Custom Data QString customData; static QMap titleMap; if ( titleMap.isEmpty() ) { titleMap.insert( QLatin1String( "Department" ), i18n( "Department" ) ); titleMap.insert( QLatin1String( "Profession" ), i18n( "Profession" ) ); titleMap.insert( QLatin1String( "AssistantsName" ), i18n( "Assistant's Name" ) ); titleMap.insert( QLatin1String( "ManagersName" ), i18n( "Manager's Name" ) ); titleMap.insert( QLatin1String( "SpousesName" ), i18nc( "Wife/Husband/...", "Partner's Name" ) ); titleMap.insert( QLatin1String( "Office" ), i18n( "Office" ) ); titleMap.insert( QLatin1String( "IMAddress" ), i18n( "IM Address" ) ); titleMap.insert( QLatin1String( "Anniversary" ), i18n( "Anniversary" ) ); titleMap.insert( QLatin1String( "AddressBook" ), i18n( "Address Book" ) ); } static QSet blacklistedKeys; if ( blacklistedKeys.isEmpty() ) { blacklistedKeys.insert( QLatin1String( "CRYPTOPROTOPREF" ) ); blacklistedKeys.insert( QLatin1String( "OPENPGPFP" ) ); blacklistedKeys.insert( QLatin1String( "SMIMEFP" ) ); blacklistedKeys.insert( QLatin1String( "CRYPTOSIGNPREF" ) ); blacklistedKeys.insert( QLatin1String( "CRYPTOENCRYPTPREF" ) ); blacklistedKeys.insert( QLatin1String( "MailPreferedFormatting" ) ); blacklistedKeys.insert( QLatin1String( "MailAllowToRemoteContent" ) ); } if ( !rawContact.customs().empty() ) { const QStringList customs = rawContact.customs(); foreach ( QString custom, customs ) { //krazy:exclude=foreach if ( custom.startsWith( QLatin1String( "KADDRESSBOOK-" ) ) ) { custom.remove( QLatin1String( "KADDRESSBOOK-X-" ) ); custom.remove( QLatin1String( "KADDRESSBOOK-" ) ); int pos = custom.indexOf( QLatin1Char( ':' ) ); QString key = custom.left( pos ); QString value = custom.mid( pos + 1 ); // convert anniversary correctly if ( key == QLatin1String( "Anniversary" ) || key == QLatin1String( "ANNIVERSARY" ) ) { const QDateTime dateTime = QDateTime::fromString( value, Qt::ISODate ); value = KGlobal::locale()->formatDate( dateTime.date() ); } else if ( key == QLatin1String( "BlogFeed" ) ) { // blog is handled separated continue; } else if ( blacklistedKeys.contains( key ) ) { continue; } // check whether we have a mapping for the title const QMap::ConstIterator keyIt = titleMap.constFind( key ); bool needToEscape = true; if ( keyIt != titleMap.constEnd() ) { key = keyIt.value(); } else { // check whether it is a custom local field foreach ( const QVariantMap &description, customFieldDescriptions() ) { if ( description.value( QLatin1String( "key" ) ).toString() == key ) { key = description.value( QLatin1String( "title" ) ).toString(); const QString descriptionType = description.value( QLatin1String( "type" ) ).toString(); if ( descriptionType == QLatin1String( "boolean" ) ) { if ( value == QLatin1String( "true" ) ) { value = i18nc( "Boolean value", "yes" ); } else { value = i18nc( "Boolean value", "no" ); } } else if ( descriptionType == QLatin1String( "date" ) ) { const QDate date = QDate::fromString( value, Qt::ISODate ); value = KGlobal::locale()->formatDate( date, KLocale::ShortDate ); } else if ( descriptionType == QLatin1String( "time" ) ) { const QTime time = QTime::fromString( value, Qt::ISODate ); value = KGlobal::locale()->formatTime( time ); } else if ( descriptionType == QLatin1String( "datetime" ) ) { const QDateTime dateTime = QDateTime::fromString( value, Qt::ISODate ); value = KGlobal::locale()->formatDateTime( dateTime, KLocale::ShortDate ); } else if ( descriptionType == QLatin1String("url") ) { value = KStringHandler::tagUrls( Qt::escape(value) ); needToEscape = false; } break; } } } if (needToEscape) value = Qt::escape( value ); customData += rowFmtStr1.arg( key ).arg( value ); } } } // Assemble all parts QString role = rawContact.title(); if ( role.isEmpty() ) { role = rawContact.role(); } if ( role.isEmpty() ) { role = rawContact.custom( QLatin1String( "KADDRESSBOOK" ), QLatin1String( "X-Profession" ) ); } QString strAddr = QString::fromLatin1( "
" "" "" "" "" // name "" "" "" // role "" "" "" // organization "") .arg( QLatin1String( "contact_photo" ) ) .arg( Qt::escape( rawContact.realName() ) ) .arg( Qt::escape( role ) ) .arg( Qt::escape( rawContact.organization() ) ); strAddr.append( dynamicPart ); strAddr.append( notes ); strAddr.append( customData ); strAddr.append( QString::fromLatin1( "
" "" // image "%2
%3
%4
" ) ); #ifdef HAVE_PRISON if (d->displayQRcode) { KConfig config( QLatin1String( "akonadi_contactrc" ) ); KConfigGroup group( &config, QLatin1String( "View" ) ); if ( group.readEntry( "QRCodes", true ) ) { strAddr.append( QString::fromLatin1( "

" "" "" "

" ) .arg( QLatin1String( "datamatrix" ) ) .arg( QLatin1String( "qrcode" ) ) ); } } #endif // HAVE_PRISON strAddr.append( QString::fromLatin1( "
\n" ) ); if ( form == EmbeddableForm ) { return strAddr; } const QString document = QString::fromLatin1( "" "" " " "" "" // text and background color "%3" // contact part "" "" ) .arg( KColorScheme( QPalette::Active, KColorScheme::View ).foreground().color().name() ) .arg( KColorScheme( QPalette::Active, KColorScheme::View ).background().color().name() ) .arg( strAddr ); return document; } void StandardContactFormatter::setDisplayQRCode( bool show ) { d->displayQRcode = show; } bool StandardContactFormatter::displayQRCode() const { return d->displayQRcode; }