00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "csshelper.h"
00033
00034 #include <kconfig.h>
00035 #include <kglobalsettings.h>
00036 #include <kdebug.h>
00037 #include <kglobal.h>
00038
00039 #include <qstring.h>
00040 #include <qapplication.h>
00041
00042 namespace KPIM {
00043
00044 namespace {
00045
00046 inline QColor darker( const QColor & c ) {
00047 int h, s, v;
00048 c.hsv( &h, &s, &v );
00049 return QColor( h, s, v*4/5, QColor::Hsv );
00050 }
00051
00052 inline QColor desaturate( const QColor & c ) {
00053 int h, s, v;
00054 c.hsv( &h, &s, &v );
00055 return QColor( h, s/8, v, QColor::Hsv );
00056 }
00057
00058 inline QColor fixValue( const QColor & c, int newV ) {
00059 int h, s, v;
00060 c.hsv( &h, &s, &v );
00061 return QColor( h, s, newV, QColor::Hsv );
00062 }
00063
00064 inline int getValueOf( const QColor & c ) {
00065 int h, s, v;
00066 c.hsv( &h, &s, &v );
00067 return v;
00068 }
00069 }
00070
00071 CSSHelper::CSSHelper( const QPaintDeviceMetrics &pdm ) :
00072 mShrinkQuotes( false ),
00073 mMetrics( pdm )
00074 {
00075
00076 mForegroundColor = QApplication::palette().active().text();
00077 mLinkColor = KGlobalSettings::linkColor();
00078 mVisitedLinkColor = KGlobalSettings::visitedLinkColor();
00079 mBackgroundColor = QApplication::palette().active().base();
00080 cHtmlWarning = QColor( 0xFF, 0x40, 0x40 );
00081
00082 cPgpEncrH = QColor( 0x00, 0x80, 0xFF );
00083 cPgpOk1H = QColor( 0x40, 0xFF, 0x40 );
00084 cPgpOk0H = QColor( 0xFF, 0xFF, 0x40 );
00085 cPgpWarnH = QColor( 0xFF, 0xFF, 0x40 );
00086 cPgpErrH = Qt::red;
00087
00088 for ( int i = 0 ; i < 3 ; ++i )
00089 mQuoteColor[i] = QColor( 0x00, 0x80 - i * 0x10, 0x00 );
00090 mRecycleQuoteColors = false;
00091
00092 QFont defaultFont = KGlobalSettings::generalFont();
00093 QFont defaultFixedFont = KGlobalSettings::fixedFont();
00094 mBodyFont = mPrintFont = defaultFont;
00095 mFixedFont = mFixedPrintFont = defaultFixedFont;
00096 defaultFont.setItalic( true );
00097 for ( int i = 0 ; i < 3 ; ++i )
00098 mQuoteFont[i] = defaultFont;
00099
00100 mBackingPixmapOn = false;
00101
00102 recalculatePGPColors();
00103 }
00104
00105 void CSSHelper::recalculatePGPColors() {
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117 const int vBG = getValueOf( mBackgroundColor );
00118 const bool lightBG = vBG >= 128;
00119 if ( cPgpOk1H == mBackgroundColor ) {
00120 cPgpOk1F = mBackgroundColor;
00121 cPgpOk1B = mBackgroundColor;
00122 } else {
00123 cPgpOk1F= darker( cPgpOk1H );
00124 cPgpOk1B = lightBG ? desaturate( cPgpOk1H ) : fixValue( cPgpOk1H, vBG );
00125 }
00126 if ( cPgpOk0H == mBackgroundColor ) {
00127 cPgpOk0F = mBackgroundColor;
00128 cPgpOk0B = mBackgroundColor;
00129 } else {
00130 cPgpOk0F = darker( cPgpOk0H );
00131 cPgpOk0B = lightBG ? desaturate( cPgpOk0H ) : fixValue( cPgpOk0H, vBG );
00132 }
00133 if ( cPgpWarnH == mBackgroundColor ) {
00134 cPgpWarnF = mBackgroundColor;
00135 cPgpWarnB = mBackgroundColor;
00136 } else {
00137 cPgpWarnF = darker( cPgpWarnH );
00138 cPgpWarnB = lightBG ? desaturate( cPgpWarnH ) : fixValue( cPgpWarnH, vBG );
00139 }
00140 if ( cPgpErrH == mBackgroundColor ) {
00141 cPgpErrF = mBackgroundColor;
00142 cPgpErrB = mBackgroundColor;
00143 } else {
00144 cPgpErrF = darker( cPgpErrH );
00145 cPgpErrB = lightBG ? desaturate( cPgpErrH ) : fixValue( cPgpErrH, vBG );
00146 }
00147 if ( cPgpEncrH == mBackgroundColor ) {
00148 cPgpEncrF = mBackgroundColor;
00149 cPgpEncrB = mBackgroundColor;
00150 } else {
00151 cPgpEncrF = darker( cPgpEncrH );
00152 cPgpEncrB = lightBG ? desaturate( cPgpEncrH ) : fixValue( cPgpEncrH, vBG );
00153 }
00154 }
00155
00156 QString CSSHelper::cssDefinitions( bool fixed ) const {
00157 return
00158 commonCssDefinitions()
00159 +
00160 "@media screen {\n\n"
00161 +
00162 screenCssDefinitions( this, fixed )
00163 +
00164 "}\n"
00165 "@media print {\n\n"
00166 +
00167 printCssDefinitions( fixed )
00168 +
00169 "}\n";
00170 }
00171
00172 QString CSSHelper::htmlHead( bool ) const {
00173 return
00174 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n"
00175 "<html><head><title></title></head>\n"
00176 "<body>\n";
00177 }
00178
00179 QString CSSHelper::quoteFontTag( int level ) const {
00180 if ( level < 0 )
00181 level = 0;
00182 static const int numQuoteLevels = sizeof mQuoteFont / sizeof *mQuoteFont;
00183 const int effectiveLevel = mRecycleQuoteColors
00184 ? level % numQuoteLevels + 1
00185 : kMin( level + 1, numQuoteLevels ) ;
00186 if ( level >= numQuoteLevels )
00187 return QString( "<div class=\"deepquotelevel%1\">" ).arg( effectiveLevel );
00188 else
00189 return QString( "<div class=\"quotelevel%1\">" ).arg( effectiveLevel );
00190 }
00191
00192 QString CSSHelper::nonQuotedFontTag() const {
00193 return "<div class=\"noquote\">";
00194 }
00195
00196 QFont CSSHelper::bodyFont( bool fixed, bool print ) const {
00197 return fixed ? ( print ? mFixedPrintFont : mFixedFont )
00198 : ( print ? mPrintFont : mBodyFont );
00199 }
00200
00201 int CSSHelper::fontSize( bool fixed, bool print ) const {
00202 return bodyFont( fixed, print ).pointSize();
00203 }
00204
00205
00206 namespace {
00207 int pointsToPixel( const QPaintDeviceMetrics & metrics, int pointSize ) {
00208 return ( pointSize * metrics.logicalDpiY() + 36 ) / 72 ;
00209 }
00210 }
00211
00212 static const char * const quoteFontSizes[] = { "85", "80", "75" };
00213
00214 QString CSSHelper::printCssDefinitions( bool fixed ) const {
00215 const QString headerFont = QString( " font-family: \"%1\" ! important;\n"
00216 " font-size: %2pt ! important;\n" )
00217 .arg( mPrintFont.family() )
00218 .arg( mPrintFont.pointSize() );
00219 const QColorGroup & cg = QApplication::palette().active();
00220
00221 const QFont printFont = bodyFont( fixed, true );
00222 QString quoteCSS;
00223 if ( printFont.italic() )
00224 quoteCSS += " font-style: italic ! important;\n";
00225 if ( printFont.bold() )
00226 quoteCSS += " font-weight: bold ! important;\n";
00227 if ( !quoteCSS.isEmpty() )
00228 quoteCSS = "div.noquote {\n" + quoteCSS + "}\n\n";
00229
00230 return
00231 QString( "body {\n"
00232 " font-family: \"%1\" ! important;\n"
00233 " font-size: %2pt ! important;\n"
00234 " color: #000000 ! important;\n"
00235 " background-color: #ffffff ! important\n"
00236 "}\n\n" )
00237 .arg( printFont.family(),
00238 QString::number( printFont.pointSize() ) )
00239 +
00240 QString( "tr.textAtmH,\n"
00241 "tr.rfc822H,\n"
00242 "tr.encrH,\n"
00243 "tr.signOkKeyOkH,\n"
00244 "tr.signOkKeyBadH,\n"
00245 "tr.signWarnH,\n"
00246 "tr.signErrH,\n"
00247 "div.header {\n"
00248 "%1"
00249 "}\n\n"
00250
00251 "div.fancy.header > div {\n"
00252 " background-color: %2 ! important;\n"
00253 " color: %3 ! important;\n"
00254 " padding: 4px ! important;\n"
00255 " border: solid %3 1px ! important;\n"
00256 "}\n\n"
00257
00258 "div.fancy.header > div a[href] { color: %3 ! important; }\n\n"
00259
00260 "div.fancy.header > table.outer{\n"
00261 " background-color: %2 ! important;\n"
00262 " color: %3 ! important;\n"
00263 " border-bottom: solid %3 1px ! important;\n"
00264 " border-left: solid %3 1px ! important;\n"
00265 " border-right: solid %3 1px ! important;\n"
00266 "}\n\n"
00267
00268 "div.spamheader {\n"
00269 " display:none ! important;\n"
00270 "}\n\n"
00271
00272 "div.htmlWarn {\n"
00273 " border: 2px solid #ffffff ! important;\n"
00274 "}\n\n"
00275
00276 "div.senderpic{\n"
00277 " font-size:0.8em ! important;\n"
00278 " border:1px solid black ! important;\n"
00279 " background-color:%2 ! important;\n"
00280 "}\n\n"
00281
00282 "div.senderstatus{\n"
00283 " text-align:center ! important;\n"
00284 "}\n\n"
00285 )
00286 .arg( headerFont,
00287 cg.background().name(),
00288 cg.foreground().name() )
00289 + quoteCSS;
00290 }
00291
00292 QString CSSHelper::screenCssDefinitions( const CSSHelper * helper, bool fixed ) const {
00293 const QString fgColor = mForegroundColor.name();
00294 const QString bgColor = mBackgroundColor.name();
00295 const QString linkColor = mLinkColor.name();
00296 const QString headerFont = QString(" font-family: \"%1\" ! important;\n"
00297 " font-size: %2px ! important;\n")
00298 .arg( mBodyFont.family() )
00299 .arg( pointsToPixel( helper->mMetrics, mBodyFont.pointSize() ) );
00300 const QString background = ( mBackingPixmapOn
00301 ? QString( " background-image:url(file://%1) ! important;\n" )
00302 .arg( mBackingPixmapStr )
00303 : QString( " background-color: %1 ! important;\n" )
00304 .arg( bgColor ) );
00305 const QString bodyFontSize = QString::number( pointsToPixel( helper->mMetrics, fontSize( fixed ) ) ) + "px" ;
00306 const QColorGroup & cg = QApplication::palette().active();
00307
00308 QString quoteCSS;
00309 if ( bodyFont( fixed ).italic() )
00310 quoteCSS += " font-style: italic ! important;\n";
00311 if ( bodyFont( fixed ).bold() )
00312 quoteCSS += " font-weight: bold ! important;\n";
00313 if ( !quoteCSS.isEmpty() )
00314 quoteCSS = "div.noquote {\n" + quoteCSS + "}\n\n";
00315
00316
00317 for ( int i = 0 ; i < 3 ; ++i ) {
00318 quoteCSS += QString( "div.quotelevel%1 {\n"
00319 " color: %2 ! important;\n" )
00320 .arg( QString::number(i+1), mQuoteColor[i].name() );
00321 if ( mQuoteFont[i].italic() )
00322 quoteCSS += " font-style: italic ! important;\n";
00323 if ( mQuoteFont[i].bold() )
00324 quoteCSS += " font-weight: bold ! important;\n";
00325 if ( mShrinkQuotes )
00326 quoteCSS += " font-size: " + QString::fromLatin1( quoteFontSizes[i] )
00327 + "% ! important;\n";
00328 quoteCSS += "}\n\n";
00329 }
00330
00331
00332 for ( int i = 0 ; i < 3 ; ++i ) {
00333 quoteCSS += QString( "div.deepquotelevel%1 {\n"
00334 " color: %2 ! important;\n" )
00335 .arg( QString::number(i+1), mQuoteColor[i].name() );
00336 if ( mQuoteFont[i].italic() )
00337 quoteCSS += " font-style: italic ! important;\n";
00338 if ( mQuoteFont[i].bold() )
00339 quoteCSS += " font-weight: bold ! important;\n";
00340 if ( mShrinkQuotes )
00341 quoteCSS += " font-size: 70% ! important;\n";
00342 quoteCSS += "}\n\n";
00343 }
00344
00345 return
00346 QString( "body {\n"
00347 " font-family: \"%1\" ! important;\n"
00348 " font-size: %2 ! important;\n"
00349 " color: %3 ! important;\n"
00350 "%4"
00351 "}\n\n" )
00352 .arg( bodyFont( fixed ).family(),
00353 bodyFontSize,
00354 fgColor,
00355 background )
00356 +
00357 QString( "a {\n"
00358 " color: %1 ! important;\n"
00359 " text-decoration: none ! important;\n"
00360 "}\n\n"
00361
00362 "table.textAtm { background-color: %2 ! important; }\n\n"
00363
00364 "tr.textAtmH {\n"
00365 " background-color: %3 ! important;\n"
00366 "%4"
00367 "}\n\n"
00368
00369 "tr.textAtmB {\n"
00370 " background-color: %3 ! important;\n"
00371 "}\n\n"
00372
00373 "table.rfc822 {\n"
00374 " background-color: %3 ! important;\n"
00375 "}\n\n"
00376
00377 "tr.rfc822H {\n"
00378 "%4"
00379 "}\n\n" )
00380 .arg( linkColor, fgColor, bgColor, headerFont )
00381 +
00382 QString( "table.encr {\n"
00383 " background-color: %1 ! important;\n"
00384 "}\n\n"
00385
00386 "tr.encrH {\n"
00387 " background-color: %2 ! important;\n"
00388 "%3"
00389 "}\n\n"
00390
00391 "tr.encrB { background-color: %4 ! important; }\n\n" )
00392 .arg( cPgpEncrF.name(),
00393 cPgpEncrH.name(),
00394 headerFont,
00395 cPgpEncrB.name() )
00396 +
00397 QString( "table.signOkKeyOk {\n"
00398 " background-color: %1 ! important;\n"
00399 "}\n\n"
00400
00401 "tr.signOkKeyOkH {\n"
00402 " background-color: %2 ! important;\n"
00403 "%3"
00404 "}\n\n"
00405
00406 "tr.signOkKeyOkB { background-color: %4 ! important; }\n\n" )
00407 .arg( cPgpOk1F.name(),
00408 cPgpOk1H.name(),
00409 headerFont,
00410 cPgpOk1B.name() )
00411 +
00412 QString( "table.signOkKeyBad {\n"
00413 " background-color: %1 ! important;\n"
00414 "}\n\n"
00415
00416 "tr.signOkKeyBadH {\n"
00417 " background-color: %2 ! important;\n"
00418 "%3"
00419 "}\n\n"
00420
00421 "tr.signOkKeyBadB { background-color: %4 ! important; }\n\n" )
00422 .arg( cPgpOk0F.name(),
00423 cPgpOk0H.name(),
00424 headerFont,
00425 cPgpOk0B.name() )
00426 +
00427 QString( "table.signWarn {\n"
00428 " background-color: %1 ! important;\n"
00429 "}\n\n"
00430
00431 "tr.signWarnH {\n"
00432 " background-color: %2 ! important;\n"
00433 "%3"
00434 "}\n\n"
00435
00436 "tr.signWarnB { background-color: %4 ! important; }\n\n" )
00437 .arg( cPgpWarnF.name(),
00438 cPgpWarnH.name(),
00439 headerFont,
00440 cPgpWarnB.name() )
00441 +
00442 QString( "table.signErr {\n"
00443 " background-color: %1 ! important;\n"
00444 "}\n\n"
00445
00446 "tr.signErrH {\n"
00447 " background-color: %2 ! important;\n"
00448 "%3"
00449 "}\n\n"
00450
00451 "tr.signErrB { background-color: %4 ! important; }\n\n" )
00452 .arg( cPgpErrF.name(),
00453 cPgpErrH.name(),
00454 headerFont,
00455 cPgpErrB.name() )
00456 +
00457 QString( "div.htmlWarn {\n"
00458 " border: 2px solid %1 ! important;\n"
00459 "}\n\n" )
00460 .arg( cHtmlWarning.name() )
00461 +
00462 QString( "div.header {\n"
00463 "%1"
00464 "}\n\n"
00465
00466 "div.fancy.header > div {\n"
00467 " background-color: %2 ! important;\n"
00468 " color: %3 ! important;\n"
00469 " border: solid %4 1px ! important;\n"
00470 "}\n\n"
00471
00472 "div.fancy.header > div a[href] { color: %3 ! important; }\n\n"
00473
00474 "div.fancy.header > div a[href]:hover { text-decoration: underline ! important; }\n\n"
00475
00476 "div.fancy.header > div.spamheader {\n"
00477 " background-color: #cdcdcd ! important;\n"
00478 " border-top: 0px ! important;\n"
00479 " padding: 3px ! important;\n"
00480 " color: black ! important;\n"
00481 " font-weight: bold ! important;\n"
00482 " font-size: smaller ! important;\n"
00483 "}\n\n"
00484
00485 "div.fancy.header > table.outer {\n"
00486 " background-color: %5 ! important;\n"
00487 " color: %4 ! important;\n"
00488 " border-bottom: solid %4 1px ! important;\n"
00489 " border-left: solid %4 1px ! important;\n"
00490 " border-right: solid %4 1px ! important;\n"
00491 "}\n\n"
00492
00493 "div.senderpic{\n"
00494 " padding: 0px ! important;\n"
00495 " font-size:0.8em ! important;\n"
00496 " border:1px solid %6 ! important;\n"
00497
00498
00499 " background-color:%5 ! important;\n"
00500 "}\n\n"
00501
00502 "div.senderstatus{\n"
00503 " text-align:center ! important;\n"
00504 "}\n\n"
00505 )
00506
00507 .arg( headerFont )
00508 .arg( cg.highlight().name(),
00509 cg.highlightedText().name(),
00510 cg.foreground().name(),
00511 cg.background().name() )
00512 .arg( cg.mid().name() )
00513 + quoteCSS;
00514 }
00515
00516 QString CSSHelper::commonCssDefinitions() const {
00517 return
00518 "div.header {\n"
00519 " margin-bottom: 10pt ! important;\n"
00520 "}\n\n"
00521
00522 "table.textAtm {\n"
00523 " margin-top: 10pt ! important;\n"
00524 " margin-bottom: 10pt ! important;\n"
00525 "}\n\n"
00526
00527 "tr.textAtmH,\n"
00528 "tr.textAtmB,\n"
00529 "tr.rfc822B {\n"
00530 " font-weight: normal ! important;\n"
00531 "}\n\n"
00532
00533 "tr.rfc822H,\n"
00534 "tr.encrH,\n"
00535 "tr.signOkKeyOkH,\n"
00536 "tr.signOkKeyBadH,\n"
00537 "tr.signWarnH,\n"
00538 "tr.signErrH {\n"
00539 " font-weight: bold ! important;\n"
00540 "}\n\n"
00541
00542 "tr.textAtmH td,\n"
00543 "tr.textAtmB td {\n"
00544 " padding: 3px ! important;\n"
00545 "}\n\n"
00546
00547 "table.rfc822 {\n"
00548 " width: 100% ! important;\n"
00549 " border: solid 1px black ! important;\n"
00550 " margin-top: 10pt ! important;\n"
00551 " margin-bottom: 10pt ! important;\n"
00552 "}\n\n"
00553
00554 "table.textAtm,\n"
00555 "table.encr,\n"
00556 "table.signWarn,\n"
00557 "table.signErr,\n"
00558 "table.signOkKeyBad,\n"
00559 "table.signOkKeyOk,\n"
00560 "div.fancy.header table {\n"
00561 " width: 100% ! important;\n"
00562 " border-width: 0px ! important;\n"
00563 "}\n\n"
00564
00565 "div.htmlWarn {\n"
00566 " margin: 0px 5% ! important;\n"
00567 " padding: 10px ! important;\n"
00568 " text-align: left ! important;\n"
00569 "}\n\n"
00570
00571 "div.fancy.header > div {\n"
00572 " font-weight: bold ! important;\n"
00573 " padding: 4px ! important;\n"
00574 "}\n\n"
00575
00576 "div.fancy.header table {\n"
00577 " padding: 2px ! important;\n"
00578 " text-align: left ! important\n"
00579 "}\n\n"
00580
00581 "div.fancy.header table th {\n"
00582 " padding: 0px ! important;\n"
00583 " white-space: nowrap ! important;\n"
00584 " border-spacing: 0px ! important;\n"
00585 " text-align: left ! important;\n"
00586 " vertical-align: top ! important;\n"
00587 "}\n\n"
00588
00589 "div.fancy.header table td {\n"
00590 " padding: 0px ! important;\n"
00591 " border-spacing: 0px ! important;\n"
00592 " text-align: left ! important;\n"
00593 " vertical-align: top ! important;\n"
00594 " width: 100% ! important;\n"
00595 "}\n\n"
00596
00597 "span.pimsmileytext {\n"
00598 " position: absolute;\n"
00599 " top: 0px;\n"
00600 " left: 0px;\n"
00601 " visibility: hidden;\n"
00602 "}\n\n"
00603
00604 "img.pimsmileyimg {\n"
00605 "}\n\n"
00606
00607 "div.quotelevelmark {\n"
00608 " position: absolute;\n"
00609 " margin-left:-10px;\n"
00610 "}\n\n"
00611 ;
00612 }
00613
00614 }