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 "a.black {\n"
00371 " color: black ! important;\n"
00372 "}\n\n"
00373
00374 "table.textAtm { background-color: %2 ! important; }\n\n"
00375
00376 "tr.textAtmH {\n"
00377 " background-color: %3 ! important;\n"
00378 "%4"
00379 "}\n\n"
00380
00381 "tr.textAtmB {\n"
00382 " background-color: %3 ! important;\n"
00383 "}\n\n"
00384
00385 "table.rfc822 {\n"
00386 " background-color: %3 ! important;\n"
00387 "}\n\n"
00388
00389 "tr.rfc822H {\n"
00390 "%4"
00391 "}\n\n" )
00392 .arg( linkColor, fgColor, bgColor, headerFont )
00393 +
00394 QString( "table.encr {\n"
00395 " background-color: %1 ! important;\n"
00396 "}\n\n"
00397
00398 "tr.encrH {\n"
00399 " background-color: %2 ! important;\n"
00400 "%3"
00401 "}\n\n"
00402
00403 "tr.encrB { background-color: %4 ! important; }\n\n" )
00404 .arg( cPgpEncrF.name(),
00405 cPgpEncrH.name(),
00406 headerFont,
00407 cPgpEncrB.name() )
00408 +
00409 QString( "table.signOkKeyOk {\n"
00410 " background-color: %1 ! important;\n"
00411 "}\n\n"
00412
00413 "tr.signOkKeyOkH {\n"
00414 " background-color: %2 ! important;\n"
00415 "%3"
00416 "}\n\n"
00417
00418 "tr.signOkKeyOkB { background-color: %4 ! important; }\n\n" )
00419 .arg( cPgpOk1F.name(),
00420 cPgpOk1H.name(),
00421 headerFont,
00422 cPgpOk1B.name() )
00423 +
00424 QString( "table.signOkKeyBad {\n"
00425 " background-color: %1 ! important;\n"
00426 "}\n\n"
00427
00428 "tr.signOkKeyBadH {\n"
00429 " background-color: %2 ! important;\n"
00430 "%3"
00431 "}\n\n"
00432
00433 "tr.signOkKeyBadB { background-color: %4 ! important; }\n\n" )
00434 .arg( cPgpOk0F.name(),
00435 cPgpOk0H.name(),
00436 headerFont,
00437 cPgpOk0B.name() )
00438 +
00439 QString( "table.signWarn {\n"
00440 " background-color: %1 ! important;\n"
00441 "}\n\n"
00442
00443 "tr.signWarnH {\n"
00444 " background-color: %2 ! important;\n"
00445 "%3"
00446 "}\n\n"
00447
00448 "tr.signWarnB { background-color: %4 ! important; }\n\n" )
00449 .arg( cPgpWarnF.name(),
00450 cPgpWarnH.name(),
00451 headerFont,
00452 cPgpWarnB.name() )
00453 +
00454 QString( "table.signErr {\n"
00455 " background-color: %1 ! important;\n"
00456 "}\n\n"
00457
00458 "tr.signErrH {\n"
00459 " background-color: %2 ! important;\n"
00460 "%3"
00461 "}\n\n"
00462
00463 "tr.signErrB { background-color: %4 ! important; }\n\n" )
00464 .arg( cPgpErrF.name(),
00465 cPgpErrH.name(),
00466 headerFont,
00467 cPgpErrB.name() )
00468 +
00469 QString( "div.htmlWarn {\n"
00470 " border: 2px solid %1 ! important;\n"
00471 "}\n\n" )
00472 .arg( cHtmlWarning.name() )
00473 +
00474 QString( "div.header {\n"
00475 "%1"
00476 "}\n\n"
00477
00478 "div.fancy.header > div {\n"
00479 " background-color: %2 ! important;\n"
00480 " color: %3 ! important;\n"
00481 " border: solid %4 1px ! important;\n"
00482 "}\n\n"
00483
00484 "div.fancy.header > div a[href] { color: %3 ! important; }\n\n"
00485
00486 "div.fancy.header > div a[href]:hover { text-decoration: underline ! important; }\n\n"
00487
00488 "div.fancy.header > div.spamheader {\n"
00489 " background-color: #cdcdcd ! important;\n"
00490 " border-top: 0px ! important;\n"
00491 " padding: 3px ! important;\n"
00492 " color: black ! important;\n"
00493 " font-weight: bold ! important;\n"
00494 " font-size: smaller ! important;\n"
00495 "}\n\n"
00496
00497 "div.fancy.header > table.outer {\n"
00498 " background-color: %5 ! important;\n"
00499 " color: %4 ! important;\n"
00500 " border-bottom: solid %4 1px ! important;\n"
00501 " border-left: solid %4 1px ! important;\n"
00502 " border-right: solid %4 1px ! important;\n"
00503 "}\n\n"
00504
00505 "div.senderpic{\n"
00506 " padding: 0px ! important;\n"
00507 " font-size:0.8em ! important;\n"
00508 " border:1px solid %6 ! important;\n"
00509
00510
00511 " background-color:%5 ! important;\n"
00512 "}\n\n"
00513
00514 "div.senderstatus{\n"
00515 " text-align:center ! important;\n"
00516 "}\n\n"
00517 )
00518
00519 .arg( headerFont )
00520 .arg( cg.highlight().name(),
00521 cg.highlightedText().name(),
00522 cg.foreground().name(),
00523 cg.background().name() )
00524 .arg( cg.mid().name() )
00525 + quoteCSS;
00526 }
00527
00528 QString CSSHelper::commonCssDefinitions() const {
00529 return
00530 "div.header {\n"
00531 " margin-bottom: 10pt ! important;\n"
00532 "}\n\n"
00533
00534 "table.textAtm {\n"
00535 " margin-top: 10pt ! important;\n"
00536 " margin-bottom: 10pt ! important;\n"
00537 "}\n\n"
00538
00539 "tr.textAtmH,\n"
00540 "tr.textAtmB,\n"
00541 "tr.rfc822B {\n"
00542 " font-weight: normal ! important;\n"
00543 "}\n\n"
00544
00545 "tr.rfc822H,\n"
00546 "tr.encrH,\n"
00547 "tr.signOkKeyOkH,\n"
00548 "tr.signOkKeyBadH,\n"
00549 "tr.signWarnH,\n"
00550 "tr.signErrH {\n"
00551 " font-weight: bold ! important;\n"
00552 "}\n\n"
00553
00554 "tr.textAtmH td,\n"
00555 "tr.textAtmB td {\n"
00556 " padding: 3px ! important;\n"
00557 "}\n\n"
00558
00559 "table.rfc822 {\n"
00560 " width: 100% ! important;\n"
00561 " border: solid 1px black ! important;\n"
00562 " margin-top: 10pt ! important;\n"
00563 " margin-bottom: 10pt ! important;\n"
00564 "}\n\n"
00565
00566 "table.textAtm,\n"
00567 "table.encr,\n"
00568 "table.signWarn,\n"
00569 "table.signErr,\n"
00570 "table.signOkKeyBad,\n"
00571 "table.signOkKeyOk,\n"
00572 "div.fancy.header table {\n"
00573 " width: 100% ! important;\n"
00574 " border-width: 0px ! important;\n"
00575 "}\n\n"
00576
00577 "div.htmlWarn {\n"
00578 " margin: 0px 5% ! important;\n"
00579 " padding: 10px ! important;\n"
00580 " text-align: left ! important;\n"
00581 "}\n\n"
00582
00583 "div.fancy.header > div {\n"
00584 " font-weight: bold ! important;\n"
00585 " padding: 4px ! important;\n"
00586 "}\n\n"
00587
00588 "div.fancy.header table {\n"
00589 " padding: 2px ! important;\n"
00590 " text-align: left ! important\n"
00591 "}\n\n"
00592
00593 "div.fancy.header table th {\n"
00594 " padding: 0px ! important;\n"
00595 " white-space: nowrap ! important;\n"
00596 " border-spacing: 0px ! important;\n"
00597 " text-align: left ! important;\n"
00598 " vertical-align: top ! important;\n"
00599 "}\n\n"
00600
00601 "div.fancy.header table td {\n"
00602 " padding: 0px ! important;\n"
00603 " border-spacing: 0px ! important;\n"
00604 " text-align: left ! important;\n"
00605 " vertical-align: top ! important;\n"
00606 " width: 100% ! important;\n"
00607 "}\n\n"
00608
00609 "span.pimsmileytext {\n"
00610 " position: absolute;\n"
00611 " top: 0px;\n"
00612 " left: 0px;\n"
00613 " visibility: hidden;\n"
00614 "}\n\n"
00615
00616 "img.pimsmileyimg {\n"
00617 "}\n\n"
00618
00619 "div.quotelevelmark {\n"
00620 " position: absolute;\n"
00621 " margin-left:-10px;\n"
00622 "}\n\n"
00623 ;
00624 }
00625
00626
00627 void CSSHelper::setBodyFont( const QFont& font )
00628 {
00629 mBodyFont = font;
00630 }
00631
00632 void CSSHelper::setPrintFont( const QFont& font )
00633 {
00634 mPrintFont = font;
00635 }
00636
00637 }