• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

kdefx

kstyle.cpp

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

kdefx

Skip menu "kdefx"
  • Main Page
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal