kdefx Library API Documentation

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