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