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 namespace KMail { 00063 00064 // 00065 // Convenience functions: 00066 // 00067 static inline QString directionOf( const QString & str ) { 00068 return str.isRightToLeft() ? "rtl" : "ltr" ; 00069 } 00070 00071 #if 0 00072 // Converts to html. Changes URLs into href's, escapes HTML special 00073 // chars and inserts the result into an <div> or <span> tag with 00074 // "dir" set to "rtl" or "ltr" depending on the direction of @p str. 00075 static QString convertToHtmlBlock( const QString & str, bool useSpan=false ) { 00076 QString dir = directionOf( str ); 00077 QString format = "<%1 dir=\"%3\">%4</%2>"; 00078 return format.arg( useSpan ? "span" : "div" ) 00079 .arg( useSpan ? "span" : "div" ) 00080 .arg( dir ) 00081 .arg( LinkLocator::convertToHtml( str ) ); 00082 } 00083 #endif 00084 00085 // ### tmp wrapper to make kmreaderwin code working: 00086 static QString strToHtml( const QString & str, bool preserveBlanks=true ) { 00087 return LinkLocator::convertToHtml( str, preserveBlanks ); 00088 } 00089 00090 // 00091 // BriefHeaderStyle 00092 // Show everything in a single line, don't show header field names. 00093 // 00094 00095 class BriefHeaderStyle : public HeaderStyle { 00096 friend class HeaderStyle; 00097 protected: 00098 BriefHeaderStyle() : HeaderStyle() {} 00099 virtual ~BriefHeaderStyle() {} 00100 00101 public: 00102 const char * name() const { return "brief"; } 00103 const HeaderStyle * next() const { return plain(); } 00104 const HeaderStyle * prev() const { return fancy(); } 00105 00106 QString format( const KMMessage * message, const HeaderStrategy * strategy, 00107 const QString & vCardName, bool printing ) const; 00108 }; 00109 00110 QString BriefHeaderStyle::format( const KMMessage * message, 00111 const HeaderStrategy * strategy, 00112 const QString & vCardName, bool printing ) const { 00113 if ( !message ) return QString::null; 00114 if ( !strategy ) 00115 strategy = HeaderStrategy::brief(); 00116 00117 // The direction of the header is determined according to the direction 00118 // of the application layout. 00119 00120 QString dir = QApplication::reverseLayout() ? "rtl" : "ltr" ; 00121 00122 // However, the direction of the message subject within the header is 00123 // determined according to the contents of the subject itself. Since 00124 // the "Re:" and "Fwd:" prefixes would always cause the subject to be 00125 // considered left-to-right, they are ignored when determining its 00126 // direction. 00127 00128 QString subjectDir; 00129 if (!message->subject().isEmpty()) 00130 subjectDir = directionOf( message->cleanSubject() ); 00131 else 00132 subjectDir = directionOf( i18n("No Subject") ); 00133 00134 // Prepare the date string (when printing always use the localized date) 00135 QString dateString; 00136 if( printing ) { 00137 QDateTime dateTime; 00138 KLocale * locale = KGlobal::locale(); 00139 dateTime.setTime_t( message->date() ); 00140 dateString = locale->formatDateTime( dateTime ); 00141 } else { 00142 dateString = message->dateStr(); 00143 } 00144 00145 QString headerStr = "<div class=\"header\" dir=\"" + dir + "\">\n"; 00146 00147 if ( strategy->showHeader( "subject" ) ) 00148 headerStr += "<div dir=\"" + subjectDir + "\">\n" 00149 "<b style=\"font-size:130%\">" + 00150 strToHtml( message->subject() ) + 00151 "</b></div>\n"; 00152 00153 QStringList headerParts; 00154 00155 if ( strategy->showHeader( "from" ) ) { 00156 QString fromPart = KMMessage::emailAddrAsAnchor( message->from(), true ); 00157 if ( !vCardName.isEmpty() ) 00158 fromPart += "&nbsp;&nbsp;<a href=\"" + vCardName + "\">" + i18n("[vCard]") + "</a>"; 00159 headerParts << fromPart; 00160 } 00161 00162 if ( strategy->showHeader( "cc" ) && !message->cc().isEmpty() ) 00163 headerParts << i18n("CC: ") + KMMessage::emailAddrAsAnchor( message->cc(), true ); 00164 00165 if ( strategy->showHeader( "bcc" ) && !message->bcc().isEmpty() ) 00166 headerParts << i18n("BCC: ") + KMMessage::emailAddrAsAnchor( message->bcc(), true ); 00167 00168 if ( strategy->showHeader( "date" ) ) 00169 headerParts << strToHtml(message->dateShortStr()); 00170 00171 // remove all empty (modulo whitespace) entries and joins them via ", \n" 00172 headerStr += " (" + headerParts.grep( QRegExp( "\\S" ) ).join( ",\n" ) + ')'; 00173 00174 headerStr += "</div>\n"; 00175 00176 // ### iterate over the rest of strategy->headerToDisplay() (or 00177 // ### all headers if DefaultPolicy == Display) (elsewhere, too) 00178 return headerStr; 00179 } 00180 00181 // 00182 // PlainHeaderStyle: 00183 // show every header field on a line by itself, 00184 // show subject larger 00185 // 00186 00187 class PlainHeaderStyle : public HeaderStyle { 00188 friend class HeaderStyle; 00189 protected: 00190 PlainHeaderStyle() : HeaderStyle() {} 00191 virtual ~PlainHeaderStyle() {} 00192 00193 public: 00194 const char * name() const { return "plain"; } 00195 const HeaderStyle * next() const { return fancy(); } 00196 const HeaderStyle * prev() const { return brief(); } 00197 00198 QString format( const KMMessage * message, const HeaderStrategy * strategy, 00199 const QString & vCardName, bool printing ) const; 00200 00201 private: 00202 QString formatAllMessageHeaders( const KMMessage * message ) const; 00203 }; 00204 00205 QString PlainHeaderStyle::format( const KMMessage * message, 00206 const HeaderStrategy * strategy, 00207 const QString & vCardName, bool printing ) const { 00208 if ( !message ) return QString::null; 00209 if ( !strategy ) 00210 strategy = HeaderStrategy::rich(); 00211 00212 // The direction of the header is determined according to the direction 00213 // of the application layout. 00214 00215 QString dir = ( QApplication::reverseLayout() ? "rtl" : "ltr" ); 00216 00217 // However, the direction of the message subject within the header is 00218 // determined according to the contents of the subject itself. Since 00219 // the "Re:" and "Fwd:" prefixes would always cause the subject to be 00220 // considered left-to-right, they are ignored when determining its 00221 // direction. 00222 00223 QString subjectDir; 00224 if (!message->subject().isEmpty()) 00225 subjectDir = directionOf( message->cleanSubject() ); 00226 else 00227 subjectDir = directionOf( i18n("No Subject") ); 00228 00229 // Prepare the date string (when printing always use the localized date) 00230 QString dateString; 00231 if( printing ) { 00232 QDateTime dateTime; 00233 KLocale* locale = KGlobal::locale(); 00234 dateTime.setTime_t( message->date() ); 00235 dateString = locale->formatDateTime( dateTime ); 00236 } 00237 else { 00238 dateString = message->dateStr(); 00239 } 00240 00241 QString headerStr = QString("<div class=\"header\" dir=\"%1\">").arg(dir); 00242 00243 if ( strategy->headersToDisplay().isEmpty() 00244 && strategy->defaultPolicy() == HeaderStrategy::Display ) { 00245 // crude way to emulate "all" headers: 00246 headerStr += formatAllMessageHeaders( message ); 00247 return headerStr + "</div>"; 00248 } 00249 00250 //case HdrLong: 00251 if ( strategy->showHeader( "subject" ) ) 00252 headerStr += QString("<div dir=\"%1\"><b style=\"font-size:130%\">" + 00253 strToHtml(message->subject()) + "</b></div>\n") 00254 .arg(subjectDir); 00255 00256 if ( strategy->showHeader( "date" ) ) 00257 headerStr.append(i18n("Date: ") + strToHtml(dateString)+"<br>\n"); 00258 00259 // Get Instant Messaging presence 00260 QString presence; 00261 QString kabcUid; 00262 if ( strategy->showHeader( "status" ) ) 00263 { 00264 KABC::AddressBook *addressBook = KABC::StdAddressBook::self(); 00265 KABC::AddresseeList addresses = addressBook->findByEmail( KPIM::getEmailAddr( message->from() ) ); 00266 ::KIMProxy *imProxy = KMKernel::self()->imProxy(); 00267 kabcUid = addresses[0].uid(); 00268 presence = imProxy->presenceString( kabcUid ); 00269 } 00270 00271 if ( strategy->showHeader( "from" ) ) { 00272 headerStr.append(i18n("From: ") + 00273 KMMessage::emailAddrAsAnchor(message->from(),FALSE)); 00274 if ( !vCardName.isEmpty() ) 00275 headerStr.append("&nbsp;&nbsp;<a href=\"" + vCardName + 00276 "\">" + i18n("[vCard]") + "</a>" ); 00277 if ( !presence.isEmpty() && strategy->showHeader( "status" ) ) 00278 headerStr.append("&nbsp;&nbsp;(<span name=\"presence-" + kabcUid + "\">" + presence + "</span>)" ); 00279 if ( strategy->showHeader( "organization" ) 00280 && !message->headerField("Organization").isEmpty()) 00281 headerStr.append("&nbsp;&nbsp;(" + 00282 strToHtml(message->headerField("Organization")) + ")"); 00283 headerStr.append("<br>\n"); 00284 } 00285 00286 if ( strategy->showHeader( "to" ) ) 00287 headerStr.append(i18n("To: ")+ 00288 KMMessage::emailAddrAsAnchor(message->to(),FALSE) + "<br>\n"); 00289 00290 if ( strategy->showHeader( "cc" ) && !message->cc().isEmpty() ) 00291 headerStr.append(i18n("CC: ")+ 00292 KMMessage::emailAddrAsAnchor(message->cc(),FALSE) + "<br>\n"); 00293 00294 if ( strategy->showHeader( "bcc" ) && !message->bcc().isEmpty() ) 00295 headerStr.append(i18n("BCC: ")+ 00296 KMMessage::emailAddrAsAnchor(message->bcc(),FALSE) + "<br>\n"); 00297 00298 if ( strategy->showHeader( "reply-to" ) && !message->replyTo().isEmpty()) 00299 headerStr.append(i18n("Reply to: ")+ 00300 KMMessage::emailAddrAsAnchor(message->replyTo(),FALSE) + "<br>\n"); 00301 00302 headerStr += "</div>\n"; 00303 00304 return headerStr; 00305 } 00306 00307 QString PlainHeaderStyle::formatAllMessageHeaders( const KMMessage * message ) const { 00308 const DwHeaders & headers = message->headers(); 00309 QString result; 00310 00311 for ( const DwField * field = headers.FirstField() ; field ; field = field->Next() ) { 00312 result += ( field->FieldNameStr() + ": " ).c_str(); 00313 result += strToHtml( field->FieldBodyStr().c_str() ); 00314 result += "<br>\n"; 00315 } 00316 00317 return result; 00318 } 00319 00320 // 00321 // FancyHeaderStyle: 00322 // Like PlainHeaderStyle, but with slick frames and background colours. 00323 // 00324 00325 class FancyHeaderStyle : public HeaderStyle { 00326 friend class HeaderStyle; 00327 protected: 00328 FancyHeaderStyle() : HeaderStyle() {} 00329 virtual ~FancyHeaderStyle() {} 00330 00331 public: 00332 const char * name() const { return "fancy"; } 00333 const HeaderStyle * next() const { return brief(); } 00334 const HeaderStyle * prev() const { return plain(); } 00335 00336 QString format( const KMMessage * message, const HeaderStrategy * strategy, 00337 const QString & vCardName, bool printing ) const; 00338 static QString imgToDataUrl( const QImage &image ); 00339 00340 }; 00341 00342 QString FancyHeaderStyle::format( const KMMessage * message, 00343 const HeaderStrategy * strategy, 00344 const QString & vCardName, bool printing ) const { 00345 if ( !message ) return QString::null; 00346 if ( !strategy ) 00347 strategy = HeaderStrategy::rich(); 00348 00349 // ### from kmreaderwin begin 00350 // The direction of the header is determined according to the direction 00351 // of the application layout. 00352 00353 QString dir = ( QApplication::reverseLayout() ? "rtl" : "ltr" ); 00354 QString headerStr = QString("<div class=\"fancy header\" dir=\"%1\">\n").arg(dir); 00355 00356 // However, the direction of the message subject within the header is 00357 // determined according to the contents of the subject itself. Since 00358 // the "Re:" and "Fwd:" prefixes would always cause the subject to be 00359 // considered left-to-right, they are ignored when determining its 00360 // direction. 00361 00362 QString subjectDir; 00363 if ( !message->subject().isEmpty() ) 00364 subjectDir = directionOf( message->cleanSubject() ); 00365 else 00366 subjectDir = directionOf( i18n("No Subject") ); 00367 00368 // Prepare the date string (when printing always use the localized date) 00369 QString dateString; 00370 if( printing ) { 00371 QDateTime dateTime; 00372 KLocale* locale = KGlobal::locale(); 00373 dateTime.setTime_t( message->date() ); 00374 dateString = locale->formatDateTime( dateTime ); 00375 } 00376 else { 00377 dateString = message->dateStr(); 00378 } 00379 00380 QString userHTML; 00381 QString presence; 00382 00383 // IM presence and kabc photo 00384 // Check first that KIMProxy has any IM presence data, to save hitting KABC 00385 // unless really necessary 00386 ::KIMProxy *imProxy = KMKernel::self()->imProxy(); 00387 QString kabcUid; 00388 if ( ( strategy->showHeader( "status" ) || strategy->showHeader( "statuspic" ) ) ) 00389 { 00390 if ( imProxy->initialize() ) 00391 { 00392 KABC::AddressBook *addressBook = KABC::StdAddressBook::self(); 00393 KABC::AddresseeList addresses = addressBook->findByEmail( KPIM::getEmailAddr( message->from() ) ); 00394 00395 if( addresses.count() == 1 ) 00396 { 00397 // kabcUid is embedded in im: URIs to indicate which IM contact to message 00398 kabcUid = addresses[0].uid(); 00399 00400 // im status 00401 presence = imProxy->presenceString( kabcUid ); 00402 if ( !presence.isEmpty() ) 00403 { 00404 QString presenceIcon = QString::fromLatin1( " <img src=\"%1\"/>" ) 00405 .arg( imgToDataUrl( imProxy->presenceIcon( kabcUid ).convertToImage() ) ); 00406 presence += presenceIcon; 00407 } 00408 // picture 00409 if ( strategy->showHeader( "statuspic" ) ) 00410 { 00411 QString photoURL; 00412 if ( addresses[0].photo().isIntern() ) 00413 { 00414 // get photo data and convert to data: url 00415 //kdDebug( 5006 ) << "INTERNAL photo found" << endl; 00416 QImage photo = addresses[0].photo().data(); 00417 if ( !photo.isNull() ) 00418 { 00419 photoURL = imgToDataUrl( photo ); 00420 } 00421 } 00422 else 00423 { 00424 //kdDebug( 5006 ) << "URL found" << endl; 00425 photoURL = addresses[0].photo().url(); 00426 if ( photoURL.startsWith("/") ) 00427 photoURL.prepend( "file:" ); 00428 } 00429 if( !photoURL.isEmpty() ) 00430 { 00431 //kdDebug( 5006 ) << "Got a photo: " << photoURL << endl; 00432 userHTML = QString("<img src=\"%1\" width=\"60\" height=\"60\">").arg( photoURL ); 00433 if ( presence.isEmpty() ) 00434 { 00435 userHTML = QString("<div class=\"senderpic\">") + userHTML + "</div>"; 00436 } 00437 else 00438 userHTML = QString( "<div class=\"senderpic\">" 00439 "<a href=\"im:%1\">%2<div class=\"senderstatus\"><span name=\"presence-%2\">%3</span></div></a>" 00440 "</div>" ).arg( kabcUid ) 00441 .arg( userHTML ) 00442 .arg( presence ); 00443 } 00444 } 00445 } 00446 else 00447 { 00448 kdDebug( 5006 ) << "Multiple / No addressees matched email address; Count is " << addresses.count() << endl; 00449 userHTML = "&nbsp;"; 00450 } 00451 } 00452 // Disabled 'Launch IM' link in headers - Will 00453 // else 00454 // if ( imProxy->imAppsAvailable() ) 00455 // presence = "<a name=\"launchim\" href=\"kmail:startIMApp\">" + i18n("Launch IM") + "</a></span>"; 00456 } 00457 // do nothing - no im apps available, leave presence empty 00458 //presence = i18n( "DCOP/InstantMessenger not installed" ); 00459 kdDebug( 5006 ) << "final presence: '" << presence << "'" << endl; 00460 //case HdrFancy: 00461 // the subject line and box below for details 00462 if ( strategy->showHeader( "subject" ) ) 00463 headerStr += QString("<div dir=\"%1\">%2</div>\n") 00464 .arg(subjectDir) 00465 .arg(message->subject().isEmpty()? 00466 i18n("No Subject") : 00467 strToHtml(message->subject())); 00468 headerStr += "<table class=\"outer\"><tr><td width=\"100%\"><table>\n"; 00469 //headerStr += "<table>\n"; 00470 // from line 00471 // the mailto: URLs can contain %3 etc., therefore usage of multiple 00472 // QString::arg is not possible 00473 if ( strategy->showHeader( "from" ) ) 00474 headerStr += QString("<tr><th>%1</th>\n" 00475 "<td>") 00476 .arg(i18n("From: ")) 00477 + KMMessage::emailAddrAsAnchor(message->from(),FALSE) 00478 + ( !vCardName.isEmpty() ? "&nbsp;&nbsp;<a href=\"" + vCardName + "\">" 00479 + i18n("[vCard]") + "</a>" 00480 : QString("") ) 00481 + ( ( !presence.isEmpty() && strategy->showHeader( "status" ) ) 00482 ? "&nbsp;&nbsp;(<span name=\"presence-" + kabcUid + "\">" + presence + "</span>)" 00483 : QString("") ) 00484 + ( message->headerField("Organization").isEmpty() 00485 ? QString("") 00486 : "&nbsp;&nbsp;(" 00487 + strToHtml(message->headerField("Organization")) 00488 + ")") 00489 + "</td></tr>\n"; 00490 // to line 00491 if ( strategy->showHeader( "to" ) ) 00492 headerStr.append(QString("<tr><th>%1</th>\n" 00493 "<td>%2</td></tr>\n") 00494 .arg(i18n("To: ")) 00495 .arg(KMMessage::emailAddrAsAnchor(message->to(),FALSE))); 00496 00497 // cc line, if any 00498 if ( strategy->showHeader( "cc" ) && !message->cc().isEmpty()) 00499 headerStr.append(QString("<tr><th>%1</th>\n" 00500 "<td>%2</td></tr>\n") 00501 .arg(i18n("CC: ")) 00502 .arg(KMMessage::emailAddrAsAnchor(message->cc(),FALSE))); 00503 00504 // Bcc line, if any 00505 if ( strategy->showHeader( "bcc" ) && !message->bcc().isEmpty()) 00506 headerStr.append(QString("<tr><th>%1</th>\n" 00507 "<td>%2</td></tr>\n") 00508 .arg(i18n("BCC: ")) 00509 .arg(KMMessage::emailAddrAsAnchor(message->bcc(),FALSE))); 00510 00511 if ( strategy->showHeader( "date" ) ) 00512 headerStr.append(QString("<tr><th>%1</th>\n" 00513 "<td dir=\"%2\">%3</td></tr>\n") 00514 .arg(i18n("Date: ")) 00515 .arg( directionOf( message->dateStr() ) ) 00516 .arg(strToHtml(dateString))); 00517 00518 // FIXME: Show status in synthetic header style field. Decide whether this or current in brackets style is best and remove one. 00519 /* if( strategy->showHeader( "status" ) ) 00520 headerStr.append( QString( "<tr><th>%1</th>\n" 00521 "<td dir=\"%2\">%3</td></tr>\n") 00522 .arg(i18n("Sender status: ")) 00523 .arg( directionOf( onlineStatus ) ) 00524 .arg(onlineStatus)); 00525 */ 00526 headerStr.append( 00527 QString("</table></td><td align=\"center\">%1</td></tr></table>\n").arg(userHTML) 00528 ); 00529 00530 headerStr += "</div>\n\n"; 00531 return headerStr; 00532 } 00533 00534 QString FancyHeaderStyle::imgToDataUrl( const QImage &image ) 00535 { 00536 QByteArray ba; 00537 QBuffer buffer( ba ); 00538 buffer.open( IO_WriteOnly ); 00539 image.save( &buffer, "PNG" ); 00540 return QString::fromLatin1("data:image/png;base64,%1").arg( KCodecs::base64Encode( ba ) ); 00541 } 00542 // 00543 // HeaderStyle abstract base: 00544 // 00545 00546 HeaderStyle::HeaderStyle() { 00547 00548 } 00549 00550 HeaderStyle::~HeaderStyle() { 00551 00552 } 00553 00554 const HeaderStyle * HeaderStyle::create( Type type ) { 00555 switch ( type ) { 00556 case Brief: return brief(); 00557 case Plain: return plain(); 00558 case Fancy: return fancy(); 00559 } 00560 kdFatal( 5006 ) << "HeaderStyle::create(): Unknown header style ( type == " 00561 << (int)type << " ) requested!" << endl; 00562 return 0; // make compiler happy 00563 } 00564 00565 const HeaderStyle * HeaderStyle::create( const QString & type ) { 00566 QString lowerType = type.lower(); 00567 if ( lowerType == "brief" ) return brief(); 00568 if ( lowerType == "plain" ) return plain(); 00569 //if ( lowerType == "fancy" ) return fancy(); // not needed, see below 00570 // don't kdFatal here, b/c the strings are user-provided 00571 // (KConfig), so fail gracefully to the default: 00572 return fancy(); 00573 } 00574 00575 static const HeaderStyle * briefStyle = 0; 00576 static const HeaderStyle * plainStyle = 0; 00577 static const HeaderStyle * fancyStyle = 0; 00578 00579 const HeaderStyle * HeaderStyle::brief() { 00580 if ( !briefStyle ) 00581 briefStyle = new BriefHeaderStyle(); 00582 return briefStyle; 00583 } 00584 00585 const HeaderStyle * HeaderStyle::plain() { 00586 if ( !plainStyle ) 00587 plainStyle = new PlainHeaderStyle(); 00588 return plainStyle; 00589 } 00590 00591 const HeaderStyle * HeaderStyle::fancy() { 00592 if ( !fancyStyle ) 00593 fancyStyle = new FancyHeaderStyle(); 00594 return fancyStyle; 00595 } 00596 00597 } // namespace KMail
KDE Logo
This file is part of the documentation for kmail Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Oct 21 19:46:45 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003