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