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