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 <tqstring.h>
00040 #include <tqapplication.h>
00041
00042 namespace KPIM {
00043
00044 namespace {
00045
00046 inline TQColor darker( const TQColor & c ) {
00047 int h, s, v;
00048 c.hsv( &h, &s, &v );
00049 return TQColor( h, s, v*4/5, TQColor::Hsv );
00050 }
00051
00052 inline TQColor desaturate( const TQColor & c ) {
00053 int h, s, v;
00054 c.hsv( &h, &s, &v );
00055 return TQColor( h, s/8, v, TQColor::Hsv );
00056 }
00057
00058 inline TQColor fixValue( const TQColor & c, int newV ) {
00059 int h, s, v;
00060 c.hsv( &h, &s, &v );
00061 return TQColor( h, s, newV, TQColor::Hsv );
00062 }
00063
00064 inline int getValueOf( const TQColor & c ) {
00065 int h, s, v;
00066 c.hsv( &h, &s, &v );
00067 return v;
00068 }
00069 }
00070
00071 CSSHelper::CSSHelper( const TQPaintDeviceMetrics &pdm ) :
00072 mShrinkQuotes( false ),
00073 mMetrics( pdm )
00074 {
00075
00076 mForegroundColor = TQApplication::palette().active().text();
00077 mLinkColor = KGlobalSettings::linkColor();
00078 mVisitedLinkColor = KGlobalSettings::visitedLinkColor();
00079 mBackgroundColor = TQApplication::palette().active().base();
00080 cHtmlWarning = TQColor( 0xFF, 0x40, 0x40 );
00081
00082 cPgpEncrH = TQColor( 0x00, 0x80, 0xFF );
00083 cPgpOk1H = TQColor( 0x40, 0xFF, 0x40 );
00084 cPgpOk0H = TQColor( 0xFF, 0xFF, 0x40 );
00085 cPgpWarnH = TQColor( 0xFF, 0xFF, 0x40 );
00086 cPgpErrH = Qt::red;
00087
00088 for ( int i = 0 ; i < 3 ; ++i )
00089 mQuoteColor[i] = TQColor( 0x00, 0x80 - i * 0x10, 0x00 );
00090 mRecycleQuoteColors = false;
00091
00092 TQFont defaultFont = KGlobalSettings::generalFont();
00093 TQFont 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 TQString 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 TQString 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 TQString 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 TQString( "<div class=\"deepquotelevel%1\">" ).arg( effectiveLevel );
00188 else
00189 return TQString( "<div class=\"quotelevel%1\">" ).arg( effectiveLevel );
00190 }
00191
00192 TQString CSSHelper::nonQuotedFontTag() const {
00193 return "<div class=\"noquote\">";
00194 }
00195
00196 TQFont 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 TQPaintDeviceMetrics & metrics, int pointSize ) {
00208 return ( pointSize * metrics.logicalDpiY() + 36 ) / 72 ;
00209 }
00210 }
00211
00212 static const char * const quoteFontSizes[] = { "85", "80", "75" };
00213
00214 TQString CSSHelper::printCssDefinitions( bool fixed ) const {
00215 const TQString headerFont = TQString( " font-family: \"%1\" ! important;\n"
00216 " font-size: %2pt ! important;\n" )
00217 .arg( mPrintFont.family() )
00218 .arg( mPrintFont.pointSize() );
00219 const TQColorGroup & cg = TQApplication::palette().active();
00220
00221 const TQFont printFont = bodyFont( fixed, true );
00222 TQString 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 TQString( "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 TQString::number( printFont.pointSize() ) )
00239 +
00240 TQString( "tr.textAtmH,\n"
00241 "tr.signInProgressH,\n"
00242 "tr.rfc822H,\n"
00243 "tr.encrH,\n"
00244 "tr.signOkKeyOkH,\n"
00245 "tr.signOkKeyBadH,\n"
00246 "tr.signWarnH,\n"
00247 "tr.signErrH,\n"
00248 "div.header {\n"
00249 "%1"
00250 "}\n\n"
00251
00252 "div.fancy.header > div {\n"
00253 " background-color: %2 ! important;\n"
00254 " color: %3 ! important;\n"
00255 " padding: 4px ! important;\n"
00256 " border: solid %3 1px ! important;\n"
00257 "}\n\n"
00258
00259 "div.fancy.header > div a[href] { color: %3 ! important; }\n\n"
00260
00261 "div.fancy.header > table.outer{\n"
00262 " background-color: %2 ! important;\n"
00263 " color: %3 ! important;\n"
00264 " border-bottom: solid %3 1px ! important;\n"
00265 " border-left: solid %3 1px ! important;\n"
00266 " border-right: solid %3 1px ! important;\n"
00267 "}\n\n"
00268
00269 "div.spamheader {\n"
00270 " display:none ! important;\n"
00271 "}\n\n"
00272
00273 "div.htmlWarn {\n"
00274 " border: 2px solid #ffffff ! important;\n"
00275 "}\n\n"
00276
00277 "div.senderpic{\n"
00278 " font-size:0.8em ! important;\n"
00279 " border:1px solid black ! important;\n"
00280 " background-color:%2 ! important;\n"
00281 "}\n\n"
00282
00283 "div.senderstatus{\n"
00284 " text-align:center ! important;\n"
00285 "}\n\n"
00286
00287 "div.noprint {\n"
00288 " display:none ! important;\n"
00289 "}\n\n"
00290 )
00291 .arg( headerFont,
00292 cg.background().name(),
00293 cg.foreground().name() )
00294 + quoteCSS;
00295 }
00296
00297 TQString CSSHelper::screenCssDefinitions( const CSSHelper * helper, bool fixed ) const {
00298 const TQString fgColor = mForegroundColor.name();
00299 const TQString bgColor = mBackgroundColor.name();
00300 const TQString linkColor = mLinkColor.name();
00301 const TQString headerFont = TQString(" font-family: \"%1\" ! important;\n"
00302 " font-size: %2px ! important;\n")
00303 .arg( mBodyFont.family() )
00304 .arg( pointsToPixel( helper->mMetrics, mBodyFont.pointSize() ) );
00305 const TQString background = ( mBackingPixmapOn
00306 ? TQString( " background-image:url(file://%1) ! important;\n" )
00307 .arg( mBackingPixmapStr )
00308 : TQString( " background-color: %1 ! important;\n" )
00309 .arg( bgColor ) );
00310 const TQString bodyFontSize = TQString::number( pointsToPixel( helper->mMetrics, fontSize( fixed ) ) ) + "px" ;
00311 const TQColorGroup & cg = TQApplication::palette().active();
00312
00313 TQString quoteCSS;
00314 if ( bodyFont( fixed ).italic() )
00315 quoteCSS += " font-style: italic ! important;\n";
00316 if ( bodyFont( fixed ).bold() )
00317 quoteCSS += " font-weight: bold ! important;\n";
00318 if ( !quoteCSS.isEmpty() )
00319 quoteCSS = "div.noquote {\n" + quoteCSS + "}\n\n";
00320
00321
00322 for ( int i = 0 ; i < 3 ; ++i ) {
00323 quoteCSS += TQString( "div.quotelevel%1 {\n"
00324 " color: %2 ! important;\n" )
00325 .arg( TQString::number(i+1), mQuoteColor[i].name() );
00326 if ( mQuoteFont[i].italic() )
00327 quoteCSS += " font-style: italic ! important;\n";
00328 if ( mQuoteFont[i].bold() )
00329 quoteCSS += " font-weight: bold ! important;\n";
00330 if ( mShrinkQuotes )
00331 quoteCSS += " font-size: " + TQString::fromLatin1( quoteFontSizes[i] )
00332 + "% ! important;\n";
00333 quoteCSS += "}\n\n";
00334 }
00335
00336
00337 for ( int i = 0 ; i < 3 ; ++i ) {
00338 quoteCSS += TQString( "div.deepquotelevel%1 {\n"
00339 " color: %2 ! important;\n" )
00340 .arg( TQString::number(i+1), mQuoteColor[i].name() );
00341 if ( mQuoteFont[i].italic() )
00342 quoteCSS += " font-style: italic ! important;\n";
00343 if ( mQuoteFont[i].bold() )
00344 quoteCSS += " font-weight: bold ! important;\n";
00345 if ( mShrinkQuotes )
00346 quoteCSS += " font-size: 70% ! important;\n";
00347 quoteCSS += "}\n\n";
00348 }
00349
00350 return
00351 TQString( "body {\n"
00352 " font-family: \"%1\" ! important;\n"
00353 " font-size: %2 ! important;\n"
00354 " color: %3 ! important;\n"
00355 "%4"
00356 "}\n\n" )
00357 .arg( bodyFont( fixed ).family(),
00358 bodyFontSize,
00359 fgColor,
00360 background )
00361 +
00362 TQString( "a {\n"
00363 " color: %1 ! important;\n"
00364 " text-decoration: none ! important;\n"
00365 "}\n\n"
00366
00367 "a.white {\n"
00368 " color: white ! important;\n"
00369 "}\n\n"
00370
00371 "a.black {\n"
00372 " color: black ! important;\n"
00373 "}\n\n"
00374
00375 "table.textAtm { background-color: %2 ! important; }\n\n"
00376
00377 "tr.textAtmH {\n"
00378 " background-color: %3 ! important;\n"
00379 "%4"
00380 "}\n\n"
00381
00382 "tr.textAtmB {\n"
00383 " background-color: %3 ! important;\n"
00384 "}\n\n"
00385
00386 "table.signInProgress,\n"
00387 "table.rfc822 {\n"
00388 " background-color: %3 ! important;\n"
00389 "}\n\n"
00390
00391 "tr.signInProgressH,\n"
00392 "tr.rfc822H {\n"
00393 "%4"
00394 "}\n\n" )
00395 .arg( linkColor, fgColor, bgColor, headerFont )
00396 +
00397 TQString( "table.encr {\n"
00398 " background-color: %1 ! important;\n"
00399 "}\n\n"
00400
00401 "tr.encrH {\n"
00402 " background-color: %2 ! important;\n"
00403 "%3"
00404 "}\n\n"
00405
00406 "tr.encrB { background-color: %4 ! important; }\n\n" )
00407 .arg( cPgpEncrF.name(),
00408 cPgpEncrH.name(),
00409 headerFont,
00410 cPgpEncrB.name() )
00411 +
00412 TQString( "table.signOkKeyOk {\n"
00413 " background-color: %1 ! important;\n"
00414 "}\n\n"
00415
00416 "tr.signOkKeyOkH {\n"
00417 " background-color: %2 ! important;\n"
00418 "%3"
00419 "}\n\n"
00420
00421 "tr.signOkKeyOkB { background-color: %4 ! important; }\n\n" )
00422 .arg( cPgpOk1F.name(),
00423 cPgpOk1H.name(),
00424 headerFont,
00425 cPgpOk1B.name() )
00426 +
00427 TQString( "table.signOkKeyBad {\n"
00428 " background-color: %1 ! important;\n"
00429 "}\n\n"
00430
00431 "tr.signOkKeyBadH {\n"
00432 " background-color: %2 ! important;\n"
00433 "%3"
00434 "}\n\n"
00435
00436 "tr.signOkKeyBadB { background-color: %4 ! important; }\n\n" )
00437 .arg( cPgpOk0F.name(),
00438 cPgpOk0H.name(),
00439 headerFont,
00440 cPgpOk0B.name() )
00441 +
00442 TQString( "table.signWarn {\n"
00443 " background-color: %1 ! important;\n"
00444 "}\n\n"
00445
00446 "tr.signWarnH {\n"
00447 " background-color: %2 ! important;\n"
00448 "%3"
00449 "}\n\n"
00450
00451 "tr.signWarnB { background-color: %4 ! important; }\n\n" )
00452 .arg( cPgpWarnF.name(),
00453 cPgpWarnH.name(),
00454 headerFont,
00455 cPgpWarnB.name() )
00456 +
00457 TQString( "table.signErr {\n"
00458 " background-color: %1 ! important;\n"
00459 "}\n\n"
00460
00461 "tr.signErrH {\n"
00462 " background-color: %2 ! important;\n"
00463 "%3"
00464 "}\n\n"
00465
00466 "tr.signErrB { background-color: %4 ! important; }\n\n" )
00467 .arg( cPgpErrF.name(),
00468 cPgpErrH.name(),
00469 headerFont,
00470 cPgpErrB.name() )
00471 +
00472 TQString( "div.htmlWarn {\n"
00473 " border: 2px solid %1 ! important;\n"
00474 "}\n\n" )
00475 .arg( cHtmlWarning.name() )
00476 +
00477 TQString( "div.header {\n"
00478 "%1"
00479 "}\n\n"
00480
00481 "div.fancy.header > div {\n"
00482 " background-color: %2 ! important;\n"
00483 " color: %3 ! important;\n"
00484 " border: solid %4 1px ! important;\n"
00485 "}\n\n"
00486
00487 "div.fancy.header > div a[href] { color: %3 ! important; }\n\n"
00488
00489 "div.fancy.header > div a[href]:hover { text-decoration: underline ! important; }\n\n"
00490
00491 "div.fancy.header > div.spamheader {\n"
00492 " background-color: #cdcdcd ! important;\n"
00493 " border-top: 0px ! important;\n"
00494 " padding: 3px ! important;\n"
00495 " color: black ! important;\n"
00496 " font-weight: bold ! important;\n"
00497 " font-size: smaller ! important;\n"
00498 "}\n\n"
00499
00500 "div.fancy.header > table.outer {\n"
00501 " background-color: %5 ! important;\n"
00502 " color: %4 ! important;\n"
00503 " border-bottom: solid %4 1px ! important;\n"
00504 " border-left: solid %4 1px ! important;\n"
00505 " border-right: solid %4 1px ! important;\n"
00506 "}\n\n"
00507
00508 "div.senderpic{\n"
00509 " padding: 0px ! important;\n"
00510 " font-size:0.8em ! important;\n"
00511 " border:1px solid %6 ! important;\n"
00512
00513
00514 " background-color:%5 ! important;\n"
00515 "}\n\n"
00516
00517 "div.senderstatus{\n"
00518 " text-align:center ! important;\n"
00519 "}\n\n"
00520 )
00521
00522 .arg( headerFont )
00523 .arg( cg.highlight().name(),
00524 cg.highlightedText().name(),
00525 cg.foreground().name(),
00526 cg.background().name() )
00527 .arg( cg.mid().name() )
00528 + quoteCSS;
00529 }
00530
00531 TQString CSSHelper::commonCssDefinitions() const {
00532 return
00533 "div.header {\n"
00534 " margin-bottom: 10pt ! important;\n"
00535 "}\n\n"
00536
00537 "table.textAtm {\n"
00538 " margin-top: 10pt ! important;\n"
00539 " margin-bottom: 10pt ! important;\n"
00540 "}\n\n"
00541
00542 "tr.textAtmH,\n"
00543 "tr.textAtmB,\n"
00544 "tr.rfc822B {\n"
00545 " font-weight: normal ! important;\n"
00546 "}\n\n"
00547
00548 "tr.signInProgressH,\n"
00549 "tr.rfc822H,\n"
00550 "tr.encrH,\n"
00551 "tr.signOkKeyOkH,\n"
00552 "tr.signOkKeyBadH,\n"
00553 "tr.signWarnH,\n"
00554 "tr.signErrH {\n"
00555 " font-weight: bold ! important;\n"
00556 "}\n\n"
00557
00558 "tr.textAtmH td,\n"
00559 "tr.textAtmB td {\n"
00560 " padding: 3px ! important;\n"
00561 "}\n\n"
00562
00563 "table.rfc822 {\n"
00564 " width: 100% ! important;\n"
00565 " border: solid 1px black ! important;\n"
00566 " margin-top: 10pt ! important;\n"
00567 " margin-bottom: 10pt ! important;\n"
00568 "}\n\n"
00569
00570 "table.textAtm,\n"
00571 "table.encr,\n"
00572 "table.signWarn,\n"
00573 "table.signErr,\n"
00574 "table.signOkKeyBad,\n"
00575 "table.signOkKeyOk,\n"
00576 "table.signInProgress,\n"
00577 "div.fancy.header table {\n"
00578 " width: 100% ! important;\n"
00579 " border-width: 0px ! important;\n"
00580 "}\n\n"
00581
00582 "div.htmlWarn {\n"
00583 " margin: 0px 5% ! important;\n"
00584 " padding: 10px ! important;\n"
00585 " text-align: left ! important;\n"
00586 "}\n\n"
00587
00588 "div.fancy.header > div {\n"
00589 " font-weight: bold ! important;\n"
00590 " padding: 4px ! important;\n"
00591 "}\n\n"
00592
00593 "div.fancy.header table {\n"
00594 " padding: 2px ! important;\n"
00595 " text-align: left ! important\n"
00596 "}\n\n"
00597
00598 "div.fancy.header table th {\n"
00599 " padding: 0px ! important;\n"
00600 " white-space: nowrap ! important;\n"
00601 " border-spacing: 0px ! important;\n"
00602 " text-align: left ! important;\n"
00603 " vertical-align: top ! important;\n"
00604 "}\n\n"
00605
00606 "div.fancy.header table td {\n"
00607 " padding: 0px ! important;\n"
00608 " border-spacing: 0px ! important;\n"
00609 " text-align: left ! important;\n"
00610 " vertical-align: top ! important;\n"
00611 " width: 100% ! important;\n"
00612 "}\n\n"
00613
00614 "span.pimsmileytext {\n"
00615 " position: absolute;\n"
00616 " top: 0px;\n"
00617 " left: 0px;\n"
00618 " visibility: hidden;\n"
00619 "}\n\n"
00620
00621 "img.pimsmileyimg {\n"
00622 "}\n\n"
00623
00624 "div.quotelevelmark {\n"
00625 " position: absolute;\n"
00626 " margin-left:-10px;\n"
00627 "}\n\n"
00628 ;
00629 }
00630
00631
00632 void CSSHelper::setBodyFont( const TQFont& font )
00633 {
00634 mBodyFont = font;
00635 }
00636
00637 void CSSHelper::setPrintFont( const TQFont& font )
00638 {
00639 mPrintFont = font;
00640 }
00641
00642 TQColor CSSHelper::pgpWarnColor() const
00643 {
00644 return cPgpWarnH;
00645 }
00646
00647 }