kmail Library API Documentation

headerstyle.cpp

00001 /*  -*- c++ -*-
00002     headerstyle.cpp
00003 
00004     This file is part of KMail, the KDE mail client.
00005     Copyright (c) 2003 Marc Mutz <mutz@kde.org>
00006 
00007     KMail is free software; you can redistribute it and/or modify it
00008     under the terms of the GNU General Public License, version 2, as
00009     published by the Free Software Foundation.
00010 
00011     KMail is distributed in the hope that it will be useful, but
00012     WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014     General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; if not, write to the Free Software
00018     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020     In addition, as a special exception, the copyright holders give
00021     permission to link the code of this program with any edition of
00022     the Qt library by Trolltech AS, Norway (or with modified versions
00023     of Qt that use the same license as Qt), and distribute linked
00024     combinations including the two.  You must obey the GNU General
00025     Public License in all respects for all of the code used other than
00026     Qt.  If you modify this file, you may extend this exception to
00027     your version of the file, but you are not obligated to do so.  If
00028     you do not wish to do so, delete this exception statement from
00029     your version.
00030 */
00031 
00032 #ifdef HAVE_CONFIG_H
00033 #include <config.h>
00034 #endif
00035 
00036 #include "headerstyle.h"
00037 
00038 #include "headerstrategy.h"
00039 #include "linklocator.h"
00040 #include "kmmessage.h"
00041 #include "kmkernel.h"
00042 
00043 #include <libkdepim/email.h>
00044 
00045 #include <mimelib/string.h>
00046 #include <mimelib/field.h>
00047 #include <mimelib/headers.h>
00048 
00049 #include <kdebug.h>
00050 #include <klocale.h>
00051 #include <kglobal.h>
00052 #include "kimproxy.h"
00053 #include <kabc/stdaddressbook.h>
00054 #include <kabc/addresseelist.h>
00055 #include <kmdcodec.h>
00056 #include <qdatetime.h>
00057 #include <qbuffer.h>
00058 #include <qimage.h>
00059 #include <qapplication.h>
00060 #include <qregexp.h>
00061 
00062 #include <kmime_header_parsing.h>
00063 using KMime::Types::AddrSpecList;
00064 #include <libkpimidentities/identity.h>
00065 #include <libkpimidentities/identitymanager.h>
00066 
00067 namespace KMail {
00068 
00069   //
00070   // Convenience functions:
00071   //
00072   static inline QString directionOf( const QString & str ) {
00073     return str.isRightToLeft() ? "rtl" : "ltr" ;
00074   }
00075 
00076 #if 0
00077   // Converts to html. Changes URLs into href's, escapes HTML special
00078   // chars and inserts the result into an <div> or <span> tag with
00079   // "dir" set to "rtl" or "ltr" depending on the direction of @p str.
00080   static QString convertToHtmlBlock( const QString & str, bool useSpan=false ) {
00081     QString dir = directionOf( str );
00082     QString format = "<%1 dir=\"%3\">%4</%2>";
00083     return format.arg( useSpan ? "span" : "div" )
00084                  .arg( useSpan ? "span" : "div" )
00085                  .arg( dir )
00086                  .arg( LinkLocator::convertToHtml( str ) );
00087   }
00088 #endif
00089 
00090   // ### tmp wrapper to make kmreaderwin code working:
00091   static QString strToHtml( const QString & str, bool preserveBlanks=true ) {
00092     return LinkLocator::convertToHtml( str, preserveBlanks );
00093   }
00094 
00095   //
00096   // BriefHeaderStyle
00097   //   Show everything in a single line, don't show header field names.
00098   //
00099 
00100   class BriefHeaderStyle : public HeaderStyle {
00101     friend class HeaderStyle;
00102   protected:
00103     BriefHeaderStyle() : HeaderStyle() {}
00104     virtual ~BriefHeaderStyle() {}
00105 
00106   public:
00107     const char * name() const { return "brief"; }
00108     const HeaderStyle * next() const { return plain(); }
00109     const HeaderStyle * prev() const { return minimal(); }
00110 
00111     QString format( const KMMessage * message, const HeaderStrategy * strategy,
00112             const QString & vCardName, bool printing ) const;
00113   };
00114 
00115   QString BriefHeaderStyle::format( const KMMessage * message,
00116                     const HeaderStrategy * strategy,
00117                     const QString & vCardName, bool printing ) const {
00118     if ( !message ) return QString::null;
00119     if ( !strategy )
00120       strategy = HeaderStrategy::brief();
00121 
00122     // The direction of the header is determined according to the direction
00123     // of the application layout.
00124 
00125     QString dir = QApplication::reverseLayout() ? "rtl" : "ltr" ;
00126 
00127     // However, the direction of the message subject within the header is
00128     // determined according to the contents of the subject itself. Since
00129     // the "Re:" and "Fwd:" prefixes would always cause the subject to be
00130     // considered left-to-right, they are ignored when determining its
00131     // direction.
00132 
00133     QString subjectDir;
00134     if (!message->subject().isEmpty())
00135       subjectDir = directionOf( message->cleanSubject() );
00136     else
00137       subjectDir = directionOf( i18n("No Subject") );
00138 
00139     // Prepare the date string (when printing always use the localized date)
00140     QString dateString;
00141     if( printing ) {
00142       QDateTime dateTime;
00143       KLocale * locale = KGlobal::locale();
00144       dateTime.setTime_t( message->date() );
00145       dateString = locale->formatDateTime( dateTime );
00146     } else {
00147       dateString = message->dateStr();
00148     }
00149 
00150     QString headerStr = "<div class=\"header\" dir=\"" + dir + "\">\n";
00151 
00152     if ( strategy->showHeader( "subject" ) )
00153       headerStr += "<div dir=\"" + subjectDir + "\">\n"
00154                "<b style=\"font-size:130%\">" +
00155                strToHtml( message->subject() ) +
00156                "</b></div>\n";
00157 
00158     QStringList headerParts;
00159 
00160     if ( strategy->showHeader( "from" ) ) {
00161       QString fromStr = message->from();
00162       if ( fromStr.isEmpty() ) // no valid email in from, maybe just a name
00163         fromStr = message->fromStrip(); // let's use that
00164       QString fromPart = KMMessage::emailAddrAsAnchor( fromStr, true );
00165       if ( !vCardName.isEmpty() )
00166         fromPart += "&nbsp;&nbsp;<a href=\"" + vCardName + "\">" + i18n("[vCard]") + "</a>";
00167       headerParts << fromPart;
00168     }
00169 
00170     if ( strategy->showHeader( "cc" ) && !message->cc().isEmpty() )
00171       headerParts << i18n("CC: ") + KMMessage::emailAddrAsAnchor( message->cc(), true );
00172 
00173     if ( strategy->showHeader( "bcc" ) && !message->bcc().isEmpty() )
00174       headerParts << i18n("BCC: ") + KMMessage::emailAddrAsAnchor( message->bcc(), true );
00175 
00176     if ( strategy->showHeader( "date" ) )
00177       headerParts << strToHtml(message->dateShortStr());
00178 
00179     // remove all empty (modulo whitespace) entries and joins them via ", \n"
00180     headerStr += " (" + headerParts.grep( QRegExp( "\\S" ) ).join( ",\n" ) + ')';
00181 
00182     headerStr += "</div>\n";
00183 
00184     // ### iterate over the rest of strategy->headerToDisplay() (or
00185     // ### all headers if DefaultPolicy == Display) (elsewhere, too)
00186     return headerStr;
00187   }
00188 
00189   //
00190   // PlainHeaderStyle:
00191   //   show every header field on a line by itself,
00192   //   show subject larger
00193   //
00194 
00195   class PlainHeaderStyle : public HeaderStyle {
00196     friend class HeaderStyle;
00197   protected:
00198     PlainHeaderStyle() : HeaderStyle() {}
00199     virtual ~PlainHeaderStyle() {}
00200 
00201   public:
00202     const char * name() const { return "plain"; }
00203     const HeaderStyle * next() const { return fancy(); }
00204     const HeaderStyle * prev() const { return brief(); }
00205 
00206     QString format( const KMMessage * message, const HeaderStrategy * strategy,
00207             const QString & vCardName, bool printing ) const;
00208 
00209   private:
00210     QString formatAllMessageHeaders( const KMMessage * message ) const;
00211   };
00212 
00213   QString PlainHeaderStyle::format( const KMMessage * message,
00214                     const HeaderStrategy * strategy,
00215                     const QString & vCardName, bool printing ) const {
00216     if ( !message ) return QString::null;
00217     if ( !strategy )
00218       strategy = HeaderStrategy::rich();
00219 
00220     // The direction of the header is determined according to the direction
00221     // of the application layout.
00222 
00223     QString dir = ( QApplication::reverseLayout() ? "rtl" : "ltr" );
00224 
00225     // However, the direction of the message subject within the header is
00226     // determined according to the contents of the subject itself. Since
00227     // the "Re:" and "Fwd:" prefixes would always cause the subject to be
00228     // considered left-to-right, they are ignored when determining its
00229     // direction.
00230 
00231     QString subjectDir;
00232     if (!message->subject().isEmpty())
00233       subjectDir = directionOf( message->cleanSubject() );
00234     else
00235       subjectDir = directionOf( i18n("No Subject") );
00236 
00237     // Prepare the date string (when printing always use the localized date)
00238     QString dateString;
00239     if( printing ) {
00240       QDateTime dateTime;
00241       KLocale* locale = KGlobal::locale();
00242       dateTime.setTime_t( message->date() );
00243       dateString = locale->formatDateTime( dateTime );
00244     }
00245     else {
00246       dateString = message->dateStr();
00247     }
00248 
00249     QString headerStr = QString("<div class=\"header\" dir=\"%1\">").arg(dir);
00250 
00251     if ( strategy->headersToDisplay().isEmpty()
00252      && strategy->defaultPolicy() == HeaderStrategy::Display ) {
00253       // crude way to emulate "all" headers:
00254       headerStr += formatAllMessageHeaders( message );
00255       return headerStr + "</div>";
00256     }
00257 
00258     //case HdrLong:
00259     if ( strategy->showHeader( "subject" ) )
00260       headerStr += QString("<div dir=\"%1\"><b style=\"font-size:130%\">" +
00261                strToHtml(message->subject()) + "</b></div>\n")
00262                         .arg(subjectDir);
00263 
00264     if ( strategy->showHeader( "date" ) )
00265       headerStr.append(i18n("Date: ") + strToHtml(dateString)+"<br>\n");
00266 
00267     // Get Instant Messaging presence
00268     QString presence;
00269     QString kabcUid;
00270     if ( strategy->showHeader( "status" ) )
00271     {
00272       KABC::AddressBook *addressBook = KABC::StdAddressBook::self();
00273       KABC::AddresseeList addresses = addressBook->findByEmail( KPIM::getEmailAddr( message->from() ) );
00274       ::KIMProxy *imProxy = KMKernel::self()->imProxy();
00275       kabcUid = addresses[0].uid();
00276       presence = imProxy->presenceString( kabcUid );
00277     }
00278 
00279     if ( strategy->showHeader( "from" ) ) {
00280       QString fromStr = message->from();
00281       if ( fromStr.isEmpty() ) // no valid email in from, maybe just a name
00282         fromStr = message->fromStrip(); // let's use that
00283       headerStr.append(i18n("From: ") +
00284           KMMessage::emailAddrAsAnchor( fromStr, false) );
00285       if ( !vCardName.isEmpty() )
00286         headerStr.append("&nbsp;&nbsp;<a href=\"" + vCardName +
00287               "\">" + i18n("[vCard]") + "</a>" );
00288       if ( !presence.isEmpty() && strategy->showHeader( "status" ) )
00289         headerStr.append("&nbsp;&nbsp;(<span name=\"presence-" + kabcUid + "\">" + presence + "</span>)" );
00290       if ( strategy->showHeader( "organization" )
00291           && !message->headerField("Organization").isEmpty())
00292         headerStr.append("&nbsp;&nbsp;(" +
00293               strToHtml(message->headerField("Organization")) + ")");
00294       headerStr.append("<br>\n");
00295     }
00296 
00297     if ( strategy->showHeader( "to" ) )
00298       headerStr.append(i18n("To: ")+
00299                KMMessage::emailAddrAsAnchor(message->to(),FALSE) + "<br>\n");
00300 
00301     if ( strategy->showHeader( "cc" ) && !message->cc().isEmpty() )
00302       headerStr.append(i18n("CC: ")+
00303                        KMMessage::emailAddrAsAnchor(message->cc(),FALSE) + "<br>\n");
00304 
00305     if ( strategy->showHeader( "bcc" ) && !message->bcc().isEmpty() )
00306       headerStr.append(i18n("BCC: ")+
00307                        KMMessage::emailAddrAsAnchor(message->bcc(),FALSE) + "<br>\n");
00308 
00309     if ( strategy->showHeader( "reply-to" ) && !message->replyTo().isEmpty())
00310       headerStr.append(i18n("Reply to: ")+
00311                      KMMessage::emailAddrAsAnchor(message->replyTo(),FALSE) + "<br>\n");
00312 
00313     headerStr += "</div>\n";
00314 
00315     return headerStr;
00316   }
00317 
00318   QString PlainHeaderStyle::formatAllMessageHeaders( const KMMessage * message ) const {
00319     const DwHeaders & headers = message->headers();
00320     QString result;
00321 
00322     for ( const DwField * field = headers.FirstField() ; field ; field = field->Next() ) {
00323       result += ( field->FieldNameStr() + ": " ).c_str();
00324       result += strToHtml( field->FieldBodyStr().c_str() );
00325       result += "<br>\n";
00326     }
00327 
00328     return result;
00329   }
00330 
00331   //
00332   // FancyHeaderStyle:
00333   //   Like PlainHeaderStyle, but with slick frames and background colours.
00334   //
00335 
00336   class FancyHeaderStyle : public HeaderStyle {
00337     friend class HeaderStyle;
00338   protected:
00339     FancyHeaderStyle() : HeaderStyle() {}
00340     virtual ~FancyHeaderStyle() {}
00341 
00342   public:
00343     const char * name() const { return "fancy"; }
00344     const HeaderStyle * next() const { return minimal(); }
00345     const HeaderStyle * prev() const { return brief(); }
00346 
00347     QString format( const KMMessage * message, const HeaderStrategy * strategy,
00348             const QString & vCardName, bool printing ) const;
00349     static QString imgToDataUrl( const QImage &image );
00350 
00351   };
00352 
00353   QString FancyHeaderStyle::format( const KMMessage * message,
00354                     const HeaderStrategy * strategy,
00355                     const QString & vCardName, bool printing ) const {
00356     if ( !message ) return QString::null;
00357     if ( !strategy )
00358       strategy = HeaderStrategy::rich();
00359 
00360     // ### from kmreaderwin begin
00361     // The direction of the header is determined according to the direction
00362     // of the application layout.
00363 
00364     QString dir = ( QApplication::reverseLayout() ? "rtl" : "ltr" );
00365     QString headerStr = QString("<div class=\"fancy header\" dir=\"%1\">\n").arg(dir);
00366 
00367     // However, the direction of the message subject within the header is
00368     // determined according to the contents of the subject itself. Since
00369     // the "Re:" and "Fwd:" prefixes would always cause the subject to be
00370     // considered left-to-right, they are ignored when determining its
00371     // direction.
00372 
00373     QString subjectDir;
00374     if ( !message->subject().isEmpty() )
00375       subjectDir = directionOf( message->cleanSubject() );
00376     else
00377       subjectDir = directionOf( i18n("No Subject") );
00378 
00379     // Prepare the date string (when printing always use the localized date)
00380     QString dateString;
00381     if( printing ) {
00382       QDateTime dateTime;
00383       KLocale* locale = KGlobal::locale();
00384       dateTime.setTime_t( message->date() );
00385       dateString = locale->formatDateTime( dateTime );
00386     }
00387     else {
00388       dateString = message->dateStr();
00389     }
00390 
00391     QString userHTML;
00392     QString presence;
00393 
00394     // IM presence and kabc photo
00395     // Check first that KIMProxy has any IM presence data, to save hitting KABC
00396     // unless really necessary
00397     ::KIMProxy *imProxy = KMKernel::self()->imProxy();
00398     QString kabcUid;
00399     if ( ( strategy->showHeader( "status" ) || strategy->showHeader( "statuspic" ) ) )
00400     {
00401       if ( imProxy->initialize() )
00402       {
00403         KABC::AddressBook *addressBook = KABC::StdAddressBook::self();
00404         KABC::AddresseeList addresses = addressBook->findByEmail( KPIM::getEmailAddr( message->from() ) );
00405 
00406         if( addresses.count() == 1 )
00407         {
00408           // kabcUid is embedded in im: URIs to indicate which IM contact to message
00409           kabcUid = addresses[0].uid();
00410 
00411           // im status
00412           presence = imProxy->presenceString( kabcUid );
00413           if ( !presence.isEmpty() )
00414           {
00415             QString presenceIcon = QString::fromLatin1( " <img src=\"%1\"/>" )
00416                 .arg( imgToDataUrl( imProxy->presenceIcon( kabcUid ).convertToImage() ) );
00417             presence += presenceIcon;
00418           }
00419           // picture
00420           if ( strategy->showHeader( "statuspic" ) )
00421           {
00422             QString photoURL;
00423             if ( addresses[0].photo().isIntern() )
00424             {
00425               // get photo data and convert to data: url
00426               //kdDebug( 5006 ) << "INTERNAL photo found" << endl;
00427               QImage photo = addresses[0].photo().data();
00428               if ( !photo.isNull() )
00429               {
00430                 photoURL = imgToDataUrl( photo );
00431               }
00432             }
00433             else
00434             {
00435               //kdDebug( 5006 ) << "URL found" << endl;
00436               photoURL = addresses[0].photo().url();
00437               if ( photoURL.startsWith("/") )
00438                 photoURL.prepend( "file:" );
00439             }
00440             if( !photoURL.isEmpty() )
00441             {
00442               //kdDebug( 5006 ) << "Got a photo: " << photoURL << endl;
00443               userHTML = QString("<img src=\"%1\" width=\"60\" height=\"60\">").arg( photoURL );
00444               if ( presence.isEmpty() )
00445               {
00446                 userHTML = QString("<div class=\"senderpic\">") + userHTML + "</div>";
00447               }
00448               else
00449                 userHTML = QString( "<div class=\"senderpic\">"
00450                                       "<a href=\"im:%1\">%2<div class=\"senderstatus\"><span name=\"presence-%2\">%3</span></div></a>"
00451                                       "</div>" ).arg( kabcUid )
00452                                                 .arg( userHTML )
00453                                                 .arg( presence );
00454             }
00455           }
00456         }
00457         else
00458         {
00459           kdDebug( 5006 ) << "Multiple / No addressees matched email address; Count is " << addresses.count() << endl;
00460           userHTML = "&nbsp;";
00461         }
00462       }
00463 // Disabled 'Launch IM' link in headers - Will
00464 //      else
00465 //        if ( imProxy->imAppsAvailable() )
00466 //          presence = "<a name=\"launchim\" href=\"kmail:startIMApp\">" + i18n("Launch IM") + "</a></span>";
00467     }
00468     // do nothing - no im apps available, leave presence empty
00469     //presence = i18n( "DCOP/InstantMessenger not installed" );
00470     kdDebug( 5006 ) << "final presence: '" << presence << "'" << endl;
00471     //case HdrFancy:
00472     // the subject line and box below for details
00473     if ( strategy->showHeader( "subject" ) )
00474       headerStr += QString("<div dir=\"%1\">%2</div>\n")
00475                         .arg(subjectDir)
00476                 .arg(message->subject().isEmpty()?
00477                  i18n("No Subject") :
00478                  strToHtml(message->subject()));
00479     headerStr += "<table class=\"outer\"><tr><td width=\"100%\"><table>\n";
00480     //headerStr += "<table>\n";
00481     // from line
00482     // the mailto: URLs can contain %3 etc., therefore usage of multiple
00483     // QString::arg is not possible
00484     if ( strategy->showHeader( "from" ) ) {
00485       QString fromStr = message->from();
00486       if ( fromStr.isEmpty() ) // no valid email in from, maybe just a name
00487         fromStr = message->fromStrip(); // let's use that
00488       headerStr += QString("<tr><th>%1</th>\n"
00489                            "<td>")
00490                            .arg(i18n("From: "))
00491                  + KMMessage::emailAddrAsAnchor( fromStr, false )
00492                  + ( !vCardName.isEmpty() ? "&nbsp;&nbsp;<a href=\"" + vCardName + "\">"
00493                                 + i18n("[vCard]") + "</a>"
00494                               : QString("") )
00495                  + ( ( !presence.isEmpty() && strategy->showHeader( "status" ) )
00496                               ? "&nbsp;&nbsp;(<span name=\"presence-" + kabcUid + "\">" + presence + "</span>)"
00497                               : QString("") )
00498                  + ( message->headerField("Organization").isEmpty()
00499                               ? QString("")
00500                               : "&nbsp;&nbsp;("
00501                                 + strToHtml(message->headerField("Organization"))
00502                                 + ")")
00503                  + "</td></tr>\n";
00504     }
00505     // to line
00506     if ( strategy->showHeader( "to" ) )
00507       headerStr.append(QString("<tr><th>%1</th>\n"
00508                    "<td>%2</td></tr>\n")
00509                             .arg(i18n("To: "))
00510                             .arg(KMMessage::emailAddrAsAnchor(message->to(),FALSE)));
00511 
00512     // cc line, if any
00513     if ( strategy->showHeader( "cc" ) && !message->cc().isEmpty())
00514       headerStr.append(QString("<tr><th>%1</th>\n"
00515                    "<td>%2</td></tr>\n")
00516                               .arg(i18n("CC: "))
00517                               .arg(KMMessage::emailAddrAsAnchor(message->cc(),FALSE)));
00518 
00519     // Bcc line, if any
00520     if ( strategy->showHeader( "bcc" ) && !message->bcc().isEmpty())
00521       headerStr.append(QString("<tr><th>%1</th>\n"
00522                    "<td>%2</td></tr>\n")
00523                               .arg(i18n("BCC: "))
00524                               .arg(KMMessage::emailAddrAsAnchor(message->bcc(),FALSE)));
00525 
00526     if ( strategy->showHeader( "date" ) )
00527       headerStr.append(QString("<tr><th>%1</th>\n"
00528                    "<td dir=\"%2\">%3</td></tr>\n")
00529                             .arg(i18n("Date: "))
00530                     .arg( directionOf( message->dateStr() ) )
00531                             .arg(strToHtml(dateString)));
00532 
00533     // FIXME: Show status in synthetic header style field.  Decide whether this or current in brackets style is best and remove one.
00534     /*    if( strategy->showHeader( "status" ) )
00535       headerStr.append( QString( "<tr><th>%1</th>\n"
00536                                  "<td dir=\"%2\">%3</td></tr>\n")
00537                                     .arg(i18n("Sender status: "))
00538                                     .arg( directionOf( onlineStatus ) )
00539                                     .arg(onlineStatus));
00540     */
00541     headerStr.append(
00542           QString("</table></td><td align=\"center\">%1</td></tr></table>\n").arg(userHTML)
00543                      );
00544 
00545     headerStr += "</div>\n\n";
00546     return headerStr;
00547   }
00548 
00549 QString FancyHeaderStyle::imgToDataUrl( const QImage &image )
00550 {
00551   QByteArray ba;
00552   QBuffer buffer( ba );
00553   buffer.open( IO_WriteOnly );
00554   image.save( &buffer, "PNG" );
00555   return QString::fromLatin1("data:image/png;base64,%1").arg( KCodecs::base64Encode( ba ) );
00556 }
00557 
00558   //
00559   // MinimalHeaderStyle:
00560   //
00561   class MinimalHeaderStyle : public HeaderStyle {
00562     friend class HeaderStyle;
00563   protected:
00564     MinimalHeaderStyle() : HeaderStyle() {}
00565     virtual ~MinimalHeaderStyle() {}
00566 
00567   public:
00568     const char * name() const { return "minimal"; }
00569     const HeaderStyle * next() const { return brief(); }
00570     const HeaderStyle * prev() const { return fancy(); }
00571 
00572     QString format( const KMMessage * message, const HeaderStrategy * strategy,
00573             const QString & vCardName, bool printing ) const;
00574   };
00575 
00576   QString MinimalHeaderStyle::format( const KMMessage * message,
00577                                     const HeaderStrategy * strategy,
00578                                     const QString & vCardName, bool printing ) const {
00579     if ( !message ) return QString::null;
00580     if ( !strategy )
00581       strategy = HeaderStrategy::minimal();
00582 
00583     // The direction of the header is determined according to the direction
00584     // of the application layout.
00585 
00586     QString dir = QApplication::reverseLayout() ? "rtl" : "ltr" ;
00587 
00588     // However, the direction of the message subject within the header is
00589     // determined according to the contents of the subject itself. Since
00590     // the "Re:" and "Fwd:" prefixes would always cause the subject to be
00591     // considered left-to-right, they are ignored when determining its
00592     // direction.
00593 
00594     QString subjectDir;
00595     if (!message->subject().isEmpty())
00596       subjectDir = directionOf( message->cleanSubject() );
00597     else
00598       subjectDir = directionOf( i18n("No Subject") );
00599 
00600     // Prepare the date string (when printing always use the localized date)
00601     QString dateString;
00602     if( printing ) {
00603       QDateTime dateTime;
00604       KLocale * locale = KGlobal::locale();
00605       dateTime.setTime_t( message->date() );
00606       dateString = locale->formatDateTime( dateTime );
00607     } else {
00608       dateString = message->dateStr();
00609     }
00610 
00611     QString headerStr = "<div class=\"header\" dir=\"" + dir + "\">\n";
00612 
00613     if ( strategy->showHeader( "subject" ) )
00614       headerStr += "<div dir=\"" + subjectDir + "\">\n"
00615                    "<b style=\"font-size:130%\">" +
00616                            strToHtml( message->subject() ) +
00617                            "</b></div>\n";
00618 
00619     QStringList headerParts;
00620 
00621     if ( strategy->showHeader( "from" ) ) {
00622       QString fromStr = message->from();
00623       if ( fromStr.isEmpty() ) // no valid email in from, maybe just a name
00624         fromStr = message->fromStrip(); // let's use that
00625       QString fromPart = KMMessage::emailAddrAsAnchor( fromStr, true );
00626       if ( !vCardName.isEmpty() )
00627         fromPart += "&nbsp;&nbsp;<a href=\"" + vCardName + "\">" + i18n("[vCard]") + "</a>";
00628       headerParts.append( i18n("From: ") + fromPart );
00629     }
00630 
00631     if ( strategy->showHeader( "to" ) ) {
00632        QStringList identities;
00633        KMime::Types::AddrSpecList toList = message->extractAddrSpecs("To");
00634        toList += message->extractAddrSpecs("Cc");
00635        if ( !toList.isEmpty() ) {
00636          KMime::Types::AddrSpecList::iterator it;
00637          for ( it  = toList.begin(); it != toList.end(); ++it ) {
00638             KPIM::Identity ident =
00639                 KMKernel::self()->identityManager()->identityForAddress( (*it).asString() );
00640             if ( !ident.isNull() &&
00641                  KMKernel::self()->identityManager()->thatIsMe( (*it).asString() ) ) {
00642               identities.append( KMMessage::emailAddrAsAnchor( ident.fullEmailAddr(), false ) );
00643             }
00644          }
00645        }
00646        if ( !identities.isEmpty() ) {
00647          headerParts.append( i18n("To: ") + identities.join(",") );
00648        } else { 
00649          // none of our identities found, let's use the full To header
00650          // happens for example with mailing list mails
00651          headerParts.append( i18n("To: ") + 
00652                  KMMessage::emailAddrAsAnchor( message->to( ), false) );
00653        }
00654     }
00655 
00656     if ( strategy->showHeader( "date" ) ) {
00657       headerParts.append(i18n("Date: ") + strToHtml(message->dateShortStr()) );
00658     }
00659 
00660     // remove all empty (modulo whitespace) entries and joins them via ", \n"
00661     headerStr += " (" + headerParts.grep( QRegExp( "\\S" ) ).join( ",\n" ) + ')';
00662 
00663     headerStr += "</div>\n";
00664 
00665     return headerStr;
00666   }
00667 
00668 
00669   //
00670   // HeaderStyle abstract base:
00671   //
00672 
00673   HeaderStyle::HeaderStyle() {
00674 
00675   }
00676 
00677   HeaderStyle::~HeaderStyle() {
00678 
00679   }
00680 
00681   const HeaderStyle * HeaderStyle::create( Type type ) {
00682     switch ( type ) {
00683     case Brief:  return brief();
00684     case Plain:  return plain();
00685     case Fancy:   return fancy();
00686     case Minimal: return minimal();
00687     }
00688     kdFatal( 5006 ) << "HeaderStyle::create(): Unknown header style ( type == "
00689             << (int)type << " ) requested!" << endl;
00690     return 0; // make compiler happy
00691   }
00692 
00693   const HeaderStyle * HeaderStyle::create( const QString & type ) {
00694     QString lowerType = type.lower();
00695     if ( lowerType == "brief" ) return brief();
00696     if ( lowerType == "plain" )  return plain();
00697     if ( lowerType == "minimal" ) return minimal();
00698     //if ( lowerType == "fancy" ) return fancy(); // not needed, see below
00699     // don't kdFatal here, b/c the strings are user-provided
00700     // (KConfig), so fail gracefully to the default:
00701     return fancy();
00702   }
00703 
00704   static const HeaderStyle * briefStyle = 0;
00705   static const HeaderStyle * plainStyle = 0;
00706   static const HeaderStyle * fancyStyle = 0;
00707   static const HeaderStyle * minimalStyle = 0;
00708 
00709   const HeaderStyle * HeaderStyle::brief() {
00710     if ( !briefStyle )
00711       briefStyle = new BriefHeaderStyle();
00712     return briefStyle;
00713   }
00714 
00715   const HeaderStyle * HeaderStyle::plain() {
00716     if ( !plainStyle )
00717       plainStyle = new PlainHeaderStyle();
00718     return plainStyle;
00719   }
00720 
00721   const HeaderStyle * HeaderStyle::fancy() {
00722     if ( !fancyStyle )
00723       fancyStyle = new FancyHeaderStyle();
00724     return fancyStyle;
00725   }
00726 
00727   const HeaderStyle * HeaderStyle::minimal() {
00728     if( !minimalStyle )
00729       minimalStyle = new MinimalHeaderStyle();
00730     return minimalStyle;
00731   }
00732 
00733 } // namespace KMail
KDE Logo
This file is part of the documentation for kmail Library Version 3.3.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Dec 21 14:24:42 2007 by doxygen 1.4.2 written by Dimitri van Heesch, © 1997-2003