kdefx Library: kstyle.cpp Source File (kdefx Library)

| # kdefx Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# kstyle.cpp

    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., 59 Temple Place - Suite 330,
    00023  * Boston, MA 02111-1307, 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 #if QT_VERSION >= 0x030300
    00987         case PM_MenuBarItemSpacing:
    00988             return 5;
    00989
    00990         case PM_ToolBarItemSpacing:
    00991             return 0;
    00992 #endif
    00993         case PM_PopupMenuScrollerHeight:
    00994             return pixelMetric( PM_ScrollBarExtent, 0);
    00995
    00996         default:
    00997             return QCommonStyle::pixelMetric( m, widget );
    00998     }
    00999 }
    01000
    01001 //Helper to find the next sibling that's not hidden
    01002 static QListViewItem* nextVisibleSibling(QListViewItem* item)
    01003 {
    01004     QListViewItem* sibling = item;
    01005     do
    01006     {
    01007         sibling = sibling->nextSibling();
    01008     }
    01009     while (sibling && !sibling->isVisible());
    01010
    01011     return sibling;
    01012 }
    01013
    01014 void KStyle::drawComplexControl( ComplexControl control,
    01015                                  QPainter* p,
    01016                                  const QWidget* widget,
    01017                                  const QRect &r,
    01018                                  const QColorGroup &cg,
    01019                                  SFlags flags,
    01020                                  SCFlags controls,
    01021                                  SCFlags active,
    01022                                  const QStyleOption &opt ) const
    01023 {
    01024     switch(control)
    01025     {
    01026         // 3 BUTTON SCROLLBAR
    01027         // ------------------------------------------------------------------------
    01028         case CC_ScrollBar: {
    01029             // Many thanks to Brad Hughes for contributing this code.
    01030             bool useThreeButtonScrollBar = (d->scrollbarType & ThreeButtonScrollBar);
    01031
    01032             const QScrollBar *sb = (const QScrollBar*)widget;
    01033             bool   maxedOut   = (sb->minValue()    == sb->maxValue());
    01034             bool   horizontal = (sb->orientation() == Qt::Horizontal);
    01035             SFlags sflags     = ((horizontal ? Style_Horizontal : Style_Default) |
    01036                                  (maxedOut   ? Style_Default : Style_Enabled));
    01037
    01038             QRect  addline, subline, subline2, addpage, subpage, slider, first, last;
    01039             subline = querySubControlMetrics(control, widget, SC_ScrollBarSubLine, opt);
    01040             addline = querySubControlMetrics(control, widget, SC_ScrollBarAddLine, opt);
    01041             subpage = querySubControlMetrics(control, widget, SC_ScrollBarSubPage, opt);
    01042             addpage = querySubControlMetrics(control, widget, SC_ScrollBarAddPage, opt);
    01043             slider  = querySubControlMetrics(control, widget, SC_ScrollBarSlider,  opt);
    01044             first   = querySubControlMetrics(control, widget, SC_ScrollBarFirst,   opt);
    01045             last    = querySubControlMetrics(control, widget, SC_ScrollBarLast,    opt);
    01046             subline2 = addline;
    01047
    01048             if ( useThreeButtonScrollBar )
    01049                 if (horizontal)
    01050                     subline2.moveBy(-addline.width(), 0);
    01051                 else
    01052                     subline2.moveBy(0, -addline.height());
    01053
    01054             // Draw the up/left button set
    01055             if ((controls & SC_ScrollBarSubLine) && subline.isValid()) {
    01056                 drawPrimitive(PE_ScrollBarSubLine, p, subline, cg,
    01057                             sflags | (active == SC_ScrollBarSubLine ?
    01058                                 Style_Down : Style_Default));
    01059
    01060                 if (useThreeButtonScrollBar && subline2.isValid())
    01061                     drawPrimitive(PE_ScrollBarSubLine, p, subline2, cg,
    01062                             sflags | (active == SC_ScrollBarSubLine ?
    01063                                 Style_Down : Style_Default));
    01064             }
    01065
    01066             if ((controls & SC_ScrollBarAddLine) && addline.isValid())
    01067                 drawPrimitive(PE_ScrollBarAddLine, p, addline, cg,
    01068                             sflags | ((active == SC_ScrollBarAddLine) ?
    01069                                         Style_Down : Style_Default));
    01070
    01071             if ((controls & SC_ScrollBarSubPage) && subpage.isValid())
    01072                 drawPrimitive(PE_ScrollBarSubPage, p, subpage, cg,
    01073                             sflags | ((active == SC_ScrollBarSubPage) ?
    01074                                         Style_Down : Style_Default));
    01075
    01076             if ((controls & SC_ScrollBarAddPage) && addpage.isValid())
    01077                 drawPrimitive(PE_ScrollBarAddPage, p, addpage, cg,
    01078                             sflags | ((active == SC_ScrollBarAddPage) ?
    01079                                         Style_Down : Style_Default));
    01080
    01081             if ((controls & SC_ScrollBarFirst) && first.isValid())
    01082                 drawPrimitive(PE_ScrollBarFirst, p, first, cg,
    01083                             sflags | ((active == SC_ScrollBarFirst) ?
    01084                                         Style_Down : Style_Default));
    01085
    01086             if ((controls & SC_ScrollBarLast) && last.isValid())
    01087                 drawPrimitive(PE_ScrollBarLast, p, last, cg,
    01088                             sflags | ((active == SC_ScrollBarLast) ?
    01089                                         Style_Down : Style_Default));
    01090
    01091             if ((controls & SC_ScrollBarSlider) && slider.isValid()) {
    01092                 drawPrimitive(PE_ScrollBarSlider, p, slider, cg,
    01093                             sflags | ((active == SC_ScrollBarSlider) ?
    01094                                         Style_Down : Style_Default));
    01095                 // Draw focus rect
    01096                 if (sb->hasFocus()) {
    01097                     QRect fr(slider.x() + 2, slider.y() + 2,
    01098                              slider.width() - 5, slider.height() - 5);
    01099                     drawPrimitive(PE_FocusRect, p, fr, cg, Style_Default);
    01100                 }
    01101             }
    01102             break;
    01103         }
    01104
    01105
    01106         // SLIDER
    01107         // -------------------------------------------------------------------
    01108         case CC_Slider: {
    01109             const QSlider* slider = (const QSlider*)widget;
    01110             QRect groove = querySubControlMetrics(CC_Slider, widget, SC_SliderGroove, opt);
    01111             QRect handle = querySubControlMetrics(CC_Slider, widget, SC_SliderHandle, opt);
    01112
    01113             // Double-buffer slider for no flicker
    01114             QPixmap pix(widget->size());
    01115             QPainter p2;
    01116             p2.begin(&pix);
    01117
    01118             if ( slider->parentWidget() &&
    01119                  slider->parentWidget()->backgroundPixmap() &&
    01120                  !slider->parentWidget()->backgroundPixmap()->isNull() ) {
    01121                 QPixmap pixmap = *(slider->parentWidget()->backgroundPixmap());
    01122                 p2.drawTiledPixmap(r, pixmap, slider->pos());
    01123             } else
    01124                 pix.fill(cg.background());
    01125
    01126             // Draw slider groove
    01127             if ((controls & SC_SliderGroove) && groove.isValid()) {
    01128                 drawKStylePrimitive( KPE_SliderGroove, &p2, widget, groove, cg, flags, opt );
    01129
    01130                 // Draw the focus rect around the groove
    01131                 if (slider->hasFocus())
    01132                     drawPrimitive(PE_FocusRect, &p2, groove, cg);
    01133             }
    01134
    01135             // Draw the tickmarks
    01136             if (controls & SC_SliderTickmarks)
    01137                 QCommonStyle::drawComplexControl(control, &p2, widget,
    01138                         r, cg, flags, SC_SliderTickmarks, active, opt);
    01139
    01140             // Draw the slider handle
    01141             if ((controls & SC_SliderHandle) && handle.isValid()) {
    01142                 if (active == SC_SliderHandle)
    01143                     flags |= Style_Active;
    01144                 drawKStylePrimitive( KPE_SliderHandle, &p2, widget, handle, cg, flags, opt );
    01145             }
    01146
    01147             p2.end();
    01148             bitBlt((QWidget*)widget, r.x(), r.y(), &pix);
    01149             break;
    01150         }
    01151
    01152         // LISTVIEW
    01153         // -------------------------------------------------------------------
    01154         case CC_ListView: {
    01155
    01156             /*
    01157              * Many thanks to TrollTech AS for donating CC_ListView from QWindowsStyle.
    01158              * CC_ListView code is Copyright (C) 1998-2000 TrollTech AS.
    01159              */
    01160
    01161             // Paint the icon and text.
    01162             if ( controls & SC_ListView )
    01163                 QCommonStyle::drawComplexControl( control, p, widget, r, cg, flags, controls, active, opt );
    01164
    01165             // If we're have a branch or are expanded...
    01166             if ( controls & (SC_ListViewBranch | SC_ListViewExpand) )
    01167             {
    01168                 // If no list view item was supplied, break
    01169                 if (opt.isDefault())
    01170                     break;
    01171
    01172                 QListViewItem *item  = opt.listViewItem();
    01173                 QListViewItem *child = item->firstChild();
    01174
    01175                 int y = r.y();
    01176                 int c;  // dotline vertice count
    01177                 int dotoffset = 0;
    01178                 QPointArray dotlines;
    01179
    01180                 if ( active == SC_All && controls == SC_ListViewExpand ) {
    01181                     // We only need to draw a vertical line
    01182                     c = 2;
    01183                     dotlines.resize(2);
    01184                     dotlines[0] = QPoint( r.right(), r.top() );
    01185                     dotlines[1] = QPoint( r.right(), r.bottom() );
    01186
    01187                 } else {
    01188
    01189                     int linetop = 0, linebot = 0;
    01190                     // each branch needs at most two lines, ie. four end points
    01191                     dotoffset = (item->itemPos() + item->height() - y) % 2;
    01192                     dotlines.resize( item->childCount() * 4 );
    01193                     c = 0;
    01194
    01195                     // skip the stuff above the exposed rectangle
    01196                     while ( child && y + child->height() <= 0 )
    01197                     {
    01198                         y += child->totalHeight();
    01199                         child = nextVisibleSibling(child);
    01200                     }
    01201
    01202                     int bx = r.width() / 2;
    01203
    01204                     // paint stuff in the magical area
    01205                     QListView* v = item->listView();
    01206                     int lh = QMAX( p->fontMetrics().height() + 2 * v->itemMargin(),
    01207                                    QApplication::globalStrut().height() );
    01208                     if ( lh % 2 > 0 )
    01209                         lh++;
    01210
    01211                     // Draw all the expand/close boxes...
    01212                     QRect boxrect;
    01213                     QStyle::StyleFlags boxflags;
    01214                     while ( child && y < r.height() )
    01215                     {
    01216                         linebot = y + lh/2;
    01217                         if ( (child->isExpandable() || child->childCount()) &&
    01218                              (child->height() > 0) )
    01219                         {
    01220                             // The primitive requires a rect.
    01221                             boxrect = QRect( bx-4, linebot-4, 9, 9 );
    01222                             boxflags = child->isOpen() ? QStyle::Style_Off : QStyle::Style_On;
    01223
    01224                             // KStyle extension: Draw the box and expand/collapse indicator
    01225                             drawKStylePrimitive( KPE_ListViewExpander, p, NULL, boxrect, cg, boxflags, opt );
    01226
    01227                             // dotlinery
    01228                             p->setPen( cg.mid() );
    01229                             dotlines[c++] = QPoint( bx, linetop );
    01230                             dotlines[c++] = QPoint( bx, linebot - 5 );
    01231                             dotlines[c++] = QPoint( bx + 5, linebot );
    01232                             dotlines[c++] = QPoint( r.width(), linebot );
    01233                             linetop = linebot + 5;
    01234                         } else {
    01235                             // just dotlinery
    01236                             dotlines[c++] = QPoint( bx+1, linebot );
    01237                             dotlines[c++] = QPoint( r.width(), linebot );
    01238                         }
    01239
    01240                         y += child->totalHeight();
    01241                         child = nextVisibleSibling(child);
    01242                     }
    01243
    01244                     if ( child ) // there's a child to draw, so move linebot to edge of rectangle
    01245                         linebot = r.height();
    01246
    01247                     if ( linetop < linebot )
    01248                     {
    01249                         dotlines[c++] = QPoint( bx, linetop );
    01250                         dotlines[c++] = QPoint( bx, linebot );
    01251                     }
    01252                 }
    01253
    01254                 // Draw all the branches...
    01255                 static int thickness = kPixelMetric( KPM_ListViewBranchThickness );
    01256                 int line; // index into dotlines
    01257                 QRect branchrect;
    01258                 QStyle::StyleFlags branchflags;
    01259                 for( line = 0; line < c; line += 2 )
    01260                 {
    01261                     // assumptions here: lines are horizontal or vertical.
    01262                     // lines always start with the numerically lowest
    01263                     // coordinate.
    01264
    01265                     // point ... relevant coordinate of current point
    01266                     // end ..... same coordinate of the end of the current line
    01267                     // other ... the other coordinate of the current point/line
    01268                     if ( dotlines[line].y() == dotlines[line+1].y() )
    01269                     {
    01270                         // Horizontal branch
    01271                         int end = dotlines[line+1].x();
    01272                         int point = dotlines[line].x();
    01273                         int other = dotlines[line].y();
    01274
    01275                         branchrect  = QRect( point, other-(thickness/2), end-point, thickness );
    01276                         branchflags = QStyle::Style_Horizontal;
    01277
    01278                         // KStyle extension: Draw the horizontal branch
    01279                         drawKStylePrimitive( KPE_ListViewBranch, p, NULL, branchrect, cg, branchflags, opt );
    01280
    01281                     } else {
    01282                         // Vertical branch
    01283                         int end = dotlines[line+1].y();
    01284                         int point = dotlines[line].y();
    01285                         int other = dotlines[line].x();
    01286                         int pixmapoffset = ((point & 1) != dotoffset ) ? 1 : 0;
    01287
    01288                         branchrect  = QRect( other-(thickness/2), point, thickness, end-point );
    01289                         if (!pixmapoffset)  // ### Hackish - used to hint the offset
    01290                             branchflags = QStyle::Style_NoChange;
    01291                         else
    01292                             branchflags = QStyle::Style_Default;
    01293
    01294                         // KStyle extension: Draw the vertical branch
    01295                         drawKStylePrimitive( KPE_ListViewBranch, p, NULL, branchrect, cg, branchflags, opt );
    01296                     }
    01297                 }
    01298             }
    01299             break;
    01300         }
    01301
    01302         default:
    01303             QCommonStyle::drawComplexControl( control, p, widget, r, cg,
    01304                                               flags, controls, active, opt );
    01305             break;
    01306     }
    01307 }
    01308
    01309
    01310 QStyle::SubControl KStyle::querySubControl( ComplexControl control,
    01311                                             const QWidget* widget,
    01312                                             const QPoint &pos,
    01313                                             const QStyleOption &opt ) const
    01314 {
    01315     QStyle::SubControl ret = QCommonStyle::querySubControl(control, widget, pos, opt);
    01316
    01317     if (d->scrollbarType == ThreeButtonScrollBar) {
    01318         // Enable third button
    01319         if (control == CC_ScrollBar && ret == SC_None)
    01320             ret = SC_ScrollBarSubLine;
    01321     }
    01322     return ret;
    01323 }
    01324
    01325
    01326 QRect KStyle::querySubControlMetrics( ComplexControl control,
    01327                                       const QWidget* widget,
    01328                                       SubControl sc,
    01329                                       const QStyleOption &opt ) const
    01330 {
    01331     QRect ret;
    01332
    01333     if (control == CC_ScrollBar)
    01334     {
    01335         bool threeButtonScrollBar = d->scrollbarType & ThreeButtonScrollBar;
    01336         bool platinumScrollBar    = d->scrollbarType & PlatinumStyleScrollBar;
    01337         bool nextScrollBar        = d->scrollbarType & NextStyleScrollBar;
    01338
    01339         const QScrollBar *sb = (const QScrollBar*)widget;
    01340         bool horizontal = sb->orientation() == Qt::Horizontal;
    01341         int sliderstart = sb->sliderStart();
    01342         int sbextent    = pixelMetric(PM_ScrollBarExtent, widget);
    01343         int maxlen      = (horizontal ? sb->width() : sb->height())
    01344                           - (sbextent * (threeButtonScrollBar ? 3 : 2));
    01345         int sliderlen;
    01346
    01347         // calculate slider length
    01348         if (sb->maxValue() != sb->minValue())
    01349         {
    01350             uint range = sb->maxValue() - sb->minValue();
    01351             sliderlen = (sb->pageStep() * maxlen) / (range + sb->pageStep());
    01352
    01353             int slidermin = pixelMetric( PM_ScrollBarSliderMin, widget );
    01354             if ( sliderlen < slidermin || range > INT_MAX / 2 )
    01355                 sliderlen = slidermin;
    01356             if ( sliderlen > maxlen )
    01357                 sliderlen = maxlen;
    01358         } else
    01359             sliderlen = maxlen;
    01360
    01361         // Subcontrols
    01362         switch (sc)
    01363         {
    01364             case SC_ScrollBarSubLine: {
    01365                 // top/left button
    01366                 if (platinumScrollBar) {
    01367                     if (horizontal)
    01368                         ret.setRect(sb->width() - 2 * sbextent, 0, sbextent, sbextent);
    01369                     else
    01370                         ret.setRect(0, sb->height() - 2 * sbextent, sbextent, sbextent);
    01371                 } else
    01372                     ret.setRect(0, 0, sbextent, sbextent);
    01373                 break;
    01374             }
    01375
    01376             case SC_ScrollBarAddLine: {
    01377                 // bottom/right button
    01378                 if (nextScrollBar) {
    01379                     if (horizontal)
    01380                         ret.setRect(sbextent, 0, sbextent, sbextent);
    01381                     else
    01382                         ret.setRect(0, sbextent, sbextent, sbextent);
    01383                 } else {
    01384                     if (horizontal)
    01385                         ret.setRect(sb->width() - sbextent, 0, sbextent, sbextent);
    01386                     else
    01387                         ret.setRect(0, sb->height() - sbextent, sbextent, sbextent);
    01388                 }
    01389                 break;
    01390             }
    01391
    01392             case SC_ScrollBarSubPage: {
    01393                 // between top/left button and slider
    01394                 if (platinumScrollBar) {
    01395                     if (horizontal)
    01396                         ret.setRect(0, 0, sliderstart, sbextent);
    01397                     else
    01398                         ret.setRect(0, 0, sbextent, sliderstart);
    01399                 } else if (nextScrollBar) {
    01400                     if (horizontal)
    01401                         ret.setRect(sbextent*2, 0, sliderstart-2*sbextent, sbextent);
    01402                     else
    01403                         ret.setRect(0, sbextent*2, sbextent, sliderstart-2*sbextent);
    01404                 } else {
    01405                     if (horizontal)
    01406                         ret.setRect(sbextent, 0, sliderstart - sbextent, sbextent);
    01407                     else
    01408                         ret.setRect(0, sbextent, sbextent, sliderstart - sbextent);
    01409                 }
    01410                 break;
    01411             }
    01412
    01413             case SC_ScrollBarAddPage: {
    01414                 // between bottom/right button and slider
    01415                 int fudge;
    01416
    01417                 if (platinumScrollBar)
    01418                     fudge = 0;
    01419                 else if (nextScrollBar)
    01420                     fudge = 2*sbextent;
    01421                 else
    01422                     fudge = sbextent;
    01423
    01424                 if (horizontal)
    01425                     ret.setRect(sliderstart + sliderlen, 0,
    01426                             maxlen - sliderstart - sliderlen + fudge, sbextent);
    01427                 else
    01428                     ret.setRect(0, sliderstart + sliderlen, sbextent,
    01429                             maxlen - sliderstart - sliderlen + fudge);
    01430                 break;
    01431             }
    01432
    01433             case SC_ScrollBarGroove: {
    01434                 int multi = threeButtonScrollBar ? 3 : 2;
    01435                 int fudge;
    01436
    01437                 if (platinumScrollBar)
    01438                     fudge = 0;
    01439                 else if (nextScrollBar)
    01440                     fudge = 2*sbextent;
    01441                 else
    01442                     fudge = sbextent;
    01443
    01444                 if (horizontal)
    01445                     ret.setRect(fudge, 0, sb->width() - sbextent * multi, sb->height());
    01446                 else
    01447                     ret.setRect(0, fudge, sb->width(), sb->height() - sbextent * multi);
    01448                 break;
    01449             }
    01450
    01451             case SC_ScrollBarSlider: {
    01452                 if (horizontal)
    01453                     ret.setRect(sliderstart, 0, sliderlen, sbextent);
    01454                 else
    01455                     ret.setRect(0, sliderstart, sbextent, sliderlen);
    01456                 break;
    01457             }
    01458
    01459             default:
    01460                 ret = QCommonStyle::querySubControlMetrics(control, widget, sc, opt);
    01461                 break;
    01462         }
    01463     } else
    01464         ret = QCommonStyle::querySubControlMetrics(control, widget, sc, opt);
    01465
    01466     return ret;
    01467 }
    01468
    01469 static const char * const kstyle_close_xpm[] = {
    01470 "12 12 2 1",
    01471 "# c #000000",
    01472 ". c None",
    01473 "............",
    01474 "............",
    01475 "..##....##..",
    01476 "...##..##...",
    01477 "....####....",
    01478 ".....##.....",
    01479 "....####....",
    01480 "...##..##...",
    01481 "..##....##..",
    01482 "............",
    01483 "............",
    01484 "............"};
    01485
    01486 static const char * const kstyle_maximize_xpm[]={
    01487 "12 12 2 1",
    01488 "# c #000000",
    01489 ". c None",
    01490 "............",
    01491 "............",
    01492 ".##########.",
    01493 ".##########.",
    01494 ".#........#.",
    01495 ".#........#.",
    01496 ".#........#.",
    01497 ".#........#.",
    01498 ".#........#.",
    01499 ".#........#.",
    01500 ".##########.",
    01501 "............"};
    01502
    01503
    01504 static const char * const kstyle_minimize_xpm[] = {
    01505 "12 12 2 1",
    01506 "# c #000000",
    01507 ". c None",
    01508 "............",
    01509 "............",
    01510 "............",
    01511 "............",
    01512 "............",
    01513 "............",
    01514 "............",
    01515 "...######...",
    01516 "...######...",
    01517 "............",
    01518 "............",
    01519 "............"};
    01520
    01521 static const char * const kstyle_normalizeup_xpm[] = {
    01522 "12 12 2 1",
    01523 "# c #000000",
    01524 ". c None",
    01525 "............",
    01526 "...#######..",
    01527 "...#######..",
    01528 "...#.....#..",
    01529 ".#######.#..",
    01530 ".#######.#..",
    01531 ".#.....#.#..",
    01532 ".#.....###..",
    01533 ".#.....#....",
    01534 ".#.....#....",
    01535 ".#######....",
    01536 "............"};
    01537
    01538
    01539 static const char * const kstyle_shade_xpm[] = {
    01540 "12 12 2 1",
    01541 "# c #000000",
    01542 ". c None",
    01543 "............",
    01544 "............",
    01545 "............",
    01546 "............",
    01547 "............",
    01548 ".....#......",
    01549 "....###.....",
    01550 "...#####....",
    01551 "..#######...",
    01552 "............",
    01553 "............",
    01554 "............"};
    01555
    01556 static const char * const kstyle_unshade_xpm[] = {
    01557 "12 12 2 1",
    01558 "# c #000000",
    01559 ". c None",
    01560 "............",
    01561 "............",
    01562 "............",
    01563 "............",
    01564 "..#######...",
    01565 "...#####....",
    01566 "....###.....",
    01567 ".....#......",
    01568 "............",
    01569 "............",
    01570 "............",
    01571 "............"};
    01572
    01573 static const char * const dock_window_close_xpm[] = {
    01574 "8 8 2 1",
    01575 "# c #000000",
    01576 ". c None",
    01577 "##....##",
    01578 ".##..##.",
    01579 "..####..",
    01580 "...##...",
    01581 "..####..",
    01582 ".##..##.",
    01583 "##....##",
    01584 "........"};
    01585
    01586 // Message box icons, from page 210 of the Windows style guide.
    01587
    01588 // Hand-drawn to resemble Microsoft's icons, but in the Mac/Netscape
    01589 // palette.  The "question mark" icon, which Microsoft recommends not
    01590 // using but a lot of people still use, is left out.
    01591
    01592 /* XPM */
    01593 static const char * const information_xpm[]={
    01594 "32 32 5 1",
    01595 ". c None",
    01596 "c c #000000",
    01597 "* c #999999",
    01598 "a c #ffffff",
    01599 "b c #0000ff",
    01600 "...........********.............",
    01601 "........***aaaaaaaa***..........",
    01602 "......**aaaaaaaaaaaaaa**........",
    01603 ".....*aaaaaaaaaaaaaaaaaa*.......",
    01604 "....*aaaaaaaabbbbaaaaaaaac......",
    01605 "...*aaaaaaaabbbbbbaaaaaaaac.....",
    01606 "..*aaaaaaaaabbbbbbaaaaaaaaac....",
    01607 ".*aaaaaaaaaaabbbbaaaaaaaaaaac...",
    01608 ".*aaaaaaaaaaaaaaaaaaaaaaaaaac*..",
    01609 "*aaaaaaaaaaaaaaaaaaaaaaaaaaaac*.",
    01610 "*aaaaaaaaaabbbbbbbaaaaaaaaaaac*.",
    01611 "*aaaaaaaaaaaabbbbbaaaaaaaaaaac**",
    01612 "*aaaaaaaaaaaabbbbbaaaaaaaaaaac**",
    01613 "*aaaaaaaaaaaabbbbbaaaaaaaaaaac**",
    01614 "*aaaaaaaaaaaabbbbbaaaaaaaaaaac**",
    01615 "*aaaaaaaaaaaabbbbbaaaaaaaaaaac**",
    01616 ".*aaaaaaaaaaabbbbbaaaaaaaaaac***",
    01617 ".*aaaaaaaaaaabbbbbaaaaaaaaaac***",
    01618 "..*aaaaaaaaaabbbbbaaaaaaaaac***.",
    01619 "...caaaaaaabbbbbbbbbaaaaaac****.",
    01620 "....caaaaaaaaaaaaaaaaaaaac****..",
    01621 ".....caaaaaaaaaaaaaaaaaac****...",
    01622 "......ccaaaaaaaaaaaaaacc****....",
    01623 ".......*cccaaaaaaaaccc*****.....",
    01624 "........***cccaaaac*******......",
    01625 "..........****caaac*****........",
    01626 ".............*caaac**...........",
    01627 "...............caac**...........",
    01628 "................cac**...........",
    01629 ".................cc**...........",
    01630 "..................***...........",
    01631 "...................**..........."};
    01632 /* XPM */
    01633 static const char* const warning_xpm[]={
    01634 "32 32 4 1",
    01635 ". c None",
    01636 "a c #ffff00",
    01637 "* c #000000",
    01638 "b c #999999",
    01639 ".............***................",
    01640 "............*aaa*...............",
    01641 "...........*aaaaa*b.............",
    01642 "...........*aaaaa*bb............",
    01643 "..........*aaaaaaa*bb...........",
    01644 "..........*aaaaaaa*bb...........",
    01645 ".........*aaaaaaaaa*bb..........",
    01646 ".........*aaaaaaaaa*bb..........",
    01647 "........*aaaaaaaaaaa*bb.........",
    01648 "........*aaaa***aaaa*bb.........",
    01649 ".......*aaaa*****aaaa*bb........",
    01650 ".......*aaaa*****aaaa*bb........",
    01651 "......*aaaaa*****aaaaa*bb.......",
    01652 "......*aaaaa*****aaaaa*bb.......",
    01653 ".....*aaaaaa*****aaaaaa*bb......",
    01654 ".....*aaaaaa*****aaaaaa*bb......",
    01655 "....*aaaaaaaa***aaaaaaaa*bb.....",
    01656 "....*aaaaaaaa***aaaaaaaa*bb.....",
    01657 "...*aaaaaaaaa***aaaaaaaaa*bb....",
    01658 "...*aaaaaaaaaa*aaaaaaaaaa*bb....",
    01659 "..*aaaaaaaaaaa*aaaaaaaaaaa*bb...",
    01660 "..*aaaaaaaaaaaaaaaaaaaaaaa*bb...",
    01661 ".*aaaaaaaaaaaa**aaaaaaaaaaa*bb..",
    01662 ".*aaaaaaaaaaa****aaaaaaaaaa*bb..",
    01663 "*aaaaaaaaaaaa****aaaaaaaaaaa*bb.",
    01664 "*aaaaaaaaaaaaa**aaaaaaaaaaaa*bb.",
    01665 "*aaaaaaaaaaaaaaaaaaaaaaaaaaa*bbb",
    01666 "*aaaaaaaaaaaaaaaaaaaaaaaaaaa*bbb",
    01667 ".*aaaaaaaaaaaaaaaaaaaaaaaaa*bbbb",
    01668 "..*************************bbbbb",
    01669 "....bbbbbbbbbbbbbbbbbbbbbbbbbbb.",
    01670 ".....bbbbbbbbbbbbbbbbbbbbbbbbb.."};
    01671 /* XPM */
    01672 static const char* const critical_xpm[]={
    01673 "32 32 4 1",
    01674 ". c None",
    01675 "a c #999999",
    01676 "* c #ff0000",
    01677 "b c #ffffff",
    01678 "...........********.............",
    01679 ".........************...........",
    01680 ".......****************.........",
    01681 "......******************........",
    01682 ".....********************a......",
    01683 "....**********************a.....",
    01684 "...************************a....",
    01685 "..*******b**********b*******a...",
    01686 "..******bbb********bbb******a...",
    01687 ".******bbbbb******bbbbb******a..",
    01688 ".*******bbbbb****bbbbb*******a..",
    01689 "*********bbbbb**bbbbb*********a.",
    01690 "**********bbbbbbbbbb**********a.",
    01691 "***********bbbbbbbb***********aa",
    01692 "************bbbbbb************aa",
    01693 "************bbbbbb************aa",
    01694 "***********bbbbbbbb***********aa",
    01695 "**********bbbbbbbbbb**********aa",
    01696 "*********bbbbb**bbbbb*********aa",
    01697 ".*******bbbbb****bbbbb*******aa.",
    01698 ".******bbbbb******bbbbb******aa.",
    01699 "..******bbb********bbb******aaa.",
    01700 "..*******b**********b*******aa..",
    01701 "...************************aaa..",
    01702 "....**********************aaa...",
    01703 "....a********************aaa....",
    01704 ".....a******************aaa.....",
    01705 "......a****************aaa......",
    01706 ".......aa************aaaa.......",
    01707 ".........aa********aaaaa........",
    01708 "...........aaaaaaaaaaa..........",
    01709 ".............aaaaaaa............"};
    01710
    01711 QPixmap KStyle::stylePixmap( StylePixmap stylepixmap,
    01712                           const QWidget* widget,
    01713                           const QStyleOption& opt) const
    01714 {
    01715     switch (stylepixmap) {
    01716         case SP_TitleBarShadeButton:
    01717             return QPixmap(const_cast<const char**>(kstyle_shade_xpm));
    01718         case SP_TitleBarUnshadeButton:
    01719             return QPixmap(const_cast<const char**>(kstyle_unshade_xpm));
    01720         case SP_TitleBarNormalButton:
    01721             return QPixmap(const_cast<const char**>(kstyle_normalizeup_xpm));
    01722         case SP_TitleBarMinButton:
    01723             return QPixmap(const_cast<const char**>(kstyle_minimize_xpm));
    01724         case SP_TitleBarMaxButton:
    01725             return QPixmap(const_cast<const char**>(kstyle_maximize_xpm));
    01726         case SP_TitleBarCloseButton:
    01727             return QPixmap(const_cast<const char**>(kstyle_close_xpm));
    01728         case SP_DockWindowCloseButton:
    01729             return QPixmap(const_cast<const char**>(dock_window_close_xpm ));
    01730         case SP_MessageBoxInformation:
    01731             return QPixmap(const_cast<const char**>(information_xpm));
    01732         case SP_MessageBoxWarning:
    01733             return QPixmap(const_cast<const char**>(warning_xpm));
    01734         case SP_MessageBoxCritical:
    01735             return QPixmap(const_cast<const char**>(critical_xpm));
    01736         default:
    01737             break;
    01738     }
    01739     return QCommonStyle::stylePixmap(stylepixmap, widget, opt);
    01740 }
    01741
    01742
    01743 int KStyle::styleHint( StyleHint sh, const QWidget* w,
    01744                        const QStyleOption &opt, QStyleHintReturn* shr) const
    01745 {
    01746     switch (sh)
    01747     {
    01748         case SH_EtchDisabledText:
    01749             return d->etchDisabledText ? 1 : 0;
    01750
    01751         case SH_PopupMenu_Scrollable:
    01752             return d->scrollablePopupmenus ? 1 : 0;
    01753
    01754         case SH_MenuBar_AltKeyNavigation:
    01755             return d->menuAltKeyNavigation ? 1 : 0;
    01756
    01757         case SH_PopupMenu_SubMenuPopupDelay:
    01758             if ( styleHint( SH_PopupMenu_SloppySubMenus, w ) )
    01759                 return QMIN( 100, d->popupMenuDelay );
    01760             else
    01761                 return d->popupMenuDelay;
    01762
    01763         case SH_PopupMenu_SloppySubMenus:
    01764             return d->sloppySubMenus;
    01765
    01766         case SH_ItemView_ChangeHighlightOnFocus:
    01767         case SH_Slider_SloppyKeyEvents:
    01768         case SH_MainWindow_SpaceBelowMenuBar:
    01769         case SH_PopupMenu_AllowActiveAndDisabled:
    01770             return 0;
    01771
    01772         case SH_Slider_SnapToValue:
    01773         case SH_PrintDialog_RightAlignButtons:
    01774         case SH_FontDialog_SelectAssociatedText:
    01775         case SH_MenuBar_MouseTracking:
    01776         case SH_PopupMenu_MouseTracking:
    01777         case SH_ComboBox_ListMouseTracking:
    01778         case SH_ScrollBar_MiddleClickAbsolutePosition:
    01779             return 1;
    01780
    01781         default:
    01782             return QCommonStyle::styleHint(sh, w, opt, shr);
    01783     }
    01784 }
    01785
    01786
    01787 bool KStyle::eventFilter( QObject* object, QEvent* event )
    01788 {
    01789     if ( d->useFilledFrameWorkaround )
    01790     {
    01791         // Make the QMenuBar/QToolBar paintEvent() cover a larger area to
    01792         // ensure that the filled frame contents are properly painted.
    01793         // We essentially modify the paintEvent's rect to include the
    01794         // panel border, which also paints the widget's interior.
    01795         // This is nasty, but I see no other way to properly repaint
    01796         // filled frames in all QMenuBars and QToolBars.
    01797         // -- Karol.
    01798         QFrame *frame = 0;
    01799         if ( event->type() == QEvent::Paint
    01800                 && (frame = ::qt_cast<QFrame*>(object)) )
    01801         {
    01802             if (frame->frameShape() != QFrame::ToolBarPanel && frame->frameShape() != QFrame::MenuBarPanel)
    01803                 return false;
    01804
    01805             bool horizontal = true;
    01806             QPaintEvent* pe = (QPaintEvent*)event;
    01807             QToolBar *toolbar = ::qt_cast< QToolBar *>( frame );
    01808             QRect r = pe->rect();
    01809
    01810             if (toolbar && toolbar->orientation() == Qt::Vertical)
    01811                 horizontal = false;
    01812
    01813             if (horizontal) {
    01814                 if ( r.height() == frame->height() )
    01815                     return false;   // Let QFrame handle the painting now.
    01816
    01817                 // Else, send a new paint event with an updated paint rect.
    01818                 QPaintEvent dummyPE( QRect( r.x(), 0, r.width(), frame->height()) );
    01819                 QApplication::sendEvent( frame, &dummyPE );
    01820             }
    01821             else {  // Vertical
    01822                 if ( r.width() == frame->width() )
    01823                     return false;
    01824
    01825                 QPaintEvent dummyPE( QRect( 0, r.y(), frame->width(), r.height()) );
    01826                 QApplication::sendEvent( frame, &dummyPE );
    01827             }
    01828
    01829             // Discard this event as we sent a new paintEvent.
    01830             return true;
    01831         }
    01832     }
    01833
    01834     return false;
    01835 }
    01836
    01837
    01838 // -----------------------------------------------------------------------------
    01839 // I N T E R N A L -  KStyle menu transparency handler
    01840 // -----------------------------------------------------------------------------
    01841
    01842 TransparencyHandler::TransparencyHandler( KStyle* style,
    01843     TransparencyEngine tEngine, float menuOpacity, bool useDropShadow )
    01844     : QObject()
    01845 {
    01846     te = tEngine;
    01847     kstyle = style;
    01848     opacity = menuOpacity;
    01849     dropShadow = useDropShadow;
    01850     pix.setOptimization(QPixmap::BestOptim);
    01851 }
    01852
    01853 TransparencyHandler::~TransparencyHandler()
    01854 {
    01855 }
    01856
    01857 // This is meant to be ugly but fast.
    01858 void TransparencyHandler::rightShadow(QImage& dst)
    01859 {
    01860     if (dst.depth() != 32)
    01861         dst = dst.convertDepth(32);
    01862
    01863     // blend top-right corner.
    01864     int pixels = dst.width() * dst.height();
    01865 #ifdef WORDS_BIGENDIAN
    01866     register unsigned char* data = dst.bits() + 1;  // Skip alpha
    01867 #else
    01868     register unsigned char* data = dst.bits();      // Skip alpha
    01869 #endif
    01870     for(register int i = 0; i < 16; i++) {
    01871         *data = (unsigned char)((*data)*top_right_corner[i]); data++;
    01872         *data = (unsigned char)((*data)*top_right_corner[i]); data++;
    01873         *data = (unsigned char)((*data)*top_right_corner[i]); data++;
    01874         data++; // skip alpha
    01875     }
    01876
    01877     pixels -= 32;   // tint right strip without rounded edges.
    01878     register int c = 0;
    01879     for(register int i = 0; i < pixels; i++) {
    01880         *data = (unsigned char)((*data)*shadow_strip[c]); data++;
    01881         *data = (unsigned char)((*data)*shadow_strip[c]); data++;
    01882         *data = (unsigned char)((*data)*shadow_strip[c]); data++;
    01883         data++; // skip alpha
    01884             ++c;
    01885         c %= 4;
    01886     }
    01887
    01888     // tint bottom edge
    01889     for(register int i = 0; i < 16; i++) {
    01890         *data = (unsigned char)((*data)*bottom_right_corner[i]); data++;
    01891         *data = (unsigned char)((*data)*bottom_right_corner[i]); data++;
    01892         *data = (unsigned char)((*data)*bottom_right_corner[i]); data++;
    01893         data++; // skip alpha
    01894     }
    01895 }
    01896
    01897 void TransparencyHandler::bottomShadow(QImage& dst)
    01898 {
    01899     if (dst.depth() != 32)
    01900         dst = dst.convertDepth(32);
    01901
    01902     int line = 0;
    01903     int width = dst.width() - 4;
    01904     double strip_data = shadow_strip[0];
    01905     double* corner = const_cast<double*>(bottom_left_corner);
    01906
    01907 #ifdef WORDS_BIGENDIAN
    01908     register unsigned char* data = dst.bits() + 1;  // Skip alpha
    01909 #else
    01910     register unsigned char* data = dst.bits();  // Skip alpha
    01911 #endif
    01912
    01913     for(int y = 0; y < 4; y++)
    01914     {
    01915         // Bottom-left Corner
    01916         for(register int x = 0; x < 4; x++) {
    01917             *data = (unsigned char)((*data)*(*corner)); data++;
    01918             *data = (unsigned char)((*data)*(*corner)); data++;
    01919             *data = (unsigned char)((*data)*(*corner)); data++;
    01920             data++; // skip alpha
    01921             corner++;
    01922         }
    01923
    01924         // Scanline
    01925         for(register int x = 0; x < width; x++) {
    01926             *data = (unsigned char)((*data)*strip_data); data++;
    01927             *data = (unsigned char)((*data)*strip_data); data++;
    01928             *data = (unsigned char)((*data)*strip_data); data++;
    01929             data++;
    01930         }
    01931
    01932         strip_data = shadow_strip[++line];
    01933     }
    01934 }
    01935
    01936 // Create a shadow of thickness 4.
    01937 void TransparencyHandler::createShadowWindows(const QPopupMenu* p)
    01938 {
    01939 #ifdef Q_WS_X11
    01940     int x2 = p->x()+p->width();
    01941     int y2 = p->y()+p->height();
    01942     QRect shadow1(x2, p->y() + 4, 4, p->height());
    01943     QRect shadow2(p->x() + 4, y2, p->width() - 4, 4);
    01944
    01945     // Create a fake drop-down shadow effect via blended Xwindows
    01946     ShadowElements se;
    01947     se.w1 = new QWidget(0, 0, WStyle_Customize | WType_Popup | WX11BypassWM );
    01948     se.w2 = new QWidget(0, 0, WStyle_Customize | WType_Popup | WX11BypassWM );
    01949     se.w1->setGeometry(shadow1);
    01950     se.w2->setGeometry(shadow2);
    01951     XSelectInput(qt_xdisplay(), se.w1->winId(), StructureNotifyMask );
    01952     XSelectInput(qt_xdisplay(), se.w2->winId(), StructureNotifyMask );
    01953
    01954     // Insert a new ShadowMap entry
    01955     shadowMap()[p] = se;
    01956
    01957     // Some hocus-pocus here to create the drop-shadow.
    01958     QPixmap pix_shadow1 = QPixmap::grabWindow(qt_xrootwin(),
    01959             shadow1.x(), shadow1.y(), shadow1.width(), shadow1.height());
    01960     QPixmap pix_shadow2 = QPixmap::grabWindow(qt_xrootwin(),
    01961             shadow2.x(), shadow2.y(), shadow2.width(), shadow2.height());
    01962
    01963     QImage img;
    01964     img = pix_shadow1.convertToImage();
    01965     rightShadow(img);
    01966     pix_shadow1.convertFromImage(img);
    01967     img = pix_shadow2.convertToImage();
    01968     bottomShadow(img);
    01969     pix_shadow2.convertFromImage(img);
    01970
    01971     // Set the background pixmaps
    01972     se.w1->setErasePixmap(pix_shadow1);
    01973     se.w2->setErasePixmap(pix_shadow2);
    01974
    01975     // Show the 'shadow' just before showing the popup menu window
    01976     // Don't use QWidget::show() so we don't confuse QEffects, thus causing broken focus.
    01977     XMapWindow(qt_xdisplay(), se.w1->winId());
    01978     XMapWindow(qt_xdisplay(), se.w2->winId());
    01979 #else
    01980     Q_UNUSED( p )
    01981 #endif
    01982 }
    01983
    01984 void TransparencyHandler::removeShadowWindows(const QPopupMenu* p)
    01985 {
    01986 #ifdef Q_WS_X11
    01987     ShadowMap::iterator it = shadowMap().find(p);
    01988     if (it != shadowMap().end())
    01989     {
    01990         ShadowElements se = it.data();
    01991         XUnmapWindow(qt_xdisplay(), se.w1->winId());    // hide
    01992         XUnmapWindow(qt_xdisplay(), se.w2->winId());
    01993         XFlush(qt_xdisplay());                          // try to hide faster
    01994         delete se.w1;
    01995         delete se.w2;
    01996         shadowMap().erase(it);
    01997     }
    01998 #else
    01999     Q_UNUSED( p )
    02000 #endif
    02001 }
    02002
    02003 bool TransparencyHandler::eventFilter( QObject* object, QEvent* event )
    02004 {
    02005 #if !defined Q_WS_MAC && !defined Q_WS_WIN
    02006     // Transparency idea was borrowed from KDE2's "MegaGradient" Style,
    02007     // Copyright (C) 2000 Daniel M. Duley <mosfet@kde.org>
    02008
    02009     // Added 'fake' menu shadows <04-Jul-2002> -- Karol
    02010     QPopupMenu* p = (QPopupMenu*)object;
    02011     QEvent::Type et = event->type();
    02012
    02013     if (et == QEvent::Show)
    02014     {
    02015         // Handle translucency
    02016         if (te != Disabled)
    02017         {
    02018             pix = QPixmap::grabWindow(qt_xrootwin(),
    02019                     p->x(), p->y(), p->width(), p->height());
    02020
    02021             switch (te) {
    02022 #ifdef HAVE_XRENDER
    02023                 case XRender:
    02024                     if (qt_use_xrender) {
    02025                         XRenderBlendToPixmap(p);
    02026                         break;
    02027                     }
    02028                     // Fall through intended
    02029 #else
    02030                 case XRender:
    02031 #endif
    02032                 case SoftwareBlend:
    02033                     blendToPixmap(p->colorGroup(), p);
    02034                     break;
    02035
    02036                 case SoftwareTint:
    02037                 default:
    02038                     blendToColor(p->colorGroup().button());
    02039             };
    02040
    02041             p->setErasePixmap(pix);
    02042         }
    02043
    02044         // Handle drop shadow
    02045         // * FIXME : !shadowMap().contains(p) is a workaround for leftover
    02046         // * shadows after duplicate show events.
    02047         // * TODO : determine real cause for duplicate events
    02048         // * till 20021005
    02049         if (dropShadow && p->width() > 16 && p->height() > 16 && !shadowMap().contains( p ))
    02050             createShadowWindows(p);
    02051     }
    02052     else if (et == QEvent::Hide)
    02053     {
    02054         // Handle drop shadow
    02055         if (dropShadow)
    02056             removeShadowWindows(p);
    02057
    02058         // Handle translucency
    02059         if (te != Disabled)
    02060             p->setErasePixmap(QPixmap());
    02061     }
    02062
    02063 #endif
    02064     return false;
    02065 }
    02066
    02067
    02068 // Blends a QImage to a predefined color, with a given opacity.
    02069 void TransparencyHandler::blendToColor(const QColor &col)
    02070 {
    02071     if (opacity < 0.0 || opacity > 1.0)
    02072         return;
    02073
    02074     QImage img = pix.convertToImage();
    02075     KImageEffect::blend(col, img, opacity);
    02076     pix.convertFromImage(img);
    02077 }
    02078
    02079
    02080 void TransparencyHandler::blendToPixmap(const QColorGroup &cg, const QPopupMenu* p)
    02081 {
    02082     if (opacity < 0.0 || opacity > 1.0)
    02083         return;
    02084
    02085     KPixmap blendPix;
    02086     blendPix.resize( pix.width(), pix.height() );
    02087
    02088     if (blendPix.width()  != pix.width() ||
    02089         blendPix.height() != pix.height())
    02090         return;
    02091
    02092     // Allow styles to define the blend pixmap - allows for some interesting effects.
    02093     kstyle->renderMenuBlendPixmap( blendPix, cg, p );
    02094
    02095     QImage blendImg = blendPix.convertToImage();
    02096     QImage backImg  = pix.convertToImage();
    02097     KImageEffect::blend(blendImg, backImg, opacity);
    02098     pix.convertFromImage(backImg);
    02099 }
    02100
    02101
    02102 #ifdef HAVE_XRENDER
    02103 // Here we go, use XRender in all its glory.
    02104 // NOTE: This is actually a bit slower than the above routines
    02105 // on non-accelerated displays. -- Karol.
    02106 void TransparencyHandler::XRenderBlendToPixmap(const QPopupMenu* p)
    02107 {
    02108     KPixmap renderPix;
    02109     renderPix.resize( pix.width(), pix.height() );
    02110
    02111     // Allow styles to define the blend pixmap - allows for some interesting effects.
    02112     kstyle->renderMenuBlendPixmap( renderPix, p->colorGroup(), p );
    02113
    02114     Display* dpy = qt_xdisplay();
    02115     Pixmap   alphaPixmap;
    02116     Picture  alphaPicture;
    02117     XRenderPictFormat        Rpf;
    02118     XRenderPictureAttributes Rpa;
    02119     XRenderColor clr;
    02120     clr.alpha = ((unsigned short)(255*opacity) << 8);
    02121
    02122     Rpf.type  = PictTypeDirect;
    02123     Rpf.depth = 8;
    02124     Rpf.direct.alphaMask = 0xff;
    02125     Rpa.repeat = True;  // Tile
    02126
    02127     XRenderPictFormat* xformat = XRenderFindFormat(dpy,
    02128         PictFormatType | PictFormatDepth | PictFormatAlphaMask, &Rpf, 0);
    02129
    02130     alphaPixmap = XCreatePixmap(dpy, p->handle(), 1, 1, 8);
    02131     alphaPicture = XRenderCreatePicture(dpy, alphaPixmap, xformat, CPRepeat, &Rpa);
    02132
    02133     XRenderFillRectangle(dpy, PictOpSrc, alphaPicture, &clr, 0, 0, 1, 1);
    02134
    02135     XRenderComposite(dpy, PictOpOver,
    02136             renderPix.x11RenderHandle(), alphaPicture, pix.x11RenderHandle(), // src, mask, dst
    02137             0, 0,   // srcx,  srcy
    02138             0, 0,   // maskx, masky
    02139             0, 0,   // dstx,  dsty
    02140             pix.width(), pix.height());
    02141
    02142     XRenderFreePicture(dpy, alphaPicture);
    02143     XFreePixmap(dpy, alphaPixmap);
    02144 }
    02145 #endif
    02146
    02147 void KStyle::virtual_hook( int, void* )
    02148 { /*BASE::virtual_hook( id, data );*/ }
    02149
    02150 // vim: set noet ts=4 sw=4:
    02151 // kate: indent-width 4; replace-tabs off; tab-width 4; space-indent off;
    02152
    02153 #include "kstyle.moc"

This file is part of the documentation for kdefx Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:17:09 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003