kstyle.cpp Source File (kdefx Library)

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

# kstyle.cpp

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

This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Jan 28 12:44:26 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001