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 #ifdef HAVE_CONFIG_H
00028 #include "config.h"
00029 #endif
00030
00031 #include <qapplication.h>
00032 #include <qbitmap.h>
00033 #include <qcleanuphandler.h>
00034 #include <qmap.h>
00035 #include <qimage.h>
00036 #include <qlistview.h>
00037 #include <qmenubar.h>
00038 #include <qpainter.h>
00039 #include <qpixmap.h>
00040 #include <qpopupmenu.h>
00041 #include <qprogressbar.h>
00042 #include <qscrollbar.h>
00043 #include <qsettings.h>
00044 #include <qslider.h>
00045 #include <qstylefactory.h>
00046 #include <qtabbar.h>
00047 #include <qtoolbar.h>
00048
00049 #include <kpixmap.h>
00050 #include <kpixmapeffect.h>
00051 #include <kimageeffect.h>
00052 #include "kstyle.h"
00053
00054 #include <X11/Xlib.h>
00055 #ifdef HAVE_XRENDER
00056 #include <X11/extensions/Xrender.h>
00057 extern bool qt_use_xrender;
00058 #endif
00059
00060 #include <limits.h>
00061
00062 namespace
00063 {
00064
00065 enum TransparencyEngine {
00066 Disabled = 0,
00067 SoftwareTint,
00068 SoftwareBlend,
00069 XRender
00070 };
00071
00072
00073 struct ShadowElements {
00074 QWidget* w1;
00075 QWidget* w2;
00076 };
00077 typedef QMap<const QPopupMenu*,ShadowElements> ShadowMap;
00078 static ShadowMap *_shadowMap = 0;
00079 QSingleCleanupHandler<ShadowMap> cleanupShadowMap;
00080 ShadowMap &shadowMap() {
00081 if ( !_shadowMap ) {
00082 _shadowMap = new ShadowMap;
00083 cleanupShadowMap.set( &_shadowMap );
00084 }
00085 return *_shadowMap;
00086 }
00087
00088
00089
00090
00091 const double top_right_corner[16] =
00092 { 0.949, 0.965, 0.980, 0.992,
00093 0.851, 0.890, 0.945, 0.980,
00094 0.706, 0.780, 0.890, 0.960,
00095 0.608, 0.706, 0.851, 0.949 };
00096
00097 const double bottom_right_corner[16] =
00098 { 0.608, 0.706, 0.851, 0.949,
00099 0.706, 0.780, 0.890, 0.960,
00100 0.851, 0.890, 0.945, 0.980,
00101 0.949, 0.965, 0.980, 0.992 };
00102
00103 const double bottom_left_corner[16] =
00104 { 0.949, 0.851, 0.706, 0.608,
00105 0.965, 0.890, 0.780, 0.706,
00106 0.980, 0.945, 0.890, 0.851,
00107 0.992, 0.980, 0.960, 0.949 };
00108
00109 const double shadow_strip[4] =
00110 { 0.565, 0.675, 0.835, 0.945 };
00111 }
00112
00113
00114 struct KStylePrivate
00115 {
00116 bool highcolor : 1;
00117 bool useFilledFrameWorkaround : 1;
00118 bool etchDisabledText : 1;
00119 bool scrollablePopupmenus : 1;
00120 bool menuAltKeyNavigation : 1;
00121 bool menuDropShadow : 1;
00122 int popupMenuDelay;
00123 float menuOpacity;
00124
00125 TransparencyEngine transparencyEngine;
00126 KStyle::KStyleScrollBarType scrollbarType;
00127 TransparencyHandler* menuHandler;
00128 KStyle::KStyleFlags flags;
00129 };
00130
00131
00132 class TransparencyHandler : public QObject
00133 {
00134 public:
00135 TransparencyHandler(KStyle* style, TransparencyEngine tEngine,
00136 float menuOpacity, bool useDropShadow);
00137 ~TransparencyHandler();
00138 bool eventFilter(QObject* object, QEvent* event);
00139
00140 protected:
00141 void blendToColor(const QColor &col);
00142 void blendToPixmap(const QColorGroup &cg, const QPopupMenu* p);
00143 #ifdef HAVE_XRENDER
00144 void XRenderBlendToPixmap(const QPopupMenu* p);
00145 #endif
00146 void createShadowWindows(const QPopupMenu* p);
00147 void removeShadowWindows(const QPopupMenu* p);
00148 void rightShadow(QImage& dst);
00149 void bottomShadow(QImage& dst);
00150 private:
00151 bool dropShadow;
00152 float opacity;
00153 QPixmap pix;
00154 KStyle* kstyle;
00155 TransparencyEngine te;
00156 };
00157
00158
00159
00160
00161
00162 KStyle::KStyle( KStyleFlags flags, KStyleScrollBarType sbtype )
00163 : QCommonStyle(), d(new KStylePrivate)
00164 {
00165 d->flags = flags;
00166 bool useMenuTransparency = (flags & AllowMenuTransparency);
00167 d->useFilledFrameWorkaround = (flags & FilledFrameWorkaround);
00168 d->scrollbarType = sbtype;
00169 d->highcolor = QPixmap::defaultDepth() > 8;
00170
00171
00172 QSettings settings;
00173 d->popupMenuDelay = settings.readNumEntry ("/KStyle/Settings/PopupMenuDelay", 256);
00174 d->etchDisabledText = settings.readBoolEntry("/KStyle/Settings/EtchDisabledText", true);
00175 d->menuAltKeyNavigation = settings.readBoolEntry("/KStyle/Settings/MenuAltKeyNavigation", true);
00176 d->scrollablePopupmenus = settings.readBoolEntry("/KStyle/Settings/ScrollablePopupMenus", false);
00177 d->menuDropShadow = settings.readBoolEntry("/KStyle/Settings/MenuDropShadow", false);
00178 d->menuHandler = NULL;
00179
00180 if (useMenuTransparency) {
00181 QString effectEngine = settings.readEntry("/KStyle/Settings/MenuTransparencyEngine", "Disabled");
00182
00183 #ifdef HAVE_XRENDER
00184 if (effectEngine == "XRender")
00185 d->transparencyEngine = XRender;
00186 #else
00187 if (effectEngine == "XRender")
00188 d->transparencyEngine = SoftwareBlend;
00189 #endif
00190 else if (effectEngine == "SoftwareBlend")
00191 d->transparencyEngine = SoftwareBlend;
00192 else if (effectEngine == "SoftwareTint")
00193 d->transparencyEngine = SoftwareTint;
00194 else
00195 d->transparencyEngine = Disabled;
00196
00197 if (d->transparencyEngine != Disabled) {
00198
00199 d->menuOpacity = settings.readDoubleEntry("/KStyle/Settings/MenuOpacity", 0.90);
00200 d->menuHandler = new TransparencyHandler(this, d->transparencyEngine,
00201 d->menuOpacity, d->menuDropShadow);
00202 }
00203 }
00204
00205
00206 if (!d->menuHandler && d->menuDropShadow)
00207 d->menuHandler = new TransparencyHandler(this, Disabled, 1.0, d->menuDropShadow);
00208 }
00209
00210
00211 KStyle::~KStyle()
00212 {
00213 if (d->menuHandler)
00214 delete d->menuHandler;
00215
00216 d->menuHandler = NULL;
00217 delete d;
00218 }
00219
00220
00221 QString KStyle::defaultStyle()
00222 {
00223 if (QPixmap::defaultDepth() > 8)
00224 return QString("Bluecurve");
00225 else
00226 return QString("light, 3rd revision");
00227 }
00228
00229
00230 void KStyle::polish( QWidget* widget )
00231 {
00232 if ( d->useFilledFrameWorkaround )
00233 {
00234 if (widget->inherits("QToolBar"))
00235 widget->installEventFilter(this);
00236 if (widget->inherits("QMenuBar"))
00237 widget->installEventFilter(this);
00238 }
00239 }
00240
00241
00242 void KStyle::unPolish( QWidget* widget )
00243 {
00244 if ( d->useFilledFrameWorkaround )
00245 {
00246 if (widget->inherits("QMenuBar"))
00247 widget->removeEventFilter(this);
00248 if (widget->inherits("QToolBar"))
00249 widget->removeEventFilter(this);
00250 }
00251 }
00252
00253
00254
00255 void KStyle::polishPopupMenu( QPopupMenu* p )
00256 {
00257 if (!p->testWState( WState_Polished ))
00258 p->setCheckable(true);
00259
00260
00261 if ( d->menuHandler &&
00262 (strcmp(p->name(), "tear off menu") != 0))
00263 p->installEventFilter(d->menuHandler);
00264 }
00265
00266
00267
00268
00269
00270
00271 void KStyle::setScrollBarType(KStyleScrollBarType sbtype)
00272 {
00273 d->scrollbarType = sbtype;
00274 }
00275
00276 KStyle::KStyleFlags KStyle::styleFlags() const
00277 {
00278 return d->flags;
00279 }
00280
00281 void KStyle::renderMenuBlendPixmap( KPixmap &pix, const QColorGroup &cg,
00282 const QPopupMenu* ) const
00283 {
00284 pix.fill(cg.button());
00285 }
00286
00287
00288 void KStyle::drawKStylePrimitive( KStylePrimitive kpe,
00289 QPainter* p,
00290 const QWidget* widget,
00291 const QRect &r,
00292 const QColorGroup &cg,
00293 SFlags flags,
00294 const QStyleOption& ) const
00295 {
00296 switch( kpe )
00297 {
00298
00299
00300
00301 case KPE_DockWindowHandle: {
00302
00303
00304 QWidget* wid = const_cast<QWidget*>(widget);
00305 bool horizontal = flags & Style_Horizontal;
00306 int x,y,w,h,x2,y2;
00307
00308 if ((wid->width() <= 2) || (wid->height() <= 2)) {
00309 p->fillRect(r, cg.highlight());
00310 return;
00311 }
00312
00313 r.rect( &x, &y, &w, &h );
00314 x2 = x + w - 1;
00315 y2 = y + h - 1;
00316
00317 QFont fnt;
00318 fnt = QApplication::font(wid);
00319 fnt.setPointSize( fnt.pointSize()-2 );
00320
00321
00322
00323
00324 QPixmap pix;
00325 if (horizontal)
00326 pix.resize( h-2, w-2 );
00327 else
00328 pix.resize( w-2, h-2 );
00329
00330 QString title = wid->parentWidget()->caption();
00331 QPainter p2;
00332 p2.begin(&pix);
00333 p2.fillRect(pix.rect(), cg.brush(QColorGroup::Highlight));
00334 p2.setPen(cg.highlightedText());
00335 p2.setFont(fnt);
00336 p2.drawText(pix.rect(), AlignCenter, title);
00337 p2.end();
00338
00339
00340 p->setPen(cg.dark());
00341 p->drawLine(x, y, x2, y);
00342 p->drawLine(x, y, x, y2);
00343 p->setPen(cg.light());
00344 p->drawLine(x+1, y2, x2, y2);
00345 p->drawLine(x2, y+1, x2, y2);
00346
00347 if (horizontal) {
00348 QWMatrix m;
00349 m.rotate(-90.0);
00350 QPixmap vpix = pix.xForm(m);
00351 bitBlt(wid, r.x()+1, r.y()+1, &vpix);
00352 } else
00353 bitBlt(wid, r.x()+1, r.y()+1, &pix);
00354
00355 break;
00356 }
00357
00358
00359
00360
00361
00362
00363
00364
00365 case KPE_ListViewExpander: {
00366
00367 int radius = (r.width() - 4) / 2;
00368 int centerx = r.x() + r.width()/2;
00369 int centery = r.y() + r.height()/2;
00370
00371
00372 p->setPen( cg.mid() );
00373 p->drawRect( r );
00374
00375
00376 p->setPen( cg.text() );
00377 p->drawLine( centerx - radius, centery, centerx + radius, centery );
00378 if ( flags & Style_On )
00379 p->drawLine( centerx, centery - radius, centerx, centery + radius );
00380 break;
00381 }
00382
00383 case KPE_ListViewBranch: {
00384
00385
00386 static QBitmap *verticalLine = 0, *horizontalLine = 0;
00387 static QCleanupHandler<QBitmap> qlv_cleanup_bitmap;
00388
00389
00390 if ( !verticalLine )
00391 {
00392
00393
00394 verticalLine = new QBitmap( 1, 129, TRUE );
00395 horizontalLine = new QBitmap( 128, 1, TRUE );
00396 QPointArray a( 64 );
00397 QPainter p2;
00398 p2.begin( verticalLine );
00399
00400 int i;
00401 for( i=0; i < 64; i++ )
00402 a.setPoint( i, 0, i*2+1 );
00403 p2.setPen( color1 );
00404 p2.drawPoints( a );
00405 p2.end();
00406 QApplication::flushX();
00407 verticalLine->setMask( *verticalLine );
00408
00409 p2.begin( horizontalLine );
00410 for( i=0; i < 64; i++ )
00411 a.setPoint( i, i*2+1, 0 );
00412 p2.setPen( color1 );
00413 p2.drawPoints( a );
00414 p2.end();
00415 QApplication::flushX();
00416 horizontalLine->setMask( *horizontalLine );
00417
00418 qlv_cleanup_bitmap.add( &verticalLine );
00419 qlv_cleanup_bitmap.add( &horizontalLine );
00420 }
00421
00422 p->setPen( cg.text() );
00423
00424 if (flags & Style_Horizontal)
00425 {
00426 int point = r.x();
00427 int other = r.y();
00428 int end = r.x()+r.width();
00429 int thickness = r.height();
00430
00431 while( point < end )
00432 {
00433 int i = 128;
00434 if ( i+point > end )
00435 i = end-point;
00436 p->drawPixmap( point, other, *horizontalLine, 0, 0, i, thickness );
00437 point += i;
00438 }
00439
00440 } else {
00441 int point = r.y();
00442 int other = r.x();
00443 int end = r.y()+r.height();
00444 int thickness = r.width();
00445 int pixmapoffset = (flags & Style_NoChange) ? 0 : 1;
00446
00447 while( point < end )
00448 {
00449 int i = 128;
00450 if ( i+point > end )
00451 i = end-point;
00452 p->drawPixmap( other, point, *verticalLine, 0, pixmapoffset, thickness, i );
00453 point += i;
00454 }
00455 }
00456
00457 break;
00458 }
00459
00460
00461
00462 case KPE_ToolBarHandle:
00463 case KPE_GeneralHandle:
00464 case KPE_SliderHandle:
00465 p->fillRect(r, cg.light());
00466 break;
00467
00468 case KPE_SliderGroove:
00469 p->fillRect(r, cg.dark());
00470 break;
00471
00472 default:
00473 p->fillRect(r, Qt::yellow);
00474 break;
00475 }
00476 }
00477
00478
00479 int KStyle::kPixelMetric( KStylePixelMetric kpm, const QWidget* ) const
00480 {
00481 int value;
00482 switch(kpm)
00483 {
00484 case KPM_ListViewBranchThickness:
00485 value = 1;
00486 break;
00487
00488 case KPM_MenuItemSeparatorHeight:
00489 case KPM_MenuItemHMargin:
00490 case KPM_MenuItemVMargin:
00491 case KPM_MenuItemHFrame:
00492 case KPM_MenuItemVFrame:
00493 case KPM_MenuItemCheckMarkHMargin:
00494 case KPM_MenuItemArrowHMargin:
00495 case KPM_MenuItemTabSpacing:
00496 default:
00497 value = 0;
00498 }
00499
00500 return value;
00501 }
00502
00503
00504
00505
00506 void KStyle::drawPrimitive( PrimitiveElement pe,
00507 QPainter* p,
00508 const QRect &r,
00509 const QColorGroup &cg,
00510 SFlags flags,
00511 const QStyleOption& opt ) const
00512 {
00513
00514
00515 if (pe == PE_DockWindowHandle)
00516 {
00517
00518 QWidget *widget, *parent;
00519
00520 if (p && p->device()->devType() == QInternal::Widget) {
00521 widget = static_cast<QWidget*>(p->device());
00522 parent = widget->parentWidget();
00523 } else
00524 return;
00525
00526
00527 if ( parent &&
00528 (parent->inherits("QToolBar") ||
00529 (parent->inherits("QMainWindow")) ))
00530
00531
00532 drawKStylePrimitive( KPE_ToolBarHandle, p, widget, r, cg, flags, opt );
00533
00534 else if ( widget->inherits("QDockWindowHandle") )
00535
00536
00537 drawKStylePrimitive( KPE_DockWindowHandle, p, widget, r, cg, flags, opt );
00538
00539 else
00540
00541 drawKStylePrimitive( KPE_GeneralHandle, p, widget, r, cg, flags, opt );
00542
00543 } else
00544 QCommonStyle::drawPrimitive( pe, p, r, cg, flags, opt );
00545 }
00546
00547
00548
00549 void KStyle::drawControl( ControlElement element,
00550 QPainter* p,
00551 const QWidget* widget,
00552 const QRect &r,
00553 const QColorGroup &cg,
00554 SFlags flags,
00555 const QStyleOption &opt ) const
00556 {
00557 switch (element)
00558 {
00559
00560
00561 case CE_TabBarTab: {
00562 const QTabBar* tb = (const QTabBar*) widget;
00563 QTabBar::Shape tbs = tb->shape();
00564 bool selected = flags & Style_Selected;
00565 int x = r.x(), y=r.y(), bottom=r.bottom(), right=r.right();
00566
00567 switch (tbs) {
00568
00569 case QTabBar::RoundedAbove: {
00570 if (!selected)
00571 p->translate(0,1);
00572 p->setPen(selected ? cg.light() : cg.shadow());
00573 p->drawLine(x, y+4, x, bottom);
00574 p->drawLine(x, y+4, x+4, y);
00575 p->drawLine(x+4, y, right-1, y);
00576 if (selected)
00577 p->setPen(cg.shadow());
00578 p->drawLine(right, y+1, right, bottom);
00579
00580 p->setPen(cg.midlight());
00581 p->drawLine(x+1, y+4, x+1, bottom);
00582 p->drawLine(x+1, y+4, x+4, y+1);
00583 p->drawLine(x+5, y+1, right-2, y+1);
00584
00585 if (selected) {
00586 p->setPen(cg.mid());
00587 p->drawLine(right-1, y+1, right-1, bottom);
00588 } else {
00589 p->setPen(cg.mid());
00590 p->drawPoint(right-1, y+1);
00591 p->drawLine(x+4, y+2, right-1, y+2);
00592 p->drawLine(x+3, y+3, right-1, y+3);
00593 p->fillRect(x+2, y+4, r.width()-3, r.height()-6, cg.mid());
00594
00595 p->setPen(cg.light());
00596 p->drawLine(x, bottom-1, right, bottom-1);
00597 p->translate(0,-1);
00598 }
00599 break;
00600 }
00601
00602 case QTabBar::RoundedBelow: {
00603 if (!selected)
00604 p->translate(0,-1);
00605 p->setPen(selected ? cg.light() : cg.shadow());
00606 p->drawLine(x, bottom-4, x, y);
00607 if (selected)
00608 p->setPen(cg.mid());
00609 p->drawLine(x, bottom-4, x+4, bottom);
00610 if (selected)
00611 p->setPen(cg.shadow());
00612 p->drawLine(x+4, bottom, right-1, bottom);
00613 p->drawLine(right, bottom-1, right, y);
00614
00615 p->setPen(cg.midlight());
00616 p->drawLine(x+1, bottom-4, x+1, y);
00617 p->drawLine(x+1, bottom-4, x+4, bottom-1);
00618 p->drawLine(x+5, bottom-1, right-2, bottom-1);
00619
00620 if (selected) {
00621 p->setPen(cg.mid());
00622 p->drawLine(right-1, y, right-1, bottom-1);
00623 } else {
00624 p->setPen(cg.mid());
00625 p->drawPoint(right-1, bottom-1);
00626 p->drawLine(x+4, bottom-2, right-1, bottom-2);
00627 p->drawLine(x+3, bottom-3, right-1, bottom-3);
00628 p->fillRect(x+2, y+2, r.width()-3, r.height()-6, cg.mid());
00629 p->translate(0,1);
00630 p->setPen(cg.dark());
00631 p->drawLine(x, y, right, y);
00632 }
00633 break;
00634 }
00635
00636 case QTabBar::TriangularAbove: {
00637 if (!selected)
00638 p->translate(0,1);
00639 p->setPen(selected ? cg.light() : cg.shadow());
00640 p->drawLine(x, bottom, x, y+6);
00641 p->drawLine(x, y+6, x+6, y);
00642 p->drawLine(x+6, y, right-6, y);
00643 if (selected)
00644 p->setPen(cg.mid());
00645 p->drawLine(right-5, y+1, right-1, y+5);
00646 p->setPen(cg.shadow());
00647 p->drawLine(right, y+6, right, bottom);
00648
00649 p->setPen(cg.midlight());
00650 p->drawLine(x+1, bottom, x+1, y+6);
00651 p->drawLine(x+1, y+6, x+6, y+1);
00652 p->drawLine(x+6, y+1, right-6, y+1);
00653 p->drawLine(right-5, y+2, right-2, y+5);
00654 p->setPen(cg.mid());
00655 p->drawLine(right-1, y+6, right-1, bottom);
00656
00657 QPointArray a(6);
00658 a.setPoint(0, x+2, bottom);
00659 a.setPoint(1, x+2, y+7);
00660 a.setPoint(2, x+7, y+2);
00661 a.setPoint(3, right-7, y+2);
00662 a.setPoint(4, right-2, y+7);
00663 a.setPoint(5, right-2, bottom);
00664 p->setPen (selected ? cg.background() : cg.mid());
00665 p->setBrush(selected ? cg.background() : cg.mid());
00666 p->drawPolygon(a);
00667 p->setBrush(NoBrush);
00668 if (!selected) {
00669 p->translate(0,-1);
00670 p->setPen(cg.light());
00671 p->drawLine(x, bottom, right, bottom);
00672 }
00673 break;
00674 }
00675
00676 default: {
00677 if (!selected)
00678 p->translate(0,-1);
00679 p->setPen(selected ? cg.light() : cg.shadow());
00680 p->drawLine(x, y, x, bottom-6);
00681 if (selected)
00682 p->setPen(cg.mid());
00683 p->drawLine(x, bottom-6, x+6, bottom);
00684 if (selected)
00685 p->setPen(cg.shadow());
00686 p->drawLine(x+6, bottom, right-6, bottom);
00687 p->drawLine(right-5, bottom-1, right-1, bottom-5);
00688 if (!selected)
00689 p->setPen(cg.shadow());
00690 p->drawLine(right, bottom-6, right, y);
00691
00692 p->setPen(cg.midlight());
00693 p->drawLine(x+1, y, x+1, bottom-6);
00694 p->drawLine(x+1, bottom-6, x+6, bottom-1);
00695 p->drawLine(x+6, bottom-1, right-6, bottom-1);
00696 p->drawLine(right-5, bottom-2, right-2, bottom-5);
00697 p->setPen(cg.mid());
00698 p->drawLine(right-1, bottom-6, right-1, y);
00699
00700 QPointArray a(6);
00701 a.setPoint(0, x+2, y);
00702 a.setPoint(1, x+2, bottom-7);
00703 a.setPoint(2, x+7, bottom-2);
00704 a.setPoint(3, right-7, bottom-2);
00705 a.setPoint(4, right-2, bottom-7);
00706 a.setPoint(5, right-2, y);
00707 p->setPen (selected ? cg.background() : cg.mid());
00708 p->setBrush(selected ? cg.background() : cg.mid());
00709 p->drawPolygon(a);
00710 p->setBrush(NoBrush);
00711 if (!selected) {
00712 p->translate(0,1);
00713 p->setPen(cg.dark());
00714 p->drawLine(x, y, right, y);
00715 }
00716 break;
00717 }
00718 };
00719
00720 break;
00721 }
00722
00723
00724
00725
00726 case CE_ProgressBarGroove: {
00727 QRect fr = subRect(SR_ProgressBarGroove, widget);
00728 drawPrimitive(PE_Panel, p, fr, cg, Style_Sunken, QStyleOption::Default);
00729 break;
00730 }
00731
00732 case CE_ProgressBarContents: {
00733
00734 const QProgressBar* pb = (const QProgressBar*)widget;
00735 QRect cr = subRect(SR_ProgressBarContents, widget);
00736 double progress = pb->progress();
00737 bool reverse = QApplication::reverseLayout();
00738 int steps = pb->totalSteps();
00739
00740 if (!cr.isValid())
00741 return;
00742
00743
00744 if (progress > 0 || steps == 0) {
00745 double pg = (steps == 0) ? 0.1 : progress / steps;
00746 int width = QMIN(cr.width(), (int)(pg * cr.width()));
00747 if (steps == 0) {
00748
00749 if (width < 1) width = 1;
00750
00751 int remWidth = cr.width() - width;
00752 if (remWidth <= 0) remWidth = 1;
00753
00754 int pstep = int(progress) % ( 2 * remWidth );
00755
00756 if ( pstep > remWidth ) {
00757
00758
00759 pstep = - (pstep - 2 * remWidth );
00760 }
00761
00762 if (reverse)
00763 p->fillRect(cr.x() + cr.width() - width - pstep, cr.y(), width, cr.height(),
00764 cg.brush(QColorGroup::Highlight));
00765 else
00766 p->fillRect(cr.x() + pstep, cr.y(), width, cr.height(),
00767 cg.brush(QColorGroup::Highlight));
00768
00769 return;
00770 }
00771
00772
00773
00774 if (d->highcolor) {
00775 QColor c(cg.highlight());
00776 KPixmap pix;
00777 pix.resize(cr.width(), cr.height());
00778 KPixmapEffect::gradient(pix, reverse ? c.light(150) : c.dark(150),
00779 reverse ? c.dark(150) : c.light(150),
00780 KPixmapEffect::HorizontalGradient);
00781 if (reverse)
00782 p->drawPixmap(cr.x()+(cr.width()-width), cr.y(), pix,
00783 cr.width()-width, 0, width, cr.height());
00784 else
00785 p->drawPixmap(cr.x(), cr.y(), pix, 0, 0, width, cr.height());
00786 } else
00787 if (reverse)
00788 p->fillRect(cr.x()+(cr.width()-width), cr.y(), width, cr.height(),
00789 cg.brush(QColorGroup::Highlight));
00790 else
00791 p->fillRect(cr.x(), cr.y(), width, cr.height(),
00792 cg.brush(QColorGroup::Highlight));
00793 }
00794 break;
00795 }
00796
00797 case CE_ProgressBarLabel: {
00798 const QProgressBar* pb = (const QProgressBar*)widget;
00799 QRect cr = subRect(SR_ProgressBarContents, widget);
00800 double progress = pb->progress();
00801 bool reverse = QApplication::reverseLayout();
00802 int steps = pb->totalSteps();
00803
00804 if (!cr.isValid())
00805 return;
00806
00807 QFont font = p->font();
00808 font.setBold(true);
00809 p->setFont(font);
00810
00811
00812 if (progress > 0 || steps == 0) {
00813 double pg = (steps == 0) ? 1.0 : progress / steps;
00814 int width = QMIN(cr.width(), (int)(pg * cr.width()));
00815 QRect crect;
00816 if (reverse)
00817 crect.setRect(cr.x()+(cr.width()-width), cr.y(), cr.width(), cr.height());
00818 else
00819 crect.setRect(cr.x()+width, cr.y(), cr.width(), cr.height());
00820
00821 p->save();
00822 p->setPen(pb->isEnabled() ? (reverse ? cg.text() : cg.highlightedText()) : cg.text());
00823 p->drawText(r, AlignCenter, pb->progressString());
00824 p->setClipRect(crect);
00825 p->setPen(reverse ? cg.highlightedText() : cg.text());
00826 p->drawText(r, AlignCenter, pb->progressString());
00827 p->restore();
00828
00829 } else {
00830 p->setPen(cg.text());
00831 p->drawText(r, AlignCenter, pb->progressString());
00832 }
00833
00834 break;
00835 }
00836
00837 default:
00838 QCommonStyle::drawControl(element, p, widget, r, cg, flags, opt);
00839 }
00840 }
00841
00842
00843 QRect KStyle::subRect(SubRect r, const QWidget* widget) const
00844 {
00845 switch(r)
00846 {
00847
00848
00849 case SR_ProgressBarGroove:
00850 return widget->rect();
00851
00852 case SR_ProgressBarContents:
00853 case SR_ProgressBarLabel: {
00854
00855 QRect rt = widget->rect();
00856 return QRect(rt.x()+2, rt.y()+2, rt.width()-4, rt.height()-4);
00857 }
00858
00859 default:
00860 return QCommonStyle::subRect(r, widget);
00861 }
00862 }
00863
00864
00865 int KStyle::pixelMetric(PixelMetric m, const QWidget* widget) const
00866 {
00867 switch(m)
00868 {
00869
00870
00871 case PM_ButtonShiftHorizontal:
00872 case PM_ButtonShiftVertical:
00873 return 1;
00874
00875
00876
00877 case PM_TabBarTabHSpace:
00878 return 24;
00879
00880 case PM_TabBarTabVSpace: {
00881 const QTabBar * tb = (const QTabBar *) widget;
00882 if ( tb->shape() == QTabBar::RoundedAbove ||
00883 tb->shape() == QTabBar::RoundedBelow )
00884 return 10;
00885 else
00886 return 4;
00887 }
00888
00889 case PM_TabBarTabOverlap: {
00890 const QTabBar* tb = (const QTabBar*)widget;
00891 QTabBar::Shape tbs = tb->shape();
00892
00893 if ( (tbs == QTabBar::RoundedAbove) ||
00894 (tbs == QTabBar::RoundedBelow) )
00895 return 0;
00896 else
00897 return 2;
00898 }
00899
00900
00901
00902 case PM_SliderLength:
00903 return 18;
00904
00905 case PM_SliderThickness:
00906 return 24;
00907
00908
00909
00910 case PM_SliderControlThickness: {
00911 const QSlider* slider = (const QSlider*)widget;
00912 QSlider::TickSetting ts = slider->tickmarks();
00913 int thickness = (slider->orientation() == Horizontal) ?
00914 slider->height() : slider->width();
00915 switch (ts) {
00916 case QSlider::NoMarks:
00917 break;
00918 case QSlider::Both:
00919 thickness = (thickness/2) + 3;
00920 break;
00921 default:
00922 thickness = ((thickness*2)/3) + 3;
00923 break;
00924 };
00925 return thickness;
00926 }
00927
00928
00929
00930 case PM_SplitterWidth:
00931 if (widget && widget->inherits("QDockWindowResizeHandle"))
00932 return 8;
00933 else
00934 return 6;
00935
00936
00937
00938 case PM_MenuBarFrameWidth:
00939 return 1;
00940
00941 case PM_DockWindowFrameWidth:
00942 return 1;
00943
00944
00945
00946 case PM_MaximumDragDistance:
00947 return -1;
00948
00949 default:
00950 return QCommonStyle::pixelMetric( m, widget );
00951 }
00952 }
00953
00954
00955 void KStyle::drawComplexControl( ComplexControl control,
00956 QPainter* p,
00957 const QWidget* widget,
00958 const QRect &r,
00959 const QColorGroup &cg,
00960 SFlags flags,
00961 SCFlags controls,
00962 SCFlags active,
00963 const QStyleOption &opt ) const
00964 {
00965 switch(control)
00966 {
00967
00968
00969 case CC_ScrollBar: {
00970
00971 bool useThreeButtonScrollBar = (d->scrollbarType & ThreeButtonScrollBar);
00972
00973 const QScrollBar *sb = (const QScrollBar*)widget;
00974 bool maxedOut = (sb->minValue() == sb->maxValue());
00975 bool horizontal = (sb->orientation() == Qt::Horizontal);
00976 SFlags sflags = ((horizontal ? Style_Horizontal : Style_Default) |
00977 (maxedOut ? Style_Default : Style_Enabled));
00978
00979 QRect addline, subline, subline2, addpage, subpage, slider, first, last;
00980 subline = querySubControlMetrics(control, widget, SC_ScrollBarSubLine, opt);
00981 addline = querySubControlMetrics(control, widget, SC_ScrollBarAddLine, opt);
00982 subpage = querySubControlMetrics(control, widget, SC_ScrollBarSubPage, opt);
00983 addpage = querySubControlMetrics(control, widget, SC_ScrollBarAddPage, opt);
00984 slider = querySubControlMetrics(control, widget, SC_ScrollBarSlider, opt);
00985 first = querySubControlMetrics(control, widget, SC_ScrollBarFirst, opt);
00986 last = querySubControlMetrics(control, widget, SC_ScrollBarLast, opt);
00987 subline2 = addline;
00988
00989 if ( useThreeButtonScrollBar )
00990 if (horizontal)
00991 subline2.moveBy(-addline.width(), 0);
00992 else
00993 subline2.moveBy(0, -addline.height());
00994
00995
00996 if ((controls & SC_ScrollBarSubLine) && subline.isValid()) {
00997 drawPrimitive(PE_ScrollBarSubLine, p, subline, cg,
00998 sflags | (active == SC_ScrollBarSubLine ?
00999 Style_Down : Style_Default));
01000
01001 if (useThreeButtonScrollBar && subline2.isValid())
01002 drawPrimitive(PE_ScrollBarSubLine, p, subline2, cg,
01003 sflags | (active == SC_ScrollBarSubLine ?
01004 Style_Down : Style_Default));
01005 }
01006
01007 if ((controls & SC_ScrollBarAddLine) && addline.isValid())
01008 drawPrimitive(PE_ScrollBarAddLine, p, addline, cg,
01009 sflags | ((active == SC_ScrollBarAddLine) ?
01010 Style_Down : Style_Default));
01011
01012 if ((controls & SC_ScrollBarSubPage) && subpage.isValid())
01013 drawPrimitive(PE_ScrollBarSubPage, p, subpage, cg,
01014 sflags | ((active == SC_ScrollBarSubPage) ?
01015 Style_Down : Style_Default));
01016
01017 if ((controls & SC_ScrollBarAddPage) && addpage.isValid())
01018 drawPrimitive(PE_ScrollBarAddPage, p, addpage, cg,
01019 sflags | ((active == SC_ScrollBarAddPage) ?
01020 Style_Down : Style_Default));
01021
01022 if ((controls & SC_ScrollBarFirst) && first.isValid())
01023 drawPrimitive(PE_ScrollBarFirst, p, first, cg,
01024 sflags | ((active == SC_ScrollBarFirst) ?
01025 Style_Down : Style_Default));
01026
01027 if ((controls & SC_ScrollBarLast) && last.isValid())
01028 drawPrimitive(PE_ScrollBarLast, p, last, cg,
01029 sflags | ((active == SC_ScrollBarLast) ?
01030 Style_Down : Style_Default));
01031
01032 if ((controls & SC_ScrollBarSlider) && slider.isValid()) {
01033 drawPrimitive(PE_ScrollBarSlider, p, slider, cg,
01034 sflags | ((active == SC_ScrollBarSlider) ?
01035 Style_Down : Style_Default));
01036
01037 if (sb->hasFocus()) {
01038 QRect fr(slider.x() + 2, slider.y() + 2,
01039 slider.width() - 5, slider.height() - 5);
01040 drawPrimitive(PE_FocusRect, p, fr, cg, Style_Default);
01041 }
01042 }
01043 break;
01044 }
01045
01046
01047
01048
01049 case CC_Slider: {
01050 const QSlider* slider = (const QSlider*)widget;
01051 QRect groove = querySubControlMetrics(CC_Slider, widget, SC_SliderGroove, opt);
01052 QRect handle = querySubControlMetrics(CC_Slider, widget, SC_SliderHandle, opt);
01053
01054
01055 QPixmap pix(widget->size());
01056 QPainter p2;
01057 p2.begin(&pix);
01058
01059 if ( slider->parentWidget() &&
01060 slider->parentWidget()->backgroundPixmap() &&
01061 !slider->parentWidget()->backgroundPixmap()->isNull() ) {
01062 QPixmap pixmap = *(slider->parentWidget()->backgroundPixmap());
01063 p2.drawTiledPixmap(r, pixmap, slider->pos());
01064 } else
01065 pix.fill(cg.background());
01066
01067
01068 if ((controls & SC_SliderGroove) && groove.isValid()) {
01069 drawKStylePrimitive( KPE_SliderGroove, &p2, widget, groove, cg, flags, opt );
01070
01071
01072 if (slider->hasFocus())
01073 drawPrimitive(PE_FocusRect, &p2, groove, cg);
01074 }
01075
01076
01077 if (controls & SC_SliderTickmarks)
01078 QCommonStyle::drawComplexControl(control, &p2, widget,
01079 r, cg, flags, SC_SliderTickmarks, active, opt);
01080
01081
01082 if ((controls & SC_SliderHandle) && handle.isValid()) {
01083 if (active == SC_SliderHandle)
01084 flags |= Style_Active;
01085 drawKStylePrimitive( KPE_SliderHandle, &p2, widget, handle, cg, flags, opt );
01086 }
01087
01088 p2.end();
01089 bitBlt((QWidget*)widget, r.x(), r.y(), &pix);
01090 break;
01091 }
01092
01093
01094
01095 case CC_ListView: {
01096
01097
01098
01099
01100
01101
01102
01103 if ( controls & SC_ListView )
01104 QCommonStyle::drawComplexControl( control, p, widget, r, cg, flags, controls, active, opt );
01105
01106
01107 if ( controls & (SC_ListViewBranch | SC_ListViewExpand) )
01108 {
01109
01110 if (opt.isDefault())
01111 break;
01112
01113 QListViewItem *item = opt.listViewItem();
01114 QListViewItem *child = item->firstChild();
01115
01116 int y = r.y();
01117 int c;
01118 int dotoffset = 0;
01119 QPointArray dotlines;
01120
01121 if ( active == SC_All && controls == SC_ListViewExpand ) {
01122
01123 c = 2;
01124 dotlines.resize(2);
01125 dotlines[0] = QPoint( r.right(), r.top() );
01126 dotlines[1] = QPoint( r.right(), r.bottom() );
01127
01128 } else {
01129
01130 int linetop = 0, linebot = 0;
01131
01132 dotoffset = (item->itemPos() + item->height() - y) % 2;
01133 dotlines.resize( item->childCount() * 4 );
01134 c = 0;
01135
01136
01137 while ( child && y + child->height() <= 0 )
01138 {
01139 y += child->totalHeight();
01140 child = child->nextSibling();
01141 }
01142
01143 int bx = r.width() / 2;
01144
01145
01146 QListView* v = item->listView();
01147 int lh = QMAX( p->fontMetrics().height() + 2 * v->itemMargin(),
01148 QApplication::globalStrut().height() );
01149 if ( lh % 2 > 0 )
01150 lh++;
01151
01152
01153 QRect boxrect;
01154 QStyle::StyleFlags boxflags;
01155 while ( child && y < r.height() )
01156 {
01157 linebot = y + lh/2;
01158 if ( (child->isExpandable() || child->childCount()) &&
01159 (child->height() > 0) )
01160 {
01161
01162 boxrect = QRect( bx-4, linebot-4, 9, 9 );
01163 boxflags = child->isOpen() ? QStyle::Style_Off : QStyle::Style_On;
01164
01165
01166 drawKStylePrimitive( KPE_ListViewExpander, p, NULL, boxrect, cg, boxflags, opt );
01167
01168
01169 p->setPen( cg.mid() );
01170 dotlines[c++] = QPoint( bx, linetop );
01171 dotlines[c++] = QPoint( bx, linebot - 5 );
01172 dotlines[c++] = QPoint( bx + 5, linebot );
01173 dotlines[c++] = QPoint( r.width(), linebot );
01174 linetop = linebot + 5;
01175 } else {
01176
01177 dotlines[c++] = QPoint( bx+1, linebot );
01178 dotlines[c++] = QPoint( r.width(), linebot );
01179 }
01180
01181 y += child->totalHeight();
01182 child = child->nextSibling();
01183 }
01184
01185 if ( child )
01186 linebot = r.height();
01187
01188 if ( linetop < linebot )
01189 {
01190 dotlines[c++] = QPoint( bx, linetop );
01191 dotlines[c++] = QPoint( bx, linebot );
01192 }
01193 }
01194
01195
01196 static int thickness = kPixelMetric( KPM_ListViewBranchThickness );
01197 int line;
01198 QRect branchrect;
01199 QStyle::StyleFlags branchflags;
01200 for( line = 0; line < c; line += 2 )
01201 {
01202
01203
01204
01205
01206
01207
01208
01209 if ( dotlines[line].y() == dotlines[line+1].y() )
01210 {
01211
01212 int end = dotlines[line+1].x();
01213 int point = dotlines[line].x();
01214 int other = dotlines[line].y();
01215
01216 branchrect = QRect( point, other-(thickness/2), end-point, thickness );
01217 branchflags = QStyle::Style_Horizontal;
01218
01219
01220 drawKStylePrimitive( KPE_ListViewBranch, p, NULL, branchrect, cg, branchflags, opt );
01221
01222 } else {
01223
01224 int end = dotlines[line+1].y();
01225 int point = dotlines[line].y();
01226 int other = dotlines[line].x();
01227 int pixmapoffset = ((point & 1) != dotoffset ) ? 1 : 0;
01228
01229 branchrect = QRect( other-(thickness/2), point, thickness, end-point );
01230 if (!pixmapoffset)
01231 branchflags = QStyle::Style_NoChange;
01232 else
01233 branchflags = QStyle::Style_Default;
01234
01235
01236 drawKStylePrimitive( KPE_ListViewBranch, p, NULL, branchrect, cg, branchflags, opt );
01237 }
01238 }
01239 }
01240 break;
01241 }
01242
01243 default:
01244 QCommonStyle::drawComplexControl( control, p, widget, r, cg,
01245 flags, controls, active, opt );
01246 break;
01247 }
01248 }
01249
01250
01251 QStyle::SubControl KStyle::querySubControl( ComplexControl control,
01252 const QWidget* widget,
01253 const QPoint &pos,
01254 const QStyleOption &opt ) const
01255 {
01256 QStyle::SubControl ret = QCommonStyle::querySubControl(control, widget, pos, opt);
01257
01258 if (d->scrollbarType == ThreeButtonScrollBar) {
01259
01260 if (control == CC_ScrollBar && ret == SC_None)
01261 ret = SC_ScrollBarSubLine;
01262 }
01263 return ret;
01264 }
01265
01266
01267 QRect KStyle::querySubControlMetrics( ComplexControl control,
01268 const QWidget* widget,
01269 SubControl sc,
01270 const QStyleOption &opt ) const
01271 {
01272 QRect ret;
01273
01274 if (control == CC_ScrollBar)
01275 {
01276 bool threeButtonScrollBar = d->scrollbarType & ThreeButtonScrollBar;
01277 bool platinumScrollBar = d->scrollbarType & PlatinumStyleScrollBar;
01278 bool nextScrollBar = d->scrollbarType & NextStyleScrollBar;
01279
01280 const QScrollBar *sb = (const QScrollBar*)widget;
01281 bool horizontal = sb->orientation() == Qt::Horizontal;
01282 int sliderstart = sb->sliderStart();
01283 int sbextent = pixelMetric(PM_ScrollBarExtent, widget);
01284 int maxlen = (horizontal ? sb->width() : sb->height())
01285 - (sbextent * (threeButtonScrollBar ? 3 : 2));
01286 int sliderlen;
01287
01288
01289 if (sb->maxValue() != sb->minValue())
01290 {
01291 uint range = sb->maxValue() - sb->minValue();
01292 sliderlen = (sb->pageStep() * maxlen) / (range + sb->pageStep());
01293
01294 int slidermin = pixelMetric( PM_ScrollBarSliderMin, widget );
01295 if ( sliderlen < slidermin || range > INT_MAX / 2 )
01296 sliderlen = slidermin;
01297 if ( sliderlen > maxlen )
01298 sliderlen = maxlen;
01299 } else
01300 sliderlen = maxlen;
01301
01302
01303 switch (sc)
01304 {
01305 case SC_ScrollBarSubLine: {
01306
01307 if (platinumScrollBar) {
01308 if (horizontal)
01309 ret.setRect(sb->width() - 2 * sbextent, 0, sbextent, sbextent);
01310 else
01311 ret.setRect(0, sb->height() - 2 * sbextent, sbextent, sbextent);
01312 } else
01313 ret.setRect(0, 0, sbextent, sbextent);
01314 break;
01315 }
01316
01317 case SC_ScrollBarAddLine: {
01318
01319 if (nextScrollBar) {
01320 if (horizontal)
01321 ret.setRect(sbextent, 0, sbextent, sbextent);
01322 else
01323 ret.setRect(0, sbextent, sbextent, sbextent);
01324 } else {
01325 if (horizontal)
01326 ret.setRect(sb->width() - sbextent, 0, sbextent, sbextent);
01327 else
01328 ret.setRect(0, sb->height() - sbextent, sbextent, sbextent);
01329 }
01330 break;
01331 }
01332
01333 case SC_ScrollBarSubPage: {
01334
01335 if (platinumScrollBar) {
01336 if (horizontal)
01337 ret.setRect(0, 0, sliderstart, sbextent);
01338 else
01339 ret.setRect(0, 0, sbextent, sliderstart);
01340 } else if (nextScrollBar) {
01341 if (horizontal)
01342 ret.setRect(sbextent*2, 0, sliderstart-2*sbextent, sbextent);
01343 else
01344 ret.setRect(0, sbextent*2, sbextent, sliderstart-2*sbextent);
01345 } else {
01346 if (horizontal)
01347 ret.setRect(sbextent, 0, sliderstart - sbextent, sbextent);
01348 else
01349 ret.setRect(0, sbextent, sbextent, sliderstart - sbextent);
01350 }
01351 break;
01352 }
01353
01354 case SC_ScrollBarAddPage: {
01355
01356 int fudge;
01357
01358 if (platinumScrollBar)
01359 fudge = 0;
01360 else if (nextScrollBar)
01361 fudge = 2*sbextent;
01362 else
01363 fudge = sbextent;
01364
01365 if (horizontal)
01366 ret.setRect(sliderstart + sliderlen, 0,
01367 maxlen - sliderstart - sliderlen + fudge, sbextent);
01368 else
01369 ret.setRect(0, sliderstart + sliderlen, sbextent,
01370 maxlen - sliderstart - sliderlen + fudge);
01371 break;
01372 }
01373
01374 case SC_ScrollBarGroove: {
01375 int multi = threeButtonScrollBar ? 3 : 2;
01376 int fudge;
01377
01378 if (platinumScrollBar)
01379 fudge = 0;
01380 else if (nextScrollBar)
01381 fudge = 2*sbextent;
01382 else
01383 fudge = sbextent;
01384
01385 if (horizontal)
01386 ret.setRect(fudge, 0, sb->width() - sbextent * multi, sb->height());
01387 else
01388 ret.setRect(0, fudge, sb->width(), sb->height() - sbextent * multi);
01389 break;
01390 }
01391
01392 case SC_ScrollBarSlider: {
01393 if (horizontal)
01394 ret.setRect(sliderstart, 0, sliderlen, sbextent);
01395 else
01396 ret.setRect(0, sliderstart, sbextent, sliderlen);
01397 break;
01398 }
01399
01400 default:
01401 ret = QCommonStyle::querySubControlMetrics(control, widget, sc, opt);
01402 break;
01403 }
01404 } else
01405 ret = QCommonStyle::querySubControlMetrics(control, widget, sc, opt);
01406
01407 return ret;
01408 }
01409
01410 static const char * const kstyle_close_xpm[] = {
01411 "12 12 2 1",
01412 "# c #000000",
01413 ". c None",
01414 "............",
01415 "............",
01416 "..##....##..",
01417 "...##..##...",
01418 "....####....",
01419 ".....##.....",
01420 "....####....",
01421 "...##..##...",
01422 "..##....##..",
01423 "............",
01424 "............",
01425 "............"};
01426
01427 static const char * const kstyle_maximize_xpm[]={
01428 "12 12 2 1",
01429 "# c #000000",
01430 ". c None",
01431 "............",
01432 "............",
01433 ".##########.",
01434 ".##########.",
01435 ".#........#.",
01436 ".#........#.",
01437 ".#........#.",
01438 ".#........#.",
01439 ".#........#.",
01440 ".#........#.",
01441 ".##########.",
01442 "............"};
01443
01444
01445 static const char * const kstyle_minimize_xpm[] = {
01446 "12 12 2 1",
01447 "# c #000000",
01448 ". c None",
01449 "............",
01450 "............",
01451 "............",
01452 "............",
01453 "............",
01454 "............",
01455 "............",
01456 "...######...",
01457 "...######...",
01458 "............",
01459 "............",
01460 "............"};
01461
01462 static const char * const kstyle_normalizeup_xpm[] = {
01463 "12 12 2 1",
01464 "# c #000000",
01465 ". c None",
01466 "............",
01467 "...#######..",
01468 "...#######..",
01469 "...#.....#..",
01470 ".#######.#..",
01471 ".#######.#..",
01472 ".#.....#.#..",
01473 ".#.....###..",
01474 ".#.....#....",
01475 ".#.....#....",
01476 ".#######....",
01477 "............"};
01478
01479
01480 static const char * const kstyle_shade_xpm[] = {
01481 "12 12 2 1",
01482 "# c #000000",
01483 ". c None",
01484 "............",
01485 "............",
01486 "............",
01487 "............",
01488 "............",
01489 ".....#......",
01490 "....###.....",
01491 "...#####....",
01492 "..#######...",
01493 "............",
01494 "............",
01495 "............"};
01496
01497 static const char * const kstyle_unshade_xpm[] = {
01498 "12 12 2 1",
01499 "# c #000000",
01500 ". c None",
01501 "............",
01502 "............",
01503 "............",
01504 "............",
01505 "..#######...",
01506 "...#####....",
01507 "....###.....",
01508 ".....#......",
01509 "............",
01510 "............",
01511 "............",
01512 "............"};
01513
01514 static const char * dock_window_close_xpm[] = {
01515 "8 8 2 1",
01516 "# c #000000",
01517 ". c None",
01518 "##....##",
01519 ".##..##.",
01520 "..####..",
01521 "...##...",
01522 "..####..",
01523 ".##..##.",
01524 "##....##",
01525 "........"};
01526
01527
01528
01529
01530
01531
01532
01533
01534 static const char * const information_xpm[]={
01535 "32 32 5 1",
01536 ". c None",
01537 "c c #000000",
01538 "* c #999999",
01539 "a c #ffffff",
01540 "b c #0000ff",
01541 "...........********.............",
01542 "........***aaaaaaaa***..........",
01543 "......**aaaaaaaaaaaaaa**........",
01544 ".....*aaaaaaaaaaaaaaaaaa*.......",
01545 "....*aaaaaaaabbbbaaaaaaaac......",
01546 "...*aaaaaaaabbbbbbaaaaaaaac.....",
01547 "..*aaaaaaaaabbbbbbaaaaaaaaac....",
01548 ".*aaaaaaaaaaabbbbaaaaaaaaaaac...",
01549 ".*aaaaaaaaaaaaaaaaaaaaaaaaaac*..",
01550 "*aaaaaaaaaaaaaaaaaaaaaaaaaaaac*.",
01551 "*aaaaaaaaaabbbbbbbaaaaaaaaaaac*.",
01552 "*aaaaaaaaaaaabbbbbaaaaaaaaaaac**",
01553 "*aaaaaaaaaaaabbbbbaaaaaaaaaaac**",
01554 "*aaaaaaaaaaaabbbbbaaaaaaaaaaac**",
01555 "*aaaaaaaaaaaabbbbbaaaaaaaaaaac**",
01556 "*aaaaaaaaaaaabbbbbaaaaaaaaaaac**",
01557 ".*aaaaaaaaaaabbbbbaaaaaaaaaac***",
01558 ".*aaaaaaaaaaabbbbbaaaaaaaaaac***",
01559 "..*aaaaaaaaaabbbbbaaaaaaaaac***.",
01560 "...caaaaaaabbbbbbbbbaaaaaac****.",
01561 "....caaaaaaaaaaaaaaaaaaaac****..",
01562 ".....caaaaaaaaaaaaaaaaaac****...",
01563 "......ccaaaaaaaaaaaaaacc****....",
01564 ".......*cccaaaaaaaaccc*****.....",
01565 "........***cccaaaac*******......",
01566 "..........****caaac*****........",
01567 ".............*caaac**...........",
01568 "...............caac**...........",
01569 "................cac**...........",
01570 ".................cc**...........",
01571 "..................***...........",
01572 "...................**..........."};
01573
01574 static const char* const warning_xpm[]={
01575 "32 32 4 1",
01576 ". c None",
01577 "a c #ffff00",
01578 "* c #000000",
01579 "b c #999999",
01580 ".............***................",
01581 "............*aaa*...............",
01582 "...........*aaaaa*b.............",
01583 "...........*aaaaa*bb............",
01584 "..........*aaaaaaa*bb...........",
01585 "..........*aaaaaaa*bb...........",
01586 ".........*aaaaaaaaa*bb..........",
01587 ".........*aaaaaaaaa*bb..........",
01588 "........*aaaaaaaaaaa*bb.........",
01589 "........*aaaa***aaaa*bb.........",
01590 ".......*aaaa*****aaaa*bb........",
01591 ".......*aaaa*****aaaa*bb........",
01592 "......*aaaaa*****aaaaa*bb.......",
01593 "......*aaaaa*****aaaaa*bb.......",
01594 ".....*aaaaaa*****aaaaaa*bb......",
01595 ".....*aaaaaa*****aaaaaa*bb......",
01596 "....*aaaaaaaa***aaaaaaaa*bb.....",
01597 "....*aaaaaaaa***aaaaaaaa*bb.....",
01598 "...*aaaaaaaaa***aaaaaaaaa*bb....",
01599 "...*aaaaaaaaaa*aaaaaaaaaa*bb....",
01600 "..*aaaaaaaaaaa*aaaaaaaaaaa*bb...",
01601 "..*aaaaaaaaaaaaaaaaaaaaaaa*bb...",
01602 ".*aaaaaaaaaaaa**aaaaaaaaaaa*bb..",
01603 ".*aaaaaaaaaaa****aaaaaaaaaa*bb..",
01604 "*aaaaaaaaaaaa****aaaaaaaaaaa*bb.",
01605 "*aaaaaaaaaaaaa**aaaaaaaaaaaa*bb.",
01606 "*aaaaaaaaaaaaaaaaaaaaaaaaaaa*bbb",
01607 "*aaaaaaaaaaaaaaaaaaaaaaaaaaa*bbb",
01608 ".*aaaaaaaaaaaaaaaaaaaaaaaaa*bbbb",
01609 "..*************************bbbbb",
01610 "....bbbbbbbbbbbbbbbbbbbbbbbbbbb.",
01611 ".....bbbbbbbbbbbbbbbbbbbbbbbbb.."};
01612
01613 static const char* const critical_xpm[]={
01614 "32 32 4 1",
01615 ". c None",
01616 "a c #999999",
01617 "* c #ff0000",
01618 "b c #ffffff",
01619 "...........********.............",
01620 ".........************...........",
01621 ".......****************.........",
01622 "......******************........",
01623 ".....********************a......",
01624 "....**********************a.....",
01625 "...************************a....",
01626 "..*******b**********b*******a...",
01627 "..******bbb********bbb******a...",
01628 ".******bbbbb******bbbbb******a..",
01629 ".*******bbbbb****bbbbb*******a..",
01630 "*********bbbbb**bbbbb*********a.",
01631 "**********bbbbbbbbbb**********a.",
01632 "***********bbbbbbbb***********aa",
01633 "************bbbbbb************aa",
01634 "************bbbbbb************aa",
01635 "***********bbbbbbbb***********aa",
01636 "**********bbbbbbbbbb**********aa",
01637 "*********bbbbb**bbbbb*********aa",
01638 ".*******bbbbb****bbbbb*******aa.",
01639 ".******bbbbb******bbbbb******aa.",
01640 "..******bbb********bbb******aaa.",
01641 "..*******b**********b*******aa..",
01642 "...************************aaa..",
01643 "....**********************aaa...",
01644 "....a********************aaa....",
01645 ".....a******************aaa.....",
01646 "......a****************aaa......",
01647 ".......aa************aaaa.......",
01648 ".........aa********aaaaa........",
01649 "...........aaaaaaaaaaa..........",
01650 ".............aaaaaaa............"};
01651
01652 QPixmap KStyle::stylePixmap( StylePixmap stylepixmap,
01653 const QWidget* widget,
01654 const QStyleOption& opt) const
01655 {
01656 switch (stylepixmap) {
01657 case SP_TitleBarShadeButton:
01658 return QPixmap(const_cast<const char**>(kstyle_shade_xpm));
01659 case SP_TitleBarUnshadeButton:
01660 return QPixmap(const_cast<const char**>(kstyle_unshade_xpm));
01661 case SP_TitleBarNormalButton:
01662 return QPixmap(const_cast<const char**>(kstyle_normalizeup_xpm));
01663 case SP_TitleBarMinButton:
01664 return QPixmap(const_cast<const char**>(kstyle_minimize_xpm));
01665 case SP_TitleBarMaxButton:
01666 return QPixmap(const_cast<const char**>(kstyle_maximize_xpm));
01667 case SP_TitleBarCloseButton:
01668 return QPixmap(const_cast<const char**>(kstyle_close_xpm));
01669 case SP_DockWindowCloseButton:
01670 return QPixmap(const_cast<const char**>(dock_window_close_xpm ));
01671 case SP_MessageBoxInformation:
01672 return QPixmap(const_cast<const char**>(information_xpm));
01673 case SP_MessageBoxWarning:
01674 return QPixmap(const_cast<const char**>(warning_xpm));
01675 case SP_MessageBoxCritical:
01676 return QPixmap(const_cast<const char**>(critical_xpm));
01677 default:
01678 break;
01679 }
01680 return QCommonStyle::stylePixmap(stylepixmap, widget, opt);
01681 }
01682
01683
01684 int KStyle::styleHint( StyleHint sh, const QWidget* w,
01685 const QStyleOption &opt, QStyleHintReturn* shr) const
01686 {
01687 switch (sh)
01688 {
01689 case SH_EtchDisabledText:
01690 return d->etchDisabledText ? 1 : 0;
01691
01692 case SH_PopupMenu_Scrollable:
01693 return d->scrollablePopupmenus ? 1 : 0;
01694
01695 case SH_MenuBar_AltKeyNavigation:
01696 return d->menuAltKeyNavigation ? 1 : 0;
01697
01698 case SH_PopupMenu_SubMenuPopupDelay:
01699 return d->popupMenuDelay;
01700
01701 case SH_ItemView_ChangeHighlightOnFocus:
01702 case SH_Slider_SloppyKeyEvents:
01703 case SH_MainWindow_SpaceBelowMenuBar:
01704 return 0;
01705
01706 case SH_Slider_SnapToValue:
01707 case SH_PrintDialog_RightAlignButtons:
01708 case SH_FontDialog_SelectAssociatedText:
01709 case SH_PopupMenu_AllowActiveAndDisabled:
01710 case SH_MenuBar_MouseTracking:
01711 case SH_PopupMenu_MouseTracking:
01712 case SH_ComboBox_ListMouseTracking:
01713 case SH_ScrollBar_MiddleClickAbsolutePosition:
01714 return 1;
01715
01716 default:
01717 return QCommonStyle::styleHint(sh, w, opt, shr);
01718 }
01719 }
01720
01721
01722 bool KStyle::eventFilter( QObject* object, QEvent* event )
01723 {
01724 if ( d->useFilledFrameWorkaround )
01725 {
01726
01727
01728
01729
01730
01731
01732
01733 if (event->type() == QEvent::Paint)
01734 {
01735 QMenuBar* menubar = 0;
01736 QToolBar* toolbar = 0;
01737 if (object->inherits("QMenuBar"))
01738 menubar = static_cast<QMenuBar*>(object);
01739 else if (object->inherits("QToolBar"))
01740 toolbar = static_cast<QToolBar*>(object);
01741 if ( menubar || toolbar )
01742 {
01743 bool horizontal = true;
01744 QPaintEvent* pe = (QPaintEvent*)event;
01745 QFrame* frame = (QFrame*)object;
01746 QRect r = pe->rect();
01747
01748 if (toolbar && toolbar->orientation() == Qt::Vertical)
01749 horizontal = false;
01750
01751 if (horizontal) {
01752 if ( r.height() == frame->height() )
01753 return false;
01754
01755
01756 QPaintEvent dummyPE( QRect( r.x(), 0, r.width(), frame->height()) );
01757 QApplication::sendEvent( frame, &dummyPE );
01758 }
01759 else {
01760 if ( r.width() == frame->width() )
01761 return false;
01762
01763 QPaintEvent dummyPE( QRect( 0, r.y(), frame->width(), r.height()) );
01764 QApplication::sendEvent( frame, &dummyPE );
01765 }
01766
01767
01768 return true;
01769 }
01770 }
01771 }
01772
01773 return false;
01774 }
01775
01776
01777
01778
01779
01780
01781 TransparencyHandler::TransparencyHandler( KStyle* style,
01782 TransparencyEngine tEngine, float menuOpacity, bool useDropShadow )
01783 : QObject()
01784 {
01785 te = tEngine;
01786 kstyle = style;
01787 opacity = menuOpacity;
01788 dropShadow = useDropShadow;
01789 pix.setOptimization(QPixmap::BestOptim);
01790 }
01791
01792 TransparencyHandler::~TransparencyHandler()
01793 {
01794 }
01795
01796
01797 void TransparencyHandler::rightShadow(QImage& dst)
01798 {
01799 if (dst.depth() != 32)
01800 dst = dst.convertDepth(32);
01801
01802
01803 int pixels = dst.width() * dst.height();
01804 #ifdef WORDS_BIGENDIAN
01805 register unsigned char* data = dst.bits() + 1;
01806 #else
01807 register unsigned char* data = dst.bits();
01808 #endif
01809 for(register int i = 0; i < 16; i++) {
01810 *data++ = (unsigned char)((*data)*top_right_corner[i]);
01811 *data++ = (unsigned char)((*data)*top_right_corner[i]);
01812 *data++ = (unsigned char)((*data)*top_right_corner[i]);
01813 data++;
01814 }
01815
01816 pixels -= 32;
01817 register int c = 0;
01818 for(register int i = 0; i < pixels; i++) {
01819 *data++ = (unsigned char)((*data)*shadow_strip[c]);
01820 *data++ = (unsigned char)((*data)*shadow_strip[c]);
01821 *data++ = (unsigned char)((*data)*shadow_strip[c]);
01822 data++;
01823 c = ++c % 4;
01824 }
01825
01826
01827 for(register int i = 0; i < 16; i++) {
01828 *data++ = (unsigned char)((*data)*bottom_right_corner[i]);
01829 *data++ = (unsigned char)((*data)*bottom_right_corner[i]);
01830 *data++ = (unsigned char)((*data)*bottom_right_corner[i]);
01831 data++;
01832 }
01833 }
01834
01835 void TransparencyHandler::bottomShadow(QImage& dst)
01836 {
01837 if (dst.depth() != 32)
01838 dst = dst.convertDepth(32);
01839
01840 int line = 0;
01841 int width = dst.width() - 4;
01842 double strip_data = shadow_strip[0];
01843 double* corner = const_cast<double*>(bottom_left_corner);
01844
01845 #ifdef WORDS_BIGENDIAN
01846 register unsigned char* data = dst.bits() + 1;
01847 #else
01848 register unsigned char* data = dst.bits();
01849 #endif
01850
01851 for(int y = 0; y < 4; y++)
01852 {
01853
01854 for(register int x = 0; x < 4; x++) {
01855 *data++ = (unsigned char)((*data)*(*corner));
01856 *data++ = (unsigned char)((*data)*(*corner));
01857 *data++ = (unsigned char)((*data)*(*corner));
01858 data++;
01859 corner++;
01860 }
01861
01862
01863 for(register int x = 0; x < width; x++) {
01864 *data++ = (unsigned char)((*data)*strip_data);
01865 *data++ = (unsigned char)((*data)*strip_data);
01866 *data++ = (unsigned char)((*data)*strip_data);
01867 data++;
01868 }
01869
01870 strip_data = shadow_strip[++line];
01871 }
01872 }
01873
01874
01875 void TransparencyHandler::createShadowWindows(const QPopupMenu* p)
01876 {
01877 int x2 = p->x()+p->width();
01878 int y2 = p->y()+p->height();
01879 QRect shadow1(x2, p->y() + 4, 4, p->height());
01880 QRect shadow2(p->x() + 4, y2, p->width() - 4, 4);
01881
01882
01883 ShadowElements se;
01884 se.w1 = new QWidget(0, 0, WStyle_Customize | WType_Popup | WX11BypassWM );
01885 se.w2 = new QWidget(0, 0, WStyle_Customize | WType_Popup | WX11BypassWM );
01886 se.w1->setGeometry(shadow1);
01887 se.w2->setGeometry(shadow2);
01888 XSelectInput(qt_xdisplay(), se.w1->winId(), StructureNotifyMask );
01889 XSelectInput(qt_xdisplay(), se.w2->winId(), StructureNotifyMask );
01890
01891
01892 shadowMap()[p] = se;
01893
01894
01895 QPixmap pix_shadow1 = QPixmap::grabWindow(qt_xrootwin(),
01896 shadow1.x(), shadow1.y(), shadow1.width(), shadow1.height());
01897 QPixmap pix_shadow2 = QPixmap::grabWindow(qt_xrootwin(),
01898 shadow2.x(), shadow2.y(), shadow2.width(), shadow2.height());
01899
01900 QImage img;
01901 img = pix_shadow1.convertToImage();
01902 rightShadow(img);
01903 pix_shadow1.convertFromImage(img);
01904 img = pix_shadow2.convertToImage();
01905 bottomShadow(img);
01906 pix_shadow2.convertFromImage(img);
01907
01908
01909 se.w1->setErasePixmap(pix_shadow1);
01910 se.w2->setErasePixmap(pix_shadow2);
01911
01912
01913
01914 XMapWindow(qt_xdisplay(), se.w1->winId());
01915 XMapWindow(qt_xdisplay(), se.w2->winId());
01916 }
01917
01918 void TransparencyHandler::removeShadowWindows(const QPopupMenu* p)
01919 {
01920 ShadowMap::iterator it = shadowMap().find(p);
01921 if (it != shadowMap().end())
01922 {
01923 ShadowElements se = it.data();
01924 XUnmapWindow(qt_xdisplay(), se.w1->winId());
01925 XUnmapWindow(qt_xdisplay(), se.w2->winId());
01926 XFlush(qt_xdisplay());
01927 delete se.w1;
01928 delete se.w2;
01929 shadowMap().erase(it);
01930 }
01931 }
01932
01933 bool TransparencyHandler::eventFilter( QObject* object, QEvent* event )
01934 {
01935
01936
01937
01938
01939 QPopupMenu* p = (QPopupMenu*)object;
01940 QEvent::Type et = event->type();
01941
01942 if (et == QEvent::Show)
01943 {
01944
01945 if (te != Disabled)
01946 {
01947 pix = QPixmap::grabWindow(qt_xrootwin(),
01948 p->x(), p->y(), p->width(), p->height());
01949
01950 switch (te) {
01951 #ifdef HAVE_XRENDER
01952 case XRender:
01953 if (qt_use_xrender) {
01954 XRenderBlendToPixmap(p);
01955 break;
01956 }
01957
01958 #else
01959 case XRender:
01960 #endif
01961 case SoftwareBlend:
01962 blendToPixmap(p->colorGroup(), p);
01963 break;
01964
01965 case SoftwareTint:
01966 default:
01967 blendToColor(p->colorGroup().button());
01968 };
01969
01970 p->setErasePixmap(pix);
01971 }
01972
01973
01974
01975
01976
01977
01978 if (dropShadow && p->width() > 16 && p->height() > 16 && !shadowMap().contains( p ))
01979 createShadowWindows(p);
01980 }
01981 else if (et == QEvent::Hide)
01982 {
01983
01984 if (dropShadow)
01985 removeShadowWindows(p);
01986
01987
01988 if (te != Disabled)
01989 p->setErasePixmap(QPixmap());
01990 }
01991
01992 return false;
01993 }
01994
01995
01996
01997 void TransparencyHandler::blendToColor(const QColor &col)
01998 {
01999 if (opacity < 0.0 || opacity > 1.0)
02000 return;
02001
02002 QImage img = pix.convertToImage();
02003 KImageEffect::blend(col, img, opacity);
02004 pix.convertFromImage(img);
02005 }
02006
02007
02008 void TransparencyHandler::blendToPixmap(const QColorGroup &cg, const QPopupMenu* p)
02009 {
02010 if (opacity < 0.0 || opacity > 1.0)
02011 return;
02012
02013 KPixmap blendPix;
02014 blendPix.resize( pix.width(), pix.height() );
02015
02016 if (blendPix.width() != pix.width() ||
02017 blendPix.height() != pix.height())
02018 return;
02019
02020
02021 kstyle->renderMenuBlendPixmap( blendPix, cg, p );
02022
02023 QImage blendImg = blendPix.convertToImage();
02024 QImage backImg = pix.convertToImage();
02025 KImageEffect::blend(blendImg, backImg, opacity);
02026 pix.convertFromImage(backImg);
02027 }
02028
02029
02030 #ifdef HAVE_XRENDER
02031
02032
02033
02034 void TransparencyHandler::XRenderBlendToPixmap(const QPopupMenu* p)
02035 {
02036 KPixmap renderPix;
02037 renderPix.resize( pix.width(), pix.height() );
02038
02039
02040 kstyle->renderMenuBlendPixmap( renderPix, p->colorGroup(), p );
02041
02042 Display* dpy = qt_xdisplay();
02043 Pixmap alphaPixmap;
02044 Picture alphaPicture;
02045 XRenderPictFormat Rpf;
02046 XRenderPictureAttributes Rpa;
02047 XRenderColor clr;
02048 clr.alpha = ((unsigned short)(255*opacity) << 8);
02049
02050 Rpf.type = PictTypeDirect;
02051 Rpf.depth = 8;
02052 Rpf.direct.alphaMask = 0xff;
02053 Rpa.repeat = True;
02054
02055 XRenderPictFormat* xformat = XRenderFindFormat(dpy,
02056 PictFormatType | PictFormatDepth | PictFormatAlphaMask, &Rpf, 0);
02057
02058 alphaPixmap = XCreatePixmap(dpy, p->handle(), 1, 1, 8);
02059 alphaPicture = XRenderCreatePicture(dpy, alphaPixmap, xformat, CPRepeat, &Rpa);
02060
02061 XRenderFillRectangle(dpy, PictOpSrc, alphaPicture, &clr, 0, 0, 1, 1);
02062
02063 XRenderComposite(dpy, PictOpOver,
02064 renderPix.x11RenderHandle(), alphaPicture, pix.x11RenderHandle(),
02065 0, 0,
02066 0, 0,
02067 0, 0,
02068 pix.width(), pix.height());
02069
02070 XRenderFreePicture(dpy, alphaPicture);
02071 XFreePixmap(dpy, alphaPixmap);
02072 }
02073 #endif
02074
02075 void KStyle::virtual_hook( int, void* )
02076 { }
02077
02078
02079
02080 #include "kstyle.moc"