/* Lipstik widget style for KDE 3 Copyright (C) 2004-2007 Patrice Tremblay http://www.poplix.info/lipstik based on Plastik: 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öglund 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 ...also based on plastikq, krisp, comix, motifplus, polyester, qtcurve... 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 "lipstik.h" #include "lipstik.moc" #include "misc.h" // some bitmaps for the radio button so it's easier to handle the circle stuff... // 13x13 static const 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 const 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 const 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 const 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 const 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 const 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 const unsigned char checkmark_aa_bits[] = { 0x45, 0x01, 0x28, 0x00, 0x11, 0x01, 0x82, 0x00, 0x44, 0x00, 0x82, 0x00, 0x11, 0x01, 0x28, 0x00, 0x45, 0x01}; static const unsigned char checkmark_dark_bits[] = { 0x82, 0x00, 0x45, 0x01, 0xaa, 0x00, 0x54, 0x00, 0x28, 0x00, 0x74, 0x00, 0xea, 0x00, 0xc5, 0x01, 0x82, 0x00}; static const unsigned char checkmark_light_bits[] = { 0x00, 0xfe, 0x82, 0xfe, 0x44, 0xfe, 0x28, 0xfe, 0x10, 0xfe, 0x08, 0xfe, 0x04, 0xfe, 0x02, 0xfe, 0x00, 0xfe}; static const 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 const unsigned char radiomark_aa_bits[] = { 0x00, 0x00, 0x44, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x00, 0x44, 0x00, 0x00, 0x00}; static const unsigned char radiomark_dark_bits[] = { 0x00, 0x00, 0x38, 0x00, 0x44, 0x00, 0xf2, 0x00, 0xfa, 0x00, 0xfa, 0x00, 0x7c, 0x00, 0x38, 0x00, 0x00, 0x00}; static const 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; // -- Style Plugin Interface ------------------------- class LipstikStylePlugin : public QStylePlugin { public: LipstikStylePlugin() {} ~LipstikStylePlugin() {} QStringList keys() const { return QStringList() << "Lipstik"; } QStyle* create( const QString& key ) { if (key.lower() == "lipstik") return new LipstikStyle; return 0; } }; Q_EXPORT_PLUGIN( LipstikStylePlugin ) // -- end -- LipstikStyle::LipstikStyle() : KStyle( AllowMenuTransparency, ThreeButtonScrollBar), kickerMode(false), kornMode(false), flatMode(false) { hoverWidget = 0; hoverTab = 0; horizontalDots = 0; verticalDots = 0; horizontalLine = 0; verticalLine = 0; QSettings settings; _contrast = settings.readNumEntry("/Qt/KDE/contrast", 6); _defaultMenuStripeColor.setNamedColor( settings.readEntry("/Qt/KWinPalette/activeBackground", "black") ); settings.beginGroup("/lipstikstyle/Settings"); _animateProgressBar = settings.readBoolEntry("/animateProgressBar", false); _drawToolBarSeparator = settings.readBoolEntry("/drawToolBarSeparator", true); _drawToolBarGradient = settings.readBoolEntry("/drawToolBarGradient", false); _invertBarGrad = settings.readBoolEntry("/invertBarGrad", 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") ); _customTabHighlightColor = settings.readBoolEntry("/customTabHighlightColor", false); _tabHighlightColor.setNamedColor( settings.readEntry("/tabHighlightColor", "black") ); _menuSpacing = settings.readNumEntry("/menuSpacing", 5); _toolBarSpacing = settings.readNumEntry("/toolBarSpacing", 0); _drawStatusBarFrame = settings.readBoolEntry("/drawStatusBarFrame", false); _scrollBarStyle = settings.readEntry("/scrollBarStyle", "WindowsStyleScrollBar"); _scrollBarWidth = settings.readEntry("/scrollBarWidth", "Small"); _paintGroove = settings.readBoolEntry("/paintGroove", true); _flatHeaders = settings.readBoolEntry("/flatHeaders", true); _sliderStyle = settings.readEntry("/sliderStyle", "sliderLipstikStyle"); _reverseGradients = settings.readBoolEntry("/reverseGradients", false); _drawTabHighlight = settings.readBoolEntry("/drawTabHighlight", true); _drawToolBarHandle = settings.readBoolEntry("/drawToolBarHandle", true); _coloredMenuBar = settings.readBoolEntry("/coloredMenuBar", false); _menuLeftSideBar = settings.readBoolEntry("/menuLeftSideBar", true); _flatStripe = settings.readBoolEntry("/flatStripe", false); _customMenuStripeColor = settings.readBoolEntry("/customMenuStripeColor", false); _menuStripeColor.setNamedColor( settings.readEntry("/menuStripeColor", "black") ); _alterMenuGradients = settings.readBoolEntry("/alterMenuGradients", true); _sharperMenuGradient = settings.readBoolEntry("/sharperMenuGradient", false); _comboboxColored = settings.readBoolEntry("/comboboxColored", false); _tickCheckMark = settings.readBoolEntry("/tickCheckMark", true); //(Keep the following around for later, I cant make it work now.) //_customArrowColor = settings.readBoolEntry("/customArrowColor", false); //_arrowColor.setNamedColor( settings.readEntry("/arrowColor", "black") ); settings.endGroup(); if( !strcmp(_scrollBarStyle,"WindowsStyleScrollBar" ) ) this->setScrollBarType(KStyle::WindowsStyleScrollBar); else if( !strcmp(_scrollBarStyle,"PlatinumStyleScrollBar" ) ) this->setScrollBarType(KStyle::PlatinumStyleScrollBar); else if( !strcmp(_scrollBarStyle,"NextStyleScrollBar" ) ) this->setScrollBarType(KStyle::NextStyleScrollBar); // setup pixmap cache... pixmapCache = new QIntCache(150000, 499); pixmapCache->setAutoDelete(true); if ( _animateProgressBar ) { animationTimer = new QTimer( this ); connect( animationTimer, SIGNAL(timeout()), this, SLOT(updateProgressPos()) ); } } void LipstikStyle::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(); } LipstikStyle::~LipstikStyle() { delete pixmapCache; delete horizontalDots; delete verticalDots; delete horizontalLine; delete verticalLine; } void LipstikStyle::polish(QApplication* app) { if (!qstrcmp(app->argv()[0], "kicker")) kickerMode = true; else if (!qstrcmp(app->argv()[0], "korn")) kornMode = true; } void LipstikStyle::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->installEventFilter(this); } else if (::qt_cast(widget)) { widget->setMouseTracking(true); widget->installEventFilter(this); } else if (::qt_cast(widget)) { widget->setBackgroundMode( NoBackground ); } else if(::qt_cast(widget)) { widget->setMouseTracking(true); widget->installEventFilter(this); } else if (widget->inherits("QSplitterHandle") || widget->inherits("QDockWindowHandle") ) { widget->installEventFilter(this); } else if (::qt_cast(widget)) { widget->installEventFilter(this); } else if ( !qstrcmp(widget->name(), "kde toolbar 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 ); } else if( !qstrcmp(widget->className(), "KonqFrameStatusBar") ) { // This disables the white background of the KonquerorFrameStatusBar. // When the green led is shown the background is set to // applications cg.midlight() so we override it to standard background. // Thanks Comix! (because this was ugly from day one!) // NOTE: Check if we can set it earlier (before painting), cause // on slow machines we can see the repainting of the bar (from white to background...) QPalette kPalette = QApplication::palette(); kPalette.setColor( QColorGroup::Midlight,kPalette.active().background() ); QApplication::setPalette( kPalette ); } KStyle::polish(widget); } void LipstikStyle::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); } else if (::qt_cast(widget)) { widget->setMouseTracking(false); widget->removeEventFilter(this); } else if (::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); } if ( ::qt_cast(widget) ) { progAnimWidgets.remove(widget); } else if( widget->inherits("KonqFrameStatusBar") ) { widget->removeEventFilter(this); } KStyle::unPolish(widget); } void LipstikStyle::khtmlWidgetDestroyed(QObject* obj) { khtmlWidgets.remove(static_cast(obj)); } void LipstikStyle::progressBarDestroyed(QObject* obj) { progAnimWidgets.remove(static_cast(obj)); } void LipstikStyle::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; 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); } } } void LipstikStyle::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 LipstikStyle::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 and 3. 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); // sides if (drawLeft) { if (horizontal) { 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), colorTop1, baseColor); } else { p->setPen(colorTop1 ); p->drawLine(r.left(), (roundUpperLeft&&drawTop)?r.top()+1:r.top(), r.left(), (roundBottomLeft&&drawBottom)?r.bottom()-1:r.bottom() ); } } if (drawRight) { if (horizontal) { 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, colorBottom1); } else { p->setPen(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) { p->setPen(colorTop1 ); 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), colorTop1, colorTop2); } } if (drawBottom) { if (horizontal) { p->setPen(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, colorBottom1); } } // button area... int width = r.width(); int height = r.height(); if (drawLeft) width--; if (drawRight) width--; if (drawTop) height--; if (drawBottom) height--; renderGradient(p, QRect(drawLeft?r.left()+1:r.left(), drawTop?r.top()+1:r.top(), width, height), colorTop2, colorBottom2, horizontal); // highlighting... if(highlightTop) { p->setPen(alphaBlendColors(colorTop1 , highlightColor, 80) ); 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, 150) ); p->drawLine(highlightLeft?r.left()+1:r.left(), r.top()+1, highlightRight?r.right()-1:r.right(), r.top()+1 ); } if(highlightBottom) { p->setPen(alphaBlendColors(colorBottom1 , highlightColor, 80) ); 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, 150) ); p->drawLine(highlightLeft?r.left()+1:r.left(), r.bottom()-1, highlightRight?r.right()-1:r.right(), r.bottom()-1 ); } if(highlightLeft) { p->setPen(alphaBlendColors(colorTop1 , highlightColor, 80) ); 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, 150) ); 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, 80) ); 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, 150) ); p->drawLine(r.right()-1, highlightTop?r.top()+1:r.top(), r.right()-1, highlightBottom?r.bottom()-1:r.bottom() ); } } void LipstikStyle::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 LipstikStyle::renderButton(QPainter *p, const QRect &r, const QColorGroup &g, bool sunken, bool mouseOver, bool horizontal, bool enabled, bool khtmlMode) 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(mouseOver) { surfaceFlags|=Is_Highlight; surfaceFlags|=Highlight_Top; surfaceFlags|=Highlight_Bottom; surfaceFlags|=Highlight_Right; surfaceFlags|=Highlight_Left; } } } 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(), getColor(g,ButtonContour), contourFlags); renderSurface(p, QRect(r.left()+1, r.top()+1, r.width()-2, r.height()-2), g.background(), g.button(), getColor(g,MouseOverHighlight), _contrast, 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 LipstikStyle::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 LipstikStyle::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; if( _reverseGradients ) { rDiff = ( c2.red()) - (rc = c1.red()); gDiff = ( c2.green()) - (gc = c1.green()); bDiff = ( c2.blue()) - (bc = c1.blue()); } else { rDiff = ( c1.red()) - (rc = c2.red()); gDiff = ( c1.green()) - (gc = c2.green()); bDiff = ( c1.blue()) - (bc = c2.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 LipstikStyle::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.mid()); p->drawConvexPolygon(QPointArray(4, corners)); p->setPen(g.mid()); 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 LipstikStyle::renderMenuBlendPixmap( KPixmap &pix, const QColorGroup &cg, const QPopupMenu* /* popup */ ) const { pix.fill( cg.background().light(105) ); } void LipstikStyle::renderTab(QPainter *p, const QRect &r, const QColorGroup &g, bool mouseOver, const bool selected, const bool bottom, const TabPosition pos, const bool triangular, const 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 (selected) { // 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(_drawTabHighlight) { if(_customTabHighlightColor) { p->setPen( alphaBlendColors(getColor(g,TabHighlight), getColor(g,PanelLight), 180) ); p->drawLine( Rs.x()+1, Rs.y(), Rs.right()-1, Rs.y() ); p->setPen( alphaBlendColors(getColor(g,TabHighlight), getColor(g,PanelLight), 110) ); p->drawLine( Rs.x(), Rs.y()+1, Rs.right(), Rs.y()+1 ); } else { p->setPen( alphaBlendColors(g.highlight(), getColor(g,PanelLight), 180) ); p->drawLine( Rs.x()+1, Rs.y(), Rs.right()-1, Rs.y() ); p->setPen( alphaBlendColors(g.highlight(), getColor(g,PanelLight), 110) ); p->drawLine( Rs.x(), Rs.y()+1, Rs.right(), Rs.y()+1 ); } } } else { p->setPen(alphaBlendColors(g.background(), g.background().dark(160), 100) ); p->drawLine(Rs.x()+1, Rs.bottom(), Rs.right()-1, Rs.bottom() ); renderGradient(p, QRect(Rs.x(), Rs.y(), 1, Rs.height()-1), getColor(g,PanelLight), getColor(g,PanelLight2)); renderGradient(p, QRect(Rs.right(), Rs.y(), 1, Rs.height()-1), getColor(g,PanelDark), getColor(g,PanelDark2)); if(_drawTabHighlight) { p->setPen( alphaBlendColors(g.highlight(), getColor(g,PanelLight), 180) ); //p->setPen(getColor(g,MouseOverHighlight) ); p->drawLine( Rs.x()+1, Rs.bottom(), Rs.right()-1, Rs.bottom() ); p->setPen( alphaBlendColors(g.highlight(), getColor(g,PanelLight), 110) ); p->drawLine( Rs.x(), Rs.bottom()-1, Rs.right(), Rs.bottom()-1 ); } } // 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) ) { p->drawPoint(r.right(), bottom?(triangular?r.bottom()-2:r.bottom()-3):(triangular?r.top()+2:r.top()+3) ); 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); } } // 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 && cornerWidget) ) { 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()-2, Rc.height()-1); } else { Rs = QRect(Rc.x(), bottom?Rc.y():Rc.y()+1, Rc.width()-1, 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|Round_UpperLeft; } else if ( (isLast&&!reverseLayout) || (isFirst&&reverseLayout) ) { contourFlags = Draw_Right|Draw_Top|Round_UpperRight; } else { contourFlags = Draw_Right|Draw_Top; } } else { if ( (isFirst&&!reverseLayout) || (isLast&&reverseLayout) ) { contourFlags = Draw_Left|Draw_Right|Draw_Bottom|Round_BottomLeft; } else if ( (isLast&&!reverseLayout) || (isFirst&&reverseLayout) ) { contourFlags = Draw_Right|Draw_Bottom|Round_BottomRight; } else { contourFlags = Draw_Right|Draw_Bottom; } } 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|Draw_Bottom|Round_UpperLeft; else surfaceFlags |= Draw_Left|Draw_Top|Draw_Bottom|Round_BottomLeft; } else if ( (isLast&&!reverseLayout) || (isFirst&&reverseLayout) ) { if(!bottom) surfaceFlags |= Draw_Right|Draw_Top|Draw_Bottom|Round_UpperRight; else surfaceFlags |= Draw_Right|Draw_Top|Draw_Bottom|Round_BottomRight; } else { surfaceFlags |= 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 LipstikStyle::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; if (horizontal) { int center = r.y()+r.height()/2; renderContour(p, QRect(r.left(), center-2, r.width(), 4), cg.background(), cg.background().dark(enabled?150:130), Draw_Left|Draw_Right|Draw_Top|Draw_Bottom); } else { int center = r.x()+r.width()/2; renderContour(p, QRect(center-2, r.top(), 4, r.height()), cg.background(), cg.background().dark(enabled?150:130), Draw_Left|Draw_Right|Draw_Top|Draw_Bottom); } 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 (_sliderStyle == "sliderLipstikStyle") { if (horizontal) { renderContour(p, QRect(xcenter-9, ycenter-7, 20, 15), cg.background(), contour, Draw_Left|Draw_Right|Draw_Top|Round_UpperLeft|Round_UpperRight| Draw_Bottom|Round_BottomLeft|Round_BottomRight); QRegion mask(xcenter-8, ycenter-6, 18, 13); p->setClipRegion(mask); uint surfaceFlags = Draw_Left|Draw_Right|Draw_Top|Round_UpperLeft|Round_UpperRight| Is_Horizontal; if(!enabled) surfaceFlags |= Is_Disabled; else if(hoverWidget == widget) { surfaceFlags |= Highlight_Right|Highlight_Left; } renderSurface(p, QRect(xcenter-8, ycenter-6, 18, 13), cg.background(), surface, getColor(cg,MouseOverHighlight), _contrast+3, surfaceFlags); renderDot(p, QPoint(xcenter-2, ycenter), surface, true, true ); renderDot(p, QPoint(xcenter+2, ycenter), surface, true, true ); p->setClipping(false); } else { renderContour(p, QRect(xcenter-7, ycenter-9, 16, 20), cg.background(), contour, Draw_Left|Draw_Right|Draw_Top|Round_UpperLeft|Round_UpperRight| Draw_Bottom|Round_BottomLeft|Round_BottomRight); QRegion mask(xcenter-6, ycenter-8, 13, 18); p->setClipRegion(mask); uint surfaceFlags = Draw_Left|Draw_Top|Draw_Bottom|Round_UpperLeft|Round_BottomLeft| Round_UpperRight|Is_Horizontal; if(!enabled) surfaceFlags |= Is_Disabled; else if(hoverWidget == widget) surfaceFlags |= Highlight_Top|Highlight_Bottom; renderSurface(p, QRect(xcenter-6, ycenter-8, 13, 18), cg.background(), surface, getColor(cg,MouseOverHighlight), _contrast+3, surfaceFlags); renderDot(p, QPoint(xcenter, ycenter-2), surface, true, true ); renderDot(p, QPoint(xcenter, ycenter+2), surface, true, true ); p->setClipping(false); } } else if (_sliderStyle == "sliderPlastikStyle") { 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); // 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, 1, 4); mask -= QRegion(xcenter-3, ycenter+5, 1, 3); mask -= QRegion(xcenter-2, ycenter+6, 1, 2); mask -= QRegion(xcenter-1, ycenter+7, 1, 1); mask -= QRegion(xcenter+1, ycenter+7, 1, 1); mask -= QRegion(xcenter+2, ycenter+6, 1, 2); mask -= QRegion(xcenter+3, ycenter+5, 1, 3); mask -= QRegion(xcenter+4, ycenter+4, 1, 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); // 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+5, ycenter-3, 3, 1); mask -= QRegion(xcenter+6, ycenter-2, 2, 1); mask -= QRegion(xcenter+7, ycenter-1, 1, 1); mask -= QRegion(xcenter+7, ycenter+1, 1, 1); mask -= QRegion(xcenter+6, ycenter+2, 2, 1); mask -= QRegion(xcenter+5, ycenter+3, 3, 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); } } else { if (horizontal) { renderContour(p, QRect(xcenter-16, ycenter-7, 33, 15), cg.background(), contour, Draw_Left|Draw_Right|Draw_Top|Round_UpperLeft|Round_UpperRight| Draw_Bottom|Round_BottomLeft|Round_BottomRight); QRegion mask(xcenter-15, ycenter-6, 31, 13); p->setClipRegion(mask); uint surfaceFlags = Draw_Left|Draw_Right|Draw_Top|Round_UpperLeft|Round_UpperRight| Is_Horizontal; if(!enabled) surfaceFlags |= Is_Disabled; else if(hoverWidget == widget) { surfaceFlags |= Highlight_Right|Highlight_Left; } renderSurface(p, QRect(xcenter-15, ycenter-6, 31, 13), cg.background(), surface, getColor(cg,MouseOverHighlight), _contrast+3, surfaceFlags); renderDot(p, QPoint(xcenter-4, ycenter), surface, true, true ); renderDot(p, QPoint(xcenter, ycenter), surface, true, true ); renderDot(p, QPoint(xcenter+4, ycenter), surface, true, true ); p->setClipping(false); } else { renderContour(p, QRect(xcenter-7, ycenter-16, 16, 33), cg.background(), contour, Draw_Left|Draw_Right|Draw_Top|Round_UpperLeft|Round_UpperRight|Draw_Bottom|Round_BottomLeft|Round_BottomRight); QRegion mask(xcenter-6, ycenter-15, 13, 31); p->setClipRegion(mask); uint surfaceFlags = Draw_Left|Draw_Top|Draw_Bottom|Round_UpperLeft|Round_BottomLeft| Round_UpperRight|Is_Horizontal; if(!enabled) surfaceFlags |= Is_Disabled; else if(hoverWidget == widget) surfaceFlags |= Highlight_Top|Highlight_Bottom; renderSurface(p, QRect(xcenter-6, ycenter-15, 13, 31), cg.background(), surface, getColor(cg,MouseOverHighlight), _contrast+3, surfaceFlags); renderDot(p, QPoint(xcenter, ycenter-4), surface, true, true ); renderDot(p, QPoint(xcenter, ycenter), surface, true, true ); renderDot(p, QPoint(xcenter, ycenter+4), surface, true, 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 LipstikStyle::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) { QPen old = p->pen(); p->setPen( alphaBlendColors(cg.highlight(), getColor(cg,PanelLight), 120) ); p->drawRect( QRect(r.topLeft(), r.bottomRight())); p->setPen(old); } else { p->drawWinFocusRect( r ); } 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) { // Pat: Here I add another header painting method to // optionnally give headers a "flat" look. if(_flatHeaders) { p->fillRect( r.left(), r.top(), r.width(), r.height(), cg.background() ); p->setPen( cg.background().dark(110) ); p->drawLine( r.left(), r.bottom(), r.right(), r.bottom() ); p->drawLine( r.right(), r.bottom(), r.right(), r.top() ); break; } else { // detect if this is the left most header item bool isFirst = false; QHeader *header = dynamic_cast(p->device() ); if (header) { isFirst = header->mapToIndex(header->sectionAt(r.x() ) ) == 0; } uint contourFlags = Draw_Right|Draw_Top|Draw_Bottom; if (isFirst) contourFlags |= Draw_Left; if(!enabled) contourFlags|=Is_Disabled; renderContour(p, r, cg.background(), getColor(cg,ButtonContour), contourFlags); uint surfaceFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom|Is_Horizontal; if(!enabled) surfaceFlags|=Is_Disabled; else { if(on||down) surfaceFlags|=Is_Sunken; else { if(mouseOver) { surfaceFlags|=Is_Highlight|Highlight_Top|Highlight_Bottom; } } } renderSurface(p, QRect(isFirst?r.left()+1:r.left(), r.top()+1, isFirst?r.width()-2:r.width()-1, r.height()-2), cg.background(), cg.button(), getColor(cg,MouseOverHighlight), _contrast, surfaceFlags); break; } } } case PE_ButtonBevel: case PE_ButtonTool: case PE_ButtonDropDown: case PE_ButtonCommand: { bool khtmlMode = opt.isDefault() ? false : khtmlWidgets.contains(opt.widget()); renderButton(p, r, cg, (on||down), mouseOver, true, enabled, khtmlMode ); 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.highlight(), 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: { const WidgetState s = enabled?(down?IsPressed:IsEnabled):IsDisabled; const QColor surface = getColor(cg, DragButtonSurface, s); bool scrollbarHighlighted = false; uint contourFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom; if(!enabled) contourFlags|=Is_Disabled; renderContour(p, r, cg.background(), getColor(cg, DragButtonContour, s), contourFlags); uint surfaceFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom|Is_Horizontal; if(hoverWidget == p->device()) { scrollbarHighlighted = true; if(horiz) surfaceFlags |= Highlight_Right|Highlight_Left; else surfaceFlags |= Highlight_Top|Highlight_Bottom; } if(!enabled) surfaceFlags|=Is_Disabled; if(r.height() >= 4) renderSurface(p, QRect(r.left()+1, r.top()+1, r.width()-2, r.height()-2), cg.background(), surface, scrollbarHighlighted?cg.highlight():cg.background(), _contrast+3, surfaceFlags); //Now draw the dots. p->setPen(alphaBlendColors(cg.background(), surface.dark(enabled?140:120), 50) ); int xPos = r.center().x(); int yPos = r.center().y(); if(horiz) { renderDot(p, QPoint(xPos-6, yPos), surface, true, true ); renderDot(p, QPoint(xPos-2, yPos), surface, true, true ); renderDot(p, QPoint(xPos+2, yPos), surface, true, true ); renderDot(p, QPoint(xPos+6, yPos), surface, true, true ); } else { //--xPos; renderDot(p, QPoint(xPos, yPos-6), surface, true, true ); renderDot(p, QPoint(xPos, yPos-2), surface, true, true ); renderDot(p, QPoint(xPos, yPos+2), surface, true, true ); renderDot(p, QPoint(xPos, yPos+6), surface, true, true ); } break; } case PE_ScrollBarAddPage: case PE_ScrollBarSubPage: { // draw double buffered to avoid flicker... QPixmap buffer; if(flags & Style_Horizontal) { buffer.resize(2, r.height() ); } else { buffer.resize(r.width(), 2 ); } QRect br(buffer.rect() ); QPainter bp(&buffer); if (on || down) { bp.fillRect(br, QBrush(cg.mid().dark())); } else { if(flags & Style_Horizontal) { bp.setPen(cg.background().dark(106)); bp.drawLine(br.left(), br.top(), br.right(), br.top()); bp.setPen(cg.background().light(106)); bp.drawLine(br.left(), br.bottom(), br.right(), br.bottom()); bp.fillRect(br.left(), br.top()+1, br.width(), br.height()-2,cg.background()); } else { bp.setPen(cg.background().dark(106)); bp.drawLine(br.left(), br.top(), br.left(), br.bottom()); bp.setPen(cg.background().light(106)); bp.drawLine(br.right(), br.top(), br.right(), br.bottom()); bp.fillRect(br.left()+1, br.top(), br.width()-2, br.height(),cg.background()); } } bp.fillRect(br, QBrush(cg.background().light(), _paintGroove?Dense4Pattern:SolidPattern)); bp.end(); p->drawTiledPixmap(r, buffer, QPoint(0, r.top()%2) ); break; } // SCROLLBAR BUTTONS // ----------------- case PE_ScrollBarSubLine: { uint contourFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom; uint surfaceFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom; if(down) surfaceFlags|=Is_Sunken; if(!enabled) { contourFlags|=Is_Disabled; surfaceFlags|=Is_Disabled; } if(horiz) { contourFlags |= Round_UpperLeft|Round_BottomLeft|Is_Horizontal; surfaceFlags |= Round_UpperLeft|Round_BottomLeft|Is_Horizontal; } else { contourFlags |= Round_UpperLeft|Round_UpperRight|Is_Horizontal; surfaceFlags |= Round_UpperLeft|Round_UpperRight|Is_Horizontal; } renderContour(p, r, cg.background(), getColor(cg, ButtonContour), contourFlags); renderSurface(p, QRect(r.left()+1, r.top()+1, r.width()-2, r.height()-2), 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 contourFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom; uint surfaceFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom; if(down) surfaceFlags|=Is_Sunken; if(!enabled) { contourFlags|=Is_Disabled; surfaceFlags|=Is_Disabled; } if(horiz) { contourFlags |= Round_UpperRight|Round_BottomRight|Is_Horizontal; surfaceFlags |= Round_UpperRight|Round_BottomRight|Is_Horizontal; } else { contourFlags |= Round_BottomLeft|Round_BottomRight|Is_Horizontal; surfaceFlags |= Round_BottomLeft|Round_BottomRight|Is_Horizontal; } renderContour(p, r, cg.background(), getColor(cg, ButtonContour), contourFlags); renderSurface(p, QRect(r.left()+1, r.top()+1, r.width()-2, r.height()-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); QColor checkmarkColor = enabled?getColor(cg,CheckMark):cg.background(); if(flags & Style_Down) { checkmarkColor = alphaBlendColors(contentColor, checkmarkColor, 150); } // draw the radio mark if (flags & Style_On || flags & Style_Down) { bmp = QBitmap(CHECKMARKSIZE, CHECKMARKSIZE, radiomark_dark_bits, true); bmp.setMask(bmp); p->setPen(alphaBlendColors(contentColor, checkmarkColor.dark(150), 50) ); p->drawPixmap(x+2, y+2, bmp); bmp = QBitmap(CHECKMARKSIZE, CHECKMARKSIZE, radiomark_light_bits, true); bmp.setMask(bmp); p->setPen(alphaBlendColors(contentColor, checkmarkColor.dark(125), 50) ); p->drawPixmap(x+2, y+2, bmp); bmp = QBitmap(CHECKMARKSIZE, CHECKMARKSIZE, radiomark_aa_bits, true); bmp.setMask(bmp); p->setPen(alphaBlendColors(contentColor, checkmarkColor.dark(150), 150) ); p->drawPixmap(x+2, y+2, 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.highlight():cg.background(); //p->fillRect(r, color); if (w > h) { if (h > 4) { int ycenter = r.height()/2; for(int k = 2*r.width()/10; k < 8*r.width()/10; k+=5) { renderDot(p, QPoint(k, ycenter-1), color, false, true); } } } else { if (w > 4) { int xcenter = r.width()/2; for(int k = 2*r.height()/10; k < 8*r.height()/10; k+=5) { renderDot(p, QPoint(xcenter-1, k), color, false, 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 { p->setPen(contentColor.dark(130) ); } 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(_drawStatusBarFrame) { // renderButton(p, r, cg, true, false, true, true, false ); renderContour(p, r, cg.background(), cg.background().dark(130), 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: { renderContour(p, r, cg.background(), cg.background().dark(200), Draw_Left|Draw_Right|Draw_Top|Draw_Bottom); 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); bool horizontal=false; if ( r.width() > r.height() ) { horizontal=true; } if (_drawToolBarGradient) { if (_invertBarGrad) { renderGradient(p, r, cg.background().dark(105), cg.background(), horizontal); } else { renderGradient(p, r, cg.background(), cg.background().dark(105), horizontal); } } else { p->fillRect(r, cg.background()); } if (_drawToolBarSeparator) { 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->fillRect(r, cg.background()); } break; } // TOOLBAR/DOCK WINDOW HANDLE // -------------------------- case PE_DockWindowResizeHandle: { renderButton(p, r, cg); break; } case PE_DockWindowHandle: { // In all cases, fill the background. QColor handleDotColor=cg.background(); //bool horiz=false; //if ( r.width() > r.height() ) { //horiz=true; //} if (_drawToolBarGradient) { if (_invertBarGrad) { renderGradient(p, r, cg.background().dark(105), cg.background(), horiz); } else { renderGradient(p, r, cg.background(), cg.background().dark(105), horiz); } } else { p->fillRect(r, cg.background()); } if(_drawToolBarHandle) { if (horiz) { int center = r.left() + (r.width()/2) - 2 ; if(hoverWidget == p->device()) handleDotColor = cg.highlight(); for(int j = kickerMode?r.top()+1:r.top()+4; j <= r.bottom()-2; j+=4) { renderDot(p, QPoint(center, j), handleDotColor, kickerMode?true:false, true); } } else { int center = r.top() + (r.height()/2) - 2 ; if(hoverWidget == p->device()) handleDotColor = cg.highlight(); for(int j = kickerMode?r.left()+1:r.left()+4; j <= r.right()-2; j+=5) { renderDot(p, QPoint(j, center+1), handleDotColor, kickerMode?true:false, true); } } } break; } // TOOLBAR SEPARATOR // ----------------- case PE_DockWindowSeparator: { if (_drawToolBarGradient) { if (_invertBarGrad) { renderGradient(p, r, cg.background().dark(105), cg.background(), horiz); } else { renderGradient(p, r, cg.background(), cg.background().dark(105), horiz); } } else { p->fillRect(r, cg.background()); } if (_drawToolBarItemSeparator) { if(horiz) { int center = r.left()+r.width()/2; 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 { int center = r.top()+r.height()/2; 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 ); } } break; } case PE_CheckMark: { // PaT: Complicated by the tick thing. if(_tickCheckMark) { const int markW = r.width() > 7 ? 7 : r.width(); const int markH = markW; int posX = r.x() + ( r.width() - markW )/2; int posY = r.y() + ( r.height() - markH )/2-1; QColor contentColor = enabled?cg.base():cg.background(); // Could do with some optimizing/caching... QPointArray a( markH*2 ); int i, xx, yy; xx = posX; yy = 3 + posY; for ( i=0; isetPen( checkmarkColor ); QPoint offset(1,1); for ( pnt = 0; pnt < (int)a.size(); pnt++ ) a[pnt]; p->drawLineSegments( a ); for ( pnt = 0; pnt < (int)a.size(); pnt++ ) a[pnt]; } else if(flags & Style_Down) { int pnt; QColor checkmarkColor = alphaBlendColors(contentColor, checkmarkColor, 150); p->setPen( checkmarkColor ); QPoint offset(1,1); for ( pnt = 0; pnt < (int)a.size(); pnt++ ) a[pnt]; p->drawLineSegments( a ); for ( pnt = 0; pnt < (int)a.size(); pnt++ ) a[pnt]; } else if(flags & Style_Off) { //Dont move yer ass. } else { int pnt; p->setPen( cg.mid() ); QPoint offset(1,1); for ( pnt = 0; pnt < (int)a.size(); pnt++ ) a[pnt]; p->drawLineSegments( a ); for ( pnt = 0; pnt < (int)a.size(); pnt++ ) a[pnt]; } } else { 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)); } a.translate((r.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 LipstikStyle::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)); p->fillRect( QRect( r.x(), r.y(), r.width(), r.height() ), 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 Rempty(reverseLayout?r.left():r.left()+w-1, r.top(), r.width()-w+1, r.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); renderContour(p, Rcontour, bg, fg.dark(160), reverseLayout ? Draw_Left|Draw_Right|Draw_Top|Draw_Bottom|Round_UpperLeft|Round_BottomLeft : Draw_Left|Draw_Right|Draw_Top|Draw_Bottom|Round_UpperRight|Round_BottomRight); QRegion mask(Rsurface); if(reverseLayout) { mask -= QRegion(Rsurface.left(), Rsurface.top(), 1, 1); mask -= QRegion(Rsurface.left(), Rsurface.bottom(), 1, 1); } else { 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; } // 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(); bool selected = false; if (flags & Style_Selected) selected = true; 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) ); 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 ); const QPushButton* button = static_cast( 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 { p->setPen(cg.buttonText()); 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; } // Make the label indicate if the button is a default button or not drawItem( p, QRect(x, y, w, h), AlignCenter|ShowPrefix, button->colorGroup(), button->isEnabled(), button->pixmap(), button->text(), -1, &button->colorGroup().buttonText() ); if ( flags & Style_HasFocus ) drawPrimitive( PE_FocusRect, p, visualRect( subRect( SR_PushButtonFocusRect, widget ), widget ), cg, flags ); 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 (active && focused) { if(_coloredMenuBar) { if(_alterMenuGradients) { uint contourFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom| Round_UpperLeft|Round_UpperRight|Round_BottomLeft|Round_BottomRight; uint surfaceFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom| Round_UpperLeft|Round_UpperRight|Round_BottomLeft|Round_BottomRight| Is_Horizontal; renderContour(p, r, alphaBlendColors(getColor(cg,MenuStripeColor), cg.background().light( 105 ), 50), cg.highlight().dark(200), contourFlags); renderSurface(p, QRect(r.left()+1, r.top()+1, r.width()-2, r.height()-2), alphaBlendColors(getColor(cg,MenuStripeColor), cg.background().light( 105 ), 50), cg.highlight(), getColor(cg,MouseOverHighlight), _sharperMenuGradient?_contrast+10:_contrast, surfaceFlags); } else { renderSurface(p, r, cg.background(), cg.highlight(), cg.highlight(), _sharperMenuGradient?_contrast+30:_contrast+3, Draw_Top|Draw_Bottom|Is_Horizontal); } p->setPen(cg.highlightedText() ); p->drawText(r, text_flags, mi->text()); } else { if (down) { drawPrimitive(PE_ButtonTool, p, r, cg, flags|Style_Down, opt); } else { drawPrimitive(PE_ButtonTool, p, r, cg, flags, opt); } p->setPen(cg.buttonText() ); p->drawText(r, text_flags, mi->text()); } } else { p->setPen(cg.buttonText() ); 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(); 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 the menu item background if (active) { if (enabled) { if(_alterMenuGradients) { uint contourFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom| Round_UpperLeft|Round_UpperRight|Round_BottomLeft|Round_BottomRight; uint surfaceFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom| Round_UpperLeft|Round_UpperRight|Round_BottomLeft|Round_BottomRight| Is_Horizontal; renderContour(p, r, alphaBlendColors(getColor(cg,MenuStripeColor), cg.background().light( 105 ), 50), cg.highlight().dark(250), contourFlags); renderSurface(p, QRect(r.left()+1, r.top()+1, r.width()-2, r.height()-2), alphaBlendColors(getColor(cg,MenuStripeColor), cg.background().light( 105 ), 50), cg.highlight(), getColor(cg,MouseOverHighlight), _sharperMenuGradient?_contrast+10:_contrast, surfaceFlags); if(_menuLeftSideBar) { p->setPen(getColor(cg,MenuStripeColor)); p->drawPoint(r.left(), r.top()); p->drawPoint(r.left(), r.bottom()); } } else { renderSurface(p, r, cg.background(), cg.highlight(), cg.highlight(), _sharperMenuGradient?_contrast+30:_contrast+3, Draw_Top|Draw_Bottom|Is_Horizontal); } } else { if(_drawFocusRect) { p->setPen(QPen(cg.highlight().dark(130), 1)); p->drawRect(QRect(r.left(), r.top(), r.width(), r.height())); } else { p->drawWinFocusRect( r ); } } } else if ( widget->erasePixmap() && !widget->erasePixmap()->isNull() ) { // Draw the transparency pixmap // Transparency in KDE3/Qt3 is an EVIL hack! Beware! p->drawPixmap( r.topLeft(), *widget->erasePixmap(), r ); } else { // Draw a solid background p->fillRect( r, cg.background().light( 105 ) ); //add a pretty bar on the left side of the menu, now looks good too! if(_menuLeftSideBar && !active) { if(_flatStripe) { p->fillRect( QRect(r.left(),r.top(), checkcol+4,r.bottom()-r.top()+1), getColor(cg, MenuStripeColor) ); } else { if(_reverseGradients) { renderGradient(p, QRect(r.left(),r.top(), checkcol+4,r.bottom()-r.top()+1), getColor(cg, MenuStripeColor), cg.background().light( 105 ), false); } else { renderGradient(p, QRect(r.left(),r.top(), checkcol+4,r.bottom()-r.top()+1),cg.background().light( 105 ), getColor(cg, MenuStripeColor), false); } } } } // Are we a menu item separator? if ( mi->isSeparator() ) { if(_menuLeftSideBar) { p->setPen( cg.mid() ); p->drawLine( r.x()+5+checkcol+4, r.y() + 1, r.right()-5-checkcol-4, r.y() + 1 ); //p->setPen( cg.light() ); //p->drawLine( r.x()+5, r.y() + 2, r.right()-5 , r.y() + 2 ); } else { p->setPen( cg.mid() ); p->drawLine( r.x()+5, r.y() + 1, r.right()-5, r.y() + 1 ); //p->setPen( cg.light() ); //p->drawLine( r.x()+5, r.y() + 2, r.right()-5 , 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; 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 ); // Do we have an icon and are checked at the same time? // Then dont draw the icon, only the check. I believe its more // apparent its checked, compared to an almost invisible pressed background only. if ( checkable && /*!active &&*/ mi->isChecked() ) { qDrawShadePanel( p, cr.x(), cr.y(), cr.width(), cr.height(), cg, true, 1, &cg.brush(QColorGroup::Midlight) ); // Draw the checkmark SFlags cflags = Style_On; if (enabled) cflags |= Style_Enabled; drawPrimitive( PE_CheckMark, p, cr, cg, cflags ); } } // Are we checked? (This time without an icon) else if ( checkable && mi->isChecked() ) { // We only have to draw the background if the menu item is inactive - // if it's active the "pressed" background is already drawn // if ( ! active ) qDrawShadePanel( p, cr.x(), cr.y(), cr.width(), cr.height(), cg, true, 1, &cg.brush(QColorGroup::Midlight) ); // Draw the checkmark SFlags cflags = Style_On; if (enabled) cflags |= Style_Enabled; drawPrimitive( PE_CheckMark, p, cr, cg, cflags ); } // Time to draw the menu item label... int xm = 2 + checkcol + 2; // X position margin if(_menuLeftSideBar) { xm = 2 + checkcol + 2 + 3; // 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(); // Does the menu item draw it's own label? 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.light() ); 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(); } else { // 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 ( 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 ) p->setPen(cg.highlightedText()); else p->setPen(cg.buttonText()); drawPrimitive( arrow, p, vr, cg, Style_Enabled ); } else { p->setPen(cg.buttonText()); drawPrimitive( arrow, p, vr, cg, enabled? Style_Enabled : Style_Default ); } } break; } // Menu and dockwindow empty space // case CE_DockWindowEmptyArea: if (_drawToolBarGradient) { QDockWindow *wind = (QDockWindow*)widget; bool horizontal=false; if ( Qt::Horizontal==wind->orientation() ) { horizontal=true; } if (_invertBarGrad) { renderGradient(p, r, cg.background().dark(105), cg.background(), horizontal); } else { renderGradient(p, r, cg.background(), cg.background().dark(105), horizontal); } } else { p->fillRect(r, cg.background()); } break; case CE_MenuBarEmptyArea: p->fillRect(r, cg.background()); break; default: KStyle::drawControl(element, p, widget, r, cg, flags, opt); } } void LipstikStyle::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 LipstikStyle::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 LipstikStyle::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); // 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(); } const QColor buttonColor = enabled?cg.button():cg.background(); 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 ((widget == hoverWidget) || (flags & Style_MouseOver)) { surfaceFlags |= Is_Highlight; if(editable) surfaceFlags |= Highlight_Left|Highlight_Right; surfaceFlags |= Highlight_Top|Highlight_Bottom; } if(_comboboxColored) { renderSurface(p, RbuttonSurface, cg.background(), getColor(cg,MouseOverHighlight), getColor(cg,MouseOverHighlight), enabled?_contrast+3:(_contrast/2), surfaceFlags); } else { renderSurface(p, RbuttonSurface, cg.background(), buttonColor, getColor(cg,MouseOverHighlight), 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 ((widget == hoverWidget) || (flags & Style_MouseOver)) { surfaceFlags |= Is_Highlight; surfaceFlags |= Highlight_Top|Highlight_Bottom; } renderSurface(p, RcontentSurface, cg.background(), buttonColor, getColor(cg,MouseOverHighlight), 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); } } else { // thin frame around the input area if (_inputFocusHighlight && hasFocus && editable && enabled) { p->setPen( getColor(cg,FocusHighlight).dark(130) ); } else { p->setPen(inputColor.dark(130) ); } 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 ); } if(_comboboxColored) { p->setPen(cg.highlightedText()); } else { 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 p->setPen( cg.buttonText() ); p->setBackgroundColor( cg.button() ); break; } // TOOLBUTTON // ---------- case CC_ToolButton: { const QToolButton *tb = (const QToolButton *) widget; QRect button, menuarea; button = querySubControlMetrics(control, widget, SC_ToolButton, opt); menuarea = querySubControlMetrics(control, widget, SC_ToolButtonMenu, opt); SFlags bflags = flags, mflags = flags; if (kornMode) { drawPrimitive(PE_ButtonTool, p, button, cg, bflags, opt); break; } else { // Tricky... (I'm lucky QtCurve has already gone there... thanks Craig!) if (_drawToolBarGradient) { const QToolBar *tbar=widget->parentWidget() ? ::qt_cast(widget->parentWidget()) : NULL; bool horizontal=false; if ( tbar != NULL ) { if ( Qt::Horizontal==tbar->orientation() ) { horizontal=true; } } if (_invertBarGrad) { renderGradient(p, r, cg.background().dark(105), cg.background(), horizontal); } else { renderGradient(p, r, cg.background(), cg.background().dark(105), horizontal); } } else { p->fillRect(r, cg.background()); } bflags &= ~Style_MouseOver; } if (active & SC_ToolButton) bflags |= Style_Down; if (active & SC_ToolButtonMenu) mflags |= Style_Down; //PaT: Added Mouse Hover FX for TabBar Buttons... Now that // was damn tricky... My proudest achievement! :) // Its not highly efficient, but im fu***ng tired... if (controls & SC_ToolButton) { // If we're pressed, on, or raised... if (bflags & (Style_Down | Style_On | Style_Raised) || widget==hoverWidget) { if ( widget == hoverWidget && tb->parentWidget()->inherits( "KTabWidget" )) { renderButton(p, r, cg, false, true, false, true, false ); } else { drawPrimitive(PE_ButtonTool, p, button, cg, bflags, opt); } } 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, cg, mflags, opt); } drawPrimitive(PE_ArrowDown, p, menuarea, cg, mflags, opt); } if (tb->hasFocus() && !tb->focusProxy()) { QRect fr = tb->rect(); fr.addCoords(2, 2, -2, -2); drawPrimitive(PE_FocusRect, p, fr, cg); } // Set the color for the ToolButton menu indicator p->setPen(cg.buttonText() ); break; } // SPINWIDGETS // ----------- case CC_SpinWidget: { static const unsigned int handleWidth = 15; const QSpinWidget *sw = dynamic_cast(widget); SFlags sflags = flags; PrimitiveElement pe; bool hasFocus = false; if (sw) hasFocus = sw->hasFocus(); const QColor buttonColor = enabled?cg.button():cg.background(); 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); 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 ((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, getColor(cg,MouseOverHighlight), _contrast, surfaceFlags); surfaceFlags = Draw_Left|Draw_Right|Draw_Top|Draw_Bottom|Is_Horizontal; if(reverseLayout) { surfaceFlags |= Round_BottomLeft; } else { surfaceFlags |= Round_BottomRight; } if ((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, getColor(cg,MouseOverHighlight), _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(130) ); } else { p->setPen(inputColor.dark(130) ); } 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 LipstikStyle::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 LipstikStyle::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 LipstikStyle::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; } // extra space between menubar items case PM_MenuBarItemSpacing: { return 3 + _menuSpacing; } // // extra space between toolbar items // // causes weird bugs... // case PM_ToolBarItemSpacing: { // return 4; // } // SCROLL BAR case PM_ScrollBarSliderMin: { return 26; } case PM_ScrollBarExtent: { if (_scrollBarWidth == "Small" ) { return 14; } else if (_scrollBarWidth == "Normal" ) { return 16; } else { return 18; } } case PM_DockWindowSeparatorExtent: return 6; // SPLITTERS // --------- case PM_SplitterWidth: { return 6; } // PROGRESSBARS // ------------ case PM_ProgressBarChunkWidth: return 10; // SLIDER // ------ case PM_SliderLength: { if (_sliderStyle == "sliderLipstikStyle" ) { return 20; } else if (_sliderStyle == "sliderPlastikStyle" ) { return 11; } else { return 33; } } // 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; 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); } } QSize LipstikStyle::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() + _menuSpacing; 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()) { h = h - _menuSpacing; } else if (mi->isSeparator()) { w = 20; h = 2; } else { if (mi->pixmap()) { h = QMAX(h, mi->pixmap()->height() + 2); } else { h = QMAX(h, 16 + 2); h = QMAX(h, popup->fontMetrics().height() + 4 ); } 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+_toolBarSpacing, 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 LipstikStyle::styleHint( StyleHint stylehint, const QWidget *widget, const QStyleOption &option, QStyleHintReturn* returnData ) const { switch (stylehint) { case SH_PopupMenu_SubMenuPopupDelay: return 96; // Motif-like delay... default: return KStyle::styleHint(stylehint, widget, option, returnData); } } bool LipstikStyle::eventFilter(QObject *obj, QEvent *ev) { if (KStyle::eventFilter(obj, ev) ) return true; if (!obj->isWidgetType() ) return 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) || ::qt_cast(obj) || ::qt_cast(obj) || obj->inherits("QDockWindowHandle") || obj->inherits("QSplitterHandle") ) { if ((ev->type() == QEvent::Enter) && static_cast(obj)->isEnabled()) { QWidget* button = static_cast(obj); hoverWidget = button; button->repaint(false); } else if ((ev->type() == QEvent::Leave) && (obj == hoverWidget) ) { QWidget* button = static_cast(obj); hoverWidget = 0; 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 LipstikStyle::getColor(const QColorGroup &cg, const ColorType t, const bool enabled)const { return getColor(cg, t, enabled?IsEnabled:IsDisabled); } QColor LipstikStyle::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 cg.button().dark(130+_contrast*6); // bright else if(highlighted) return cg.button().dark(130+_contrast*9); // dark else return cg.button().dark(130+_contrast*8); // normal } else { return cg.background().dark(120+_contrast*8); } } case DragButtonSurface: { if(enabled) { if(pressed) return cg.button().dark(100-_contrast); // bright else if(highlighted) return cg.button().light(100+_contrast); // dark else return cg.button(); // normal } else { return cg.background(); } } case PanelContour: return cg.background().dark(130+_contrast*8); case PanelDark: return alphaBlendColors(cg.background(), cg.background().dark(100+_contrast*5), 110); case PanelDark2: return alphaBlendColors(cg.background(), cg.background().dark(90+_contrast*5), 110); case PanelLight: return alphaBlendColors(cg.background(), cg.background().light(100+_contrast*5), 110); case PanelLight2: return alphaBlendColors(cg.background(), cg.background().light(90+_contrast*5), 110); case MouseOverHighlight: if( _customOverHighlightColor ) return _overHighlightColor; else return cg.highlight(); case MenuStripeColor: if( _customMenuStripeColor ) return _menuStripeColor; else return alphaBlendColors(_defaultMenuStripeColor, cg.background().light(110), 110); case FocusHighlight: if( _customFocusHighlightColor ) return _focusHighlightColor; else return cg.highlight(); case CheckMark: if( _customCheckMarkColor ) return _checkMarkColor; else return cg.highlight().dark(130); case TabHighlight: if( _customTabHighlightColor ) return _tabHighlightColor; else return cg.highlight(); // case Arrows: // if( _customArrowColor ) // return _arrowColor; // else // return cg.buttonText(); default: return cg.background(); } }