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 "div.noprint {\n"
00287 " display:none ! important;\n"
00288 "}\n\n"
00289 )
00290 .arg( headerFont,
00291 cg.background().name(),
00292 cg.foreground().name() )
00293 + quoteCSS;
00294 }
00295
00296 QString CSSHelper::screenCssDefinitions( const CSSHelper * helper, bool fixed ) const {
00297 const QString fgColor = mForegroundColor.name();
00298 const QString bgColor = mBackgroundColor.name();
00299 const QString linkColor = mLinkColor.name();
00300 const QString headerFont = QString(" font-family: \"%1\" ! important;\n"
00301 " font-size: %2px ! important;\n")
00302 .arg( mBodyFont.family() )
00303 .arg( pointsToPixel( helper->mMetrics, mBodyFont.pointSize() ) );
00304 const QString background = ( mBackingPixmapOn
00305 ? QString( " background-image:url(file://%1) ! important;\n" )
00306 .arg( mBackingPixmapStr )
00307 : QString( " background-color: %1 ! important;\n" )
00308 .arg( bgColor ) );
00309 const QString bodyFontSize = QString::number( pointsToPixel( helper->mMetrics, fontSize( fixed ) ) ) + "px" ;
00310 const QColorGroup & cg = QApplication::palette().active();
00311
00312 QString quoteCSS;
00313 if ( bodyFont( fixed ).italic() )
00314 quoteCSS += " font-style: italic ! important;\n";
00315 if ( bodyFont( fixed ).bold() )
00316 quoteCSS += " font-weight: bold ! important;\n";
00317 if ( !quoteCSS.isEmpty() )
00318 quoteCSS = "div.noquote {\n" + quoteCSS + "}\n\n";
00319
00320
00321 for ( int i = 0 ; i < 3 ; ++i ) {
00322 quoteCSS += QString( "div.quotelevel%1 {\n"
00323 " color: %2 ! important;\n" )
00324 .arg( QString::number(i+1), mQuoteColor[i].name() );
00325 if ( mQuoteFont[i].italic() )
00326 quoteCSS += " font-style: italic ! important;\n";
00327 if ( mQuoteFont[i].bold() )
00328 quoteCSS += " font-weight: bold ! important;\n";
00329 if ( mShrinkQuotes )
00330 quoteCSS += " font-size: " + QString::fromLatin1( quoteFontSizes[i] )
00331 + "% ! important;\n";
00332 quoteCSS += "}\n\n";
00333 }
00334
00335
00336 for ( int i = 0 ; i < 3 ; ++i ) {
00337 quoteCSS += QString( "div.deepquotelevel%1 {\n"
00338 " color: %2 ! important;\n" )
00339 .arg( QString::number(i+1), mQuoteColor[i].name() );
00340 if ( mQuoteFont[i].italic() )
00341 quoteCSS += " font-style: italic ! important;\n";
00342 if ( mQuoteFont[i].bold() )
00343 quoteCSS += " font-weight: bold ! important;\n";
00344 if ( mShrinkQuotes )
00345 quoteCSS += " font-size: 70% ! important;\n";
00346 quoteCSS += "}\n\n";
00347 }
00348
00349 return
00350 QString( "body {\n"
00351 " font-family: \"%1\" ! important;\n"
00352 " font-size: %2 ! important;\n"
00353 " color: %3 ! important;\n"
00354 "%4"
00355 "}\n\n" )
00356 .arg( bodyFont( fixed ).family(),
00357 bodyFontSize,
00358 fgColor,
00359 background )
00360 +
00361 QString( "a {\n"
00362 " color: %1 ! important;\n"
00363 " text-decoration: none ! important;\n"
00364 "}\n\n"
00365
00366 "a.white {\n"
00367 " color: white ! important;\n"
00368 "}\n\n"
00369
00370 "table.textAtm { background-color: %2 ! important; }\n\n"
00371
00372 "tr.textAtmH {\n"
00373 " background-color: %3 ! important;\n"
00374 "%4"
00375 "}\n\n"
00376
00377 "tr.textAtmB {\n"
00378 " background-color: %3 ! important;\n"
00379 "}\n\n"
00380
00381 "table.rfc822 {\n"
00382 " background-color: %3 ! important;\n"
00383 "}\n\n"
00384
00385 "tr.rfc822H {\n"
00386 "%4"
00387 "}\n\n" )
00388 .arg( linkColor, fgColor, bgColor, headerFont )
00389 +
00390 QString( "table.encr {\n"
00391 " background-color: %1 ! important;\n"
00392 "}\n\n"
00393
00394 "tr.encrH {\n"
00395 " background-color: %2 ! important;\n"
00396 "%3"
00397 "}\n\n"
00398
00399 "tr.encrB { background-color: %4 ! important; }\n\n" )
00400 .arg( cPgpEncrF.name(),
00401 cPgpEncrH.name(),
00402 headerFont,
00403 cPgpEncrB.name() )
00404 +
00405 QString( "table.signOkKeyOk {\n"
00406 " background-color: %1 ! important;\n"
00407 "}\n\n"
00408
00409 "tr.signOkKeyOkH {\n"
00410 " background-color: %2 ! important;\n"
00411 "%3"
00412 "}\n\n"
00413
00414 "tr.signOkKeyOkB { background-color: %4 ! important; }\n\n" )
00415 .arg( cPgpOk1F.name(),
00416 cPgpOk1H.name(),
00417 headerFont,
00418 cPgpOk1B.name() )
00419 +
00420 QString( "table.signOkKeyBad {\n"
00421 " background-color: %1 ! important;\n"
00422 "}\n\n"
00423
00424 "tr.signOkKeyBadH {\n"
00425 " background-color: %2 ! important;\n"
00426 "%3"
00427 "}\n\n"
00428
00429 "tr.signOkKeyBadB { background-color: %4 ! important; }\n\n" )
00430 .arg( cPgpOk0F.name(),
00431 cPgpOk0H.name(),
00432 headerFont,
00433 cPgpOk0B.name() )
00434 +
00435 QString( "table.signWarn {\n"
00436 " background-color: %1 ! important;\n"
00437 "}\n\n"
00438
00439 "tr.signWarnH {\n"
00440 " background-color: %2 ! important;\n"
00441 "%3"
00442 "}\n\n"
00443
00444 "tr.signWarnB { background-color: %4 ! important; }\n\n" )
00445 .arg( cPgpWarnF.name(),
00446 cPgpWarnH.name(),
00447 headerFont,
00448 cPgpWarnB.name() )
00449 +
00450 QString( "table.signErr {\n"
00451 " background-color: %1 ! important;\n"
00452 "}\n\n"
00453
00454 "tr.signErrH {\n"
00455 " background-color: %2 ! important;\n"
00456 "%3"
00457 "}\n\n"
00458
00459 "tr.signErrB { background-color: %4 ! important; }\n\n" )
00460 .arg( cPgpErrF.name(),
00461 cPgpErrH.name(),
00462 headerFont,
00463 cPgpErrB.name() )
00464 +
00465 QString( "div.htmlWarn {\n"
00466 " border: 2px solid %1 ! important;\n"
00467 "}\n\n" )
00468 .arg( cHtmlWarning.name() )
00469 +
00470 QString( "div.header {\n"
00471 "%1"
00472 "}\n\n"
00473
00474 "div.fancy.header > div {\n"
00475 " background-color: %2 ! important;\n"
00476 " color: %3 ! important;\n"
00477 " border: solid %4 1px ! important;\n"
00478 "}\n\n"
00479
00480 "div.fancy.header > div a[href] { color: %3 ! important; }\n\n"
00481
00482 "div.fancy.header > div a[href]:hover { text-decoration: underline ! important; }\n\n"
00483
00484 "div.fancy.header > div.spamheader {\n"
00485 " background-color: #cdcdcd ! important;\n"
00486 " border-top: 0px ! important;\n"
00487 " padding: 3px ! important;\n"
00488 " color: black ! important;\n"
00489 " font-weight: bold ! important;\n"
00490 " font-size: smaller ! important;\n"
00491 "}\n\n"
00492
00493 "div.fancy.header > table.outer {\n"
00494 " background-color: %5 ! important;\n"
00495 " color: %4 ! important;\n"
00496 " border-bottom: solid %4 1px ! important;\n"
00497 " border-left: solid %4 1px ! important;\n"
00498 " border-right: solid %4 1px ! important;\n"
00499 "}\n\n"
00500
00501 "div.senderpic{\n"
00502 " padding: 0px ! important;\n"
00503 " font-size:0.8em ! important;\n"
00504 " border:1px solid %6 ! important;\n"
00505
00506
00507 " background-color:%5 ! important;\n"
00508 "}\n\n"
00509
00510 "div.senderstatus{\n"
00511 " text-align:center ! important;\n"
00512 "}\n\n"
00513 )
00514
00515 .arg( headerFont )
00516 .arg( cg.highlight().name(),
00517 cg.highlightedText().name(),
00518 cg.foreground().name(),
00519 cg.background().name() )
00520 .arg( cg.mid().name() )
00521 + quoteCSS;
00522 }
00523
00524 QString CSSHelper::commonCssDefinitions() const {
00525 return
00526 "div.header {\n"
00527 " margin-bottom: 10pt ! important;\n"
00528 "}\n\n"
00529
00530 "table.textAtm {\n"
00531 " margin-top: 10pt ! important;\n"
00532 " margin-bottom: 10pt ! important;\n"
00533 "}\n\n"
00534
00535 "tr.textAtmH,\n"
00536 "tr.textAtmB,\n"
00537 "tr.rfc822B {\n"
00538 " font-weight: normal ! important;\n"
00539 "}\n\n"
00540
00541 "tr.rfc822H,\n"
00542 "tr.encrH,\n"
00543 "tr.signOkKeyOkH,\n"
00544 "tr.signOkKeyBadH,\n"
00545 "tr.signWarnH,\n"
00546 "tr.signErrH {\n"
00547 " font-weight: bold ! important;\n"
00548 "}\n\n"
00549
00550 "tr.textAtmH td,\n"
00551 "tr.textAtmB td {\n"
00552 " padding: 3px ! important;\n"
00553 "}\n\n"
00554
00555 "table.rfc822 {\n"
00556 " width: 100% ! important;\n"
00557 " border: solid 1px black ! important;\n"
00558 " margin-top: 10pt ! important;\n"
00559 " margin-bottom: 10pt ! important;\n"
00560 "}\n\n"
00561
00562 "table.textAtm,\n"
00563 "table.encr,\n"
00564 "table.signWarn,\n"
00565 "table.signErr,\n"
00566 "table.signOkKeyBad,\n"
00567 "table.signOkKeyOk,\n"
00568 "div.fancy.header table {\n"
00569 " width: 100% ! important;\n"
00570 " border-width: 0px ! important;\n"
00571 "}\n\n"
00572
00573 "div.htmlWarn {\n"
00574 " margin: 0px 5% ! important;\n"
00575 " padding: 10px ! important;\n"
00576 " text-align: left ! important;\n"
00577 "}\n\n"
00578
00579 "div.fancy.header > div {\n"
00580 " font-weight: bold ! important;\n"
00581 " padding: 4px ! important;\n"
00582 "}\n\n"
00583
00584 "div.fancy.header table {\n"
00585 " padding: 2px ! important;\n"
00586 " text-align: left ! important\n"
00587 "}\n\n"
00588
00589 "div.fancy.header table th {\n"
00590 " padding: 0px ! important;\n"
00591 " white-space: nowrap ! important;\n"
00592 " border-spacing: 0px ! important;\n"
00593 " text-align: left ! important;\n"
00594 " vertical-align: top ! important;\n"
00595 "}\n\n"
00596
00597 "div.fancy.header table td {\n"
00598 " padding: 0px ! important;\n"
00599 " border-spacing: 0px ! important;\n"
00600 " text-align: left ! important;\n"
00601 " vertical-align: top ! important;\n"
00602 " width: 100% ! important;\n"
00603 "}\n\n"
00604
00605 "span.pimsmileytext {\n"
00606 " position: absolute;\n"
00607 " top: 0px;\n"
00608 " left: 0px;\n"
00609 " visibility: hidden;\n"
00610 "}\n\n"
00611
00612 "img.pimsmileyimg {\n"
00613 "}\n\n"
00614
00615 "div.quotelevelmark {\n"
00616 " position: absolute;\n"
00617 " margin-left:-10px;\n"
00618 "}\n\n"
00619 ;
00620 }
00621
00622
00623 void CSSHelper::setBodyFont( const QFont& font )
00624 {
00625 mBodyFont = font;
00626 }
00627
00628 void CSSHelper::setPrintFont( const QFont& font )
00629 {
00630 mPrintFont = font;
00631 }
00632
00633 }