From 460c52653ab0dcca6f19a4f492ed2c5e4e963ab0 Mon Sep 17 00:00:00 2001 From: toma Date: Wed, 25 Nov 2009 17:56:58 +0000 Subject: Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features. BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdepim@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da --- kmail/headerstyle.cpp | 983 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 983 insertions(+) create mode 100644 kmail/headerstyle.cpp (limited to 'kmail/headerstyle.cpp') diff --git a/kmail/headerstyle.cpp b/kmail/headerstyle.cpp new file mode 100644 index 000000000..26e615d90 --- /dev/null +++ b/kmail/headerstyle.cpp @@ -0,0 +1,983 @@ +/* -*- c++ -*- + headerstyle.cpp + + This file is part of KMail, the KDE mail client. + Copyright (c) 2003 Marc Mutz + + KMail is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License, version 2, as + published by the Free Software Foundation. + + KMail 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "headerstyle.h" + +#include "headerstrategy.h" +#include "kmkernel.h" +#include "linklocator.h" +#include "kmmessage.h" +#include "spamheaderanalyzer.h" +#include "globalsettings.h" + +#include +#include +using namespace KPIM; + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace KMail { + + // + // Convenience functions: + // + static inline QString directionOf( const QString & str ) { + return str.isRightToLeft() ? "rtl" : "ltr" ; + } + +#if 0 + // Converts to html. Changes URLs into href's, escapes HTML special + // chars and inserts the result into an
or tag with + // "dir" set to "rtl" or "ltr" depending on the direction of @p str. + static QString convertToHtmlBlock( const QString & str, bool useSpan=false ) { + QString dir = directionOf( str ); + QString format = "<%1 dir=\"%3\">%4"; + return format.arg( useSpan ? "span" : "div" ) + .arg( useSpan ? "span" : "div" ) + .arg( dir ) + .arg( LinkLocator::convertToHtml( str ) ); + } +#endif + + // ### tmp wrapper to make kmreaderwin code working: + static QString strToHtml( const QString & str, + int flags = LinkLocator::PreserveSpaces ) { + return LinkLocator::convertToHtml( str, flags ); + } + + // + // BriefHeaderStyle + // Show everything in a single line, don't show header field names. + // + + class BriefHeaderStyle : public HeaderStyle { + friend class ::KMail::HeaderStyle; + protected: + BriefHeaderStyle() : HeaderStyle() {} + virtual ~BriefHeaderStyle() {} + + public: + const char * name() const { return "brief"; } + const HeaderStyle * next() const { return plain(); } + const HeaderStyle * prev() const { return fancy(); } + + QString format( const KMMessage * message, const HeaderStrategy * strategy, + const QString & vCardName, bool printing, bool topLevel ) const; + }; + + QString BriefHeaderStyle::format( const KMMessage * message, + const HeaderStrategy * strategy, + const QString & vCardName, bool printing, bool topLevel ) const { + if ( !message ) return QString::null; + if ( !strategy ) + strategy = HeaderStrategy::brief(); + + // The direction of the header is determined according to the direction + // of the application layout. + + QString dir = QApplication::reverseLayout() ? "rtl" : "ltr" ; + + // However, the direction of the message subject within the header is + // determined according to the contents of the subject itself. Since + // the "Re:" and "Fwd:" prefixes would always cause the subject to be + // considered left-to-right, they are ignored when determining its + // direction. + + QString subjectDir; + if (!message->subject().isEmpty()) + subjectDir = directionOf( message->cleanSubject() ); + else + subjectDir = directionOf( i18n("No Subject") ); + + // Prepare the date string (when printing always use the localized date) + QString dateString; + if( printing ) { + QDateTime dateTime; + KLocale * locale = KGlobal::locale(); + dateTime.setTime_t( message->date() ); + dateString = locale->formatDateTime( dateTime ); + } else { + dateString = message->dateStr(); + } + + QString headerStr = "
\n"; + + if ( strategy->showHeader( "subject" ) ) + headerStr += "
\n" + "" + + strToHtml( message->subject() ) + + "
\n"; + + QStringList headerParts; + + if ( strategy->showHeader( "from" ) ) { + QString fromStr = message->from(); + if ( fromStr.isEmpty() ) // no valid email in from, maybe just a name + fromStr = message->fromStrip(); // let's use that + QString fromPart = KMMessage::emailAddrAsAnchor( fromStr, true ); + if ( !vCardName.isEmpty() ) + fromPart += "  " + i18n("[vCard]") + ""; + headerParts << fromPart; + } + + if ( strategy->showHeader( "cc" ) && !message->cc().isEmpty() ) + headerParts << i18n("CC: ") + KMMessage::emailAddrAsAnchor( message->cc(), true ); + + if ( strategy->showHeader( "bcc" ) && !message->bcc().isEmpty() ) + headerParts << i18n("BCC: ") + KMMessage::emailAddrAsAnchor( message->bcc(), true ); + + if ( strategy->showHeader( "date" ) ) + headerParts << strToHtml(message->dateShortStr()); + + // remove all empty (modulo whitespace) entries and joins them via ", \n" + headerStr += " (" + headerParts.grep( QRegExp( "\\S" ) ).join( ",\n" ) + ')'; + + headerStr += "
\n"; + + // ### iterate over the rest of strategy->headerToDisplay() (or + // ### all headers if DefaultPolicy == Display) (elsewhere, too) + return headerStr; + } + + // + // PlainHeaderStyle: + // show every header field on a line by itself, + // show subject larger + // + + class PlainHeaderStyle : public HeaderStyle { + friend class ::KMail::HeaderStyle; + protected: + PlainHeaderStyle() : HeaderStyle() {} + virtual ~PlainHeaderStyle() {} + + public: + const char * name() const { return "plain"; } + const HeaderStyle * next() const { return fancy(); } + const HeaderStyle * prev() const { return brief(); } + + QString format( const KMMessage * message, const HeaderStrategy * strategy, + const QString & vCardName, bool printing, bool topLevel ) const; + + private: + QString formatAllMessageHeaders( const KMMessage * message ) const; + }; + + QString PlainHeaderStyle::format( const KMMessage * message, + const HeaderStrategy * strategy, + const QString & vCardName, bool printing, bool topLevel ) const { + if ( !message ) return QString::null; + if ( !strategy ) + strategy = HeaderStrategy::rich(); + + // The direction of the header is determined according to the direction + // of the application layout. + + QString dir = ( QApplication::reverseLayout() ? "rtl" : "ltr" ); + + // However, the direction of the message subject within the header is + // determined according to the contents of the subject itself. Since + // the "Re:" and "Fwd:" prefixes would always cause the subject to be + // considered left-to-right, they are ignored when determining its + // direction. + + QString subjectDir; + if (!message->subject().isEmpty()) + subjectDir = directionOf( message->cleanSubject() ); + else + subjectDir = directionOf( i18n("No Subject") ); + + // Prepare the date string (when printing always use the localized date) + QString dateString; + if( printing ) { + QDateTime dateTime; + KLocale* locale = KGlobal::locale(); + dateTime.setTime_t( message->date() ); + dateString = locale->formatDateTime( dateTime ); + } + else { + dateString = message->dateStr(); + } + + QString headerStr; + + if ( strategy->headersToDisplay().isEmpty() + && strategy->defaultPolicy() == HeaderStrategy::Display ) { + // crude way to emulate "all" headers - Note: no strings have + // i18n(), so direction should always be ltr. + headerStr= QString("
"); + headerStr += formatAllMessageHeaders( message ); + return headerStr + "
"; + } + + headerStr = QString("
").arg(dir); + + //case HdrLong: + if ( strategy->showHeader( "subject" ) ) + headerStr += QString("
" + + strToHtml(message->subject()) + "
\n") + .arg(subjectDir); + + if ( strategy->showHeader( "date" ) ) + headerStr.append(i18n("Date: ") + strToHtml(dateString)+"
\n"); + +#if 0 + // Get Instant Messaging presence + QString presence; + QString kabcUid; + if ( strategy->showHeader( "status" ) ) + { + KABC::AddressBook *addressBook = KABC::StdAddressBook::self( true ); + KABC::AddresseeList addresses = addressBook->findByEmail( KPIM::getFirstEmailAddress( message->from() ) ); + ::KIMProxy *imProxy = KMKernel::self()->imProxy(); + kabcUid = addresses[0].uid(); + presence = imProxy->presenceString( kabcUid ); + } +#endif + + if ( strategy->showHeader( "from" ) ) { + QString fromStr = message->from(); + if ( fromStr.isEmpty() ) // no valid email in from, maybe just a name + fromStr = message->fromStrip(); // let's use that + headerStr.append(i18n("From: ") + + KMMessage::emailAddrAsAnchor( fromStr, false, "", true ) ); + if ( !vCardName.isEmpty() ) + headerStr.append("  " + i18n("[vCard]") + "" ); +#if 0 + if ( !presence.isEmpty() && strategy->showHeader( "status" ) ) + headerStr.append("  (" + presence + ")" ); +#endif + + if ( strategy->showHeader( "organization" ) + && !message->headerField("Organization").isEmpty()) + headerStr.append("  (" + + strToHtml(message->headerField("Organization")) + ")"); + headerStr.append("
\n"); + } + + if ( strategy->showHeader( "to" ) ) + headerStr.append(i18n("To: ")+ + KMMessage::emailAddrAsAnchor(message->to(),false) + "
\n"); + + if ( strategy->showHeader( "cc" ) && !message->cc().isEmpty() ) + headerStr.append(i18n("CC: ")+ + KMMessage::emailAddrAsAnchor(message->cc(),false) + "
\n"); + + if ( strategy->showHeader( "bcc" ) && !message->bcc().isEmpty() ) + headerStr.append(i18n("BCC: ")+ + KMMessage::emailAddrAsAnchor(message->bcc(),false) + "
\n"); + + if ( strategy->showHeader( "reply-to" ) && !message->replyTo().isEmpty()) + headerStr.append(i18n("Reply to: ")+ + KMMessage::emailAddrAsAnchor(message->replyTo(),false) + "
\n"); + + headerStr += "
\n"; + + return headerStr; + } + + QString PlainHeaderStyle::formatAllMessageHeaders( const KMMessage * message ) const { + const DwHeaders & headers = message->headers(); + QString result; + + for ( const DwField * field = headers.FirstField() ; field ; field = field->Next() ) { + result += ( field->FieldNameStr() + ": " ).c_str(); + result += strToHtml( field->FieldBodyStr().c_str() ); + result += "
\n"; + } + + return result; + } + + // + // FancyHeaderStyle: + // Like PlainHeaderStyle, but with slick frames and background colours. + // + + class FancyHeaderStyle : public HeaderStyle { + friend class ::KMail::HeaderStyle; + protected: + FancyHeaderStyle() : HeaderStyle() {} + virtual ~FancyHeaderStyle() {} + + public: + const char * name() const { return "fancy"; } + const HeaderStyle * next() const { return enterprise(); } + const HeaderStyle * prev() const { return plain(); } + + QString format( const KMMessage * message, const HeaderStrategy * strategy, + const QString & vCardName, bool printing, bool topLevel ) const; + static QString imgToDataUrl( const QImage & image, + const char *fmt = "PNG" ); + + private: + static QString drawSpamMeter( double percent, const QString & filterHeader ); + + }; + + QString FancyHeaderStyle::drawSpamMeter( double percent, + const QString & filterHeader ) + { + QImage meterBar( 20, 1, 8, 24 ); + const unsigned short gradient[20][3] = { + { 0, 255, 0 }, + { 27, 254, 0 }, + { 54, 252, 0 }, + { 80, 250, 0 }, + { 107, 249, 0 }, + { 135, 247, 0 }, + { 161, 246, 0 }, + { 187, 244, 0 }, + { 214, 242, 0 }, + { 241, 241, 0 }, + { 255, 228, 0 }, + { 255, 202, 0 }, + { 255, 177, 0 }, + { 255, 151, 0 }, + { 255, 126, 0 }, + { 255, 101, 0 }, + { 255, 76, 0 }, + { 255, 51, 0 }, + { 255, 25, 0 }, + { 255, 0, 0 } + }; + meterBar.setColor( 21, qRgb( 255, 255, 255 ) ); + meterBar.setColor( 22, qRgb( 170, 170, 170 ) ); + if ( percent < 0 ) // grey is for errors + meterBar.fill( 22 ); + else { + meterBar.fill( 21 ); + int max = QMIN( 20, static_cast( percent ) / 5 ); + for ( int i = 0; i < max; ++i ) { + meterBar.setColor( i+1, qRgb( gradient[i][0], gradient[i][1], + gradient[i][2] ) ); + meterBar.setPixel( i, 0, i+1 ); + } + } + QString titleText = i18n("%1% probability of being spam.\n\nFull report:\n%2") + .arg( QString::number( percent ), filterHeader ); + return QString("  ") + .arg( imgToDataUrl( meterBar, "PPM" ), QString::number( 20 ), + QString::number( 5 ), titleText ); + } + + + QString FancyHeaderStyle::format( const KMMessage * message, + const HeaderStrategy * strategy, + const QString & vCardName, bool printing, bool topLevel ) const { + if ( !message ) return QString::null; + if ( !strategy ) + strategy = HeaderStrategy::rich(); + + KConfigGroup configReader( KMKernel::config(), "Reader" ); + + // ### from kmreaderwin begin + // The direction of the header is determined according to the direction + // of the application layout. + + QString dir = ( QApplication::reverseLayout() ? "rtl" : "ltr" ); + QString headerStr = QString("
\n").arg(dir); + + // However, the direction of the message subject within the header is + // determined according to the contents of the subject itself. Since + // the "Re:" and "Fwd:" prefixes would always cause the subject to be + // considered left-to-right, they are ignored when determining its + // direction. + + QString subjectDir; + if ( !message->subject().isEmpty() ) + subjectDir = directionOf( message->cleanSubject() ); + else + subjectDir = directionOf( i18n("No Subject") ); + + // Prepare the date string (when printing always use the localized date) + QString dateString; + if( printing ) { + QDateTime dateTime; + KLocale* locale = KGlobal::locale(); + dateTime.setTime_t( message->date() ); + dateString = locale->formatDateTime( dateTime ); + } + else { + dateString = message->dateStr(); + } + + // Spam header display. + // If the spamSpamStatus config value is true then we look for headers + // from a few spam filters and try to create visually meaningful graphics + // out of the spam scores. + + QString spamHTML; + + if ( configReader.readBoolEntry( "showSpamStatus", true ) ) { + SpamScores scores = SpamHeaderAnalyzer::getSpamScores( message ); + for ( SpamScoresIterator it = scores.begin(); it != scores.end(); ++it ) + spamHTML += (*it).agent() + " " + + drawSpamMeter( (*it).score(), (*it).spamHeader() ); + } + + QString userHTML; + QString presence; + + // IM presence and kabc photo + + ::KIMProxy *imProxy = KMKernel::self()->imProxy(); + QString kabcUid; + KABC::AddressBook *addressBook = KABC::StdAddressBook::self( true ); + KABC::AddresseeList addresses = addressBook->findByEmail( KPIM::getFirstEmailAddress( message->from() ) ); + + QString photoURL; + int photoWidth = 60; + int photoHeight = 60; + if( addresses.count() == 1 ) + { + // kabcUid is embedded in im: URIs to indicate which IM contact to message + kabcUid = addresses[0].uid(); + + if ( imProxy->initialize() ) { + // im status + presence = imProxy->presenceString( kabcUid ); + if ( !presence.isEmpty() ) + { + QString presenceIcon = QString::fromLatin1( " " ) + .arg( imgToDataUrl( imProxy->presenceIcon( kabcUid ).convertToImage() ) ); + presence += presenceIcon; + } + } + // picture + if ( addresses[0].photo().isIntern() ) + { + // get photo data and convert to data: url + //kdDebug( 5006 ) << "INTERNAL photo found" << endl; + QImage photo = addresses[0].photo().data(); + if ( !photo.isNull() ) + { + photoWidth = photo.width(); + photoHeight = photo.height(); + // scale below 60, otherwise it can get way too large + if ( photoHeight > 60 ) { + double ratio = ( double )photoHeight / ( double )photoWidth; + photoHeight = 60; + photoWidth = (int)( 60 / ratio ); + photo = photo.smoothScale( photoWidth, photoHeight ); + } + photoURL = imgToDataUrl( photo ); + } + } + else + { + //kdDebug( 5006 ) << "URL found" << endl; + photoURL = addresses[0].photo().url(); + if ( photoURL.startsWith("/") ) + photoURL.prepend( "file:" ); + } + } + else // TODO: find a usable one + { + kdDebug( 5006 ) << "Multiple / No addressees matched email address; Count is " << addresses.count() << endl; + userHTML = " "; + } + + if( photoURL.isEmpty() ) { + // no photo, look for a Face header + QString faceheader = message->headerField( "Face" ); + if ( !faceheader.isEmpty() ) { + QImage faceimage; + + kdDebug( 5006 ) << "Found Face: header" << endl; + + QCString facestring = faceheader.utf8(); + // Spec says header should be less than 998 bytes + // Face: is 5 characters + if ( facestring.length() < 993 ) { + QByteArray facearray; + KCodecs::base64Decode(facestring, facearray); + + QImage faceimage; + if ( faceimage.loadFromData( facearray, "png" ) ) { + // Spec says image must be 48x48 pixels + if ( (48 == faceimage.width()) && (48 == faceimage.height()) ) { + photoURL = imgToDataUrl( faceimage ); + photoWidth = 48; + photoHeight = 48; + } else { + kdDebug( 5006 ) << "Face: header image is" << faceimage.width() << "by" << faceimage.height() <<"not 48x48 Pixels" << endl; + } + } else { + kdDebug( 5006 ) << "Failed to load decoded png from Face: header" << endl; + } + } else { + kdDebug( 5006 ) << "Face: header too long at " << facestring.length() << endl; + } + } + } + + if( photoURL.isEmpty() ) + { + // no photo, look for a X-Face header + QString xfaceURL; + QString xfhead = message->headerField( "X-Face" ); + if ( !xfhead.isEmpty() ) + { + KXFace xf; + photoURL = imgToDataUrl( xf.toImage( xfhead ) ); + photoWidth = 48; + photoHeight = 48; + + } + } + + if( !photoURL.isEmpty() ) + { + //kdDebug( 5006 ) << "Got a photo: " << photoURL << endl; + userHTML = QString("") + .arg( photoURL ).arg( photoWidth ).arg( photoHeight ); + if ( presence.isEmpty() ) { + userHTML = QString("
") + userHTML + "
"; + } else { + userHTML = QString( "
" + "%2
" + "%4
" + "
" ).arg( kabcUid ) + .arg( userHTML ) + .arg( kabcUid ) + .arg( presence ); + } + } else { + // we don't have a photo, just show presence, if we have it + if ( !presence.isEmpty() ) + userHTML = QString( "
" + "%3
" ) + .arg( kabcUid ) + .arg( kabcUid ) + .arg( presence ); + } +#if 0 + // Disabled 'Launch IM' link in headers - Will + if ( imProxy->imAppsAvailable() ) + presence = "" + i18n("Launch IM") + ""; + // do nothing - no im apps available, leave presence empty + //presence = i18n( "DCOP/InstantMessenger not installed" ); + kdDebug( 5006 ) << "final presence: '" << presence << "'" << endl; +#endif + + + //case HdrFancy: + // the subject line and box below for details + if ( strategy->showHeader( "subject" ) ) { + const int flags = LinkLocator::PreserveSpaces | + ( GlobalSettings::self()->showEmoticons() ? + LinkLocator::ReplaceSmileys : 0 ); + headerStr += QString("
%2
\n") + .arg(subjectDir) + .arg(message->subject().isEmpty()? + i18n("No Subject") : + strToHtml( message->subject(), flags )); + } + headerStr += "
\n"; + //headerStr += "
\n"; + // from line + // the mailto: URLs can contain %3 etc., therefore usage of multiple + // QString::arg is not possible + if ( strategy->showHeader( "from" ) ) { + QString fromStr = message->from(); + if ( fromStr.isEmpty() ) // no valid email in from, maybe just a name + fromStr = message->fromStrip(); // let's use that + headerStr += QString("\n" + "\n"; + } + // to line + if ( strategy->showHeader( "to" ) ) + headerStr.append(QString("\n" + "\n") + .arg(i18n("To: ")) + .arg(KMMessage::emailAddrAsAnchor(message->to(),false))); + + // cc line, if any + if ( strategy->showHeader( "cc" ) && !message->cc().isEmpty()) + headerStr.append(QString("\n" + "\n") + .arg(i18n("CC: ")) + .arg(KMMessage::emailAddrAsAnchor(message->cc(),false))); + + // Bcc line, if any + if ( strategy->showHeader( "bcc" ) && !message->bcc().isEmpty()) + headerStr.append(QString("\n" + "\n") + .arg(i18n("BCC: ")) + .arg(KMMessage::emailAddrAsAnchor(message->bcc(),false))); + + if ( strategy->showHeader( "date" ) ) + headerStr.append(QString("\n" + "\n") + .arg(i18n("Date: ")) + .arg( directionOf( message->dateStr() ) ) + .arg(strToHtml(dateString))); + + if ( GlobalSettings::self()->showUserAgent() ) { + if ( strategy->showHeader( "user-agent" ) ) { + if ( !message->headerField("User-Agent").isEmpty() ) { + headerStr.append(QString("\n" + "\n") + .arg(i18n("User-Agent: ")) + .arg( strToHtml( message->headerField("User-Agent") ) ) ); + } + } + + if ( strategy->showHeader( "x-mailer" ) ) { + if ( !message->headerField("X-Mailer").isEmpty() ) { + headerStr.append(QString("\n" + "\n") + .arg(i18n("X-Mailer: ")) + .arg( strToHtml( message->headerField("X-Mailer") ) ) ); + } + } + } + + // FIXME: Show status in synthetic header style field. Decide whether this or current in brackets style is best and remove one. + /* if( strategy->showHeader( "status" ) ) + headerStr.append( QString( "\n" + "\n") + .arg(i18n("Sender status: ")) + .arg( directionOf( onlineStatus ) ) + .arg(onlineStatus)); + */ + headerStr.append( QString("" ) ); + headerStr.append( + QString( "
%1") + .arg(i18n("From: ")) + + KMMessage::emailAddrAsAnchor( fromStr, false ) + + ( !message->headerField( "Resent-From" ).isEmpty() ? " " + + i18n("(resent from %1)") + .arg( KMMessage::emailAddrAsAnchor( + message->headerField( "Resent-From" ),false) ) + : QString("") ) + + ( !vCardName.isEmpty() ? "  " + + i18n("[vCard]") + "" + : QString("") ) +#if 0 + + ( ( !presence.isEmpty() ) + ? "  (" + presence + ")" + : QString("") ) +#endif + + ( message->headerField("Organization").isEmpty() + ? QString("") + : "  (" + + strToHtml(message->headerField("Organization")) + + ")") + + "
%1%2
%1%2
%1%2
%1%3
%1%2
%1%2
%1%3
%1
\n" ).arg(userHTML) ); + + if ( !spamHTML.isEmpty() ) + headerStr.append( QString( "
%2 %3
\n") + .arg( subjectDir, i18n("Spam Status:"), spamHTML ) ); + + headerStr += "
\n\n"; + return headerStr; + } + + QString FancyHeaderStyle::imgToDataUrl( const QImage &image, const char* fmt ) + { + QByteArray ba; + QBuffer buffer( ba ); + buffer.open( IO_WriteOnly ); + image.save( &buffer, fmt ); + return QString::fromLatin1("data:image/%1;base64,%2") + .arg( fmt, KCodecs::base64Encode( ba ) ); + } + +// ##################### + + class EnterpriseHeaderStyle : public HeaderStyle { + friend class ::KMail::HeaderStyle; + protected: + EnterpriseHeaderStyle() : HeaderStyle() {} + virtual ~EnterpriseHeaderStyle() {} + + public: + const char * name() const { return "enterprise"; } + const HeaderStyle * next() const { return brief(); } + const HeaderStyle * prev() const { return fancy(); } + + QString format( const KMMessage * message, const HeaderStrategy * strategy, + const QString & vCardName, bool printing, bool topLevel ) const; + }; + + QString EnterpriseHeaderStyle::format( const KMMessage * message, + const HeaderStrategy * strategy, + const QString & vCardName, bool printing, bool topLevel ) const { + if ( !message ) return QString::null; + if ( !strategy ) + strategy = HeaderStrategy::brief(); + + // The direction of the header is determined according to the direction + // of the application layout. + + QString dir = QApplication::reverseLayout() ? "rtl" : "ltr" ; + + // However, the direction of the message subject within the header is + // determined according to the contents of the subject itself. Since + // the "Re:" and "Fwd:" prefixes would always cause the subject to be + // considered left-to-right, they are ignored when determining its + // direction. + + QString subjectDir; + if (!message->subject().isEmpty()) + subjectDir = directionOf( message->cleanSubject() ); + else + subjectDir = directionOf( i18n("No Subject") ); + + // colors depend on if its encapsulated or not + QColor fontColor(Qt::white); + QString linkColor = "class =\"white\""; + const QColor activeColor = qApp->palette().active().highlight(); + QColor activeColorDark = activeColor.dark(130); + // reverse colors for encapsulated + if( !topLevel ){ + activeColorDark = activeColor.dark(50); + fontColor = qApp->palette().active().text(); + linkColor = ""; + } + + QStringList headerParts; + if( strategy->showHeader( "to" ) ) + headerParts << KMMessage::emailAddrAsAnchor( message->to(), false, linkColor ); + + if ( strategy->showHeader( "cc" ) && !message->cc().isEmpty() ) + headerParts << i18n("CC: ") + KMMessage::emailAddrAsAnchor( message->cc(), true, linkColor ); + + if ( strategy->showHeader( "bcc" ) && !message->bcc().isEmpty() ) + headerParts << i18n("BCC: ") + KMMessage::emailAddrAsAnchor( message->bcc(), true, linkColor ); + + // remove all empty (modulo whitespace) entries and joins them via ", \n" + QString headerPart = " " + headerParts.grep( QRegExp( "\\S" ) ).join( ", " ); + + // Prepare the date string (when printing always use the localized date) + QString dateString; + if( printing ) { + QDateTime dateTime; + KLocale * locale = KGlobal::locale(); + dateTime.setTime_t( message->date() ); + dateString = locale->formatDateTime( dateTime ); + } else { + dateString = message->dateStr(); + } + + QString imgpath(locate("data","kmail/pics/")); + imgpath.append("enterprise_"); + const QString borderSettings(" padding-top: 0px; padding-bottom: 0px; border-width: 0px "); + QString headerStr (""); + + // 3D borders + if(topLevel) + headerStr += + "
 
" + "
 
"; + + headerStr += "" + "
"+dateString+"
" + // #0057ae + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "
\n" + " \n"; + + // subject + //strToHtml( message->subject() ) + if ( strategy->showHeader( "subject" ) ){ + headerStr += + " \n" + " \n" + " \n" + " \n"; + } + + // from + if ( strategy->showHeader( "from" ) ){ + QString fromStr = message->from(); + if ( fromStr.isEmpty() ) // no valid email in from, maybe just a name + fromStr = message->fromStrip(); // let's use that + // TODO vcard + QString fromPart = KMMessage::emailAddrAsAnchor( fromStr, true, linkColor ); + if ( !vCardName.isEmpty() ) + fromPart += "  " + i18n("[vCard]") + ""; + //TDDO strategy date + //if ( strategy->showHeader( "date" ) ) + headerStr += + " \n" + " \n" + " " + " "; + } + + // to, cc, bcc + headerStr += + " " + " " + " " + " "; + + // header-bottom + headerStr += + "
"+message->subject()+"
"+i18n("From: ")+""+ fromPart +"
"+i18n("To: ")+"" + +headerPart+ + "
\n" + "
\n" + " \n" + "
\n"; + + // kmail icon + if(topLevel) { + headerStr += + "
\n" + "\n" + "
\n"; + + // attachments + headerStr += + "
" + "
" + "
\n"; + } + + headerStr += "
"; + + // TODO + // spam status + // ### iterate over the rest of strategy->headerToDisplay() (or + // ### all headers if DefaultPolicy == Display) (elsewhere, too) + return headerStr; + } + +// ##################### + + // + // HeaderStyle abstract base: + // + + HeaderStyle::HeaderStyle() { + + } + + HeaderStyle::~HeaderStyle() { + + } + + const HeaderStyle * HeaderStyle::create( Type type ) { + switch ( type ) { + case Brief: return brief(); + case Plain: return plain(); + case Fancy: return fancy(); + case Enterprise: return enterprise(); + } + kdFatal( 5006 ) << "HeaderStyle::create(): Unknown header style ( type == " + << (int)type << " ) requested!" << endl; + return 0; // make compiler happy + } + + const HeaderStyle * HeaderStyle::create( const QString & type ) { + QString lowerType = type.lower(); + if ( lowerType == "brief" ) return brief(); + if ( lowerType == "plain" ) return plain(); + if ( lowerType == "enterprise" ) return enterprise(); + //if ( lowerType == "fancy" ) return fancy(); // not needed, see below + // don't kdFatal here, b/c the strings are user-provided + // (KConfig), so fail gracefully to the default: + return fancy(); + } + + static const HeaderStyle * briefStyle = 0; + static const HeaderStyle * plainStyle = 0; + static const HeaderStyle * fancyStyle = 0; + static const HeaderStyle * enterpriseStyle = 0; + + const HeaderStyle * HeaderStyle::brief() { + if ( !briefStyle ) + briefStyle = new BriefHeaderStyle(); + return briefStyle; + } + + const HeaderStyle * HeaderStyle::plain() { + if ( !plainStyle ) + plainStyle = new PlainHeaderStyle(); + return plainStyle; + } + + const HeaderStyle * HeaderStyle::fancy() { + if ( !fancyStyle ) + fancyStyle = new FancyHeaderStyle(); + return fancyStyle; + } + + const HeaderStyle * HeaderStyle::enterprise() { + if ( !enterpriseStyle ) + enterpriseStyle = new EnterpriseHeaderStyle(); + return enterpriseStyle; + } + +} // namespace KMail -- cgit v1.2.1