/* Polyester widget style for KDE 3 Copyright (C) 2006 Marco Martin based on Plastik widget style for KDE 3 Copyright (C) 2003 Sandro Giessl based on the KDE style "dotNET": Copyright (C) 2001-2002, Chris Lee Carsten Pfeiffer Karol Szwed Drawing routines completely reimplemented from KDE3 HighColor, which was originally based on some stuff from the KDE2 HighColor. based on drawing routines of the style "Keramik": Copyright (c) 2002 Malte Starostik (c) 2002,2003 Maksim Orlovich based on the KDE3 HighColor Style Copyright (C) 2001-2002 Karol Szwed (C) 2001-2002 Fredrik H�lund Drawing routines adapted from the KDE2 HCStyle, Copyright (C) 2000 Daniel M. Duley (C) 2000 Dirk Mueller (C) 2001 Martijn Klingens Progressbar code based on KStyle, Copyright (C) 2001-2002 Karol Szwed This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "polyester.h" #include "polyester.moc" #include "misc.h" // some bitmaps for the radio button so it's easier to handle the circle stuff... // 13x13 static unsigned char radiobutton_mask_bits[] = { 0xf8, 0x03, 0xfc, 0x07, 0xfe, 0x0f, 0xff, 0x1f, 0xff, 0x1f, 0xff, 0x1f, 0xff, 0x1f, 0xff, 0x1f, 0xff, 0x1f, 0xff, 0x1f, 0xfe, 0x0f, 0xfc, 0x07, 0xf8, 0x03}; static unsigned char radiobutton_contour_bits[] = { 0xf0, 0x01, 0x0c, 0x06, 0x02, 0x08, 0x02, 0x08, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x02, 0x08, 0x02, 0x08, 0x0c, 0x06, 0xf0, 0x01}; static unsigned char radiobutton_aa_inside_bits[] = { 0x00, 0x00, 0x10, 0x01, 0x04, 0x04, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x04, 0x04, 0x10, 0x01, 0x00, 0x00}; static unsigned char radiobutton_aa_outside_bits[] = { 0x08, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x08, 0x02}; static unsigned char radiobutton_highlight1_bits[] = { 0x00, 0x00, 0xf0, 0x01, 0x1c, 0x07, 0x04, 0x04, 0x06, 0x0c, 0x02, 0x08, 0x02, 0x08, 0x02, 0x08, 0x06, 0x0c, 0x04, 0x04, 0x1c, 0x07, 0xf0, 0x01, 0x00, 0x00}; static unsigned char radiobutton_highlight2_bits[] = { 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x18, 0x03, 0x08, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x02, 0x18, 0x03, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00}; // check mark const uint CHECKMARKSIZE = 9; // 9x9 static unsigned char checkmark_aa_bits[] = { 0x45, 0x01, 0x28, 0x00, 0x11, 0x01, 0x82, 0x00, 0x44, 0x00, 0x82, 0x00, 0x11, 0x01, 0x28, 0x00, 0x45, 0x01}; static unsigned char checkmark_dark_bits[] = { 0x82, 0x00, 0x45, 0x01, 0xaa, 0x00, 0x54, 0x00, 0x28, 0x00, 0x74, 0x00, 0xea, 0x00, 0xc5, 0x01, 0x82, 0x00}; static unsigned char checkmark_light_bits[] = { 0x00, 0xfe, 0x82, 0xfe, 0x44, 0xfe, 0x28, 0xfe, 0x10, 0xfe, 0x08, 0xfe, 0x04, 0xfe, 0x02, 0xfe, 0x00, 0xfe}; static unsigned char checkmark_tristate_bits[] = { 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00}; // radio mark const uint RADIOMARKSIZE = 9; // 9x9 static unsigned char radiomark_aa_bits[] = { 0x00, 0x00, 0x44, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x00, 0x44, 0x00, 0x00, 0x00}; static unsigned char radiomark_dark_bits[] = { 0x00, 0x00, 0x38, 0x00, 0x44, 0x00, 0xf2, 0x00, 0xfa, 0x00, 0xfa, 0x00, 0x7c, 0x00, 0x38, 0x00, 0x00, 0x00}; static unsigned char radiomark_light_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x0c, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // popupmenu item constants... static const int itemHMargin = 6; static const int itemFrame = 2; static const int arrowHMargin = 6; static const int rightBorder = 12; static const uint TIMERINTERVAL = 25; // msec static const int ANIMATIONSTEPS = 20; // -- Style Plugin Interface ------------------------- class PolyesterStylePlugin : public QStylePlugin { public: PolyesterStylePlugin() {} ~PolyesterStylePlugin() {} QStringList keys() const { return QStringList() << "Polyester"; } QStyle* create( const QString& key ) { if (key.lower() == "polyester") return new PolyesterStyle; return 0; } }; KDE_Q_EXPORT_PLUGIN( PolyesterStylePlugin ) // -- end -- PolyesterStyle::PolyesterStyle() : KStyle( AllowMenuTransparency, ThreeButtonScrollBar), kickerMode(false), kornMode(false), flatMode(false) { hoverWidget = 0; hoverTab = 0; hoverHeaderId = -1; horizontalDots = 0; verticalDots = 0; horizontalLine = 0; verticalLine = 0; QSettings settings; _contrast = settings.readNumEntry("/Qt/KDE/contrast", 6); settings.beginGroup("/polyesterstyle/Settings"); _useLowerCaseText = settings.readBoolEntry("/useLowerCaseText", false); _scrollBarLines = settings.readBoolEntry("/scrollBarLines", false); _scrollBarStyle = settings.readEntry("/scrollBarStyle", "ThreeButtonScrollBar"); _scrollBarExtent = settings.readNumEntry("/scrollBarSize", 16); if(_scrollBarExtent < 8 || _scrollBarExtent > 48) _scrollBarExtent = 16; _animateProgressBar = settings.readBoolEntry("/animateProgressBar", false); _animateButton = settings.readBoolEntry("/animateButton", false); /*don't animate buttons in gtk-qt or openoffice, they aren't able to do so :-)*/ if( ( qstrcmp( qApp->argv() [ 0 ], "unknown" ) == 0 ) || ( qstrcmp( qApp->argv() [ 0 ], "soffice.bin" ) == 0 )) _animateButton = false; _animateButtonToDark = settings.readBoolEntry("/animateButtonToDark", false); _buttonStyle = settings.readEntry("/buttonStyle", "glass"); _lightBorder= settings.readBoolEntry("/lightBorder", true); _coloredScrollBar = settings.readBoolEntry("/coloredScrollBar", true); _centeredTabBar = settings.readBoolEntry("/centeredTabBar", false); _highLightTab = settings.readBoolEntry("/highLightTab", true); _statusBarFrame = settings.readBoolEntry("/statusBarFrame", true); _colorizeSortedHeader = settings.readBoolEntry("/colorizeSortedHeader", true); _menuItemSpacing = settings.readNumEntry("/menuItemSpacing", 8); if( _menuItemSpacing > 12 || _menuItemSpacing < 0 ) _menuItemSpacing = 8; _buttonMenuItem = settings.readBoolEntry("/buttonMenuItem", true); _menuBarEmphasis = settings.readBoolEntry("/menuBarEmphasis", false); _menuBarEmphasisBorder = settings.readBoolEntry("/menuBarEmphasisBorder", true); if( _menuBarEmphasis ) _customMenuBarEmphasisColor = settings.readBoolEntry("/customMenuBarEmphasisColor", false); else _customMenuBarEmphasisColor = false; _menuBarEmphasisColor = settings.readEntry("/menuBarEmphasisColor", "black"); _menuStripe = settings.readBoolEntry("/menuStripe", true); _shadowedMenuBarText = settings.readBoolEntry("/shadowedMenuBarText", true); _shadowedButtonsText = settings.readBoolEntry("/shadowedButtonsText", true); _drawToolBarSeparator = settings.readBoolEntry("/drawToolBarSeparator", true); _drawToolBarItemSeparator = settings.readBoolEntry("/drawToolBarItemSeparator", true); _drawFocusRect = settings.readBoolEntry("/drawFocusRect", true); _drawTriangularExpander = settings.readBoolEntry("/drawTriangularExpander", false); _inputFocusHighlight = settings.readBoolEntry("/inputFocusHighlight", true); _customOverHighlightColor = settings.readBoolEntry("/customOverHighlightColor", false); _overHighlightColor.setNamedColor( settings.readEntry("/overHighlightColor", "black") ); _customFocusHighlightColor = settings.readBoolEntry("/customFocusHighlightColor", false); _focusHighlightColor.setNamedColor( settings.readEntry("/focusHighlightColor", "black") ); _customCheckMarkColor = settings.readBoolEntry("/customCheckMarkColor", false); _checkMarkColor.setNamedColor( settings.readEntry("/checkMarkColor", "black") ); settings.endGroup(); /*HACK: hack for gtk-qt: mozillas only works with windows style scrollbars, even if the other gtk apps works with other styles, at the moment I don't have a way to choose only mozilla apps, because qstrcmp( qApp->argv() [ 0 ], "firefox-bin" ) == 0 does not work (qApp->argv() [ 0 ] is always unknown on gtk-qt apps) also, the menu stripe is turned off because it's managed too bad, in particular by (of course) firefox this hack may be disabled in the future, let's see...*/ if( !qstrcmp( qApp->argv() [ 0 ], "unknown" ) ) { _scrollBarType = KStyle::WindowsStyleScrollBar; _menuStripe = false; } //Thanks, Lipstik :-) else if( !strcmp(_scrollBarStyle,"ThreeButtonScrollBar" ) ) _scrollBarType = KStyle::ThreeButtonScrollBar; else if( !strcmp(_scrollBarStyle,"WindowsStyleScrollBar" ) ) _scrollBarType = KStyle::WindowsStyleScrollBar; else if( !strcmp(_scrollBarStyle,"PlatinumStyleScrollBar" ) ) _scrollBarType = KStyle::PlatinumStyleScrollBar; else if( !strcmp(_scrollBarStyle,"NextStyleScrollBar" ) ) _scrollBarType = KStyle::NextStyleScrollBar; //HACK for gtk-qt: if setScrollBarType is called wxwidgets applications will broke /*if( qstrcmp( qApp->argv() [ 0 ], "unknown" ) ) this->setScrollBarType(_scrollBarType);*/ this->setScrollBarType(_scrollBarType); // setup pixmap cache... pixmapCache = new QIntCache(150000, 499); pixmapCache->setAutoDelete(true); if ( _animateProgressBar ) { animationTimer = new QTimer( this ); connect( animationTimer, SIGNAL(timeout()), this, SLOT(updateProgressPos()) ); } if ( _animateButton ) { btnAnimTimer = new QTimer( this ); connect( btnAnimTimer, SIGNAL(timeout()), this, SLOT(animate()) ); } //create and empty image for the alpha blended menu stripe alphaStripe = new QImage(); } void PolyesterStyle::updateProgressPos() { QProgressBar* pb; //Update the registered progressbars. QMap::iterator iter; bool visible = false; for (iter = progAnimWidgets.begin(); iter != progAnimWidgets.end(); iter++) { if ( !::qt_cast(iter.key()) ) continue; pb = dynamic_cast(iter.key()); if ( iter.key() -> isEnabled() && pb -> progress() != pb->totalSteps() ) { // update animation Offset of the current Widget iter.data() = (iter.data() + 1) % 20; iter.key()->update(); } if (iter.key()->isVisible()) visible = true; } if (!visible) animationTimer->stop(); } void PolyesterStyle::animate() { btnAnimTimer->stop(); int animationDelta = 1; if( _animateButtonToDark ) animationDelta = -1; bool mustStop = true; for ( AnimWidgetMap::iterator it = animWidgets.begin(); it != animWidgets.end(); ++it) { QWidget *widget = it.key(); if( animWidgets[widget].active == true ) { mustStop = false; if(abs(animWidgets[widget].animFrame) < ANIMATIONSTEPS) { if ( _animateButton ) { animWidgets[widget].animFrame += animationDelta; widget->repaint(false); } else { animWidgets[widget].animFrame = ANIMATIONSTEPS; } } } else { if(abs(animWidgets[widget].animFrame) > 0) { mustStop = false; if ( _animateButton ) { animWidgets[widget].animFrame -= animationDelta; widget->repaint(false); } else { animWidgets[widget].animFrame = 0; } // btnAnimTimer->start(TIMERINTERVAL, true); // single-shot } } } if( !mustStop ) btnAnimTimer->start(TIMERINTERVAL, true); // single-shot } PolyesterStyle::~PolyesterStyle() { delete pixmapCache; delete horizontalDots; delete verticalDots; delete horizontalLine; delete verticalLine; } void PolyesterStyle::polish(QApplication* app) { if (!qstrcmp(app->argv()[0], "kicker")) kickerMode = true; else if (!qstrcmp(app->argv()[0], "korn")) kornMode = true; } void PolyesterStyle::polish(QWidget* widget) { if( !strcmp(widget->name(), "__khtml") ) { // is it a khtml widget...? khtmlWidgets[widget] = true; connect(widget, SIGNAL(destroyed(QObject*)), this, SLOT(khtmlWidgetDestroyed(QObject*))); } // use qt_cast where possible to check if the widget inheits one of the classes. might improve // performance compared to QObject::inherits() if ( ::qt_cast(widget) || ::qt_cast(widget) || ::qt_cast(widget) || ::qt_cast(widget) || ::qt_cast(widget) || ::qt_cast(widget) || ::qt_cast(widget) || widget->inherits("QSplitterHandle") ) { // widget->setBackgroundMode(PaletteBackground); widget->installEventFilter(this); if( _animateButton ) { //TODO: discover if it's going to stay deleted... //if (!btnAnimTimer->isActive()) // btnAnimTimer->start( TIMERINTERVAL, false ); animWidgets[widget].active = false; connect(widget, SIGNAL(destroyed(QObject*)), this, SLOT(animWidgetDestroyed(QObject*))); } QSlider *slider = ::qt_cast(widget); if(slider) { connect(slider, SIGNAL(sliderMoved(int)), this, SLOT(sliderThumbMoved(int))); connect(slider, SIGNAL(valueChanged(int)), this, SLOT(sliderThumbMoved(int))); } } else if (::qt_cast(widget)) { widget->installEventFilter(this); } else if (::qt_cast(widget)) { widget->setMouseTracking(true); widget->installEventFilter(this); } else if (::qt_cast(widget)) { widget->setBackgroundMode( NoBackground ); } else if ( !qstrcmp(widget->name(), "kde toolbar widget") ) { widget->installEventFilter(this); } else if (::qt_cast(widget)) { connect(widget->parent(), SIGNAL(contentsMoving(int, int)), widget, SLOT(update())); widget->installEventFilter(this); }else if (::qt_cast(widget)) { widget->installEventFilter(this); } if( _animateProgressBar && ::qt_cast(widget) ) { widget->installEventFilter(this); progAnimWidgets[widget] = 0; connect(widget, SIGNAL(destroyed(QObject*)), this, SLOT(progressBarDestroyed(QObject*))); if (!animationTimer->isActive()) animationTimer->start( 50, false ); } KStyle::polish(widget); } void PolyesterStyle::unPolish(QWidget* widget) { if( !strcmp(widget->name(), "__khtml") ) { // is it a khtml widget...? khtmlWidgets.remove(widget); } // use qt_cast to check if the widget inheits one of the classes. if ( ::qt_cast(widget) || ::qt_cast(widget) || ::qt_cast(widget) || ::qt_cast(widget) || ::qt_cast(widget) || ::qt_cast(widget) || ::qt_cast(widget) || ::qt_cast(widget) || widget->inherits("QSplitterHandle") ) { widget->removeEventFilter(this); animWidgets.remove(widget); } else if (::qt_cast(widget) || ::qt_cast(widget) || ::qt_cast(widget)) { widget->setMouseTracking(false); widget->removeEventFilter(this); } else if (::qt_cast(widget)) { widget->setBackgroundMode( PaletteBackground ); } else if ( !qstrcmp(widget->name(), "kde toolbar widget") ) { widget->removeEventFilter(this); } const QSlider *slider = ::qt_cast(widget); if(slider && sliderValues.contains(slider)) sliderValues.remove(slider); if ( ::qt_cast(widget) ) { progAnimWidgets.remove(widget); } KStyle::unPolish(widget); } /*a bunch of slots stuff...*/ void PolyesterStyle::khtmlWidgetDestroyed(QObject* obj) { khtmlWidgets.remove(static_cast(obj)); } void PolyesterStyle::progressBarDestroyed(QObject* obj) { progAnimWidgets.remove(static_cast(obj)); } void PolyesterStyle::animWidgetDestroyed(QObject* obj) { animWidgets.remove(static_cast(obj)); } void PolyesterStyle::renderContour(QPainter *p, const QRect &r, const QColor &backgroundColor, const QColor &contour, const uint flags) const { if((r.width() <= 0)||(r.height() <= 0)) return; const bool drawLeft = flags&Draw_Left; const bool drawRight = flags&Draw_Right; const bool drawTop = flags&Draw_Top; const bool drawBottom = flags&Draw_Bottom; const bool disabled = flags&Is_Disabled; const bool alphaBlend = flags&Draw_AlphaBlend; const bool sharpTopLeft = flags&Sharp_UpperLeft; const bool sharpTopRight = flags&Sharp_UpperRight; const bool sharpBottomLeft = flags&Sharp_BottomLeft; const bool sharpBottomRight = flags&Sharp_BottomRight; QColor contourColor; if (disabled) { contourColor = backgroundColor.dark(150); } else { contourColor = contour; } // sides p->setPen( alphaBlendColors(backgroundColor, contourColor, 50) ); if(drawLeft) p->drawLine(r.left(), drawTop?r.top()+2:r.top(), r.left(), drawBottom?r.bottom()-2:r.bottom()); if(drawRight) p->drawLine(r.right(), drawTop?r.top()+2:r.top(), r.right(), drawBottom?r.bottom()-2:r.bottom()); if(drawTop) p->drawLine(drawLeft?r.left()+2:r.left(), r.top(), drawRight?r.right()-2:r.right(), r.top()); if(drawBottom) p->drawLine(drawLeft?r.left()+2:r.left(), r.bottom(), drawRight?r.right()-2:r.right(), r.bottom()); // edges const int alphaAA = 110; // the alpha value for anti-aliasing... // first part... p->setPen(alphaBlendColors(backgroundColor, contourColor, 50) ); if(drawLeft && drawTop) { switch(flags&Round_UpperLeft) { case false: p->drawPoint(r.left()+1, r.top()); p->drawPoint(r.left(), r.top()+1); break; default: p->drawPoint(r.left()+1, r.top()+1); } } if(drawLeft && drawBottom) { switch(flags&Round_BottomLeft) { case false: p->drawPoint(r.left()+1, r.bottom()); p->drawPoint(r.left(), r.bottom()-1); break; default: p->drawPoint(r.left()+1, r.bottom()-1); } } if(drawRight && drawTop) { switch(flags&Round_UpperRight) { case false: p->drawPoint(r.right()-1, r.top()); p->drawPoint(r.right(), r.top()+1); break; default: p->drawPoint(r.right()-1, r.top()+1); } } if(drawRight && drawBottom) { switch(flags&Round_BottomRight) { case false: p->drawPoint(r.right()-1, r.bottom()); p->drawPoint(r.right(), r.bottom()-1); break; default: p->drawPoint(r.right()-1, r.bottom()-1); } } // second part... fill edges in case we don't paint alpha-blended p->setPen( backgroundColor ); if (!alphaBlend) { if(flags&Round_UpperLeft && drawLeft && drawTop) { p->drawPoint( r.x(), r.y() ); } if(flags&Round_BottomLeft && drawLeft && drawBottom) { p->drawPoint( r.x(), r.bottom() ); } if(flags&Round_UpperRight && drawRight && drawTop) { p->drawPoint( r.right(), r.y() ); } if(flags&Round_BottomRight && drawRight && drawBottom) { p->drawPoint( r.right(), r.bottom() ); } } // third part... anti-aliasing... if(drawLeft && drawTop) { switch(flags&Round_UpperLeft) { case false: renderPixel(p,QPoint(r.left(),r.top()),alphaAA,contourColor,backgroundColor,alphaBlend); break; default: renderPixel(p,QPoint(r.left()+1,r.top()),alphaAA,contourColor,backgroundColor,alphaBlend); renderPixel(p,QPoint(r.left(),r.top()+1),alphaAA,contourColor,backgroundColor,alphaBlend); } } if(drawLeft && drawBottom) { switch(flags&Round_BottomLeft) { case false: renderPixel(p,QPoint(r.left(),r.bottom()),alphaAA,contourColor,backgroundColor,alphaBlend); break; default: renderPixel(p,QPoint(r.left()+1,r.bottom()),alphaAA,contourColor,backgroundColor,alphaBlend); renderPixel(p,QPoint(r.left(),r.bottom()-1),alphaAA,contourColor,backgroundColor,alphaBlend); } } if(drawRight && drawTop) { switch(flags&Round_UpperRight) { case false: renderPixel(p,QPoint(r.right(),r.top()),alphaAA,contourColor,backgroundColor,alphaBlend); break; default: renderPixel(p,QPoint(r.right()-1,r.top()),alphaAA,contourColor,backgroundColor,alphaBlend); renderPixel(p,QPoint(r.right(),r.top()+1),alphaAA,contourColor,backgroundColor,alphaBlend); } } if(drawRight && drawBottom) { switch(flags&Round_BottomRight) { case false: renderPixel(p,QPoint(r.right(),r.bottom()),alphaAA,contourColor,backgroundColor,alphaBlend); break; default: renderPixel(p,QPoint(r.right()-1,r.bottom()),alphaAA,contourColor,backgroundColor,alphaBlend); renderPixel(p,QPoint(r.right(),r.bottom()-1),alphaAA,contourColor,backgroundColor,alphaBlend); } } //HACK: paint the sharp border over the rest, it's NoGooD(tm) p->setPen( alphaBlendColors(backgroundColor, contourColor, 50) ); if( !(flags&Round_UpperLeft) && sharpTopLeft ) p->drawPoint( r.left(), r.top() ); if( !(flags&Round_UpperRight) && sharpTopRight ) p->drawPoint( r.right(), r.top() ); if( !(flags&Round_BottomLeft) && sharpBottomLeft ) p->drawPoint( r.left(), r.bottom() ); if( !(flags&Round_BottomRight) && sharpBottomRight ) p->drawPoint( r.right(), r.bottom() ); } void PolyesterStyle::renderMask(QPainter *p, const QRect &r, const QColor &color, const uint flags) const { if((r.width() <= 0)||(r.height() <= 0)) return; const bool roundUpperLeft = flags&Round_UpperLeft; const bool roundUpperRight = flags&Round_UpperRight; const bool roundBottomLeft = flags&Round_BottomLeft; const bool roundBottomRight = flags&Round_BottomRight; p->fillRect (QRect(r.x()+1, r.y()+1, r.width()-2, r.height()-2) , color); p->setPen(color); // sides p->drawLine(roundUpperLeft?r.x()+1:r.x(), r.y(), roundUpperRight?r.right()-1:r.right(), r.y() ); p->drawLine(roundBottomLeft?r.x()+1:r.x(), r.bottom(), roundBottomRight?r.right()-1:r.right(), r.bottom() ); p->drawLine(r.x(), roundUpperLeft?r.y()+1:r.y(), r.x(), roundBottomLeft?r.bottom()-1:r.bottom() ); p->drawLine(r.right(), roundUpperLeft?r.y()+1:r.y(), r.right(), roundBottomLeft?r.bottom()-1:r.bottom() ); } void PolyesterStyle::renderSurface(QPainter *p, const QRect &r, const QColor &backgroundColor, const QColor &buttonColor, const QColor &highlightColor, int intensity, const uint flags) const { if((r.width() <= 0)||(r.height() <= 0)) return; const bool disabled = flags&Is_Disabled; const bool drawLeft = flags&Draw_Left; const bool drawRight = flags&Draw_Right; const bool drawTop = flags&Draw_Top; const bool drawBottom = flags&Draw_Bottom; const bool roundUpperLeft = flags&Round_UpperLeft; const bool roundUpperRight = flags&Round_UpperRight; const bool roundBottomLeft = flags&Round_BottomLeft; const bool roundBottomRight = flags&Round_BottomRight; const bool sunken = flags&Is_Sunken; const bool horizontal = flags&Is_Horizontal; bool highlight = false, highlightLeft = false, highlightRight = false, highlightTop = false, highlightBottom = false; // only highlight if not sunken & not disabled... if(!sunken && !disabled) { highlight = (flags&Is_Highlight); highlightLeft = (flags&Highlight_Left); highlightRight = (flags&Highlight_Right); highlightTop = (flags&Highlight_Top); highlightBottom = (flags&Highlight_Bottom); } QColor baseColor = alphaBlendColors(backgroundColor, disabled?backgroundColor:buttonColor, 10); if (disabled) { intensity = 2; } else if (highlight) { // blend this _slightly_ with the background baseColor = alphaBlendColors(baseColor, highlightColor, 240); } else if (sunken) { // enforce a common sunken-style... baseColor = baseColor.dark(110+intensity); //intensity = _contrast*2; } // some often needed colors... // 1 more intensive than 2. const QColor colorTop1 = alphaBlendColors(baseColor, sunken?baseColor.dark(100+intensity*2):baseColor.light(100+intensity*2), 80); const QColor colorTop2 = alphaBlendColors(baseColor, sunken?baseColor.dark(100+intensity):baseColor.light(100+intensity), 80); const QColor colorBottom1 = alphaBlendColors(baseColor, sunken?baseColor.light(100+intensity*2):baseColor.dark(100+intensity*2), 80); const QColor colorBottom2 = alphaBlendColors(baseColor, sunken?baseColor.light(100+intensity):baseColor.dark(100+intensity), 80); const QColor colorBorder = colorTop1.light(100+_contrast); // sides if (drawLeft) { if (horizontal && !_lightBorder) { int height = r.height(); if (roundUpperLeft || !drawTop) height--; if (roundBottomLeft || !drawBottom) height--; renderGradient(p, QRect(r.left(), (roundUpperLeft&&drawTop)?r.top()+1:r.top(), 1, height), colorBorder, baseColor); } else { p->setPen(colorBorder ); p->drawLine(r.left(), (roundUpperLeft&&drawTop)?r.top()+1:r.top(), r.left(), (roundBottomLeft&&drawBottom)?r.bottom()-1:r.bottom() ); } } if (drawRight) { if (horizontal && !_lightBorder) { int height = r.height(); // TODO: there's still a bogus in it: when edge4 is Thick // and we don't whant to draw the Top, we have a unpainted area if (roundUpperRight || !drawTop) height--; if (roundBottomRight || !drawBottom) height--; renderGradient(p, QRect(r.right(), (roundUpperRight&&drawTop)?r.top()+1:r.top(), 1, height), baseColor, _lightBorder&&!sunken?colorBorder:colorBottom1); } else { /*3d effect or light borders?*/ p->setPen(_lightBorder&&!sunken?colorBorder:colorBottom1 ); p->drawLine(r.right(), (roundUpperRight&&drawTop)?r.top()+1:r.top(), r.right(), (roundBottomRight&&drawBottom)?r.bottom()-1:r.bottom() ); } } if (drawTop) { if ( horizontal || _lightBorder ) { p->setPen( colorBorder ); p->drawLine((roundUpperLeft&&drawLeft)?r.left()+1:r.left(), r.top(), (roundUpperRight&&drawRight)?r.right()-1:r.right(), r.top() ); } else { int width = r.width(); if (roundUpperLeft || !drawLeft) width--; if (roundUpperRight || !drawRight) width--; renderGradient(p, QRect((roundUpperLeft&&drawLeft)?r.left()+1:r.left(), r.top(), width, 1), colorTop2, colorBorder, false ); } } if (drawBottom) { if ( horizontal|| _lightBorder ) { p->setPen(_lightBorder&&!sunken?colorBorder:colorBottom1 ); p->drawLine((roundBottomLeft&&drawLeft)?r.left()+1:r.left(), r.bottom(), (roundBottomRight&&drawRight)?r.right()-1:r.right(), r.bottom() ); } else { int width = r.width(); if (roundBottomLeft || !drawLeft) width--; if (roundBottomRight || !drawRight) width--; renderGradient(p, QRect((roundBottomLeft&&drawLeft)?r.left()+1:r.left(), r.bottom(), width, 1), colorBottom2, _lightBorder&&!sunken?colorBorder:colorBottom1, false); } } // button area... int width = r.width(); int height = r.height(); if (drawLeft) width--; if (drawRight) width--; if (drawTop) height--; if (drawBottom) height--; int left = r.left(); int top = r.top(); if (drawLeft) left++; if (drawTop) top++; if( !strcmp(_buttonStyle,"gradients" ) /*|| sunken*/ ){ //polyester style renderGradient(p, QRect(drawLeft?r.left()+1:r.left(), drawTop?r.top()+1:r.top(), width, height), colorTop2, colorBottom2, horizontal); } else if( !strcmp(_buttonStyle,"glass" ) ){ //glass buttons /*create a copy of the two colors, otherwise ugly things(tm) happens...*/ const QColor colorTop3 = QColor(colorTop1.rgb()).light(100+_contrast); const QColor colorBottom3 = QColor(colorBottom2.rgb()).light(100+_contrast); //halfsize is half of height or width depending in the scrollbar is horizontal // round on upper int if the size is odd int halfsize; if( horizontal ) halfsize = height%2==0?height/2:(height/2)+1; else halfsize = width%2==0?width/2:(width/2)+1; renderGradient(p, QRect(left, top, horizontal?width:width/2, horizontal?height/2:height), colorTop2, colorBottom3, horizontal); renderGradient(p, QRect(horizontal?left:left+width/2, horizontal?top+height/2:top, horizontal?width:halfsize, horizontal?halfsize:height), colorBottom2, colorTop2, horizontal); }else if( !strcmp(_buttonStyle,"reverseGradients" ) ){ //lipstik style renderGradient(p, QRect(drawLeft?r.left()+1:r.left(), drawTop?r.top()+1:r.top(), width, height), colorBottom2, colorTop2, horizontal); }else{ //flat style renderGradient(p, QRect(drawLeft?r.left()+1:r.left(), drawTop?r.top()+1:r.top(), width, height), buttonColor, buttonColor, horizontal); } // highlighting... if(highlightTop) { p->setPen(alphaBlendColors(colorTop1 , highlightColor, 20) ); p->drawLine((roundUpperLeft&&drawLeft)?r.left()+1:r.left(), r.top(), (roundUpperRight&&drawRight)?r.right()-1:r.right(), r.top() ); p->setPen(alphaBlendColors(colorTop2 , highlightColor, 90) ); p->drawLine(highlightLeft?r.left()+1:r.left(), r.top()+1, highlightRight?r.right()-1:r.right(), r.top()+1 ); if( roundUpperLeft&&drawLeft&&!highlightLeft ) { p->drawPoint(r.left(),r.top()+2); p->setPen(alphaBlendColors(colorTop1 , highlightColor, 20) ); p->drawPoint(r.left(),r.top()+1); } if( roundUpperRight&&drawRight&&!highlightRight ) { p->setPen(alphaBlendColors(colorTop1 , highlightColor, 20) ); p->drawPoint(r.right(),r.top()+1); p->setPen(alphaBlendColors(colorTop2 , highlightColor, 90) ); p->drawPoint(r.right(),r.top()+2); } } if(highlightBottom) { p->setPen(alphaBlendColors(colorBottom1 , highlightColor, 20) ); p->drawLine((roundBottomLeft&&drawLeft)?r.left()+1:r.left(), r.bottom(), (roundBottomRight&&drawRight)?r.right()-1:r.right(), r.bottom() ); p->setPen(alphaBlendColors(colorBottom2 , highlightColor, 90) ); p->drawLine(highlightLeft?r.left()+1:r.left(), r.bottom()-1, highlightRight?r.right()-1:r.right(), r.bottom()-1 ); if( roundBottomLeft&&drawLeft&&!highlightLeft ) { p->drawPoint(r.left(),r.bottom()-2); p->setPen(alphaBlendColors(colorBottom1 , highlightColor, 20) ); p->drawPoint(r.left(),r.bottom()-1); } if( roundBottomRight&&drawRight&&!highlightRight ) { p->setPen(alphaBlendColors(colorBottom2 , highlightColor, 90) ); p->drawPoint(r.right(),r.bottom()-2); p->setPen(alphaBlendColors(colorBottom1 , highlightColor, 20) ); p->drawPoint(r.right(),r.bottom()-1); } } if(highlightLeft) { p->setPen(alphaBlendColors(colorTop1 , highlightColor, 20) ); p->drawLine(r.left(), (roundUpperLeft&&drawTop)?r.top()+1:r.top(), r.left(), (roundBottomLeft&&drawBottom)?r.bottom()-1:r.bottom() ); p->setPen(alphaBlendColors(colorTop2 , highlightColor, 90) ); p->drawLine(r.left()+1, highlightTop?r.top()+1:r.top(), r.left()+1, highlightBottom?r.bottom()-1:r.bottom() ); } if(highlightRight) { p->setPen(alphaBlendColors(colorBottom1 , highlightColor, 20) ); p->drawLine(r.right(), (roundUpperRight&&drawTop)?r.top()+1:r.top(), r.right(), (roundBottomRight&&drawBottom)?r.bottom()-1:r.bottom() ); p->setPen(alphaBlendColors(colorBottom2 , highlightColor, 90) ); p->drawLine(r.right()-1, highlightTop?r.top()+1:r.top(), r.right()-1, highlightBottom?r.bottom()-1:r.bottom() ); } } void PolyesterStyle::renderPixel(QPainter *p, const QPoint &pos, const int alpha, const QColor &color, const QColor &background, bool fullAlphaBlend) const { if(fullAlphaBlend) // full alpha blend: paint into an image with alpha buffer and convert to a pixmap ... { QRgb rgb = color.rgb(); // generate a quite unique key -- use the unused width field to store the alpha value. CacheEntry search(cAlphaDot, alpha, 0, rgb); int key = search.key(); CacheEntry *cacheEntry; if( (cacheEntry = pixmapCache->find(key)) ) { if( search == *cacheEntry ) { // match! we can draw now... if(cacheEntry->pixmap) p->drawPixmap(pos, *(cacheEntry->pixmap) ); return; } else { //Remove old entry in case of a conflict! pixmapCache->remove( key ); } } QImage aImg(1,1,32); // 1x1 aImg.setAlphaBuffer(true); aImg.setPixel(0,0,qRgba(qRed(rgb),qGreen(rgb),qBlue(rgb),alpha)); QPixmap *result = new QPixmap(aImg); p->drawPixmap(pos, *result); // add to the cache... CacheEntry *toAdd = new CacheEntry(search); toAdd->pixmap = result; bool insertOk = pixmapCache->insert( key, toAdd, result->depth()/8); if(!insertOk) delete result; } else // don't use an alpha buffer: calculate the resulting color from the alpha value, the fg- and the bg-color. { QRgb rgb_a = color.rgb(); QRgb rgb_b = background.rgb(); int a = alpha; if(a>255) a = 255; if(a<0) a = 0; int a_inv = 255 - a; QColor res = QColor( qRgb(qRed(rgb_b)*a_inv/255 + qRed(rgb_a)*a/255, qGreen(rgb_b)*a_inv/255 + qGreen(rgb_a)*a/255, qBlue(rgb_b)*a_inv/255 + qBlue(rgb_a)*a/255) ); p->setPen(res); p->drawPoint(pos); } } void PolyesterStyle::renderButton(QPainter *p, const QRect &r, const QColorGroup &g, bool sunken, bool mouseOver, bool horizontal, bool enabled, bool khtmlMode, int animFrame, bool isDefault //TODO: move here all the default-button related code? ) const { // small fix for the kicker buttons... if(kickerMode) enabled = true; const QPen oldPen( p->pen() ); uint contourFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom; if(!enabled) contourFlags|=Is_Disabled; if(khtmlMode) contourFlags|=Draw_AlphaBlend; uint surfaceFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom; if(horizontal) surfaceFlags|=Is_Horizontal; if(!enabled) surfaceFlags|=Is_Disabled; else { if(sunken) surfaceFlags|=Is_Sunken; else { if(((animFrame != 0) || mouseOver) && (!_animateButton||!isDefault)) { surfaceFlags|=Is_Highlight; if(horizontal) { surfaceFlags|=Highlight_Top; surfaceFlags|=Highlight_Bottom; } else { surfaceFlags|=Highlight_Left; surfaceFlags|=Highlight_Right; } } } } if (!flatMode) { contourFlags |= Round_UpperLeft|Round_UpperRight|Round_BottomLeft|Round_BottomRight; surfaceFlags |= Round_UpperLeft|Round_UpperRight|Round_BottomLeft|Round_BottomRight; renderContour(p, r, g.background(), (isDefault?getColor(g,ButtonContour).dark(100+_contrast*10):getColor(g,ButtonContour)), contourFlags); /*Colorize to mouseHover only the default button, the others will get lighter or darker*/ if(!isDefault) { renderSurface(p, QRect(r.left()+1, r.top()+1, r.width()-2, r.height()-2), g.background(), g.button().light(100+animFrame), (_animateButton?alphaBlendColors( getColor(g,MouseOverHighlight),g.button(), 20*animFrame ):getColor(g,MouseOverHighlight)), _contrast, surfaceFlags); } else { //12.8 is the maximum amount of blending (256) / ANIMATIONSTEPS (20) QColor buttonColor = alphaBlendColors( g.highlight(), g.button(), (int)(12.8*animFrame)+50); renderSurface(p, QRect(r.left()+1, r.top()+1, r.width()-2, r.height()-2), g.background(), buttonColor.light(100+animFrame), getColor(g,MouseOverHighlight), _contrast+animFrame, surfaceFlags); } } else { renderContour(p, r, g.background(), g.button().dark(105+_contrast*3), contourFlags); renderSurface(p, QRect(r.left()+1, r.top()+1, r.width()-2, r.height()-2), g.background(), g.button(), getColor(g,MouseOverHighlight), _contrast/2, surfaceFlags); flatMode = false; } p->setPen(oldPen); } void PolyesterStyle::renderDot(QPainter *p, const QPoint &point, const QColor &baseColor, const bool thick, const bool sunken) const { const QColor topColor = alphaBlendColors(baseColor, sunken?baseColor.dark(130):baseColor.light(150), 70); const QColor bottomColor = alphaBlendColors(baseColor, sunken?baseColor.light(150):baseColor.dark(130), 70); p->setPen(topColor ); p->drawLine(point.x(), point.y(), point.x()+1, point.y()); p->drawPoint(point.x(), point.y()+1); p->setPen(bottomColor ); if(thick) { p->drawLine(point.x()+1, point.y()+2, point.x()+2, point.y()+2); p->drawPoint(point.x()+2, point.y()+1); } else { p->drawPoint(point.x()+1, point.y()+1); } } void PolyesterStyle::renderGradient(QPainter *painter, const QRect &rect, const QColor &c1, const QColor &c2, bool horizontal) const { if((rect.width() <= 0)||(rect.height() <= 0)) return; // generate a quite unique key for this surface. CacheEntry search(cGradientTile, horizontal ? 0 : rect.width(), horizontal ? rect.height() : 0, c1.rgb(), c2.rgb(), horizontal ); int key = search.key(); CacheEntry *cacheEntry; if( (cacheEntry = pixmapCache->find(key)) ) { if( search == *cacheEntry ) { // match! we can draw now... if(cacheEntry->pixmap) { painter->drawTiledPixmap(rect, *(cacheEntry->pixmap) ); } return; } else { // Remove old entry in case of a conflict! // This shouldn't happen very often, see comment in CacheEntry. pixmapCache->remove(key); } } // there wasn't anything matching in the cache, create the pixmap now... QPixmap *result = new QPixmap(horizontal ? 10 : rect.width(), horizontal ? rect.height() : 10); QPainter p(result); int r_w = result->rect().width(); int r_h = result->rect().height(); int r_x, r_y, r_x2, r_y2; result->rect().coords(&r_x, &r_y, &r_x2, &r_y2); int rDiff, gDiff, bDiff; int rc, gc, bc; register int x, y; rDiff = ( c2.red()) - (rc = c1.red()); gDiff = ( c2.green()) - (gc = c1.green()); bDiff = ( c2.blue()) - (bc = c1.blue()); register int rl = rc << 16; register int gl = gc << 16; register int bl = bc << 16; int rdelta = ((1<<16) / (horizontal ? r_h : r_w)) * rDiff; int gdelta = ((1<<16) / (horizontal ? r_h : r_w)) * gDiff; int bdelta = ((1<<16) / (horizontal ? r_h : r_w)) * bDiff; // these for-loops could be merged, but the if's in the inner loop // would make it slow if(horizontal) { for ( y = 0; y < r_h; y++ ) { rl += rdelta; gl += gdelta; bl += bdelta; p.setPen(QColor(rl>>16, gl>>16, bl>>16)); p.drawLine(r_x, r_y+y, r_x2, r_y+y); } } else { for( x = 0; x < r_w; x++) { rl += rdelta; gl += gdelta; bl += bdelta; p.setPen(QColor(rl>>16, gl>>16, bl>>16)); p.drawLine(r_x+x, r_y, r_x+x, r_y2); } } p.end(); // draw the result... painter->drawTiledPixmap(rect, *result); // insert into cache using the previously created key. CacheEntry *toAdd = new CacheEntry(search); toAdd->pixmap = result; bool insertOk = pixmapCache->insert( key, toAdd, result->width()*result->height()*result->depth()/8 ); if(!insertOk) delete result; } void PolyesterStyle::renderPanel(QPainter *p, const QRect &r, const QColorGroup &g, const bool pseudo3d, const bool sunken) const { int x, x2, y, y2, w, h; r.rect(&x,&y,&w,&h); r.coords(&x, &y, &x2, &y2); if (kickerMode && p->device() && p->device()->devType() == QInternal::Widget && QCString(static_cast(p->device())->className()) == "FittsLawFrame") { // Stolen wholesale from Keramik. I don't like it, but oh well. if (sunken) { const QCOORD corners[] = { x2, y, x2, y2, x, y2, x, y }; p->setPen(g.background().dark()); p->drawConvexPolygon(QPointArray(4, corners)); p->setPen(g.background().light()); p->drawPolyline(QPointArray(4, corners), 0, 3); } else { const QCOORD corners[] = { x, y2, x, y, x2, y, x2, y2 }; p->setPen(g.background().dark()); p->drawPolygon(QPointArray(4, corners)); p->setPen(g.background().light()); p->drawPolyline(QPointArray(4, corners), 0, 3); } } else { renderContour(p, r, g.background(), getColor(g, PanelContour) ); if(pseudo3d) { if (sunken) { p->setPen(getColor(g, PanelDark) ); } else { p->setPen(getColor(g, PanelLight) ); } p->drawLine(r.left()+2, r.top()+1, r.right()-2, r.top()+1); p->drawLine(r.left()+1, r.top()+2, r.left()+1, r.bottom()-2); if (sunken) { p->setPen(getColor(g, PanelLight) ); } else { p->setPen(getColor(g, PanelDark) ); } p->drawLine(r.left()+2, r.bottom()-1, r.right()-2, r.bottom()-1); p->drawLine(r.right()-1, r.top()+2, r.right()-1, r.bottom()-2); } } } void PolyesterStyle::renderMenuBlendPixmap( KPixmap &pix, const QColorGroup &cg, const QPopupMenu* /* popup */ ) const { pix.fill( cg.background().light(105) ); } void PolyesterStyle::renderTab(QPainter *p, const QRect &r, const QColorGroup &g, bool mouseOver, const SelectedTab selected, const bool bottom, const TabPosition pos, const bool triangular, bool cornerWidget) const { const bool reverseLayout = QApplication::reverseLayout(); const bool isFirst = (pos == First) || (pos == Single); const bool isLast = (pos == Last); const bool isSingle = (pos == Single); /*if the tabbar is centered always render the left rounded connection of the first tab*/ if( _centeredTabBar && !reverseLayout && isFirst ) cornerWidget = true; if (selected == ThisTab) { // is selected // the top part of the tab which is nearly the same for all positions QRect Rc; // contour if (!bottom) { if (isFirst && !cornerWidget && !reverseLayout) { Rc = QRect(r.x(), r.y(), r.width()-1, r.height()-3); } else if (isFirst && !cornerWidget && reverseLayout) { Rc = QRect(r.x()+1, r.y(), r.width()-1, r.height()-3); } else { Rc = QRect(r.x()+1, r.y(), r.width()-2, r.height()-3); } } else { if (isFirst && !cornerWidget && !reverseLayout) { Rc = QRect(r.x(), r.y()+3, r.width()-1, r.height()-3); } else if (isFirst && !cornerWidget && reverseLayout) { Rc = QRect(r.x()+1, r.y()+3, r.width()-1, r.height()-3); } else { Rc = QRect(r.x()+1, r.y()+3, r.width()-2, r.height()-3); } } const QRect Rs(Rc.x()+1, bottom?Rc.y():Rc.y()+1, Rc.width()-2, Rc.height()-1); // the resulting surface // the area where the fake border shoudl appear const QRect Rb(r.x(), bottom?r.top():Rc.bottom()+1, r.width(), r.height()-Rc.height() ); uint contourFlags = Draw_Left|Draw_Right; if(!bottom) { contourFlags |= Draw_Top|Round_UpperLeft|Round_UpperRight; } else { contourFlags |= Draw_Bottom|Round_BottomLeft|Round_BottomRight; } renderContour(p, Rc, g.background(), getColor(g,PanelContour), contourFlags); // surface if(!bottom) { p->setPen(getColor(g,PanelLight) ); p->drawLine(Rs.x()+1, Rs.y(), Rs.right()-1, Rs.y() ); renderGradient(p, QRect(Rs.x(), Rs.y()+1, 1, Rs.height()-1), getColor(g,PanelLight), getColor(g,PanelLight2)); renderGradient(p, QRect(Rs.right(), Rs.y()+1, 1, Rs.height()-1), getColor(g,PanelDark), getColor(g,PanelDark2)); if( !strcmp(_buttonStyle,"glass" ) ){ renderGradient(p, QRect(Rs.x()+1, Rs.y()+1, Rs.width()-2, Rs.height()/2), g.background().light(100+_contrast), g.background()); renderGradient(p, QRect(Rs.x()+1, Rs.y()+Rs.height()/2, Rs.width()-2, Rs.height()/2), g.background().dark(100+_contrast), g.background()); }else if( !strcmp(_buttonStyle,"gradients" ) ) renderGradient(p, QRect(Rs.x()+1, Rs.y()+1, Rs.width()-2, Rs.height()-1), getColor(g,PanelLight), g.background()); else if( !strcmp(_buttonStyle,"reverseGradients" ) ) renderGradient(p, QRect(Rs.x()+1, Rs.y()+1, Rs.width()-2, Rs.height()-1), g.background().dark(100+_contrast), g.background()); else renderGradient(p, QRect(Rs.x()+1, Rs.y()+1, Rs.width()-2, Rs.height()-1), g.background(), g.background()); if( _highLightTab ) { p->fillRect( QRect(Rs.x()+1, Rs.y(), Rs.width()-2, 2), g.highlight()); p->setPen( g.highlight() ); p->drawLine( Rs.x(), Rs.y()+1, Rs.x(), Rs.y()+2 ); p->drawLine( Rs.right(), Rs.y()+1, Rs.right(), Rs.y()+2 ); } /*renderSurface(p, Rs, g.background(), g.button(), getColor(g,MouseOverHighlight), _contrast, Draw_Top|Draw_Bottom|Is_Horizontal);*/ } else { p->setPen(g.highlight()); //p->drawLine(Rs.x()+1, Rs.bottom(), Rs.right()-1, Rs.bottom() ); if( _highLightTab ) { p->fillRect(Rs.x()+1, Rs.bottom()-1, Rs.width()-2, 2, g.highlight() ); p->drawLine(Rs.x(), Rs.bottom()-2, Rs.x(), Rs.bottom()-1 ); p->drawLine(Rs.right(), Rs.bottom()-2, Rs.right(), Rs.bottom()-1 ); } renderGradient(p, QRect(Rs.x(), Rs.y(), 1, Rs.height()-4), getColor(g,PanelLight), getColor(g,PanelLight2)); renderGradient(p, QRect(Rs.right(), Rs.y(), 1, Rs.height()-4), getColor(g,PanelDark), getColor(g,PanelDark2)); renderSurface(p, QRect(Rs.x()+1, Rs.y(), Rs.width()-2, Rs.height()-3), g.background(), g.button(), g.highlight(), _contrast, Is_Horizontal); } // some "position specific" paintings... // draw parts of the inactive tabs around... if(!isSingle) { p->setPen(alphaBlendColors(g.background(), getColor(g, ButtonContour), 50) ); if((!isFirst&&!reverseLayout) || (!isLast&&reverseLayout) ) { p->drawPoint(r.left(), bottom?(triangular?r.bottom()-2:r.bottom()-3):(triangular?r.top()+2:r.top()+3) ); /*renderSurface(p, QRect(r.left(), bottom?r.top()+3:(triangular?r.top()+3:r.top()+4), 1, (triangular?r.height()-6:r.height()-7) ), g.background(), g.button(), getColor(g,MouseOverHighlight), _contrast, Draw_Top|Draw_Bottom|Is_Horizontal);*/ } if((!isLast&&!reverseLayout) || (!isFirst&&reverseLayout) ) { //for some strange cause i must set the pen color again... p->setPen(alphaBlendColors(g.background(), getColor(g, ButtonContour), 50) ); p->drawPoint(r.right(), bottom?(triangular?r.bottom()-2:r.bottom()-3):(triangular?r.top()+2:r.top()+3) ); #if 0 renderSurface(p, QRect(r.right(), bottom?r.top()+3:(triangular?r.top()+3:r.top()+4), 1, (triangular?r.height()-6:r.height()-7) ), g.background(), g.button(), getColor(g,MouseOverHighlight), _contrast, Draw_Top|Draw_Bottom|Is_Horizontal/*|((bottom?Highlight_Bottom:Highlight_Top):0)*/); #endif } } // left connection from the panel border to the tab. :) if(isFirst && !reverseLayout && !cornerWidget) { p->setPen(alphaBlendColors(g.background(), getColor(g,PanelContour), 50) ); p->drawLine(Rb.x(), Rb.y(), Rb.x(), Rb.bottom() ); p->setPen(getColor(g,PanelLight) ); p->drawLine(Rb.x()+1, Rb.y(), Rb.x()+1, Rb.bottom() ); } else if(isFirst && reverseLayout && !cornerWidget) { p->setPen(alphaBlendColors(g.background(), getColor(g,PanelContour), 50) ); p->drawLine(Rb.right(), Rb.y(), Rb.right(), Rb.bottom() ); p->setPen(getColor(g,PanelDark) ); p->drawLine(Rb.right()-1, Rb.y(), Rb.right()-1, Rb.bottom() ); } // rounded connections to the panel... if(!bottom) { // left if( (!isFirst && !reverseLayout) || (reverseLayout) || (isFirst && !reverseLayout && cornerWidget) ) { p->setPen( alphaBlendColors(g.background(), getColor(g,PanelContour), 50) ); p->drawPoint(Rb.x(), Rb.y()); p->setPen( alphaBlendColors(g.background(), getColor(g,PanelContour), 150) ); p->drawPoint(Rb.x(), Rb.y()+1); p->drawPoint(Rb.x()+1, Rb.y()); } // right if( (!reverseLayout) || (!isFirst && reverseLayout) || (isFirst && reverseLayout) ) { p->setPen( alphaBlendColors(g.background(), getColor(g,PanelContour), 50) ); p->drawPoint(Rb.right(), Rb.y()); p->setPen( alphaBlendColors(g.background(), getColor(g,PanelContour), 150) ); p->drawPoint(Rb.right(), Rb.y()+1); p->drawPoint(Rb.right()-1, Rb.y()); } } else { // left if( (!isFirst && !reverseLayout) || (reverseLayout) || (isFirst && !reverseLayout && cornerWidget) ) { p->setPen( alphaBlendColors(g.background(), getColor(g,PanelContour), 50) ); p->drawPoint(Rb.x(), Rb.bottom()); p->setPen( alphaBlendColors(g.background(), getColor(g,PanelContour), 150) ); p->drawPoint(Rb.x(), Rb.bottom()-1); p->drawPoint(Rb.x()+1, Rb.bottom()); } // right if( (!reverseLayout) || (!isFirst && reverseLayout) || (isFirst && reverseLayout && cornerWidget) ) { p->setPen( alphaBlendColors(g.background(), getColor(g,PanelContour), 50) ); p->drawPoint(Rb.right(), Rb.bottom()); p->setPen( alphaBlendColors(g.background(), getColor(g,PanelContour), 150) ); p->drawPoint(Rb.right(), Rb.bottom()-1); p->drawPoint(Rb.right()-1, Rb.bottom()); } } } else { // inactive tabs // the top part of the tab which is nearly the same for all positions QRect Rc; // contour if (isFirst&&reverseLayout ) { Rc = QRect(r.x()+1, (bottom?r.y()+2:(triangular?r.y()+2:r.y()+3)), r.width()-2, (triangular?r.height()-4:r.height()-5) ); } else { Rc = QRect(r.x()+1, (bottom?r.y()+2:(triangular?r.y()+2:r.y()+3)), r.width()-1, (triangular?r.height()-4:r.height()-5) ); } QRect Rs; // the resulting surface if ( (isFirst&&!reverseLayout) || (isLast&&reverseLayout) ) Rs = QRect(Rc.x()+1, bottom?Rc.y():Rc.y()+1, Rc.width()-(selected == OtherTab?2:1), Rc.height()-1); else if( reverseLayout ){ Rs = QRect(Rc.x()-(selected == NextTab?1:0), bottom?Rc.y():Rc.y()+1, Rc.width()-(selected == OtherTab?1:0), Rc.height()-1); } else{ Rs = QRect(Rc.x()-(selected == PrevTab?1:0), bottom?Rc.y():Rc.y()+1, Rc.width()-(selected == OtherTab?1:0), Rc.height()-1); } // the area where the fake border shoudl appear const QRect Rb(r.x(), bottom?r.y():Rc.bottom()+1, r.width(), 2 ); uint contourFlags; if(!bottom) { if ( (isFirst&&!reverseLayout) || (isLast&&reverseLayout) ) { contourFlags = Draw_Left|Draw_Right|Draw_Top|Sharp_UpperRight|Round_UpperLeft; } else if ( (isLast&&!reverseLayout) || (isFirst&&reverseLayout) ) { contourFlags = Draw_Right|Draw_Top|Sharp_UpperLeft|Round_UpperRight; } else { contourFlags = Draw_Right|Draw_Top|Sharp_UpperLeft|Sharp_UpperRight; } } else { if ( (isFirst&&!reverseLayout) || (isLast&&reverseLayout) ) { contourFlags = Draw_Left|Draw_Right|Draw_Bottom|Sharp_BottomRight|Round_BottomLeft; } else if ( (isLast&&!reverseLayout) || (isFirst&&reverseLayout) ) { contourFlags = Draw_Right|Draw_Bottom|Sharp_BottomLeft|Round_BottomRight; } else { contourFlags = Draw_Right|Draw_Bottom|Sharp_BottomLeft|Sharp_BottomRight; } } renderContour(p, Rc, g.background(), getColor(g, ButtonContour), contourFlags); uint surfaceFlags = Is_Horizontal; if(mouseOver) { surfaceFlags |= (bottom?Highlight_Bottom:Highlight_Top); surfaceFlags |= Is_Highlight; } if ( (isFirst&&!reverseLayout) || (isLast&&reverseLayout) ) { if(!bottom) surfaceFlags |= Draw_Left|Draw_Top|Round_UpperLeft; else surfaceFlags |= Draw_Left|Draw_Bottom|Round_BottomLeft; } else if ( (isLast&&!reverseLayout) || (isFirst&&reverseLayout) ) { if(!bottom) surfaceFlags |= Draw_Right|Draw_Top|Round_UpperRight; else surfaceFlags |= Draw_Right|Draw_Bottom|Round_BottomRight; } else { surfaceFlags |= (!bottom?Draw_Top:Draw_Bottom); } renderSurface(p, Rs, g.background(), g.button(), getColor(g,MouseOverHighlight), _contrast, surfaceFlags); // some "position specific" paintings... // fake parts of the panel border if(!bottom) { p->setPen(alphaBlendColors(g.background(), getColor(g,PanelContour), 50) ); p->drawLine(Rb.x(), Rb.y(), ((isLast&&!reverseLayout)||(isFirst&&reverseLayout&&cornerWidget))?Rb.right():Rb.right()-1, Rb.y()); p->setPen(getColor(g,PanelLight) ); p->drawLine(Rb.x(), Rb.y()+1, ((isLast&&!reverseLayout)||(isFirst&&reverseLayout&&cornerWidget))?Rb.right():Rb.right()-1, Rb.y()+1 ); } else { p->setPen(alphaBlendColors(g.background(), getColor(g,PanelContour), 50) ); p->drawLine(Rb.x(), Rb.bottom(), ((isLast&&!reverseLayout)||(isFirst&&reverseLayout&&cornerWidget))?Rb.right():Rb.right()-1, Rb.bottom()); p->setPen(getColor(g,PanelDark) ); p->drawLine(Rb.x(), Rb.bottom()-1, ((isLast&&!reverseLayout)||(isFirst&&reverseLayout&&cornerWidget))?Rb.right():Rb.right()-1, Rb.bottom()-1 ); } // fake the panel border edge for tabs which are aligned left-most // (i.e. only if there is no widget in the corner of the tabwidget!) if(isFirst&&!reverseLayout&&!cornerWidget) // normal layout { if (!bottom) { p->setPen(alphaBlendColors(g.background(), getColor(g,PanelContour), 50) ); p->drawPoint(Rb.x()+1, Rb.y()+1 ); p->setPen(alphaBlendColors(g.background(), getColor(g,PanelContour), 150) ); p->drawPoint(Rb.x(), Rb.y()+1 ); p->setPen(g.background() ); p->drawPoint(Rb.x(), Rb.y() ); p->setPen(alphaBlendColors( alphaBlendColors(g.background(), getColor(g, ButtonContour), 50), getColor(g,PanelContour), 150) ); p->drawPoint(Rb.x()+1, Rb.y() ); } else { p->setPen(alphaBlendColors(g.background(), getColor(g,PanelContour), 50) ); p->drawPoint(Rb.x()+1, Rb.bottom()-1 ); p->setPen(alphaBlendColors(g.background(), getColor(g,PanelContour), 150) ); p->drawPoint(Rb.x(), Rb.bottom()-1 ); p->setPen(g.background() ); p->drawPoint(Rb.x(), Rb.bottom() ); p->setPen(alphaBlendColors( alphaBlendColors(g.background(), getColor(g, ButtonContour), 50), getColor(g,PanelContour), 150) ); p->drawPoint(Rb.x()+1, Rb.bottom() ); } } else if(isFirst&&reverseLayout&&!cornerWidget) // reverse layout { if (!bottom) { p->setPen(alphaBlendColors(g.background(), getColor(g,PanelContour), 50) ); p->drawPoint(Rb.right()-1, Rb.y()+1 ); p->setPen(alphaBlendColors(g.background(), getColor(g,PanelContour), 150) ); p->drawPoint(Rb.right(), Rb.y()+1 ); p->setPen(g.background() ); p->drawPoint(Rb.right(), Rb.y() ); p->setPen(alphaBlendColors( alphaBlendColors(g.background(), getColor(g, ButtonContour), 50), getColor(g,PanelContour), 150) ); p->drawPoint(Rb.right()-1, Rb.y() ); } else { p->setPen(alphaBlendColors(g.background(), getColor(g,PanelContour), 50) ); p->drawPoint(Rb.right()-1, Rb.bottom()-1 ); p->setPen(alphaBlendColors(g.background(), getColor(g,PanelContour), 150) ); p->drawPoint(Rb.right(), Rb.bottom()-1 ); p->setPen(g.background() ); p->drawPoint(Rb.right(), Rb.bottom() ); p->setPen(alphaBlendColors( alphaBlendColors(g.background(), getColor(g, ButtonContour), 50), getColor(g,PanelContour), 150) ); p->drawPoint(Rb.right()-1, Rb.bottom() ); } } } } void PolyesterStyle::sliderThumbMoved(int val) { QSlider *slider = ::qt_cast(sender()); if(slider) { sliderValues.insert(slider, val); slider->repaint(false); } } void PolyesterStyle::drawKStylePrimitive(KStylePrimitive kpe, QPainter *p, const QWidget* widget, const QRect &r, const QColorGroup &cg, SFlags flags, const QStyleOption& opt) const { // some "global" vars... const bool enabled = (flags & Style_Enabled); // SLIDER // ------ switch( kpe ) { case KPE_SliderGroove: { const QSlider* slider = (const QSlider*)widget; bool horizontal = slider->orientation() == Horizontal; int value = slider->value(); if(sliderValues.contains(slider)) value = sliderValues[slider]; if (horizontal) { int center = r.y()+r.height()/2; //double coloredWidth = ((double)r.width()/slider->maxValue())*slider->value(); double sliderLength = pixelMetric( PM_SliderLength, widget); double halfSliderLength = pixelMetric( PM_SliderLength, widget)/2; double coloredWidth = ((((double)r.width()-sliderLength)/ (slider->maxValue()-slider->minValue()))* (slider->value() - slider->minValue()) )+halfSliderLength; if( QApplication::reverseLayout() ) coloredWidth = r.width() - coloredWidth; /*renderContour(p, QRect(r.left(), center-3, r.width(), 5), cg.background(), cg.background().dark(enabled?150:130), Draw_Left|Draw_Right|Draw_Top|Draw_Bottom);*/ /*p->fillRect(r.left()+1, center-1, (int)(coloredWidth), 2, enabled?cg.highlight():cg.background().dark(120));*/ //colored part renderContour(p, QRect(r.left(), center-3, (int)coloredWidth, 5), cg.background(), enabled && _coloredScrollBar?getColor(cg, DragButtonContour, IsEnabled) :cg.background().dark(130), Draw_Left|Draw_Right|Draw_Top|Draw_Bottom); renderGradient(p, QRect(r.left()+1, center-2, (int)coloredWidth, 3), enabled && _coloredScrollBar?cg.highlight().light(100+_contrast*4) :cg.background().dark(120-_contrast), enabled && _coloredScrollBar?cg.highlight() :cg.background().dark(120), true); //empty part renderContour(p, QRect((int)coloredWidth, center-3, r.width()-(int)coloredWidth, 5), cg.background(), cg.background().dark(enabled?150:130), Draw_Left|Draw_Right|Draw_Top|Draw_Bottom); renderGradient(p, QRect((int)coloredWidth, center-2, r.width()-(int)coloredWidth-1, 3), cg.background().dark(100+_contrast*4), cg.background().light(100+_contrast), true); } else { int center = r.x()+r.width()/2; //double coloredHeight = ((double)r.height()/slider->maxValue())*slider->value(); double sliderLength = pixelMetric( PM_SliderLength, widget); double halfSliderLength = pixelMetric( PM_SliderLength, widget)/2; double nonColoredHeight = ((((double)r.height()-sliderLength)/ (slider->maxValue()-slider->minValue()))* (slider->value() - slider->minValue()) )+halfSliderLength; /*renderContour(p, QRect(center-3, r.top(), 5, r.height()), cg.background(), cg.background().dark(enabled?150:130), Draw_Left|Draw_Right|Draw_Top|Draw_Bottom);*/ /*p->fillRect(center-1, (int)(coloredHeight), 3, r.height(), enabled?cg.highlight():cg.background().dark(120));*/ //colored part renderContour(p, QRect(center-3, (int)nonColoredHeight, 5, r.height()-(int)nonColoredHeight), cg.background(), enabled && _coloredScrollBar?getColor(cg, DragButtonContour, IsEnabled) :cg.background().dark(130), Draw_Left|Draw_Right|Draw_Top|Draw_Bottom); renderGradient(p, QRect(center-2, (int)nonColoredHeight, 3, r.height()-(int)nonColoredHeight-1), enabled?cg.highlight().light(100+_contrast*4) :cg.background().dark(120-_contrast), enabled?cg.highlight() :cg.background().dark(120), false); //empty part renderContour(p, QRect(center-3, r.top(), 5, (int)nonColoredHeight), cg.background(), cg.background().dark(enabled?150:130), Draw_Left|Draw_Right|Draw_Top|Draw_Bottom); renderGradient(p, QRect(center-2, r.y()+1, 3, (int)nonColoredHeight), cg.background().dark(100+_contrast*4), cg.background().light(100+_contrast), false); } break; } case KPE_SliderHandle: { const QSlider* slider = (const QSlider*)widget; bool horizontal = slider->orientation() == Horizontal; const bool pressed = (flags&Style_Active); const WidgetState s = enabled?(pressed?IsPressed:IsEnabled):IsDisabled; const QColor contour = getColor(cg,DragButtonContour,s), surface = getColor(cg,DragButtonSurface,s); int xcenter = (r.left()+r.right()) / 2; int ycenter = (r.top()+r.bottom()) / 2; if (horizontal) { renderContour(p, QRect(xcenter-5, ycenter-6, 11, 10), cg.background(), contour, Draw_Left|Draw_Right|Draw_Top|Round_UpperLeft|Round_UpperRight); // manual contour: vertex p->setPen(alphaBlendColors(cg.background(), contour, 50) ); p->drawPoint(xcenter-5+1, ycenter+4); p->drawPoint(xcenter+5-1, ycenter+4); p->drawPoint(xcenter-5+2, ycenter+5); p->drawPoint(xcenter+5-2, ycenter+5); p->drawPoint(xcenter-5+3, ycenter+6); p->drawPoint(xcenter+5-3, ycenter+6); p->drawPoint(xcenter-5+4, ycenter+7); p->drawPoint(xcenter+5-4, ycenter+7); // 3d effect of vertex if( enabled && _coloredScrollBar ) { if( _lightBorder ) p->setPen( cg.highlight().light(110+_contrast*2) ); else p->setPen( cg.highlight().dark(110+_contrast*2) ); } else { if( _lightBorder ) p->setPen( cg.background().light(110+_contrast*2) ); else p->setPen( cg.background().dark(110+_contrast*2) ); } p->drawPoint(xcenter-5+2, ycenter+4); p->drawPoint(xcenter+5-2, ycenter+4); p->drawPoint(xcenter-5+3, ycenter+5); p->drawPoint(xcenter+5-3, ycenter+5); p->drawPoint(xcenter-5+4, ycenter+6); p->drawPoint(xcenter+5-4, ycenter+6); p->drawPoint(xcenter, ycenter+7); // anti-aliasing of the contour... sort of. :) p->setPen(alphaBlendColors(cg.background(), contour, 80) ); p->drawPoint(xcenter, ycenter+8); p->setPen(alphaBlendColors(cg.background(), contour, 150) ); p->drawPoint(xcenter-5, ycenter+4); p->drawPoint(xcenter+5, ycenter+4); p->drawPoint(xcenter-5+1, ycenter+5); p->drawPoint(xcenter+5-1, ycenter+5); p->drawPoint(xcenter-5+2, ycenter+6); p->drawPoint(xcenter+5-2, ycenter+6); p->drawPoint(xcenter-5+3, ycenter+7); p->drawPoint(xcenter+5-3, ycenter+7); p->setPen(alphaBlendColors(cg.background(), contour, 190) ); p->drawPoint(xcenter-5+4, ycenter+8); p->drawPoint(xcenter+5-4, ycenter+8); QRegion mask(xcenter-4, ycenter-5, 9, 13); mask -= QRegion(xcenter-4, ycenter+4, 2, 4); mask -= QRegion(xcenter-3, ycenter+5, 2, 3); mask -= QRegion(xcenter-2, ycenter+6, 2, 2); mask -= QRegion(xcenter-1, ycenter+7, 2, 1); mask -= QRegion(xcenter+1, ycenter+7, 1, 1); mask -= QRegion(xcenter+1, ycenter+6, 2, 2); mask -= QRegion(xcenter+2, ycenter+5, 2, 3); mask -= QRegion(xcenter+3, ycenter+4, 2, 4); p->setClipRegion(mask); uint surfaceFlags = Draw_Left|Draw_Right|Draw_Top|Round_UpperLeft|Round_UpperRight|Is_Horizontal; if(!enabled) surfaceFlags |= Is_Disabled; renderSurface(p, QRect(xcenter-4, ycenter-5, 9, 13), cg.background(), surface, getColor(cg,MouseOverHighlight), _contrast+3, surfaceFlags); renderDot(p, QPoint(xcenter-3, ycenter-3), surface, false, true ); renderDot(p, QPoint(xcenter+2, ycenter-3), surface, false, true ); p->setClipping(false); } else { renderContour(p, QRect(xcenter-6, ycenter-5, 10, 11), cg.background(), contour, Draw_Left|Draw_Top|Draw_Bottom|Round_UpperLeft|Round_BottomLeft); // manual contour: vertex p->setPen(alphaBlendColors(cg.background(), contour, 50) ); p->drawPoint(xcenter+4, ycenter-5+1); p->drawPoint(xcenter+4, ycenter+5-1); p->drawPoint(xcenter+5, ycenter-5+2); p->drawPoint(xcenter+5, ycenter+5-2); p->drawPoint(xcenter+6, ycenter-5+3); p->drawPoint(xcenter+6, ycenter+5-3); p->drawPoint(xcenter+7, ycenter-5+4); p->drawPoint(xcenter+7, ycenter+5-4); // 3d effect of vertex if( enabled && _coloredScrollBar ) { if( _lightBorder ) p->setPen( cg.highlight().light(110+_contrast*2) ); else p->setPen( cg.highlight().dark(110+_contrast*2) ); } else { if( _lightBorder ) p->setPen( cg.background().light(110+_contrast*2) ); else p->setPen( cg.background().dark(110+_contrast*2) ); } p->drawPoint(xcenter+4, ycenter-5+2); p->drawPoint(xcenter+4, ycenter+5-2); p->drawPoint(xcenter+5, ycenter-5+3); p->drawPoint(xcenter+5, ycenter+5-3); p->drawPoint(xcenter+6, ycenter-5+4); p->drawPoint(xcenter+6, ycenter+5-4); p->drawPoint(xcenter+7, ycenter); // anti-aliasing. ...sort of :) p->setPen(alphaBlendColors(cg.background(), contour, 80) ); p->drawPoint(xcenter+8, ycenter); p->setPen(alphaBlendColors(cg.background(), contour, 150) ); p->drawPoint(xcenter+4, ycenter-5); p->drawPoint(xcenter+4, ycenter+5); p->drawPoint(xcenter+5, ycenter-5+1); p->drawPoint(xcenter+5, ycenter+5-1); p->drawPoint(xcenter+6, ycenter-5+2); p->drawPoint(xcenter+6, ycenter+5-2); p->drawPoint(xcenter+7, ycenter-5+3); p->drawPoint(xcenter+7, ycenter+5-3); p->setPen(alphaBlendColors(cg.background(), contour, 190) ); p->drawPoint(xcenter+8, ycenter-5+4); p->drawPoint(xcenter+8, ycenter+5-4); QRegion mask(xcenter-5, ycenter-4, 13, 9); mask -= QRegion(xcenter+4, ycenter-4, 4, 1); mask -= QRegion(xcenter+4, ycenter-3, 4, 1); mask -= QRegion(xcenter+5, ycenter-2, 3, 1); mask -= QRegion(xcenter+6, ycenter-1, 2, 1); mask -= QRegion(xcenter+7, ycenter, 2, 1); mask -= QRegion(xcenter+6, ycenter+1, 2, 1); mask -= QRegion(xcenter+5, ycenter+2, 3, 1); mask -= QRegion(xcenter+4, ycenter+3, 4, 1); mask -= QRegion(xcenter+4, ycenter+4, 4, 1); p->setClipRegion(mask); uint surfaceFlags = Draw_Left|Draw_Top|Draw_Bottom|Round_UpperLeft|Round_BottomLeft| Round_UpperRight|Is_Horizontal; if(!enabled) surfaceFlags |= Is_Disabled; renderSurface(p, QRect(xcenter-5, ycenter-4, 13, 9), cg.background(), surface, getColor(cg,MouseOverHighlight), _contrast+3, surfaceFlags); renderDot(p, QPoint(xcenter-3, ycenter-3), surface, false, true ); renderDot(p, QPoint(xcenter-3, ycenter+2), surface, false, true ); p->setClipping(false); } break; } case KPE_ListViewExpander: { int radius = (r.width() - 4) / 2; int centerx = r.x() + r.width()/2; int centery = r.y() + r.height()/2; renderContour(p, r, cg.base(), cg.dark(), Draw_Left|Draw_Right|Draw_Top|Draw_Bottom|Round_UpperLeft|Round_UpperRight|Round_BottomLeft|Round_BottomRight ); p->setPen( cg.text() ); if(!_drawTriangularExpander) { // plus or minus p->drawLine( centerx - radius, centery, centerx + radius, centery ); if ( flags & Style_On ) // Collapsed = On p->drawLine( centerx, centery - radius, centerx, centery + radius ); } else if(_drawTriangularExpander) { if( flags & Style_On ) drawPrimitive(PE_ArrowRight, p, QRect(r.x()+1,r.y()+1,r.width(),r.height()), cg,ButtonContour, flags); if( flags & Style_Off ) drawPrimitive(PE_ArrowDown, p, QRect(r.x()+1,r.y()+1,r.width(),r.height()), cg,ButtonContour, flags); } break; } // copied and slightly modified from KStyle. case KPE_ListViewBranch: { // Typical Windows style listview branch element (dotted line). // Create the dotline pixmaps if not already created if ( !verticalLine ) { // make 128*1 and 1*128 bitmaps that can be used for // drawing the right sort of lines. verticalLine = new QBitmap( 1, 129, true ); horizontalLine = new QBitmap( 128, 1, true ); QPointArray a( 64 ); QPainter p2; p2.begin( verticalLine ); int i; for( i=0; i < 64; i++ ) a.setPoint( i, 0, i*2+1 ); p2.setPen( color1 ); p2.drawPoints( a ); p2.end(); QApplication::flushX(); verticalLine->setMask( *verticalLine ); p2.begin( horizontalLine ); for( i=0; i < 64; i++ ) a.setPoint( i, i*2+1, 0 ); p2.setPen( color1 ); p2.drawPoints( a ); p2.end(); QApplication::flushX(); horizontalLine->setMask( *horizontalLine ); } p->setPen( cg.mid() ); if (flags & Style_Horizontal) { int point = r.x(); int other = r.y(); int end = r.x()+r.width(); int thickness = r.height(); while( point < end ) { int i = 128; if ( i+point > end ) i = end-point; p->drawPixmap( point, other, *horizontalLine, 0, 0, i, thickness ); point += i; } } else { int point = r.y(); int other = r.x(); int end = r.y()+r.height(); int thickness = r.width(); int pixmapoffset = (flags & Style_NoChange) ? 0 : 1; // ### Hackish while( point < end ) { int i = 128; if ( i+point > end ) i = end-point; p->drawPixmap( other, point, *verticalLine, 0, pixmapoffset, thickness, i ); point += i; } } break; } default: KStyle::drawKStylePrimitive(kpe, p, widget, r, cg, flags, opt); } } void PolyesterStyle::drawPrimitive(PrimitiveElement pe, QPainter *p, const QRect &r, const QColorGroup &cg, SFlags flags, const QStyleOption &opt ) const { bool down = flags & Style_Down; bool on = flags & Style_On; bool sunken = flags & Style_Sunken; bool horiz = flags & Style_Horizontal; const bool enabled = flags & Style_Enabled; const bool mouseOver = flags & Style_MouseOver; bool hasFocus = flags & Style_HasFocus; int x = r.x(); int y = r.y(); int w = r.width(); int h = r.height(); int x2, y2; r.coords(&x, &y, &x2, &y2); switch(pe) { // BUTTONS // ------- case PE_FocusRect: { if(_drawFocusRect) //FIXME: it's necessary to be configurable? naaah :) { //Figuring out in what beast we are painting... QWidget *widget = dynamic_cast( p->device() ); //rendercontour isn't able to draw with negative measures //rounded border in a listview/listbox is ugly //also if the background and the border color are equal the result is ugly //also no rouded border when there is no parent widget if( r.width() < 0 || r.height() < 0 || (widget && !widget->parentWidget()) || (widget && (dynamic_cast( widget->parent() ) || dynamic_cast( widget->parent())) ) || cg.background() == getColor(cg, ButtonContour) ) { p->setPen( getColor(cg, ButtonContour) ); p->drawRect( r ); break; } QColor backgroundColor; if( widget ) backgroundColor = widget->paletteBackgroundColor(); else backgroundColor = cg.background(); renderContour(p, r, backgroundColor, getColor(cg,ButtonContour), Draw_Left| Draw_Right|Draw_Top|Draw_Bottom| Round_UpperLeft|Round_UpperRight| Round_BottomLeft|Round_BottomRight|Draw_AlphaBlend ); } break; } case PE_HeaderSection: { // the taskbar buttons seems to be painted with PE_HeaderSection but I // want them look like normal buttons (at least for now. :) ) if(!kickerMode) { // detect if this is the first/last header item bool isFirst = false; bool isLast = false; // header item id int headerId = -1; //is the section sorted? bool sortedSection = false; //orientation Qt::Orientation orientation = Qt::Horizontal; QHeader *header = dynamic_cast(p->device() ); QListView *list = NULL; if (header) { list = dynamic_cast(header->parent()); int headerPos = (header->orientation()==Qt::Horizontal?r.x():r.y()); headerId = header->sectionAt( headerPos + header->offset()); isFirst = header->mapToIndex(header->sectionAt(headerPos ) + header->offset()) == 0; isLast = header->mapToIndex(header->sectionAt(headerPos ) + header->offset()) == header->count()-1; sortedSection = _colorizeSortedHeader&&(header->sortIndicatorSection() == headerId); orientation = header->orientation(); } //Passes always sharp, when Round is on sharp is ignored //so this doesn't cause damage uint contourFlags = Draw_Right|Draw_Bottom| Sharp_BottomLeft|Sharp_BottomRight| Sharp_UpperLeft|Sharp_UpperRight; if(!enabled) contourFlags|=Is_Disabled; //if horizontal draw always the top contour, else always the left one if( orientation == Qt::Horizontal ) contourFlags |= Draw_Top; else contourFlags |= Draw_Left; //round first header contour and draw the border that usually is not drawn if( isFirst && orientation == Qt::Horizontal ) contourFlags |= Draw_Left|Round_UpperLeft; if( isFirst && orientation == Qt::Vertical ) contourFlags |= Draw_Top|Round_UpperLeft; //round last header contour //if it's horizontal and we are in a QListView, round only if resizemode !=NoColumn if( isLast && orientation == Qt::Horizontal /*&& (( list && list->resizeMode() != QListView::NoColumn) || !list)*/ ) contourFlags |= Round_UpperRight; if( isLast && orientation == Qt::Vertical ) contourFlags |= Round_BottomLeft; /* The function renderContour(p, r, cg.background(), getColor(cg,ButtonContour), contourFlags); is called after rendersurface */ uint surfaceFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom|Is_Horizontal; if(!enabled) surfaceFlags|=Is_Disabled; else { if(isFirst) surfaceFlags |= Round_UpperLeft; if(isLast) surfaceFlags |= Round_UpperRight; if( !list || (list && list->sortColumn() != -1) ) { if(on||down) surfaceFlags|=Is_Sunken; else { if( (hoverWidget == p->device()) && headerId == hoverHeaderId ) { /*remedy to a Qt bug that triggers only on horizontal headers*/ if( (header && header->orientation()==Qt::Vertical) || (header && (header->sectionPos(headerId) + header->sectionSize(headerId) - header->offset() > r.x())) ) surfaceFlags|=Is_Highlight|Highlight_Top; } } } } renderSurface(p, QRect(isFirst?r.left()+1:r.left(), r.top()+1, isFirst?r.width()-2:r.width()-1, r.height()-2), cg.background(), sortedSection?alphaBlendColors(cg.highlight(), cg.button(), 70):cg.button(), getColor(cg,MouseOverHighlight), _contrast, surfaceFlags); renderContour(p, r, cg.background(), getColor(cg,ButtonContour), contourFlags); break; } } case PE_ButtonBevel: case PE_ButtonTool: case PE_ButtonDropDown: case PE_ButtonCommand: { bool khtmlMode = khtmlWidgets.contains(opt.widget()); int animFrame = 0; if( _animateButton && animWidgets.contains(opt.widget()) ) animFrame = (int)animWidgets[opt.widget()].animFrame; renderButton(p, r, cg, (on||down), mouseOver, true, enabled, khtmlMode, animFrame, flags & Style_ButtonDefault ); break; } case PE_ButtonDefault: { uint contourFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom| Round_UpperLeft|Round_UpperRight|Round_BottomLeft|Round_BottomRight; if(!enabled) contourFlags|=Is_Disabled; renderContour(p, r, cg.background(), cg.background().dark(120), contourFlags); break; } case PE_SpinWidgetPlus: case PE_SpinWidgetMinus: { p->setPen( cg.buttonText() ); int l = QMIN( w-2, h-2 ); // make the length even so that we get a nice symmetric plus... if(l%2 != 0) --l; QPoint c = r.center(); p->drawLine( c.x()-l/2, c.y(), c.x()+l/2, c.y() ); if ( pe == PE_SpinWidgetPlus ) { p->drawLine( c.x(), c.y()-l/2, c.x(), c.y()+l/2 ); } break; } case PE_ScrollBarSlider: { /*a little bit complicated: deciding if the scrollbar is enabled, pressed, with mouse over or not. Everything with the right dependencies*/ const WidgetState s = enabled?(down?IsPressed: ((hoverWidget == p->device())? IsHighlighted:IsEnabled)):IsDisabled; const QColor surface = getColor(cg, DragButtonSurface, s); uint contourFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom|Sharp_UpperLeft|Sharp_UpperRight|Sharp_BottomLeft|Sharp_BottomRight; if(!enabled) contourFlags|=Is_Disabled; uint surfaceFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom; if( !_coloredScrollBar && hoverWidget == p->device() ) { if( !horiz ) surfaceFlags |= Highlight_Top|Highlight_Bottom; else surfaceFlags |= Highlight_Left|Highlight_Right; } renderContour(p, r, cg.background(), getColor(cg, DragButtonContour, s), contourFlags); if(horiz) surfaceFlags|=Is_Horizontal; if(!enabled) surfaceFlags|=Is_Disabled; if(down) surfaceFlags|= Is_Sunken; if(r.height() >= 4) { renderSurface(p, QRect(r.left()+1, r.top()+1, r.width()-2, r.height()-2), cg.background(), surface, cg.highlight(), _contrast+3, surfaceFlags); } const int xPos = r.center().x(); const int yPos = r.center().y(); const int displacement = 5; if( !horiz && r.height() > 24) { for( int i = -displacement; i <= displacement; i+=displacement) { if(_scrollBarLines) { p->setPen(alphaBlendColors(cg.background(), surface.dark(enabled?140:120), 50) ); p->drawLine(r.x()+1, yPos+i, r.right()-1, yPos+i); p->setPen(alphaBlendColors(cg.background(), surface.light(enabled?120:110), 50) ); p->drawLine(r.x()+1, yPos+i+1, r.right()-1, yPos+i+1); } else { renderDot(p, QPoint(xPos-3, yPos+i), surface, true, true ); renderDot(p, QPoint(xPos+2, yPos+i), surface, true, true ); } } } else if( r.width() > 24 ) { for( int i = -displacement; i <= displacement; i+=displacement) { if(_scrollBarLines) { p->setPen(alphaBlendColors(cg.background(), surface.dark(enabled?140:120), 50) ); p->drawLine(xPos+i, r.y()+1, xPos+i, r.bottom()-1); p->setPen(alphaBlendColors(cg.background(), surface.light(enabled?120:110), 50) ); p->drawLine(xPos+i+1, r.y()+1, xPos+i+1, r.bottom()-1); } else { renderDot(p, QPoint(xPos+i, yPos-3), surface, true, true ); renderDot(p, QPoint(xPos+i, yPos+2), surface, true, true ); } } } break; } case PE_ScrollBarAddPage: case PE_ScrollBarSubPage: { if (on || down) { p->fillRect(r, QBrush(cg.mid().dark())); } else { if(flags & Style_Horizontal) { uint contourFlags = Draw_Top|Draw_Bottom; uint surfaceFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom|Is_Sunken|Is_Horizontal; //coordinates for the surface uint xs=x,ws=w; if( pe == PE_ScrollBarSubPage && ( _scrollBarType == KStyle::PlatinumStyleScrollBar ) ) { contourFlags |= Draw_Left|Round_UpperLeft|Round_BottomLeft; surfaceFlags |= Round_UpperLeft|Round_BottomLeft; xs++; ws--; } else if( pe == PE_ScrollBarAddPage && ( _scrollBarType == KStyle::NextStyleScrollBar ) ) { contourFlags |= Draw_Right|Round_UpperRight|Round_BottomRight; surfaceFlags |= Round_UpperRight|Round_BottomRight; ws--; } renderContour(p, r, cg.background(), getColor(cg, ButtonContour), contourFlags); QRect gradientRect( xs,y+1,ws,h/2 ); renderGradient( p, gradientRect, cg.background().dark(100+_contrast), cg.background().light(100+_contrast)); p->fillRect( QRect(xs,gradientRect.bottom()+1,ws,h-2-gradientRect.height()), cg.background().light(100+_contrast) ); } else { uint contourFlags = Draw_Left|Draw_Right; uint surfaceFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom|Is_Sunken; //coordinates for the surface uint ys=y,hs=h; if( pe == PE_ScrollBarSubPage && ( _scrollBarType == KStyle::PlatinumStyleScrollBar ) ) { contourFlags |= Draw_Top|Round_UpperLeft|Round_UpperRight; surfaceFlags |= Round_UpperLeft|Round_UpperRight; ys++; hs--; } else if( pe == PE_ScrollBarAddPage && ( _scrollBarType == KStyle::NextStyleScrollBar ) ) { contourFlags |= Draw_Bottom|Round_BottomLeft|Round_BottomRight; surfaceFlags |= Round_BottomLeft|Round_BottomRight; hs--; } renderContour(p, r, cg.background(), getColor(cg, ButtonContour), contourFlags); QRect gradientRect( x+1,ys,w/2,hs ); renderGradient( p, gradientRect, cg.background().dark(100+_contrast), cg.background().light(100+_contrast), false); p->fillRect( QRect(gradientRect.right()+1, ys, w-2-gradientRect.width(), hs), cg.background().light(100+_contrast) ); } } break; } // SCROLLBAR BUTTONS // ----------------- case PE_ScrollBarSubLine: { uint contourFlags = Draw_Left| (r.x()==0||down?Draw_Right:0)| Draw_Top| (r.y()==0||down?Draw_Bottom:0); uint surfaceFlags = Draw_Left|Draw_Top|Draw_Right|Draw_Bottom; if(down) surfaceFlags|=Is_Sunken; if(!enabled) { contourFlags|=Is_Disabled; surfaceFlags|=Is_Disabled; } if(horiz) { if(r.x()==0) { contourFlags |= Round_UpperLeft|Round_BottomLeft|Is_Horizontal; surfaceFlags |= Round_UpperLeft|Round_BottomLeft|Is_Horizontal; } else { contourFlags |= Is_Horizontal; surfaceFlags |= Is_Horizontal; } } else { if(r.y()==0) { contourFlags |= Round_UpperLeft|Round_UpperRight; surfaceFlags |= Round_UpperLeft|Round_UpperRight; } } /* if(!down && !horiz && r.y() != 0) { p->setPen(cg.background().light(120)); p->drawLine(r.left(), r.bottom(), r.right(), r.bottom()); }*/ //render two dots at bottom/right corners p->setPen(getColor(cg, ButtonContour).light(120)); if( horiz ) { contourFlags |= Sharp_UpperRight|Sharp_BottomRight; if( r.x() != 0 ) contourFlags |= Sharp_UpperLeft|Sharp_BottomRight; } else { contourFlags |= Sharp_BottomLeft|Sharp_BottomRight; if( r.y() != 0 ) contourFlags |= Sharp_UpperLeft|Sharp_UpperRight; } renderContour(p, r, cg.background(), getColor(cg, ButtonContour), contourFlags); renderSurface(p, QRect(r.left()+1, r.top()+1, r.width()-(r.x()==0?2:1), r.height()-(r.y()==0?2:1)), cg.background(), cg.button(), getColor(cg,MouseOverHighlight), _contrast+3, surfaceFlags); p->setPen(cg.foreground()); drawPrimitive((horiz ? PE_ArrowLeft : PE_ArrowUp), p, r, cg, flags); break; } case PE_ScrollBarAddLine: { uint isNext = _scrollBarType == KStyle::NextStyleScrollBar; uint contourFlags = (!isNext||!horiz||down?Draw_Left:0)| Draw_Right| (!isNext||horiz||down?Draw_Top:0)| Draw_Bottom; uint surfaceFlags = contourFlags; if(down) surfaceFlags|=Is_Sunken; if(!enabled) { contourFlags|=Is_Disabled; surfaceFlags|=Is_Disabled; } if( horiz && !isNext) { contourFlags |= Round_UpperRight|Round_BottomRight|Is_Horizontal; surfaceFlags |= Round_UpperRight|Round_BottomRight|Is_Horizontal; } else if( !isNext ){ contourFlags |= Round_BottomLeft|Round_BottomRight; surfaceFlags |= Round_BottomLeft|Round_BottomRight; } else if( horiz && isNext){ contourFlags |= Is_Horizontal; surfaceFlags |= Is_Horizontal; } //render two dots at top/left corners p->setPen(getColor(cg, ButtonContour).light(120)); if( horiz ) { contourFlags |= Sharp_UpperLeft|Sharp_BottomLeft; if( _scrollBarType == KStyle::NextStyleScrollBar ) contourFlags |= Sharp_UpperRight|Sharp_BottomRight; } else { contourFlags |= Sharp_UpperLeft|Sharp_UpperRight; if( _scrollBarType == KStyle::NextStyleScrollBar ) contourFlags |= Sharp_BottomLeft|Sharp_BottomRight; } renderContour(p, r, cg.background(), getColor(cg, ButtonContour), contourFlags); renderSurface(p, QRect(r.left()+(!isNext||!horiz?1:0), r.top()+(!isNext||horiz?1:0), r.width()-(isNext&&horiz?1:2), r.height()-(isNext&&!horiz?1:2)), cg.background(), cg.button(), getColor(cg,MouseOverHighlight), _contrast+3, surfaceFlags); p->setPen(cg.foreground()); drawPrimitive((horiz ? PE_ArrowRight : PE_ArrowDown), p, r, cg, flags); break; } // CHECKBOXES // ---------- case PE_Indicator: { QColor contentColor = enabled?cg.base():cg.background(); uint contourFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom; if(!enabled) { contourFlags |= Is_Disabled; } renderContour(p, r, cg.background(), getColor(cg, ButtonContour), contourFlags); // surface uint surfaceFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom|Is_Horizontal; if(!enabled) { surfaceFlags |= Is_Disabled; } else if(mouseOver) { contentColor = alphaBlendColors(contentColor, getColor(cg,MouseOverHighlight), 240); surfaceFlags |= Is_Highlight; surfaceFlags |= Highlight_Left|Highlight_Right| Highlight_Top|Highlight_Bottom; } renderSurface(p, QRect(r.x()+1, r.y()+1, r.width()-2, r.height()-2), cg.background(), contentColor, getColor(cg,MouseOverHighlight), enabled?_contrast+3:(_contrast/2), surfaceFlags); drawPrimitive(PE_CheckMark, p, r, cg, flags); break; } case PE_IndicatorMask: { p->fillRect (r, color1); break; } // RADIOBUTTONS // ------------ case PE_ExclusiveIndicator: { const QColor contourColor = getColor(cg, ButtonContour, enabled); QColor contentColor = enabled?cg.base():cg.background(); QBitmap bmp; bmp = QBitmap(13, 13, radiobutton_mask_bits, true); // first the surface... uint surfaceFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom|Is_Horizontal; if(!enabled) { surfaceFlags |= Is_Disabled; } else if (mouseOver) { contentColor = alphaBlendColors(contentColor, getColor(cg,MouseOverHighlight), 240); } p->setClipRegion(bmp); renderSurface(p, r, cg.background(), contentColor, getColor(cg,MouseOverHighlight), enabled?_contrast+3:(_contrast/2), surfaceFlags); p->setClipping(false); // ...then contour, anti-alias, mouseOver... // contour bmp = QBitmap(13, 13, radiobutton_contour_bits, true); bmp.setMask(bmp); p->setPen(alphaBlendColors(cg.background(), contourColor, 50) ); p->drawPixmap(x, y, bmp); // anti-alias outside bmp = QBitmap(13, 13, radiobutton_aa_outside_bits, true); bmp.setMask(bmp); p->setPen(alphaBlendColors(cg.background(), contourColor, 150) ); p->drawPixmap(x, y, bmp); // highlighting... if(mouseOver) { bmp = QBitmap(13, 13, radiobutton_highlight1_bits, true); bmp.setMask(bmp); p->setPen(alphaBlendColors(contentColor, getColor(cg,MouseOverHighlight), 80) ); p->drawPixmap(x, y, bmp); bmp = QBitmap(13, 13, radiobutton_highlight2_bits, true); bmp.setMask(bmp); p->setPen(alphaBlendColors(contentColor, getColor(cg,MouseOverHighlight), 150) ); p->drawPixmap(x, y, bmp); } // anti-alias inside, "above" the higlighting! bmp = QBitmap(13, 13, radiobutton_aa_inside_bits, true); bmp.setMask(bmp); if(mouseOver) { p->setPen(alphaBlendColors(getColor(cg,MouseOverHighlight), contourColor, 180) ); } else { p->setPen(alphaBlendColors(contentColor, contourColor, 180) ); } p->drawPixmap(x, y, bmp); break; } case PE_ExclusiveIndicatorMask: { p->fillRect(r, color0); QBitmap bmp; bmp = QBitmap(13, 13, radiobutton_mask_bits, true); bmp.setMask(bmp); p->setPen(color1); p->drawPixmap(x, y, bmp); break; } // GENERAL PANELS // -------------- case PE_Splitter: { // highlight on mouse over QColor color = (hoverWidget == p->device())?cg.background().light(100+_contrast):cg.background(); p->fillRect(r, color); if (w > h) { if (h > 4) { int ycenter = r.height()/2; for(int k = r.width()/2-12; k <= r.width()/2+12; k+=6) { renderDot(p, QPoint(k, ycenter-1), color, true, true); } } } else { if (w > 4) { int xcenter = r.width()/2; for(int k = r.height()/2-12; k <= r.height()/2+12; k+=6){ renderDot(p, QPoint(xcenter-1, k), color, true, true); } } } break; } case PE_PanelGroupBox: case PE_GroupBoxFrame: { if ( opt.isDefault() || opt.lineWidth() <= 0 ) break; renderPanel(p, r, cg, false); break; } case PE_WindowFrame: case PE_Panel: { if ( opt.isDefault() || opt.lineWidth() <= 0 ) break; renderPanel(p, r, cg, true, sunken); break; } case PE_PanelLineEdit: { bool isReadOnly = false; bool isEnabled = true; // panel is highlighted by default if it has focus, but if we have access to the // widget itself we can try to avoid highlighting in case it's readOnly or disabled. if (p->device() && dynamic_cast(p->device())) { QLineEdit* lineEdit = dynamic_cast(p->device()); isReadOnly = lineEdit->isReadOnly(); isEnabled = lineEdit->isEnabled(); } uint contourFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom| Round_UpperLeft|Round_UpperRight|Round_BottomLeft|Round_BottomRight; // HACK!! // // In order to draw nice edges in khtml, we need to paint alpha-blended. // On the other hand, we can't paint alpha-blended in normal widgets. // // In this place there is no reliable way to detect if we are in khtml; the // only thing we know is that khtml buffers its widgets into a pixmap. So // when the paint device is a QPixmap, chances are high that we are in khtml. // It's possible that this breaks other things, so let's see how it works... if (p->device() && dynamic_cast(p->device() ) ) { contourFlags += Draw_AlphaBlend; } if ( _inputFocusHighlight && hasFocus && !isReadOnly && isEnabled) { renderContour(p, r, cg.background(), getColor(cg,FocusHighlight,enabled), contourFlags ); } else { renderContour(p, r, cg.background(), getColor(cg, ButtonContour, enabled), contourFlags ); } const QColor contentColor = enabled?cg.base():cg.background(); if (_inputFocusHighlight && hasFocus && !isReadOnly && isEnabled) { p->setPen( getColor(cg,FocusHighlight).dark(130) ); } else { // deciding if the 3d effect should be done or not p->setPen(contentColor.dark(100+(_lightBorder?-30:30)) ); } p->drawLine(r.left()+1, r.top()+2, r.left()+1, r.bottom()-2 ); p->drawLine(r.left()+2, r.top()+1, r.right()-2, r.top()+1 ); if (_inputFocusHighlight && hasFocus && !isReadOnly && isEnabled) { p->setPen( getColor(cg,FocusHighlight).light(130) ); } else { p->setPen(contentColor.light(130) ); } p->drawLine(r.left()+2, r.bottom()-1, r.right()-2, r.bottom()-1 ); p->drawLine(r.right()-1, r.top()+2, r.right()-1, r.bottom()-2 ); break; } case PE_StatusBarSection: { if(_statusBarFrame) { renderContour(p, r, cg.background(), cg.background().dark(160), Draw_Left|Draw_Right|Draw_Top|Draw_Bottom); } break; } //case PE_TabBarBase: // Still not sure what this one does case PE_PanelTabWidget: { renderPanel(p, r, cg, true, sunken); break; } case PE_PanelPopup: { /*TODO: is there a way tho check if we are a menubar popup or a normal popup? so in the menubar popup (QApplication::reverseLayout()?Sharp_UpperRight:Sharp_UpperLeft)| could be added */ renderContour(p, r, cg.background(), cg.background().dark(200), Draw_Left|Draw_Right|Draw_Top|Draw_Bottom|Draw_AlphaBlend); break; } // MENU / TOOLBAR PANEL // -------------------- case PE_PanelMenuBar: case PE_PanelDockWindow: { // fix for toolbar lag (from Mosfet Liquid) QWidget* w = dynamic_cast(p->device()); if(w && w->backgroundMode() == PaletteButton) w->setBackgroundMode(PaletteBackground); p->fillRect(r, cg.brush(QColorGroup::Background)); if ( _drawToolBarSeparator && //don't draw the separator under the menubars if the emphasys with border is on !( pe==PE_PanelMenuBar && _menuBarEmphasis && _menuBarEmphasisBorder ) ) { if ( r.width() > r.height() ) { // avoid drawing a double light line if(!_lightBorder) { p->setPen( getColor(cg, PanelLight) ); p->drawLine( r.left(), r.top(), r.right(), r.top() ); p->setPen( getColor(cg, PanelDark) ); p->drawLine( r.left(), r.bottom(), r.right(), r.bottom() ); } else { p->setPen( cg.background().dark(100+_contrast*4) ); p->drawLine( r.left(), r.bottom(), r.right(), r.bottom() ); } } else { if(!_lightBorder) { p->setPen( getColor(cg, PanelLight) ); p->drawLine( r.left(), r.top(), r.left(), r.bottom() ); p->setPen( getColor(cg, PanelDark) ); p->drawLine( r.right(), r.top(), r.right(), r.bottom() ); } else { p->setPen( cg.background().dark(100+_contrast*4) ); p->drawLine( r.left(), r.top(), r.left(), r.bottom() ); } } } break; } // TOOLBAR/DOCK WINDOW HANDLE // -------------------------- case PE_DockWindowResizeHandle: { renderButton(p, r, cg); break; } case PE_DockWindowHandle: { int counter = 1; int hCenter = r.left()+r.width()/2; int vCenter = r.top()+r.bottom()/2; /*handles littler, nicer*/ if(horiz) { for(int j = vCenter-6; j <= vCenter+6; j+=6) { renderDot(p, QPoint(hCenter, j), cg.background(), true, true); counter++; } } else { for(int j = hCenter-12; j <= hCenter+12; j+=6) { renderDot(p, QPoint(j, vCenter), cg.background(), true, true); counter++; } } break; } // TOOLBAR SEPARATOR // ----------------- case PE_DockWindowSeparator: { p->fillRect(r, cg.background()); if(_drawToolBarItemSeparator) { if(horiz) { int center = r.left()+r.width()/2; if(!_lightBorder) { p->setPen( getColor(cg, PanelDark) ); p->drawLine( center-1, r.top()+3, center-1, r.bottom()-3 ); p->setPen( getColor(cg, PanelLight) ); p->drawLine( center, r.top()+3, center, r.bottom()-3 ); } else { p->setPen( cg.background().dark(100+_contrast*4) ); p->drawLine( center, r.top()+3, center, r.bottom()-3 ); } } else { int center = r.top()+r.height()/2; if(!_lightBorder) { p->setPen( getColor(cg, PanelDark) ); p->drawLine( r.x()+3, center-1, r.right()-3, center-1 ); p->setPen( getColor(cg, PanelLight) ); p->drawLine( r.x()+3, center, r.right()-3, center ); } else { p->setPen( cg.background().dark(100+_contrast*4) ); p->drawLine( r.x()+3, center, r.right()-3, center ); } } } break; } case PE_CheckMark: { const QColor contentColor = enabled?cg.base():cg.background(); QColor checkmarkColor = enabled?getColor(cg,CheckMark):cg.background(); if(flags & Style_Down) { checkmarkColor = alphaBlendColors(contentColor, checkmarkColor, 150); } int x = r.center().x() - 4, y = r.center().y() - 4; QBitmap bmp; if( flags & Style_On ) { bmp = QBitmap(CHECKMARKSIZE, CHECKMARKSIZE, checkmark_dark_bits, true); bmp.setMask(bmp); p->setPen(alphaBlendColors(contentColor, checkmarkColor.dark(150), 50) ); p->drawPixmap(x, y, bmp); bmp = QBitmap(CHECKMARKSIZE, CHECKMARKSIZE, checkmark_light_bits, true); bmp.setMask(bmp); p->setPen(alphaBlendColors(contentColor, checkmarkColor.dark(125), 50) ); p->drawPixmap(x, y, bmp); bmp = QBitmap(CHECKMARKSIZE, CHECKMARKSIZE, checkmark_aa_bits, true); bmp.setMask(bmp); p->setPen(alphaBlendColors(contentColor, checkmarkColor.dark(150), 150) ); p->drawPixmap(x, y, bmp); } else if ( flags & Style_Off ) { // empty } else { // tristate bmp = QBitmap(CHECKMARKSIZE, CHECKMARKSIZE, checkmark_tristate_bits, true); bmp.setMask(bmp); p->setPen(alphaBlendColors(contentColor, checkmarkColor.dark(150), 50) ); p->drawPixmap(x, y, bmp); } break; } case PE_SpinWidgetUp: case PE_SpinWidgetDown: case PE_HeaderArrow: case PE_ArrowUp: case PE_ArrowDown: case PE_ArrowLeft: case PE_ArrowRight: { QPointArray a; switch (pe) { case PE_SpinWidgetUp: case PE_ArrowUp: { a.setPoints(7, u_arrow); break; } case PE_SpinWidgetDown: case PE_ArrowDown: { a.setPoints(7, d_arrow); break; } case PE_ArrowLeft: { a.setPoints(7, l_arrow); break; } case PE_ArrowRight: { a.setPoints(7, r_arrow); break; } default: { if (flags & Style_Up) { a.setPoints(7, u_arrow); } else { a.setPoints(7, d_arrow); } } } const QWMatrix oldMatrix( p->worldMatrix() ); if (flags & Style_Down) { p->translate(pixelMetric(PM_ButtonShiftHorizontal), pixelMetric(PM_ButtonShiftVertical)); } int x = r.x(); //move PE_HeaderArrow toghether the headerlabel /*HACK: brutally move the header arrow; maybe in the future a more clean solution will be possible*/ if( pe == PE_HeaderArrow && !QApplication::reverseLayout()) { QHeader *header = dynamic_cast(p->device() ); if (header && header->orientation()==Qt::Horizontal) { int section = header->sectionAt(x + header->offset()); x = header->sectionSize(section) + header->sectionPos(section) - header->offset() - 16; } } a.translate((x+r.width()/2), (r.y()+r.height()/2)); // extra-pixel-shift, correcting some visual tics... switch(pe) { case PE_ArrowLeft: case PE_ArrowRight: a.translate(0, -1); break; case PE_SpinWidgetUp: case PE_SpinWidgetDown: a.translate(+1, 0); break; default: a.translate(0, 0); } if (p->pen() == QPen::NoPen) { if (flags & Style_Enabled) { p->setPen(cg.buttonText()); } else { p->setPen(cg.highlightedText()); } } p->drawLineSegments(a, 0, 3); p->drawPoint(a[6]); p->setWorldMatrix( oldMatrix ); break; } default: { return KStyle::drawPrimitive(pe, p, r, cg, flags, opt); } } } void PolyesterStyle::drawControl(ControlElement element, QPainter *p, const QWidget *widget, const QRect &r, const QColorGroup &cg, SFlags flags, const QStyleOption& opt) const { const bool reverseLayout = QApplication::reverseLayout(); const bool enabled = (flags & Style_Enabled); switch (element) { // PROGRESSBAR // ----------- case CE_ProgressBarGroove: { const QColor content = enabled?cg.base():cg.background(); renderContour(p, r, cg.background(), getColor(cg, ButtonContour, enabled) ); p->setPen(content.dark(105) ); p->drawLine(r.left()+2, r.top()+1, r.right()-2, r.top()+1 ); p->drawLine(r.left()+1, r.top()+2, r.left()+1, r.bottom()-2); p->setPen(content.light(105) ); p->drawLine(r.left()+2, r.bottom()-1, r.right()-2, r.bottom()-1 ); p->drawLine(r.right()-1, r.top()+2, r.right()-1, r.bottom()-2); break; } case CE_ProgressBarContents: { const QProgressBar *pb = dynamic_cast(widget); int steps = pb->totalSteps(); const QColor bg = enabled?cg.base():cg.background(); // background const QColor fg = enabled?cg.highlight():cg.background().dark(110); // foreground if( steps == 0 ) { // Busy indicator static const int barWidth = 10; int progress = pb->progress() % (2*(r.width()-barWidth)); if( progress < 0) progress = 0; if( progress > r.width()-barWidth ) progress = (r.width()-barWidth)-(progress-(r.width()-barWidth)); renderGradient( p, QRect( r.x(), r.y(), r.width(), r.height()/2 ), bg.dark(100+_contrast), bg ); p->fillRect( QRect( r.x(), (r.height()/2)+1, r.width(), r.height()-(r.height()/2)+1 ), bg ); renderContour( p, QRect( r.x()+progress, r.y(), barWidth, r.height() ), bg, fg.dark(160), Draw_Left|Draw_Right|Draw_Top|Draw_Bottom|Round_UpperRight| Round_BottomRight|Round_UpperLeft|Round_BottomLeft ); renderSurface(p, QRect( r.x()+progress+1, r.y()+1, barWidth-2, r.height()-2 ), bg, fg, cg.highlight(), 2*(_contrast/3), Draw_Right|Draw_Left|Draw_Top|Draw_Bottom| Round_UpperRight|Round_BottomRight| Round_UpperLeft|Round_BottomLeft|Is_Horizontal); } else { double percent = static_cast(pb->progress()) / static_cast(steps); int w = static_cast(r.width() * percent); // renderContour/renderSurface handle small sizes not very well, so set a minimal // progressbar width... if(w<4) w = 4; int w2 = r.width()-(r.width()-w); QRect RemptyGradient(reverseLayout?r.left():r.left()+w-1, r.top(), r.width()-w+1, r.height()/2 ); QRect Rempty( RemptyGradient.x(), RemptyGradient.bottom()+1, RemptyGradient.width(), r.height()-RemptyGradient.height()); QRect Rcontour(reverseLayout?r.right()-w2+1:r.left(), r.top(), w2, r.height() ); QRect Rsurface(Rcontour.left()+1, Rcontour.top()+1, w2-2, Rcontour.height()-2); p->fillRect(Rempty, bg); renderGradient( p, RemptyGradient, bg.dark(100+_contrast), bg ); //moved after the surface in order to not get it overwritten //by the ugly left sharp borders of the surface renderContour(p, Rcontour, bg, fg.dark(160), Draw_Left|Draw_Right|Draw_Top|Draw_Bottom| Round_UpperRight|Round_BottomRight|Round_UpperLeft|Round_BottomLeft); QRegion mask(Rsurface); mask -= QRegion(Rsurface.left(), Rsurface.top(), 1, 1); mask -= QRegion(Rsurface.left(), Rsurface.bottom(), 1, 1); mask -= QRegion(Rsurface.right(), Rsurface.top(), 1, 1); mask -= QRegion(Rsurface.right(), Rsurface.bottom(), 1, 1); p->setClipRegion(mask); int counter = 0; QPixmap surfaceTile(21, r.height()-2); QPainter surfacePainter(&surfaceTile); // - 21 pixel - // __________ // | ` `| <- 3 // | 1 | 2 | // |____,____,| <- 3 // 1 = light, 11 pixel, 1 pixel overlapping with 2 // 2 = dark, 11 pixel, 1 pixel overlapping with 3 // 3 = light edges const int tileHeight = surfaceTile.height(); // 3 renderSurface(&surfacePainter, QRect(20, 0, 11, tileHeight), fg.light(105), fg, cg.highlight(), 2*(_contrast/3), reverseLayout ? Draw_Right|Draw_Left|Draw_Top|Draw_Bottom| Round_UpperLeft|Round_BottomLeft|Is_Horizontal : Draw_Right|Draw_Left|Draw_Top|Draw_Bottom| Round_UpperRight|Round_BottomRight| Is_Horizontal); // 2 renderSurface(&surfacePainter, QRect(10, 0, 11, tileHeight), fg, fg.light(105), cg.highlight(), 2*(_contrast/3), reverseLayout ? Draw_Right|Draw_Left|Draw_Top|Draw_Bottom| Round_UpperLeft|Round_BottomLeft|Is_Horizontal : Draw_Right|Draw_Left|Draw_Top|Draw_Bottom| Round_UpperRight|Round_BottomRight|Is_Horizontal); // 1 renderSurface(&surfacePainter, QRect(0, 0, 11, tileHeight), fg.light(105), fg, cg.highlight(), 2*(_contrast/3), reverseLayout ? Draw_Right|Draw_Left|Draw_Top|Draw_Bottom| Round_UpperLeft|Round_BottomLeft|Is_Horizontal : Draw_Right|Draw_Left|Draw_Top|Draw_Bottom| Round_UpperRight|Round_BottomRight|Is_Horizontal); surfacePainter.end(); int staticShift = 0; int animShift = 0; if (!_animateProgressBar) { staticShift = (reverseLayout ? Rsurface.left() : Rsurface.right()) % 40 - 40; } else { // find the animation Offset for the current Widget QWidget* nonConstWidget = const_cast(widget); QMapConstIterator iter = progAnimWidgets.find(nonConstWidget); if (iter != progAnimWidgets.end()) animShift = iter.data(); } while( (counter*10) < (Rsurface.width()+20) ) { counter++; if (reverseLayout) { // from right to left, overlap 1 pixel with the previously drawn tile p->drawPixmap(Rsurface.right()-counter*20-animShift+40+staticShift, r.top()+1, surfaceTile); } else { // from left to right, overlap 1 pixel with the previously drawn tile p->drawPixmap(Rsurface.left()+counter*20+animShift-40+staticShift, r.top()+1, surfaceTile); } } p->setClipping(false); } break; } //TABBAR TEXT (code from Qt libraries Copyright Trolltech 2006) //-------------- case CE_TabBarLabel:{ if ( opt.isDefault() ) break; const uint text_flags = AlignVCenter | AlignHCenter | ShowPrefix | DontClip | SingleLine; QTab *t = opt.tab(); const QTabBar * tb = ( const QTabBar * ) widget; QRect tr = r; if ( t->identifier() == tb->currentTab()) { tr.moveTop( tr.top() - pixelMetric( QStyle::PM_TabBarTabShiftVertical, tb ) ); tr.moveLeft( tr.left() - pixelMetric( QStyle::PM_TabBarTabShiftHorizontal, tb ) ); } if(_shadowedButtonsText) { p->setPen( cg.button().dark(120+_contrast)); p->drawText(QRect(tr.x()+1, tr.y()+1, tr.width(), tr.height()), text_flags, opt.tab()->text()); } drawItem( p, tr, AlignCenter | ShowPrefix, cg, flags & Style_Enabled, 0, t->text() ); if ( (flags & Style_HasFocus) && !t->text().isEmpty() ) drawPrimitive( PE_FocusRect, p, r, cg, Style_Default, opt ); break; } // RADIOBUTTONS // ------------ case CE_RadioButton: { drawPrimitive(PE_ExclusiveIndicator, p, r, cg, flags); const QColor contentColor = enabled?cg.base():cg.background(); QColor checkmarkColor = enabled?getColor(cg,CheckMark):cg.background(); if(flags & Style_Down) { checkmarkColor = alphaBlendColors(contentColor, checkmarkColor, 150); } if (flags & Style_On || flags & Style_Down) { int x = r.center().x() - 4, y = r.center().y() - 4; QBitmap bmp; bmp = QBitmap(CHECKMARKSIZE, CHECKMARKSIZE, radiomark_dark_bits, true); bmp.setMask(bmp); p->setPen(alphaBlendColors(contentColor, checkmarkColor.dark(150), 50) ); p->drawPixmap(x, y, bmp); bmp = QBitmap(CHECKMARKSIZE, CHECKMARKSIZE, radiomark_light_bits, true); bmp.setMask(bmp); p->setPen(alphaBlendColors(contentColor, checkmarkColor.dark(125), 50) ); p->drawPixmap(x, y, bmp); bmp = QBitmap(CHECKMARKSIZE, CHECKMARKSIZE, radiomark_aa_bits, true); bmp.setMask(bmp); p->setPen(alphaBlendColors(contentColor, checkmarkColor.dark(150), 150) ); p->drawPixmap(x, y, bmp); } break; } // TABS // ---- case CE_TabBarTab: { const QTabBar * tb = (const QTabBar *) widget; bool cornerWidget = false; if( ::qt_cast(tb->parent()) ) { const QTabWidget *tw = (const QTabWidget*)tb->parent(); // is there a corner widget in the (top) left edge? QWidget *cw = tw->cornerWidget(Qt::TopLeft); if(cw) cornerWidget = true; } QTabBar::Shape tbs = tb->shape(); SelectedTab selected = OtherTab; if( flags & Style_Selected ) selected = ThisTab; else if( tb->indexOf(tb->currentTab()) - (tb->indexOf(opt.tab()->identifier())) == -1) selected = PrevTab; else if( tb->indexOf(tb->currentTab()) - (tb->indexOf(opt.tab()->identifier())) == 1) selected = NextTab; TabPosition pos; if (tb->count() == 1) { pos = Single; } else if ((tb->indexOf(opt.tab()->identifier()) == 0)) { pos = First; } else if (tb->indexOf(opt.tab()->identifier()) == tb->count() - 1) { pos = Last; } else { pos = Middle; } bool mouseOver = false; if (opt.tab() == hoverTab) { mouseOver = true; flags |= Style_MouseOver; } switch (tbs) { case QTabBar::TriangularAbove: // renderTriangularTab(p, r, cg, (flags & Style_MouseOver), selected, false, pos); renderTab(p, r, cg, mouseOver, selected, false, pos, true, cornerWidget); break; case QTabBar::RoundedAbove: renderTab(p, r, cg, mouseOver, selected, false, pos, false, cornerWidget); break; case QTabBar::TriangularBelow: // renderTriangularTab(p, r, cg, (flags & Style_MouseOver), selected, true, pos); renderTab(p, r, cg, mouseOver, selected, true, pos, true, cornerWidget); break; case QTabBar::RoundedBelow: renderTab(p, r, cg, mouseOver, selected, true, pos, false, cornerWidget); break; default: KStyle::drawControl(element, p, widget, r, cg, flags, opt); } break; } case CE_PushButton: { QPushButton *button = (QPushButton *)widget; const bool isDefault = enabled && button->isDefault(); if (button->isFlat() ) flatMode = true; if (widget == hoverWidget) flags |= Style_MouseOver; QColorGroup g2 = cg; if (isDefault) g2.setColor(QColorGroup::Background, cg.background().dark(120) ); int animFrame = 0; if( _animateButton && animWidgets.contains( button )){ animFrame = animWidgets[button].animFrame; g2.setColor( QColorGroup::Button, cg.button().light(100+animFrame) ); } drawPrimitive(PE_ButtonBevel, p, isDefault?QRect(r.x()+1,r.y()+1,r.width()-2,r.height()-2):r, g2, flags, QStyleOption(button) ); if (isDefault ) { drawPrimitive(PE_ButtonDefault, p, r, cg, flags); } break; } case CE_PushButtonLabel: { int x, y, w, h; r.rect( &x, &y, &w, &h ); QPushButton* button = (QPushButton *)( widget ); bool active = button->isOn() || button->isDown(); bool cornArrow = false; // Shift button contents if pushed. if ( active ) { x += pixelMetric(PM_ButtonShiftHorizontal, widget); y += pixelMetric(PM_ButtonShiftVertical, widget); flags |= Style_Sunken; } // Does the button have a popup menu? if ( button->isMenuButton() ) { int dx = pixelMetric( PM_MenuButtonIndicator, widget ); if ( button->iconSet() && !button->iconSet()->isNull() && (dx + button->iconSet()->pixmap (QIconSet::Small, QIconSet::Normal, QIconSet::Off ).width()) >= w ) { cornArrow = true; //To little room. Draw the arrow in the corner, don't adjust the widget } else { drawPrimitive( PE_ArrowDown, p, visualRect( QRect(x + w - dx - 8, y + 2, dx, h - 4), r ), cg, flags, opt ); w -= dx; } } // Draw the icon if there is one if ( button->iconSet() && !button->iconSet()->isNull() ) { QIconSet::Mode mode = QIconSet::Disabled; QIconSet::State state = QIconSet::Off; if (button->isEnabled()) mode = button->hasFocus() ? QIconSet::Active : QIconSet::Normal; if (button->isToggleButton() && button->isOn()) state = QIconSet::On; QPixmap pixmap = button->iconSet()->pixmap( QIconSet::Small, mode, state ); if (button->text().isEmpty() && !button->pixmap()) p->drawPixmap( x + w/2 - pixmap.width()/2, y + h / 2 - pixmap.height() / 2, pixmap ); else p->drawPixmap( x + 4, y + h / 2 - pixmap.height() / 2, pixmap ); if (cornArrow) //Draw over the icon drawPrimitive( PE_ArrowDown, p, visualRect( QRect(x + w - 6, x + h - 6, 7, 7), r ), cg, flags, opt ); int pw = pixmap.width(); x += pw + 4; w -= pw + 4; } //making the text of the default button always readable with a cute animation int animFrame = 0; if( _animateButton && button->isDefault() && animWidgets.contains( button )) animFrame = animWidgets[button].animFrame; //12.8 is the maximum amount of blending (256) / ANIMATIONSTEPS (20) QColor textColor = alphaBlendColors( cg.highlightedText(), button->colorGroup().buttonText(), (int)(12.8*animFrame) ); // shadow on button text if( _shadowedButtonsText && button->isEnabled() && button->text() ) { QColor shadowColor = alphaBlendColors( cg.highlight(), cg.button(), (int)(12.8*animFrame) ).dark(120+_contrast); drawItem( p, QRect(x+1, y+1, w, h), AlignCenter|ShowPrefix, button->colorGroup(), button->isEnabled(), button->pixmap(), _useLowerCaseText?button->text().lower():button->text(), -1, &shadowColor ); } drawItem( p, QRect(x, y, w, h), AlignCenter|ShowPrefix, button->colorGroup(), button->isEnabled(), button->pixmap(), _useLowerCaseText?button->text().lower():button->text(), -1, &textColor ); if ( flags & Style_HasFocus ) { QColorGroup g2 = cg; drawPrimitive( PE_FocusRect, p, visualRect( subRect( SR_PushButtonFocusRect, widget ), widget ), g2, flags, opt ); } break; } // MENUBAR ITEM (sunken panel on mouse over) // ----------------------------------------- case CE_MenuBarItem: { QMenuItem *mi = opt.menuItem(); bool active = flags & Style_Active; bool focused = flags & Style_HasFocus; bool down = flags & Style_Down; const int text_flags = AlignVCenter | AlignHCenter | ShowPrefix | DontClip | SingleLine; if( _menuBarEmphasis ) { QMenuBar *mb = (QMenuBar*)widget; renderSurface(p, mb->rect(), cg.background(), getColor(cg, MenuBarEmphasis), cg.background(), _contrast+3, Is_Horizontal); } else { p->fillRect(r, cg.background()); } if (active && focused) { if (down) { //drawPrimitive(PE_ButtonTool, p, r, cg, flags|Style_Down, opt); //code to draw the menubar item as a tab (ugly?) renderSurface(p, QRect(r.left()+1, r.top()+1, r.width()-2, r.height()), cg.highlight(), cg.highlight(), cg.highlight(), _contrast, Is_Horizontal|Draw_Right|Draw_Top|Draw_Left); renderContour(p, r, getColor(cg, MenuBarEmphasis), cg.highlight().dark(100+_contrast*8), Draw_Right|Draw_Top|Draw_Left|Round_UpperRight|Round_UpperLeft); //renderTab( p, QRect(r.left(), r.top(), r.width(), r.height()+2), cg, false, true, false, Single, false, false); } else { renderSurface(p, QRect(r.left()+1, r.top()+1, r.width()-2, r.height()-2), cg.background(), getColor(cg, MenuBarEmphasis), cg.background(), _contrast, Is_Horizontal|Draw_Right|Draw_Top|Draw_Left|Draw_Bottom); renderContour(p, r, getColor(cg, MenuBarEmphasis), getColor(cg, MenuBarEmphasis).dark(120+_contrast*8), Draw_Right|Draw_Top|Draw_Left|Round_UpperRight|Round_UpperLeft|Draw_Bottom|Round_BottomRight|Round_BottomLeft); //not used this because of the possible custom menubar color //drawPrimitive(PE_ButtonTool, p, r, cg, flags, opt); } } if ( _shadowedMenuBarText ){ if (active && focused && down) p->setPen(cg.highlight().dark(100+_contrast*2) ); else p->setPen(getColor(cg, MenuBarEmphasis).dark(100+_contrast*2) ); p->drawText(r.x()+1, r.y()+1, r.width(), r.height(), text_flags, mi->text()); } if (active && focused && down) p->setPen(cg.highlightedText() ); else if( _customMenuBarEmphasisColor ) p->setPen( (qGray(_menuBarEmphasisColor.rgb())>150?cg.foreground():white) ); else p->setPen( cg.foreground() ); p->drawText(r, text_flags, mi->text()); break; } // POPUPMENU ITEM (highlighted on mouseover) // ------------------------------------------ case CE_PopupMenuItem: { const QPopupMenu *popupmenu = static_cast< const QPopupMenu * >( widget ); QMenuItem *mi = opt.menuItem(); if ( !mi ) { // Don't leave blank holes if we set NoBackground for the QPopupMenu. // This only happens when the popupMenu spans more than one column. if (! ( widget->erasePixmap() && !widget->erasePixmap()->isNull() ) ) p->fillRect( r, cg.background().light( 105 ) ); break; } int tab = opt.tabWidth(); int checkcol = opt.maxIconWidth(); int stripeWidth = max(checkcol+(int)(checkcol/8),22); bool enabled = mi->isEnabled(); bool checkable = popupmenu->isCheckable(); bool active = flags & Style_Active; bool etchtext = styleHint( SH_EtchDisabledText ); bool reverse = QApplication::reverseLayout(); if ( checkable ) checkcol = QMAX( checkcol, 20 ); //draw a solid background... if (! ( widget->erasePixmap() && !widget->erasePixmap()->isNull() ) ) { p->fillRect( r, cg.background().light( 105 ) ); if( _menuStripe ) { if( !QApplication::reverseLayout() ) p->fillRect( QRect(r.left(), r.top(), stripeWidth, r.height()), cg.background().dark( 100+_contrast ) ); else p->fillRect( QRect(r.right()-23, r.top(), stripeWidth, r.height()), cg.background().dark( 100+_contrast ) ); } } //...or draw the transparency pixmap else { p->drawPixmap( r.topLeft(), *widget->erasePixmap(), r ); if( _menuStripe ) { //do this loop only ONE time :) //this could give problems to apps which have popup menus with different icon sizes... if( alphaStripe->isNull() ) { alphaStripe->create(stripeWidth, r.height(), stripeWidth); alphaStripe->setAlphaBuffer(true); for( int i = 0; i < stripeWidth; i++) for( int j = 0; j < r.height(); j++) alphaStripe->setPixel(i,j, qRgba(0, 0 , 0, 20)); } if( !QApplication::reverseLayout() ) p->drawPixmap( r.topLeft(), *alphaStripe ); else p->drawPixmap( r.topRight(), *alphaStripe ); } } // is this menu item highlighted? if (active) { QRect r2 = QRect(r.left()+1, r.top()+1, r.width()-2, r.height()-2); QRect r3 = QRect(r.left()+2, r.top()+2, r.width()-4, r.height()-4); if (enabled) { if (_buttonMenuItem ) { renderSurface(p, r3, cg.background(), cg.highlight(), cg.highlight(), _contrast+3, Is_Horizontal|Draw_Right|Draw_Top|Draw_Bottom|Draw_Left); renderContour(p, r2, cg.background(), cg.highlight().dark(100+_contrast*8), Draw_Right|Draw_Top|Draw_Bottom|Draw_Left|Round_UpperRight|Round_UpperLeft|Round_BottomRight|Round_BottomLeft|Draw_AlphaBlend); } else renderSurface(p, r, cg.background(), cg.highlight(), cg.highlight(), _contrast+3, Is_Horizontal|Draw_Top|Draw_Bottom); } //disabled else { if (_buttonMenuItem ) { renderSurface(p, r3, cg.background(), cg.background().light(120), cg.highlight(), _contrast+3, Is_Horizontal|Round_UpperLeft|Round_BottomRight|Round_BottomLeft); renderContour(p, r2, cg.background(), cg.background().dark(100+_contrast*5), Draw_Right|Draw_Top|Draw_Bottom|Draw_Left|Round_UpperRight|Round_UpperLeft|Round_BottomRight|Round_BottomLeft|Draw_AlphaBlend); } else renderSurface(p, r, cg.background(), cg.background().light(120), cg.highlight(), _contrast+3, Is_Horizontal|Draw_Top|Draw_Bottom|Draw_Left|Draw_Right); } } // Are we a menu item separator? if ( mi->isSeparator() ) { p->setPen( cg.mid() ); if( !QApplication::reverseLayout() ) { p->drawLine( r.x()+stripeWidth, r.y() + 1, r.right()-5, r.y() + 1 ); if( !_lightBorder) { p->setPen( cg.light() ); p->drawLine( r.x()+stripeWidth, r.y() + 2, r.right()-5 , r.y() + 2 ); } } else { p->drawLine( r.x()+5, r.y() + 1, r.right()-24, r.y() + 1 ); if( !_lightBorder) { p->setPen( cg.light() ); p->drawLine( r.x()+5, r.y() + 2, r.right()-24 , r.y() + 2 ); } } break; } QRect cr = visualRect( QRect( r.x() + 2, r.y() + 2, checkcol - 1, r.height() - 4 ), r ); // Do we have an icon? if ( mi->iconSet() ) { QIconSet::Mode mode; // Select the correct icon from the iconset if (active) mode = enabled?QIconSet::Active:QIconSet::Disabled; else mode = enabled?QIconSet::Normal:QIconSet::Disabled; // Do we have an icon and are checked at the same time? // Then draw a "pressed" background behind the icon if ( checkable && /*!active &&*/ mi->isChecked() ) drawPrimitive(QStyle::PE_Indicator, p, cr, cg, QStyle::Style_Enabled | QStyle::Style_Active | QStyle::Style_Off ); /*qDrawShadePanel( p, cr.x(), cr.y(), cr.width(), cr.height(), cg, true, 1, &cg.brush(QColorGroup::Midlight) );*/ // Draw the icon QPixmap pixmap = mi->iconSet()->pixmap(QIconSet::Small, mode); QRect pmr( 0, 0, pixmap.width(), pixmap.height() ); pmr.moveCenter( cr.center() ); p->drawPixmap( pmr.topLeft(), pixmap ); } // Are we checked? (This time without an icon) else if ( checkable && mi->isChecked() ) { int style = QStyle::Style_Enabled | QStyle::Style_Active | QStyle::Style_On ; drawPrimitive(QStyle::PE_Indicator, p, cr, cg, style); } // Time to draw the menu item label... int xm = 2 + checkcol + 2; // X position margin int xp = reverse ? // X position r.x() + tab + rightBorder + itemHMargin + itemFrame - 1 : r.x() + xm; int offset = reverse ? -1 : 1; // Shadow offset for etched text // Label width (minus the width of the accelerator portion) int tw = r.width() - xm - tab - arrowHMargin - itemHMargin * 3 - itemFrame + 1; // Set the color for enabled and disabled text // (used for both active and inactive menu items) p->setPen( enabled ? cg.buttonText() : cg.mid() ); // This color will be used instead of the above if the menu item // is active and disabled at the same time. (etched text) QColor discol = cg.mid(); if ( mi->custom() ) { int m = 2; // Save the painter state in case the custom // paint method changes it in some way p->save(); // Draw etched text if we're inactive and the menu item is disabled if ( etchtext && !enabled && !active ) { p->setPen( cg.foreground() ); mi->custom()->paint( p, cg, active, enabled, xp+offset, r.y()+m+1, tw, r.height()-2*m ); p->setPen( discol ); } mi->custom()->paint( p, cg, active, enabled, xp, r.y()+m, tw, r.height()-2*m ); p->restore(); } // The menu item doesn't draw it's own label QString s = mi->text(); // Does the menu item have a text label? if ( !s.isNull() ) { int t = s.find( '\t' ); int m = 2; int text_flags = AlignVCenter | ShowPrefix | DontClip | SingleLine; text_flags |= reverse ? AlignRight : AlignLeft; //QColor draw = cg.text(); QColor draw = (active && enabled) ? cg.highlightedText () : cg.foreground(); p->setPen(draw); // Does the menu item have a tabstop? (for the accelerator text) if ( t >= 0 ) { int tabx = reverse ? r.x() + rightBorder + itemHMargin + itemFrame : r.x() + r.width() - tab - rightBorder - itemHMargin - itemFrame; // Draw the right part of the label (accelerator text) if ( etchtext && !enabled ) { // Draw etched text if we're inactive and the menu item is disabled p->setPen( cg.light() ); p->drawText( tabx+offset, r.y()+m+1, tab, r.height()-2*m, text_flags, s.mid( t+1 ) ); p->setPen( discol ); } p->drawText( tabx, r.y()+m, tab, r.height()-2*m, text_flags, s.mid( t+1 ) ); s = s.left( t ); } // Draw the left part of the label (or the whole label // if there's no accelerator) if ( !mi->custom() && etchtext && !enabled ) { // Etched text again for inactive disabled menu items... p->setPen( cg.light() ); p->drawText( xp+offset, r.y()+m+1, tw, r.height()-2*m, text_flags, s, t ); p->setPen( discol ); } p->drawText( xp, r.y()+m, tw, r.height()-2*m, text_flags, s, t ); p->setPen(cg.text()); } // The menu item doesn't have a text label // Check if it has a pixmap instead else if ( mi->pixmap() ) { QPixmap *pixmap = mi->pixmap(); // Draw the pixmap if ( pixmap->depth() == 1 ) p->setBackgroundMode( OpaqueMode ); int diffw = ( ( r.width() - pixmap->width() ) / 2 ) + ( ( r.width() - pixmap->width() ) % 2 ); p->drawPixmap( r.x()+diffw, r.y()+1, *pixmap ); if ( pixmap->depth() == 1 ) p->setBackgroundMode( TransparentMode ); } // Does the menu item have a submenu? if ( mi->popup() ) { PrimitiveElement arrow = reverse ? PE_ArrowLeft : PE_ArrowRight; int dim = pixelMetric(PM_MenuButtonIndicator) - 1; QRect vr = visualRect( QRect( r.x() + r.width() - 5 - 1 - dim, r.y() + r.height() / 2 - dim / 2, dim, dim), r ); // Draw an arrow at the far end of the menu item if ( active ) { if ( enabled ) discol = cg.buttonText(); QColorGroup g2( discol, cg.highlight(), white, white, enabled ? white : discol, discol, white ); drawPrimitive( arrow, p, vr, g2, Style_Enabled ); } else drawPrimitive( arrow, p, vr, cg, enabled ? Style_Enabled : Style_Default ); } break; } // Menu and dockwindow empty space // case CE_DockWindowEmptyArea: p->fillRect(r, cg.background()); break; case CE_MenuBarEmptyArea: if( _menuBarEmphasis ) { renderSurface(p, r, cg.background(), getColor(cg, MenuBarEmphasis), cg.background(), _contrast+3, Is_Horizontal); if( _menuBarEmphasisBorder ) renderContour(p, r, cg.background(), getColor(cg, MenuBarEmphasis).dark(115), Draw_Left|Draw_Top|Draw_Bottom|Draw_Right| Round_UpperLeft|Round_UpperRight| Round_BottomRight|Round_BottomLeft); } else p->fillRect(r, cg.background()); // if ( _drawToolBarSeparator ) { // p->setPen( getColor(cg, PanelDark) ); // p->drawLine( r.left(), r.bottom(), r.right(), r.bottom() ); // } break; case CE_HeaderLabel: { const QHeader *header = static_cast< const QHeader * >( widget ); if( !header ) break; int headerId = header->sectionAt( (header->orientation()==Qt::Horizontal?r.x():r.y()) + header->offset()); QString s = header->label(headerId); // Does the header have a text label? if( !s.isNull() ) { int t = s.find( '\t' ); bool reverse = QApplication::reverseLayout(); int text_flags = AlignVCenter | ShowPrefix | DontClip | SingleLine; text_flags |= reverse ? AlignRight : AlignLeft; p->setPen(cg.text()); /*draw the text label always attempting to display the entire label, except when reverse layout the text label is already shown entirely*/ p->drawText( r.x()<=2&&!reverse?2:r.x(), r.y(), r.width(), r.height(), text_flags, s, t ); } QIconSet *iS = header->iconSet(headerId); if( iS ) { QIconSet::Mode mode = QIconSet::Normal; QIconSet::State state = QIconSet::On; QPixmap pixmap = iS->pixmap( QIconSet::Small, mode, state ); p->drawPixmap(r.x(), r.y()+r.height()/2-pixmap.height()/2, pixmap); } break; } default: KStyle::drawControl(element, p, widget, r, cg, flags, opt); } } void PolyesterStyle::drawControlMask(ControlElement element, QPainter *p, const QWidget *w, const QRect &r, const QStyleOption &opt) const { switch (element) { case CE_PushButton: { p->fillRect (r, color0); renderMask(p, r, color1, Round_UpperLeft|Round_UpperRight|Round_BottomLeft|Round_BottomRight); break; } default: { KStyle::drawControlMask (element, p, w, r, opt); } } } void PolyesterStyle::drawComplexControlMask(ComplexControl c, QPainter *p, const QWidget *w, const QRect &r, const QStyleOption &o) const { switch (c) { case CC_SpinWidget: case CC_ListView: case CC_ComboBox: { p->fillRect (r, color0); renderMask(p, r, color1, Round_UpperLeft|Round_UpperRight|Round_BottomLeft|Round_BottomRight); break; } default: { KStyle::drawComplexControlMask (c, p, w, r, o); } } } void PolyesterStyle::drawComplexControl(ComplexControl control, QPainter *p, const QWidget *widget, const QRect &r, const QColorGroup &cg, SFlags flags, SCFlags controls, SCFlags active, const QStyleOption& opt) const { const bool reverseLayout = QApplication::reverseLayout(); const bool enabled = (flags & Style_Enabled); switch(control) { // COMBOBOX // -------- case CC_ComboBox: { static const unsigned int handleWidth = 15; //const QComboBox *cb = dynamic_cast(widget); QComboBox *cb = (QComboBox *)(widget); // **hack**: cast away const-ness for animation support! // at the moment cb is only needed to check if the combo box is editable or not. // if cb doesn't exist, just assume false and the app (gideon! ;) ) at least doesn't crash. bool editable = false; bool hasFocus = false; if (cb) { editable = cb->editable(); hasFocus = cb->hasFocus(); } int animFrame = 0; if( _animateButton && animWidgets.contains( cb )) animFrame = animWidgets[cb].animFrame; const QColor buttonColor = enabled?cg.button().light(100+animFrame):cg.background(); const QColor highlightColor = (_animateButton?alphaBlendColors( getColor(cg,MouseOverHighlight),cg.button(), 20*animFrame ):getColor(cg,MouseOverHighlight)); const QColor inputColor = enabled?(editable?cg.base():cg.button()) :cg.background(); uint contourFlags = 0; if( khtmlWidgets.contains(cb) ) contourFlags |= Draw_AlphaBlend; if (_inputFocusHighlight && hasFocus && editable && enabled) { QRect editField = querySubControlMetrics(control, widget, SC_ComboBoxEditField); QRect editFrame = r; QRect buttonFrame = r; uint editFlags = contourFlags; uint buttonFlags = contourFlags; // Hightlight only the part of the contour next to the control button if (reverseLayout) { // querySubControlMetrics doesn't work right for reverse Layout int dx = r.right() - editField.right(); editFrame.setLeft(editFrame.left() + dx); buttonFrame.setRight(editFrame.left() - 1); editFlags |= Draw_Right|Draw_Top|Draw_Bottom|Round_UpperRight|Round_BottomRight; buttonFlags |= Draw_Left|Draw_Top|Draw_Bottom|Round_UpperLeft|Round_BottomLeft; } else { editFrame.setRight(editField.right()); buttonFrame.setLeft(editField.right() + 1); editFlags |= Draw_Left|Draw_Top|Draw_Bottom|Round_UpperLeft|Round_BottomLeft; buttonFlags |= Draw_Right|Draw_Top|Draw_Bottom|Round_UpperRight|Round_BottomRight; } renderContour(p, editFrame, cg.background(), getColor(cg,FocusHighlight,enabled), editFlags); renderContour(p, buttonFrame, cg.background(), getColor(cg, ButtonContour, enabled), buttonFlags); } else { contourFlags |= Draw_Left|Draw_Right|Draw_Top|Draw_Bottom| Round_UpperLeft|Round_UpperRight|Round_BottomLeft|Round_BottomRight; renderContour(p, r, cg.background(), getColor(cg, ButtonContour, enabled), contourFlags); } //extend the contour: between input and handler... p->setPen(alphaBlendColors(cg.background(), getColor(cg, ButtonContour, enabled), 50) ); if(reverseLayout) { p->drawLine(r.left()+1+handleWidth, r.top()+1, r.left()+1+handleWidth, r.bottom()-1); } else { p->drawLine(r.right()-handleWidth-1, r.top()+1, r.right()-handleWidth-1, r.bottom()-1); } const QRect RbuttonSurface(reverseLayout?r.left()+1:r.right()-handleWidth, r.top()+1, handleWidth, r.height()-2); const QRect RcontentSurface(reverseLayout?r.left()+1+handleWidth+1:r.left()+1, r.top()+1, r.width()-handleWidth-3, r.height()-2); // handler uint surfaceFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom|Is_Horizontal; if(reverseLayout) { surfaceFlags |= Round_UpperLeft|Round_BottomLeft; } else { surfaceFlags |= Round_UpperRight|Round_BottomRight; } if ( (animFrame != 0) || (widget == hoverWidget) || (flags & Style_MouseOver)) { surfaceFlags |= Is_Highlight; if(editable) surfaceFlags |= Highlight_Left|Highlight_Right; surfaceFlags |= Highlight_Top|Highlight_Bottom; } renderSurface(p, RbuttonSurface, cg.background(), buttonColor, highlightColor, enabled?_contrast+3:(_contrast/2), surfaceFlags); if(!editable) { surfaceFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom|Is_Horizontal; if(reverseLayout) { surfaceFlags |= Round_UpperRight|Round_BottomRight; } else { surfaceFlags |= Round_UpperLeft|Round_BottomLeft; } if ( (animFrame != 0) || (widget == hoverWidget) || (flags & Style_MouseOver)) { surfaceFlags |= Is_Highlight; surfaceFlags |= Highlight_Top|Highlight_Bottom; } renderSurface(p, RcontentSurface, cg.background(), buttonColor, highlightColor, enabled?_contrast+3:(_contrast/2), surfaceFlags); if (hasFocus) { drawPrimitive(PE_FocusRect, p, QRect(RcontentSurface.x() + 2, RcontentSurface.y() + 2, RcontentSurface.width() - 4, RcontentSurface.height() - 4), cg, Style_Default, opt); } } else { // thin frame around the input area if (_inputFocusHighlight && hasFocus && editable && enabled) { p->setPen( getColor(cg,FocusHighlight).dark(130) ); } else { p->setPen(inputColor.dark(100+(_lightBorder?-30:30)) ); } p->drawLine(RcontentSurface.x(), reverseLayout?RcontentSurface.y():RcontentSurface.y()+1, RcontentSurface.x(), reverseLayout?RcontentSurface.bottom():RcontentSurface.bottom()-1); p->drawLine(RcontentSurface.x()+1, RcontentSurface.y(), reverseLayout?RcontentSurface.right()-1:RcontentSurface.right(), RcontentSurface.y() ); if (_inputFocusHighlight && hasFocus && editable && enabled) { p->setPen( getColor(cg,FocusHighlight).light(130) ); } else { p->setPen(inputColor.light(130) ); } p->drawLine(reverseLayout?RcontentSurface.x():RcontentSurface.x()+1, RcontentSurface.bottom(), reverseLayout?RcontentSurface.right()-1:RcontentSurface.right(), RcontentSurface.bottom() ); p->drawLine(RcontentSurface.right(), RcontentSurface.top()+1, RcontentSurface.right(), RcontentSurface.bottom()-1 ); // input area p->fillRect(RcontentSurface.x()+1, RcontentSurface.y()+1, RcontentSurface.width()-2, RcontentSurface.height()-2, inputColor ); } p->setPen(cg.foreground()); drawPrimitive(PE_SpinWidgetDown, p, RbuttonSurface, cg, Style_Default|Style_Enabled|Style_Raised); // QComboBox draws the text using cg.text(), we can override this // from here TODO: shadow here? p->setPen( cg.buttonText() ); p->setBackgroundColor( cg.button() ); break; } // TOOLBUTTON // ---------- case CC_ToolButton: { QToolButton *tb = (QToolButton *) widget;// **hack**: cast away const-ness for animation support! QColorGroup g2 = cg; int animFrame = 0; if( _animateButton && animWidgets.contains( tb )){ animFrame = animWidgets[tb].animFrame; g2.setColor( QColorGroup::Button, cg.button().light(100+animFrame) ); } QRect button, menuarea; button = querySubControlMetrics(control, widget, SC_ToolButton, opt); menuarea = querySubControlMetrics(control, widget, SC_ToolButtonMenu, opt); SFlags bflags = flags, mflags = flags; SFlags borderFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom| Round_UpperLeft|Round_UpperRight|Round_BottomLeft|Round_BottomRight; if (kornMode) { drawPrimitive(PE_ButtonTool, p, button, g2, bflags, opt); break; } else { // don't want to have the buttoncolor as the background... p->fillRect(r, cg.background().light(100+animFrame)); renderContour(p, r, cg.background(), cg.background().dark(100+(abs(animFrame)*_contrast)), borderFlags); bflags &= ~Style_MouseOver; } if (active & SC_ToolButton) bflags |= Style_Down; if (active & SC_ToolButtonMenu) mflags |= Style_Down; if (controls & SC_ToolButton) { // If we're pressed, on, or raised... if (bflags & (Style_Down | Style_On | Style_Raised) || widget==hoverWidget ) { drawPrimitive(PE_ButtonTool, p, button, g2, bflags, opt); if( _animateButton && tb->autoRaise() && !(bflags & Style_On) && !active ) renderContour(p, r, cg.background(), cg.background().dark(100+(abs(animFrame)*_contrast)), borderFlags); } else if (tb->parentWidget() && tb->parentWidget()->backgroundPixmap() && !tb->parentWidget()->backgroundPixmap()->isNull()) { QPixmap pixmap = *(tb->parentWidget()->backgroundPixmap()); p->drawTiledPixmap( r, pixmap, tb->pos() ); } } // Draw a toolbutton menu indicator if required if (controls & SC_ToolButtonMenu) { if (mflags & (Style_Down | Style_On | Style_Raised)) { drawPrimitive(PE_ButtonDropDown, p, menuarea, g2, mflags, opt); } drawPrimitive(PE_ArrowDown, p, menuarea, g2, mflags, opt); } if (tb->hasFocus() && !tb->focusProxy()) { QRect fr = tb->rect(); fr.addCoords(2, 2, -2, -2); drawPrimitive(PE_FocusRect, p, fr, g2, Style_Default, opt); } // Set the color for the ToolButton menu indicator p->setPen(cg.buttonText() ); break; } // SPINWIDGETS // ----------- case CC_SpinWidget: { static const unsigned int handleWidth = 15; QSpinWidget *sw = (QSpinWidget *)(widget);// **hack**: cast away const-ness for animation support! SFlags sflags = flags; PrimitiveElement pe; bool hasFocus = false; if (sw) hasFocus = sw->hasFocus(); int animFrame = 0; if( _animateButton && animWidgets.contains( sw )){ animFrame = animWidgets[sw].animFrame; } const QColor buttonColor = enabled?cg.button().light(100+animFrame):cg.background(); const QColor highlightColor = (_animateButton?alphaBlendColors( getColor(cg,MouseOverHighlight),cg.button(), 20*animFrame ):getColor(cg,MouseOverHighlight)); const QColor inputColor = enabled?cg.base():cg.background(); // contour const bool heightDividable = ((r.height()%2) == 0); if (_inputFocusHighlight && hasFocus && enabled) { QRect editField = querySubControlMetrics(control, widget, SC_SpinWidgetEditField); QRect editFrame = r; QRect buttonFrame = r; uint editFlags = 0; uint buttonFlags = 0; // Hightlight only the part of the contour next to the control buttons if (reverseLayout) { // querySubControlMetrics doesn't work right for reverse Layout int dx = r.right() - editField.right(); editFrame.setLeft(editFrame.left() + dx); buttonFrame.setRight(editFrame.left() - 1); editFlags |= Draw_Right|Draw_Top|Draw_Bottom|Round_UpperRight|Round_BottomRight; buttonFlags |= Draw_Left|Draw_Top|Draw_Bottom|Round_UpperLeft|Round_BottomLeft; } else { editFrame.setRight(editField.right()); buttonFrame.setLeft(editField.right() + 1); editFlags |= Draw_Left|Draw_Top|Draw_Bottom|Round_UpperLeft|Round_BottomLeft; buttonFlags |= Draw_Right|Draw_Top|Draw_Bottom|Round_UpperRight|Round_BottomRight; } renderContour(p, editFrame, cg.background(), cg.highlight(), editFlags); renderContour(p, buttonFrame, cg.background(), getColor(cg, ButtonContour, enabled), buttonFlags); } else { renderContour(p, querySubControlMetrics(control, widget, SC_SpinWidgetFrame), cg.background(), getColor(cg, ButtonContour, enabled) ); } p->setPen(alphaBlendColors(cg.background(), getColor(cg, ButtonContour, enabled), 50) ); p->drawLine(reverseLayout?r.left()+1+handleWidth:r.right()-handleWidth-1, r.top()+1, reverseLayout?r.left()+1+handleWidth:r.right()-handleWidth-1, r.bottom()-1); p->drawLine(reverseLayout?r.left()+1:r.right()-handleWidth, r.top()+1+(r.height()-2)/2, reverseLayout?r.left()+handleWidth:r.right()-1, r.top()+1+(r.height()-2)/2); //commented out because I always prefer that only one line is drawn /*if(heightDividable) p->drawLine(reverseLayout?r.left()+1:r.right()-handleWidth, r.top()+1+(r.height()-2)/2-1, reverseLayout?r.left()+handleWidth:r.right()-1, r.top()+1+(r.height()-2)/2-1);*/ // surface QRect upRect = QRect(reverseLayout?r.left()+1:r.right()-handleWidth, r.top()+1, handleWidth, (r.height()-2)/2); QRect downRect = QRect(reverseLayout?r.left()+1:r.right()-handleWidth, heightDividable?r.top()+1+((r.height()-2)/2):r.top()+1+((r.height()-2)/2)+1, handleWidth, ((r.height()-2)/2) ); if(heightDividable) { //upRect = QRect(upRect.left(), upRect.top(), upRect.width(), upRect.height()-1 ); downRect = QRect(downRect.left(), downRect.top()+1, downRect.width(), downRect.height()-1 ); } uint surfaceFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom|Is_Horizontal; if(reverseLayout) { surfaceFlags |= Round_UpperLeft; } else { surfaceFlags |= Round_UpperRight; } if ( (animFrame != 0) || (widget == hoverWidget) || (sflags & Style_MouseOver)) { surfaceFlags |= Is_Highlight; surfaceFlags |= Highlight_Top|Highlight_Left|Highlight_Right; } if (active==SC_SpinWidgetUp) surfaceFlags|=Is_Sunken; if(!enabled) surfaceFlags|=Is_Disabled; renderSurface(p, upRect, cg.background(), buttonColor, highlightColor, _contrast, surfaceFlags); surfaceFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom|Is_Horizontal; if(reverseLayout) { surfaceFlags |= Round_BottomLeft; } else { surfaceFlags |= Round_BottomRight; } if ( (animFrame != 0) || (widget == hoverWidget) || (sflags & Style_MouseOver)) { surfaceFlags |= Is_Highlight; surfaceFlags |= Highlight_Bottom|Highlight_Left|Highlight_Right; } if (active==SC_SpinWidgetDown) surfaceFlags|=Is_Sunken; if(!enabled) surfaceFlags|=Is_Disabled; renderSurface(p, downRect, cg.background(), buttonColor, highlightColor, _contrast, surfaceFlags); // icons... sflags = Style_Default | Style_Enabled; if (active == SC_SpinWidgetUp) { sflags |= Style_On; sflags |= Style_Sunken; } else sflags |= Style_Raised; if (sw->buttonSymbols() == QSpinWidget::PlusMinus) pe = PE_SpinWidgetPlus; else pe = PE_SpinWidgetUp; p->setPen(cg.foreground()); drawPrimitive(pe, p, upRect, cg, sflags); sflags = Style_Default | Style_Enabled; if (active == SC_SpinWidgetDown) { sflags |= Style_On; sflags |= Style_Sunken; } else sflags |= Style_Raised; if (sw->buttonSymbols() == QSpinWidget::PlusMinus) pe = PE_SpinWidgetMinus; else pe = PE_SpinWidgetDown; p->setPen(cg.foreground()); drawPrimitive(pe, p, downRect, cg, sflags); // thin frame around the input area const QRect Rcontent = QRect(reverseLayout?r.left()+1+handleWidth+1:r.left()+1, r.top()+1, r.width()-1-2-handleWidth, r.height()-2); if (_inputFocusHighlight && hasFocus && enabled) { p->setPen( getColor(cg,FocusHighlight).dark(100+(_lightBorder?-30:30)) ); } else { p->setPen(inputColor.dark(100+(_lightBorder?-30:30)) ); } p->drawLine(Rcontent.left(), reverseLayout?Rcontent.top():Rcontent.top()+1, Rcontent.left(), reverseLayout?Rcontent.bottom():Rcontent.bottom()-1 ); p->drawLine(Rcontent.left()+1, Rcontent.top(), reverseLayout?Rcontent.right()-1:Rcontent.right(), Rcontent.top() ); if (_inputFocusHighlight && hasFocus && enabled) { p->setPen( getColor(cg,FocusHighlight).light(130) ); } else { p->setPen(inputColor.light(130) ); } p->drawLine(Rcontent.left()+1, Rcontent.bottom(), Rcontent.right()-1, Rcontent.bottom() ); p->drawLine(Rcontent.right(), Rcontent.top()+1, Rcontent.right(), reverseLayout?Rcontent.bottom()-1:Rcontent.bottom() ); break; } default: KStyle::drawComplexControl(control, p, widget, r, cg, flags, controls, active, opt); break; } } QRect PolyesterStyle::subRect(SubRect r, const QWidget *widget) const { switch (r) { case SR_ComboBoxFocusRect: { return querySubControlMetrics( CC_ComboBox, widget, SC_ComboBoxEditField ); } // Don't use KStyles progressbar subrect // TODO: case SR_ProgressBarGroove: { return QRect(widget->rect()); } case SR_ProgressBarContents: case SR_ProgressBarLabel: { QRect rw = widget->rect(); return QRect(rw.left()+2, rw.top()+2, rw.width()-4, rw.height()-4 ); } default: { return KStyle::subRect(r, widget); } } } QRect PolyesterStyle::querySubControlMetrics(ComplexControl control, const QWidget *widget, SubControl subcontrol, const QStyleOption &opt) const { if (!widget) { return QRect(); } QRect r(widget->rect()); switch (control) { case CC_ComboBox: { switch (subcontrol) { case SC_ComboBoxEditField: { // TODO: is the handler width in pixelmetric? return QRect(r.left()+2, r.top()+2, r.width()-4-15-1, r.height()-4); } default: { return KStyle::querySubControlMetrics(control, widget, subcontrol, opt); } } break; } case CC_SpinWidget: { const int fw = 2; // Frame width... const bool heightDividable = ((r.height()%2) == 0); QSize bs; if(heightDividable) { bs.setHeight(QMAX(8, (r.height()-2)/2)); } else { bs.setHeight(QMAX(8, (r.height()-2-1)/2)); } bs.setWidth(15); const int buttonsLeft = /*reverseLayout?r.left()+1:*/r.right()-bs.width(); switch (subcontrol) { case SC_SpinWidgetUp: { return QRect(buttonsLeft, r.top()+1, bs.width(), bs.height() ); } case SC_SpinWidgetDown: { if(heightDividable) { return QRect(buttonsLeft, r.top()+1+bs.height(), bs.width(), r.height()-(bs.height()+2) ); } else { return QRect(buttonsLeft, r.top()+1+bs.height()+1, bs.width(), r.height()-(bs.height()+2+1) ); } } case SC_SpinWidgetFrame: { return QRect(r.left(), r.top(), r.width(), r.height() ); } case SC_SpinWidgetEditField: { return QRect(r.left()+fw, r.top()+fw, r.width()-(bs.width()+1+2*fw), r.height()-2*fw); } case SC_SpinWidgetButtonField: { return QRect(buttonsLeft, r.top()+1, bs.width(), r.height()-2); } default: { return KStyle::querySubControlMetrics(control, widget, subcontrol, opt); } } break; } default: { return KStyle::querySubControlMetrics(control, widget, subcontrol, opt); } } } int PolyesterStyle::pixelMetric(PixelMetric m, const QWidget *widget) const { switch(m) { // TABS // ---- case PM_TabBarTabVSpace: { const QTabBar * tb = (const QTabBar *) widget; if (tb->shape() == QTabBar::RoundedAbove || tb->shape() == QTabBar::RoundedBelow) return 12; else return 4; } case PM_TabBarTabOverlap: { return 1; } #if (QT_VERSION >= 0x030300) // requires Qt 3.3 // extra space between menubar items case PM_MenuBarItemSpacing: { return 5; } #endif // #if (QT_VERSION >= 0x030300) // requires Qt 3.3 // // extra space between toolbar items // case PM_ToolBarItemSpacing: { // return 4; // } // #endif // SCROLL BAR case PM_ScrollBarSliderMin: { return 21; } case PM_ScrollBarExtent: { return _scrollBarExtent; } case PM_DockWindowSeparatorExtent: return 6; // SPLITTERS // --------- case PM_SplitterWidth: { return 6; } // PROGRESSBARS // ------------ case PM_ProgressBarChunkWidth: return 10; // SLIDER // ------ case PM_SliderLength: return 11; // MENU INDICATOR // -------------- case PM_MenuButtonIndicator: return 8; // CHECKBOXES / RADIO BUTTONS // -------------------------- case PM_ExclusiveIndicatorWidth: // Radiobutton size case PM_ExclusiveIndicatorHeight: // 13x13 case PM_IndicatorWidth: // Checkbox size case PM_IndicatorHeight: // 13x13 return 13; // FRAMES // ------ case PM_SpinBoxFrameWidth: return 1; case PM_MenuBarFrameWidth: return 1; //FIXME: change menubar height case PM_DefaultFrameWidth: { if(widget && ::qt_cast(widget)) return 1; else return 2; } case PM_ButtonDefaultIndicator: { return 0; } case PM_ButtonMargin: { return 2; } case PM_ButtonShiftVertical: case PM_ButtonShiftHorizontal: { return 1; } default: return KStyle::pixelMetric(m, widget); } } int PolyesterStyle::kPixelMetric(KStylePixelMetric kpm, const QWidget *widget) const { switch(kpm) { case KPM_MenuItemSeparatorHeight: return 2; default: return KStyle::kPixelMetric(kpm, widget); } } QSize PolyesterStyle::sizeFromContents(ContentsType t, const QWidget *widget, const QSize &s, const QStyleOption &opt) const { switch (t) { case CT_PopupMenuItem: { if (!widget || opt.isDefault()) return s; const QPopupMenu *popup = dynamic_cast(widget); QMenuItem *mi = opt.menuItem(); int maxpmw = opt.maxIconWidth(); int w = s.width(), h = s.height(); bool checkable = popup->isCheckable(); if (mi->custom()) { w = mi->custom()->sizeHint().width(); h = mi->custom()->sizeHint().height(); if (!mi->custom()->fullSpan() ) h += 4; } else if (mi->widget()) { // don't change the size in this case. } else if (mi->isSeparator()) { w = 20; h = 3; } else { if (mi->pixmap()) { h = QMAX(h, mi->pixmap()->height() + 2); } else { h = QMAX(h, 16 + 2 ); h = QMAX(h, popup->fontMetrics().height() + _menuItemSpacing ); } if (mi->iconSet()) { h = QMAX(h, mi->iconSet()->pixmap(QIconSet::Small, QIconSet::Normal).height() + 2); } } if (!mi->text().isNull() && (mi->text().find('\t') >= 0)) { w += itemHMargin + itemFrame*2 + 7; } else if (mi->popup()) { w += 2 * arrowHMargin; } if (maxpmw) { w += maxpmw + 6; } if (checkable && maxpmw < 20) { w += 20 - maxpmw; } if (checkable || maxpmw > 0) { w += 12; } w += rightBorder; return QSize(w, h); } case CT_PushButton: { const QPushButton* btn = static_cast(widget); int w = s.width() + 2 * pixelMetric(PM_ButtonMargin, widget); int h = s.height() + 2 * pixelMetric(PM_ButtonMargin, widget); if ( btn->text().isEmpty() && s.width() < 32 ) return QSize(w, h); return QSize( w+25, h+5 ); } case CT_ToolButton: { if(widget->parent() && ::qt_cast(widget->parent()) ) return QSize( s.width()+2*4, s.height()+2*4 ); else return KStyle::sizeFromContents (t, widget, s, opt); } default: return KStyle::sizeFromContents (t, widget, s, opt); } return KStyle::sizeFromContents (t, widget, s, opt); } int PolyesterStyle::styleHint( StyleHint stylehint, const QWidget *widget, const QStyleOption &option, QStyleHintReturn* returnData ) const { switch (stylehint) { case SH_PopupMenu_SubMenuPopupDelay: return 96; // Motif-like delay... case QStyle::SH_TabBar_Alignment: /*if reverseLayout is enabled, the centering of tabs is disabled, due to a bug in rendering*/ if (_centeredTabBar && !QApplication::reverseLayout()) return Qt::AlignHCenter; //Suggestion by Daniel Molkentin, //algorithm from QT4 QWindowsXPStyle Copyright 2006 Trolltech //this exists since Qt3.2 #if (QT_VERSION >= 0x030200) case SH_LineEdit_PasswordCharacter: { if (widget) { const QFontMetrics &fm = widget->fontMetrics(); if (fm.inFont(QChar(0x25CF))) { return 0x25CF; } else if (fm.inFont(QChar(0x2022))) { return 0x2022; } } else { return '*'; } } #endif default: return KStyle::styleHint(stylehint, widget, option, returnData); } } bool PolyesterStyle::eventFilter(QObject *obj, QEvent *ev) { if (KStyle::eventFilter(obj, ev) ) return true; if (!obj->isWidgetType() ) return false; //header mouse over if ( ::qt_cast(obj) ) { QWidget* widget = static_cast(obj); if ((ev->type() == QEvent::Leave) && static_cast(obj)->isEnabled()) { hoverWidget = 0; hoverHeaderId = -1; widget->repaint(false); } else if ((ev->type() == QEvent::MouseMove) && static_cast(obj)->isEnabled()) { QMouseEvent * mEvent = ( QMouseEvent * ) ev; QHeader* header = static_cast(widget); hoverWidget = widget; int tempHover = hoverHeaderId; if( header->orientation()==Qt::Horizontal ) hoverHeaderId = header->sectionAt( mEvent->x()+header->offset() ); else hoverHeaderId = header->sectionAt( mEvent->y()+header->offset() ); if( tempHover != hoverHeaderId ) widget->update(); } } /*Scrollbar Mouse over*/ if ( ::qt_cast(obj) ) { QWidget* widget = static_cast(obj); if ((ev->type() == QEvent::Enter) && static_cast(obj)->isEnabled()) { hoverWidget = widget; widget->repaint(false); } else if ((ev->type() == QEvent::Leave) && static_cast(obj)->isEnabled()) { hoverWidget = 0; widget->repaint(false); } } // focus highlight if ( ::qt_cast(obj) ) { QWidget* widget = static_cast(obj); if ( ::qt_cast(widget->parentWidget()) ) { QWidget* spinbox = widget->parentWidget(); if ((ev->type() == QEvent::FocusIn) || (ev->type() == QEvent::FocusOut)) { spinbox->repaint(false); } return false; } if ((ev->type() == QEvent::FocusIn) || (ev->type() == QEvent::FocusOut)) { widget->repaint(false); } return false; } //Hover highlight... use qt_cast to check if the widget inheits one of the classes. if ( ::qt_cast(obj) || ::qt_cast(obj) || ::qt_cast(obj) || ::qt_cast(obj) || ::qt_cast(obj) || ::qt_cast(obj) || obj->inherits("QSplitterHandle") ) { if ((ev->type() == QEvent::Enter) && static_cast(obj)->isEnabled()) { QWidget* button = static_cast(obj); hoverWidget = button; //only animate widgets that support animation :-) if(_animateButton && !::qt_cast(obj) && !::qt_cast(obj)){ animWidgets[button].active = true; // if timer isn't running, start it now for glow-in animation. if( !btnAnimTimer->isActive() ) btnAnimTimer->start( TIMERINTERVAL, false ); } button->repaint(false); } else if ((ev->type() == QEvent::Leave) && (obj == hoverWidget) ) { QWidget* button = static_cast(obj); hoverWidget = 0; //only animate widgets that support animation :-) if(_animateButton && !::qt_cast(obj) && !::qt_cast(obj)){ animWidgets[button].active = false; // if timer isn't running, start it now for glow-out animation. if( !btnAnimTimer->isActive() ) btnAnimTimer->start( TIMERINTERVAL, false ); } button->repaint(false); } return false; } if ( ::qt_cast(obj) ) { if ((ev->type() == QEvent::Enter) && static_cast(obj)->isEnabled()) { QWidget* tabbar = static_cast(obj); hoverWidget = tabbar; hoverTab = 0; tabbar->repaint(false); } else if (ev->type() == QEvent::MouseMove) { QTabBar *tabbar = dynamic_cast(obj); QMouseEvent *me = dynamic_cast(ev); if (tabbar && me) { // avoid unnecessary repaints (which otherwise would occour on every // MouseMove event causing high cpu load). bool repaint = true; QTab *tab = tabbar->selectTab(me->pos() ); if (hoverTab == tab) repaint = false; hoverTab = tab; if (repaint) tabbar->repaint(false); } } else if (ev->type() == QEvent::Leave) { QWidget* tabbar = static_cast(obj); hoverWidget = 0; hoverTab = 0; tabbar->repaint(false); } return false; } // Track show events for progress bars if ( _animateProgressBar && ::qt_cast(obj) ) { if ((ev->type() == QEvent::Show) && !animationTimer->isActive()) { animationTimer->start( 50, false ); } } if ( !qstrcmp(obj->name(), "kde toolbar widget") ) { QWidget* lb = static_cast(obj); if (lb->backgroundMode() == Qt::PaletteButton) lb->setBackgroundMode(Qt::PaletteBackground); lb->removeEventFilter(this); } return false; } QColor PolyesterStyle::getColor(const QColorGroup &cg, const ColorType t, const bool enabled)const { return getColor(cg, t, enabled?IsEnabled:IsDisabled); } QColor PolyesterStyle::getColor(const QColorGroup &cg, const ColorType t, const WidgetState s)const { const bool enabled = (s != IsDisabled) && ((s == IsEnabled) || (s == IsPressed) || (s == IsHighlighted)); const bool pressed = (s == IsPressed); const bool highlighted = (s == IsHighlighted); switch(t) { case ButtonContour: return enabled ? cg.button().dark(130+_contrast*8) : cg.background().dark(120+_contrast*8); case DragButtonContour: { if(enabled) { if(pressed) return _coloredScrollBar?cg.highlight().dark(130+_contrast*6) :cg.background().dark(130+_contrast*6); // bright else if(highlighted) return _coloredScrollBar?cg.highlight().dark(130+_contrast*9) :cg.background().dark(130+_contrast*9); // dark else return _coloredScrollBar?cg.highlight().dark(130+_contrast*8) :cg.background().dark(130+_contrast*8); // normal } else { return cg.background().dark(120+_contrast*8); } } case DragButtonSurface: { if(enabled) { if(pressed) return _coloredScrollBar?cg.highlight().dark(100-_contrast):cg.button().dark(100-_contrast); // bright else if(highlighted) return _coloredScrollBar?cg.highlight().light(100+_contrast):cg.button().light(100+_contrast); // dark else return _coloredScrollBar?cg.highlight():cg.button(); // normal } else { return cg.background(); } } case PanelContour: return cg.background().dark(160+_contrast*8); case PanelDark: if( !_lightBorder ) return alphaBlendColors(cg.background(), cg.background().dark(120+_contrast*5), 110); else return alphaBlendColors(cg.background(), cg.background().light(120+_contrast*5), 110); case PanelDark2: if( !_lightBorder ) return alphaBlendColors(cg.background(), cg.background().dark(110+_contrast*5), 110); else return alphaBlendColors(cg.background(), cg.background().light(110+_contrast*5), 110); case PanelLight: return alphaBlendColors(cg.background(), cg.background().light(120+_contrast*5), 110); case PanelLight2: return alphaBlendColors(cg.background(), cg.background().light(110+_contrast*5), 110); case MouseOverHighlight: if( _customOverHighlightColor ) return _overHighlightColor; else return cg.highlight(); case FocusHighlight: if( _customFocusHighlightColor ) return _focusHighlightColor; else return cg.highlight(); case CheckMark: if( _customCheckMarkColor ) return _checkMarkColor; else return cg.foreground(); case MenuBarEmphasis: if( _customMenuBarEmphasisColor ) return _menuBarEmphasisColor; else return cg.background(); default: return cg.background(); } }