00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "helper.h"
00023
00024 #include <KGlobalSettings>
00025 #include <KColorUtils>
00026 #include <KColorScheme>
00027
00028 #include <QtGui/QWidget>
00029 #include <QtGui/QPainter>
00030
00031 #include <math.h>
00032
00033 const double OxygenHelper::_shadowGain = 1.5;
00034
00035
00036
00037
00038
00039 OxygenHelper::OxygenHelper(const QByteArray &componentName)
00040 : _componentData(componentName, 0, KComponentData::SkipMainComponentRegistration)
00041 {
00042 _config = _componentData.config();
00043 _contrast = KGlobalSettings::contrastF(_config);
00044 _bgcontrast = 0.3;
00045
00046 m_backgroundCache.setMaxCost(64);
00047 m_windecoButtonCache.setMaxCost(64);
00048 m_windecoButtonGlowCache.setMaxCost(64);
00049 }
00050
00051 KSharedConfigPtr OxygenHelper::config() const
00052 {
00053 return _config;
00054 }
00055
00056 void OxygenHelper::reloadConfig()
00057 {
00058 double old_contrast = _contrast;
00059
00060 _config->reparseConfiguration();
00061 _contrast = KGlobalSettings::contrastF(_config);
00062
00063 if (_contrast != old_contrast)
00064 invalidateCaches();
00065 }
00066
00067 void OxygenHelper::renderWindowBackground(QPainter *p, const QRect &clipRect, const QWidget *widget, const QPalette & pal, int y_shift)
00068 {
00069 const QWidget* window = widget->window();
00070
00071 const QWidget* w = widget;
00072 int x = 0, y = -y_shift;
00073 while (!w->isWindow()) {
00074 x += w->geometry().x();
00075 y += w->geometry().y();
00076 w = w->parentWidget();
00077 }
00078
00079 if (clipRect.isValid()) {
00080 p->save();
00081 p->setClipRegion(clipRect,Qt::IntersectClip);
00082 }
00083 QRect r = window->rect();
00084 QColor color = pal.color(window->backgroundRole());
00085 int splitY = qMin(300, 3*r.height()/4);
00086
00087 QRect upperRect = QRect(-x, -y, r.width(), splitY);
00088 QPixmap tile = verticalGradient(color, splitY);
00089 p->drawTiledPixmap(upperRect, tile);
00090
00091 QRect lowerRect = QRect(-x, splitY-y, r.width(), r.height() - splitY-y_shift);
00092 p->fillRect(lowerRect, backgroundBottomColor(color));
00093
00094 int radialW = qMin(600, r.width());
00095 int frameH = 10;
00096 QRect radialRect = QRect((r.width() - radialW) / 2-x, -y, radialW, 64-frameH);
00097 if (clipRect.intersects(radialRect))
00098 {
00099 tile = radialGradient(color, radialW);
00100 p->drawPixmap(radialRect, tile);
00101 }
00102
00103 if (clipRect.isValid())
00104 p->restore();
00105 }
00106
00107 void OxygenHelper::invalidateCaches()
00108 {
00109 m_backgroundCache.clear();
00110 m_windecoButtonCache.clear();
00111 m_windecoButtonGlowCache.clear();
00112 }
00113
00114 bool OxygenHelper::lowThreshold(const QColor &color)
00115 {
00116 QColor darker = KColorScheme::shade(color, KColorScheme::MidShade, 0.5);
00117 return KColorUtils::luma(darker) > KColorUtils::luma(color);
00118 }
00119
00120 QColor OxygenHelper::alphaColor(QColor color, double alpha)
00121 {
00122 if (alpha >= 1.0)
00123 return color;
00124 color.setAlphaF(qMax(0.0, alpha) * color.alphaF());
00125 return color;
00126 }
00127
00128 QColor OxygenHelper::backgroundRadialColor(const QColor &color) const
00129 {
00130 if (lowThreshold(color))
00131 return KColorScheme::shade(color, KColorScheme::LightShade, 0.0);
00132 else
00133 return KColorScheme::shade(color, KColorScheme::LightShade, _bgcontrast);
00134 }
00135
00136 QColor OxygenHelper::backgroundTopColor(const QColor &color) const
00137 {
00138 if (lowThreshold(color))
00139 return KColorScheme::shade(color, KColorScheme::MidlightShade, 0.0);
00140 else
00141 return KColorScheme::shade(color, KColorScheme::MidlightShade, _bgcontrast);
00142 }
00143
00144 QColor OxygenHelper::backgroundBottomColor(const QColor &color) const
00145 {
00146 QColor midColor = KColorScheme::shade(color, KColorScheme::MidShade, 0.0);
00147 if (lowThreshold(color))
00148 return midColor;
00149
00150 double by = KColorUtils::luma(color), my = KColorUtils::luma(midColor);
00151 return KColorUtils::shade(color, (my - by) * _bgcontrast);
00152 }
00153
00154 QColor OxygenHelper::calcLightColor(const QColor &color) const
00155 {
00156 return KColorScheme::shade(color, KColorScheme::LightShade, _contrast);
00157 }
00158
00159 QColor OxygenHelper::calcDarkColor(const QColor &color) const
00160 {
00161 if (lowThreshold(color))
00162 return KColorUtils::mix(calcLightColor(color), color, 0.2 + 0.8 * _contrast);
00163 else
00164 return KColorScheme::shade(color, KColorScheme::MidShade, _contrast);
00165 }
00166
00167 QColor OxygenHelper::calcShadowColor(const QColor &color) const
00168 {
00169 return KColorScheme::shade(KColorUtils::mix(QColor(255,255,255),color, color.alpha()*(1/255.0)),
00170 KColorScheme::ShadowShade, _contrast);
00171
00172 }
00173
00174 QColor OxygenHelper::backgroundColor(const QColor &color, int height, int y)
00175 {
00176 double h = height * 0.5;
00177 if (y > height>>1) {
00178 double a = double(y) / h;
00179 return KColorUtils::mix(backgroundTopColor(color), color, a);
00180 }
00181 else {
00182 double a = (double(y) - h) / h;
00183 return KColorUtils::mix(color, backgroundBottomColor(color), a);
00184 }
00185 }
00186
00187 QPixmap OxygenHelper::verticalGradient(const QColor &color, int height)
00188 {
00189 quint64 key = (quint64(color.rgba()) << 32) | height | 0x8000;
00190 QPixmap *pixmap = m_backgroundCache.object(key);
00191
00192 if (!pixmap)
00193 {
00194 pixmap = new QPixmap(32, height);
00195
00196 QLinearGradient gradient(0, 0, 0, height);
00197 gradient.setColorAt(0.0, backgroundTopColor(color));
00198 gradient.setColorAt(0.5, color);
00199 gradient.setColorAt(1.0, backgroundBottomColor(color));
00200
00201 QPainter p(pixmap);
00202 p.setCompositionMode(QPainter::CompositionMode_Source);
00203 p.fillRect(pixmap->rect(), gradient);
00204
00205 m_backgroundCache.insert(key, pixmap);
00206 }
00207
00208 return *pixmap;
00209 }
00210
00211 QPixmap OxygenHelper::radialGradient(const QColor &color, int width)
00212 {
00213 quint64 key = (quint64(color.rgba()) << 32) | width | 0xb000;
00214 QPixmap *pixmap = m_backgroundCache.object(key);
00215
00216 if (!pixmap)
00217 {
00218
00219 pixmap = new QPixmap(width, 64);
00220 pixmap->fill(QColor(0,0,0,0));
00221 QColor radialColor = backgroundRadialColor(color);
00222 radialColor.setAlpha(255);
00223 QRadialGradient gradient(64, 0, 64);
00224 gradient.setColorAt(0, radialColor);
00225 radialColor.setAlpha(101);
00226 gradient.setColorAt(0.5, radialColor);
00227 radialColor.setAlpha(37);
00228 gradient.setColorAt(0.75, radialColor);
00229 radialColor.setAlpha(0);
00230 gradient.setColorAt(1, radialColor);
00231
00232 QPainter p(pixmap);
00233 p.scale(width/128.0,1);
00234 p.fillRect(QRect(0,0,128,64), gradient);
00235
00236 m_backgroundCache.insert(key, pixmap);
00237 }
00238
00239 return *pixmap;
00240 }
00241
00242 void OxygenHelper::drawShadow(QPainter &p, const QColor &color, int size) const
00243 {
00244 double m = double(size-2)*0.5;
00245
00246 const double offset = 0.8;
00247 double k0 = (m-4.0) / m;
00248 QRadialGradient shadowGradient(m+1.0, m+offset+1.0, m);
00249 for (int i = 0; i < 8; i++) {
00250 double k1 = (k0 * double(8 - i) + double(i)) * 0.125;
00251 double a = (cos(3.14159 * i * 0.125) + 1.0) * 0.25;
00252 shadowGradient.setColorAt(k1, alphaColor(color, a * _shadowGain));
00253 }
00254 shadowGradient.setColorAt(1.0, alphaColor(color, 0.0));
00255 p.setBrush(shadowGradient);
00256 p.drawEllipse(QRectF(0, 0, size, size));
00257 }
00258
00259 QLinearGradient OxygenHelper::decoGradient(const QRect &r, const QColor &color)
00260 {
00261 QColor light = KColorScheme::shade(color, KColorScheme::LightShade, _contrast * 0.7);
00262 QColor dark = KColorScheme::shade(color, KColorScheme::DarkShade, _contrast * 0.7);
00263 double y = KColorUtils::luma(color);
00264 double yd = KColorUtils::luma(dark);
00265 double yl = KColorUtils::luma(light);
00266
00267 QLinearGradient gradient(r.topLeft(), r.bottomLeft());
00268 if (yd > y)
00269 {
00270 gradient.setColorAt(0.2, color);
00271 gradient.setColorAt(0.8, dark);
00272 }
00273 else if (yl < y)
00274 {
00275 gradient.setColorAt(0.2, light);
00276 gradient.setColorAt(0.8, color);
00277 }
00278 else
00279 {
00280 gradient.setColorAt(0.2, dark);
00281 gradient.setColorAt(0.5, color);
00282 gradient.setColorAt(0.8, light);
00283 }
00284
00285 return gradient;
00286 }
00287
00288 QPixmap OxygenHelper::windecoButton(const QColor &color, bool pressed, int size)
00289 {
00290 quint64 key = (quint64(color.rgba()) << 32) | (size << 1) | pressed;
00291 QPixmap *pixmap = m_windecoButtonCache.object(key);
00292
00293 if (!pixmap)
00294 {
00295 pixmap = new QPixmap(size, size);
00296 pixmap->fill(Qt::transparent);
00297
00298 QPainter p(pixmap);
00299 p.setRenderHints(QPainter::Antialiasing);
00300 p.setPen(Qt::NoPen);
00301
00302 double u = size/21.0;
00303
00304 QColor light = calcLightColor(color);
00305 QColor dark = calcDarkColor(color);
00306 QColor shadow = calcShadowColor(color);
00307
00308 QRectF rect(0.0, 0.0, size, size);
00309 QRectF buttonRect = rect.adjusted(2*u,2*u,-2*u,-2*u);
00310
00311 QLinearGradient fill(QPointF(0.0, 0.0*u),
00312 QPointF(0.0, 21.0*u));
00313 fill.setColorAt(0.0, alphaColor(light, 0.7));
00314 fill.setColorAt(1.0, alphaColor(dark, 0.7));
00315
00316 p.setBrush(fill);
00317 p.drawEllipse(buttonRect);
00318 p.setBrush(Qt::NoBrush);
00319
00320
00321 if (pressed)
00322 {
00323 p.setPen(alphaColor(dark, 0.4));
00324 p.drawEllipse(buttonRect.adjusted(0.9, 0.6, -0.7, -0.7).adjusted(1.7,1.7,-1.7,-1.7));
00325 p.setPen(alphaColor(dark, 0.8));
00326 p.drawEllipse(buttonRect.adjusted(0.9, 0.6, -0.7, -0.7).adjusted(1.2,1.2,-1.2,-1.2));
00327 }
00328 p.setPen(QPen(KColorUtils::mix(dark, shadow, 0.12), 2.0));
00329 p.drawEllipse(buttonRect.adjusted(0.9, 0.6, -0.7, -0.7).adjusted(0,0.1,0,-0.1));
00330 p.setPen(QPen(KColorUtils::mix(dark, shadow, 0.6), 1.2));
00331 p.drawEllipse(buttonRect.adjusted(1.0, 1.4, -0.8, -0.8));
00332
00333
00334 QLinearGradient lightgr(QPointF(0.0, 0.0*u),
00335 QPointF(0.0, 21.0*u));
00336 lightgr.setColorAt(0.0, Qt::transparent);
00337 lightgr.setColorAt(1.0, light);
00338 p.setPen(QPen(lightgr, 1.7));
00339 p.drawEllipse(buttonRect.adjusted(0.0, -0.5, -0.1, 0.0));
00340
00341 m_windecoButtonCache.insert(key, pixmap);
00342 }
00343
00344 return *pixmap;
00345 }
00346
00347 QPixmap OxygenHelper::windecoButtonGlow(const QColor &color, int size)
00348 {
00349 quint64 key = (quint64(color.rgba()) << 32) | size;
00350 QPixmap *pixmap = m_windecoButtonGlowCache.object(key);
00351
00352 if (!pixmap)
00353 {
00354 pixmap = new QPixmap(size, size);
00355 pixmap->fill(Qt::transparent);
00356
00357 QPainter p(pixmap);
00358 p.setRenderHints(QPainter::Antialiasing);
00359 p.setPen(Qt::NoPen);
00360
00361 double u = size/21.0;
00362 QRectF rect(0.0, 0.0, size, size);
00363 QRectF buttonRect = rect.adjusted(2*u,2*u,-2*u,-2*u);
00364
00365
00366 p.setBrush(QColor(0,0,0,125));
00367 p.drawEllipse(rect.adjusted(u, 0, -u, -2*u));
00368
00369
00370 QColor dark = calcDarkColor(color);
00371 QColor light = calcLightColor(color);
00372
00373 QRadialGradient glow(QPointF(size/2.0, size/2.0 + 0.25), size/2.0);
00374 glow.setColorAt(12.0 / 21.0, Qt::transparent);
00375 glow.setColorAt(16.0 / 21.0, dark);
00376 glow.setColorAt(18.0 / 21.0, alphaColor(light, 0.25));
00377 glow.setColorAt(20.0 / 21.0, Qt::transparent);
00378
00379 p.setCompositionMode(QPainter::CompositionMode_SourceIn);
00380 p.setBrush(glow);
00381 p.drawEllipse(rect);
00382
00383 m_windecoButtonGlowCache.insert(key, pixmap);
00384 }
00385
00386 return *pixmap;
00387 }
00388
00389 QPixmap OxygenHelper::glow(const QColor &color, int size, int rsize)
00390 {
00391 QPixmap pixmap(rsize, rsize);
00392 pixmap.fill(QColor(0,0,0,0));
00393
00394 QPainter p(&pixmap);
00395 p.setRenderHints(QPainter::Antialiasing);
00396 p.setPen(Qt::NoPen);
00397 p.setWindow(0,0,size,size);
00398
00399 QRectF r(0, 0, size, size);
00400 double m = double(size)*0.5;
00401
00402 const double width = 3.0;
00403 const double bias = _glowBias * double(size) / double(rsize);
00404 double k0 = (m-width+bias) / m;
00405 QRadialGradient glowGradient(m, m, m);
00406 for (int i = 0; i < 8; i++) {
00407 double k1 = (k0 * double(8 - i) + double(i)) * 0.125;
00408 double a = 1.0 - sqrt(i * 0.125);
00409 glowGradient.setColorAt(k1, alphaColor(color, a));
00410 }
00411 glowGradient.setColorAt(1.0, alphaColor(color, 0.0));
00412
00413
00414 p.setBrush(glowGradient);
00415 p.drawEllipse(r);
00416
00417
00418 p.setCompositionMode(QPainter::CompositionMode_DestinationOut);
00419 p.setBrush(QBrush(Qt::black));
00420 p.drawEllipse(r.adjusted(width, width, -width, -width));
00421
00422 p.end();
00423
00424 return pixmap;
00425 }
00426
00427 void OxygenHelper::drawFloatFrame(QPainter *p, const QRect r, const QColor &color, bool drawUglyShadow, bool isActive, const QColor &frameColor) const
00428 {
00429 p->setRenderHint(QPainter::Antialiasing);
00430 QRect frame = r;
00431 frame.adjust(1,1,-1,-1);
00432 int x,y,w,h;
00433 frame.getRect(&x, &y, &w, &h);
00434
00435 QColor light = calcLightColor(backgroundTopColor(color));
00436 QColor dark = calcLightColor(backgroundBottomColor(color));
00437 QColor glow = KColorUtils::mix(QColor(128,128,128),frameColor,0.7);
00438
00439 p->setBrush(Qt::NoBrush);
00440
00441 if (drawUglyShadow) {
00442 if(isActive) {
00443 p->setPen(glow);
00444 p->drawLine(QPointF(x+4, y-0.5), QPointF(x+w-4, y-0.5));
00445 p->drawArc(QRectF(x-0.5, y-0.5, 11, 11),90*16, 90*16);
00446 p->drawArc(QRectF(x+w-11+0.5, y-0.5, 11, 11), 0, 90*16);
00447 p->drawLine(QPointF(x-0.5, y+4), QPointF(x-0.5, y+h-4));
00448 p->drawLine(QPointF(x+w+0.5, y+4), QPointF(x+w+0.5, y+h-4));
00449 p->drawArc(QRectF(0.5, y+h-11+0.5, 11, 11),180*16, 90*16);
00450 p->drawArc(QRectF(x+w-11+0.5, y+h-11+0.5, 11, 11),270*16, 90*16);
00451 p->drawLine(QPointF(x+4, y+h+0.5), QPointF(x+w-4, y+h+0.5));
00452 light = KColorUtils::mix(light, frameColor);
00453 dark = KColorUtils::mix(dark, frameColor);
00454 }
00455 else {
00456 QColor shadow = KColorUtils::darken(color, 0.0, 0.0);
00457 p->setPen(KColorUtils::darken(shadow, 0.2));
00458 p->drawLine(QPointF(x+4, y-0.5), QPointF(x+w-4, y-0.5));
00459 p->drawArc(QRectF(x-0.5, y-0.5, 11, 11),90*16, 90*16);
00460 p->drawArc(QRectF(x+w-11+0.5, y-0.5, 11, 11), 0, 90*16);
00461 p->setPen(KColorUtils::darken(shadow, 0.35));
00462 p->drawLine(QPointF(x-0.5, y+4), QPointF(x-0.5, y+h-4));
00463 p->drawLine(QPointF(x+w+0.5, y+4), QPointF(x+w+0.5, y+h-4));
00464 p->setPen(KColorUtils::darken(shadow, 0.45));
00465 p->drawArc(QRectF(0.5, y+h-11+0.5, 11, 11),180*16, 90*16);
00466 p->drawArc(QRectF(x+w-11+0.5, y+h-11+0.5, 11, 11),270*16, 90*16);
00467 p->setPen(KColorUtils::darken(shadow, 0.6));
00468 p->drawLine(QPointF(x+4, y+h+0.5), QPointF(x+w-4, y+h+0.5));
00469 }
00470 }
00471
00472 p->setPen(QPen(light, 0.8));
00473 p->drawLine(QPointF(x+4, y+0.6), QPointF(x+w-4, y+0.6));
00474 QLinearGradient lg = QLinearGradient(0.0, 1.5, 0.0, 4.5);
00475 lg.setColorAt(0, light);
00476 lg.setColorAt(1, dark);
00477 p->setPen(QPen(lg, 0.8));
00478 p->drawArc(QRectF(x+0.6, y+0.6, 9, 9),90*16, 90*16);
00479 p->drawArc(QRectF(x+w-9-0.6, y+0.6, 9, 9), 0, 90*16);
00480 p->drawLine(QPointF(x+0.6, y+4), QPointF(x+0.6, y+h-4));
00481 p->drawLine(QPointF(x+w-0.6, y+4), QPointF(x+w-0.6, y+h-4));
00482
00483 return;
00484 }
00485
00486 void OxygenHelper::drawSeparator(QPainter *p, const QRect &rect, const QColor &color, Qt::Orientation orientation) const
00487 {
00488 QColor light = calcLightColor(color);
00489 QColor dark = calcDarkColor(color);
00490
00491 bool antialias = p->testRenderHint(QPainter::Antialiasing);
00492 p->setRenderHint(QPainter::Antialiasing,false);
00493
00494 QPoint start,end,offset;
00495
00496 if (orientation == Qt::Horizontal) {
00497 start = QPoint(rect.x(),rect.y()+rect.height()/2-1);
00498 end = QPoint(rect.right(),rect.y()+rect.height()/2-1);
00499 offset = QPoint(0,1);
00500 } else {
00501 start = QPoint(rect.x()+rect.width()/2-1,rect.y());
00502 end = QPoint(rect.x()+rect.width()/2-1,rect.bottom());
00503 offset = QPoint(1,0);
00504 light.setAlpha(150);
00505 }
00506
00507 QLinearGradient lg(start,end);
00508 lg.setColorAt(0.3, dark);
00509 lg.setColorAt(0.7, dark);
00510 dark.setAlpha(0);
00511 lg.setColorAt(0.0, dark);
00512 lg.setColorAt(1.0, dark);
00513 p->setPen(QPen(lg,1));
00514
00515 if (orientation == Qt::Horizontal)
00516 p->drawLine(start,end);
00517 else
00518 p->drawLine(start+offset,end+offset);
00519
00520 lg = QLinearGradient(start,end);
00521 lg.setColorAt(0.3, light);
00522 lg.setColorAt(0.7, light);
00523 light.setAlpha(0);
00524 lg.setColorAt(0.0, light);
00525 lg.setColorAt(1.0, light);
00526 p->setPen(QPen(lg,1));
00527
00528
00529 if (orientation == Qt::Horizontal)
00530 p->drawLine(start+offset,end+offset);
00531 else
00532 {
00533 p->drawLine(start,end);
00534 p->drawLine(start+offset*2,end+offset*2);
00535 }
00536
00537 p->setRenderHint(QPainter::Antialiasing, antialias);
00538 }
00539