/* $Id$ This file is part of the KDE libraries Copyright (C) 1999 Daniel M. Duley KDE3 port (C) 2001-2002 Maksim Orlovich Port version 0.9.7 Palette setup code is from KApplication, Copyright (C) 1997 Matthias Kalle Dalheimer (kalle@kde.org) Copyright (C) 1998, 1999, 2000 KDE Team Includes code portions from the KDE HighColor style. KDE3 HighColor Style Copyright (C) 2001 Karol Szwed (C) 2001 Fredrik Höglund Drawing routines adapted from the KDE2 HCStyle, Copyright (C) 2000 Daniel M. Duley (C) 2000 Dirk Mueller (C) 2001 Martijn Klingens This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kthemebase.h" #include #include #include #include #include #include #include #include typedef TQMap Prop; template class TQIntCache ; /* Bugs: Can't delete old slider image when calculating the rotated one for some reason. */ //Shamelessly stolen from KConfigBase static TQColor readColorEntry( TQSettings* s, const char *pKey, const TQColor* pDefault ) { TQColor aRetColor; int nRed = 0, nGreen = 0, nBlue = 0; TQString aValue = s->readEntry( pKey ); if ( !aValue.isEmpty() ) { if ( aValue.at( 0 ) == '#' ) { aRetColor.setNamedColor( aValue ); } else { bool bOK; // find first part (red) int nIndex = aValue.find( ',' ); if ( nIndex == -1 ) { // return a sensible default -- Bernd if ( pDefault ) aRetColor = *pDefault; return aRetColor; } nRed = aValue.left( nIndex ).toInt( &bOK ); // find second part (green) int nOldIndex = nIndex; nIndex = aValue.find( ',', nOldIndex + 1 ); if ( nIndex == -1 ) { // return a sensible default -- Bernd if ( pDefault ) aRetColor = *pDefault; return aRetColor; } nGreen = aValue.mid( nOldIndex + 1, nIndex - nOldIndex - 1 ).toInt( &bOK ); // find third part (blue) nBlue = aValue.right( aValue.length() - nIndex - 1 ).toInt( &bOK ); aRetColor.setRgb( nRed, nGreen, nBlue ); } } else { if ( pDefault ) aRetColor = *pDefault; } return aRetColor; } static const char * const widgetEntries[] = { // unsunken widgets (see header) "PushButton", "ComboBox", "HSBarSlider", "VSBarSlider", "Bevel", "ToolButton", "ScrollButton", "HScrollDeco", "VScrollDeco", "ComboDeco", "MenuItem", "Tab", "ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight", // sunken widgets "PushButtonDown", "ComboBoxDown", "HSBarSliderDown", "VSBarSliderDown", "BevelDown", "ToolButtonDown", "ScrollButtonDown", "HScrollDecoDown", "VScrollDecoDown", "ComboDecoDown", "MenuItemDown", "TabDown", "SunkenArrowUp", "SunkenArrowDown", "SunkenArrowLeft", "SunkenArrowRight", // everything else "HScrollGroove", "VScrollGroove", "Slider", "SliderGroove", "CheckBoxDown", "CheckBox", "CheckBoxTri", "RadioDown", "Radio", "HBarHandle", "VBarHandle", "ToolBar", "Splitter", "CheckMark", "MenuBar", "DisableArrowUp", "DisableArrowDown", "DisableArrowLeft", "DisableArrowRight", "ProgressBar", "ProgressBackground", "MenuBarItem", "Background", "RotSlider", "RotInactiveTab", "RotActiveTab", }; #define INHERIT_ITEMS 16 class KThemeBasePrivate { public: /** Color overrides flags..*/ bool overrideForeground; bool overrideBackground; bool overrideSelectForeground; bool overrideSelectBackground; bool overrideWindowForeground; bool overrideWindowBackground; /** * Colors to override defaults with.. */ TQColor overrideForegroundCol; TQColor overrideBackgroundCol; TQColor overrideSelectForegroundCol; TQColor overrideSelectBackgroundCol; TQColor overrideWindowForegroundCol; TQColor overrideWindowBackgroundCol; int contrast; TQMap > props; TQMap colorCache; /* A heuristic routine that tries to determine the avergae color of the image Wouldn't work for things like sliders, etc. */ TQColor pixmapAveColor( const TQPixmap* p ) { if ( colorCache.contains( p ) ) return colorCache[ p ]; TQImage to_ave = p->convertToImage(); double h = 0, s = 0, v = 0; int count = 0; int dh, ds, dv; for ( int x = 0; x < p->width(); x++ ) { TQColor pix( to_ave.pixel( x, p->height() / 2 ) ); pix.hsv( &dh, &ds, &dv ); h += dh; s += ds; v += dv; count++; } for ( int y = 0; y < p->height(); y++ ) { TQColor pix( to_ave.pixel( p->width() / 2, y ) ); pix.hsv( &dh, &ds, &dv ); h += dh; s += ds; v += dv; count++; } colorCache[ p ] = TQColor( int( h / count + 0.5 ), int( s / count + 0.5 ), int( v / count + 0.5 ), TQColor::Hsv ); return colorCache[ p ]; } }; // This is used to encode the keys. I used to use masks but I think this // bitfield is nicer :) I don't know why C++ coders don't use these more.. // (mosfet) struct kthemeKeyData { unsigned int id : 6; unsigned int width : 12; unsigned int height : 12; unsigned int border : 1; unsigned int mask : 1; }; union kthemeKey{ kthemeKeyData data; unsigned int cacheKey; }; void KThemeBase::generateBorderPix( int i ) { // separate pixmap into separate components if ( pbPixmaps[ i ] ) { // evidently I have to do masks manually... const TQBitmap * srcMask = pbPixmaps[ i ] ->mask(); TQBitmap destMask( pbWidth[ i ], pbWidth[ i ] ); TQPixmap tmp( pbWidth[ i ], pbWidth[ i ] ); bitBlt( &tmp, 0, 0, pbPixmaps[ i ], 0, 0, pbWidth[ i ], pbWidth[ i ], Qt::CopyROP, false ); if ( srcMask ) { bitBlt( &destMask, 0, 0, srcMask, 0, 0, pbWidth[ i ], pbWidth[ i ], Qt::CopyROP, false ); tmp.setMask( destMask ); } pbPixmaps[ i ] ->setBorder( KThemePixmap::TopLeft, tmp ); bitBlt( &tmp, 0, 0, pbPixmaps[ i ], pbPixmaps[ i ] ->width() - pbWidth[ i ], 0, pbWidth[ i ], pbWidth[ i ], Qt::CopyROP, false ); if ( srcMask ) { bitBlt( &destMask, 0, 0, srcMask, pbPixmaps[ i ] ->width() - pbWidth[ i ], 0, pbWidth[ i ], pbWidth[ i ], Qt::CopyROP, false ); tmp.setMask( destMask ); } pbPixmaps[ i ] ->setBorder( KThemePixmap::TopRight, tmp ); bitBlt( &tmp, 0, 0, pbPixmaps[ i ], 0, pbPixmaps[ i ] ->height() - pbWidth[ i ], pbWidth[ i ], pbWidth[ i ], Qt::CopyROP, false ); if ( srcMask ) { bitBlt( &destMask, 0, 0, srcMask, 0, pbPixmaps[ i ] ->height() - pbWidth[ i ], pbWidth[ i ], pbWidth[ i ], Qt::CopyROP, false ); tmp.setMask( destMask ); } pbPixmaps[ i ] ->setBorder( KThemePixmap::BottomLeft, tmp ); bitBlt( &tmp, 0, 0, pbPixmaps[ i ], pbPixmaps[ i ] ->width() - pbWidth[ i ], pbPixmaps[ i ] ->height() - pbWidth[ i ], pbWidth[ i ], pbWidth[ i ], Qt::CopyROP, false ); if ( srcMask ) { bitBlt( &destMask, 0, 0, srcMask, pbPixmaps[ i ] ->width() - pbWidth[ i ], pbPixmaps[ i ] ->height() - pbWidth[ i ], pbWidth[ i ], pbWidth[ i ], Qt::CopyROP, false ); tmp.setMask( destMask ); } pbPixmaps[ i ] ->setBorder( KThemePixmap::BottomRight, tmp ); tmp.resize( pbPixmaps[ i ] ->width() - pbWidth[ i ] * 2, pbWidth[ i ] ); destMask.resize( pbPixmaps[ i ] ->width() - pbWidth[ i ] * 2, pbWidth[ i ] ); bitBlt( &tmp, 0, 0, pbPixmaps[ i ], pbWidth[ i ], 0, pbPixmaps[ i ] ->width() - pbWidth[ i ] * 2, pbWidth[ i ], Qt::CopyROP, false ); if ( srcMask ) { bitBlt( &destMask, 0, 0, srcMask, pbWidth[ i ], 0, pbPixmaps[ i ] ->width() - pbWidth[ i ] * 2, pbWidth[ i ], Qt::CopyROP, false ); tmp.setMask( destMask ); } pbPixmaps[ i ] ->setBorder( KThemePixmap::Top, tmp ); bitBlt( &tmp, 0, 0, pbPixmaps[ i ], pbWidth[ i ], pbPixmaps[ i ] ->height() - pbWidth[ i ], pbPixmaps[ i ] ->width() - pbWidth[ i ] * 2, pbWidth[ i ], Qt::CopyROP, false ); if ( srcMask ) { bitBlt( &destMask, 0, 0, srcMask, pbWidth[ i ], pbPixmaps[ i ] ->height() - pbWidth[ i ], pbPixmaps[ i ] ->width() - pbWidth[ i ] * 2, pbWidth[ i ], Qt::CopyROP, false ); tmp.setMask( destMask ); } pbPixmaps[ i ] ->setBorder( KThemePixmap::Bottom, tmp ); tmp.resize( pbWidth[ i ], pbPixmaps[ i ] ->height() - pbWidth[ i ] * 2 ); destMask.resize( pbWidth[ i ], pbPixmaps[ i ] ->height() - pbWidth[ i ] * 2 ); bitBlt( &tmp, 0, 0, pbPixmaps[ i ], 0, pbWidth[ i ], pbWidth[ i ], pbPixmaps[ i ] ->height() - pbWidth[ i ] * 2, Qt::CopyROP, false ); if ( srcMask ) { bitBlt( &destMask, 0, 0, srcMask, 0, pbWidth[ i ], pbWidth[ i ], pbPixmaps[ i ] ->height() - pbWidth[ i ] * 2, Qt::CopyROP, false ); tmp.setMask( destMask ); } pbPixmaps[ i ] ->setBorder( KThemePixmap::Left, tmp ); bitBlt( &tmp, 0, 0, pbPixmaps[ i ], pbPixmaps[ i ] ->width() - pbWidth[ i ], pbWidth[ i ], pbWidth[ i ], pbPixmaps[ i ] ->height() - pbWidth[ i ] * 2, Qt::CopyROP, false ); if ( srcMask ) { bitBlt( &destMask, 0, 0, srcMask, pbPixmaps[ i ] ->width() - pbWidth[ i ], pbWidth[ i ], pbWidth[ i ], pbPixmaps[ i ] ->height() - pbWidth[ i ] * 2, Qt::CopyROP, false ); tmp.setMask( destMask ); } pbPixmaps[ i ] ->setBorder( KThemePixmap::Right, tmp ); } else qWarning( "KThemeBase: Tried making border from empty pixmap\n" ); } void KThemeBase::copyWidgetConfig( int sourceID, int destID, TQString *pixnames, TQString *brdnames ) { scaleHints[ destID ] = scaleHints[ sourceID ]; gradients[ destID ] = gradients[ sourceID ]; blends[ destID ] = blends[ sourceID ]; bContrasts[ destID ] = bContrasts[ sourceID ]; borders[ destID ] = borders[ sourceID ]; highlights[ destID ] = highlights[ sourceID ]; if ( grLowColors[ sourceID ] ) grLowColors[ destID ] = new TQColor( *grLowColors[ sourceID ] ); else grLowColors[ destID ] = NULL; if ( grHighColors[ sourceID ] ) grHighColors[ destID ] = new TQColor( *grHighColors[ sourceID ] ); else grHighColors[ destID ] = NULL; if ( colors[ sourceID ] ) colors[ destID ] = new TQColorGroup( *colors[ sourceID ] ); else colors[ destID ] = NULL; // pixmap pixnames[ destID ] = pixnames[ sourceID ]; duplicate[ destID ] = false; pixmaps[ destID ] = NULL; images[ destID ] = NULL; if ( !pixnames[ destID ].isEmpty() ) { if ( scaleHints[ sourceID ] == TileScale && blends[ sourceID ] == 0.0 ) { pixmaps[ destID ] = pixmaps[ sourceID ]; duplicate[ destID ] = true; } if ( !duplicate[ destID ] ) { pixmaps[ destID ] = loadPixmap( pixnames[ destID ] ); if ( scaleHints[ destID ] == TileScale && blends[ destID ] == 0.0 ) images[ destID ] = NULL; else images[ destID ] = loadImage( pixnames[ destID ] ); } } // border pixmap pbDuplicate[ destID ] = false; pbPixmaps[ destID ] = NULL; pbWidth[ destID ] = pbWidth[ sourceID ]; brdnames[ destID ] = brdnames[ sourceID ]; if ( !brdnames[ destID ].isEmpty() ) { pbPixmaps[ destID ] = pbPixmaps[ sourceID ]; pbDuplicate[ destID ] = true; } if ( sourceID == ActiveTab && destID == InactiveTab ) aTabLine = iTabLine; else if ( sourceID == InactiveTab && destID == ActiveTab ) iTabLine = aTabLine; } void KThemeBase::readConfig( Qt::GUIStyle /*style*/ ) { #define PREBLEND_ITEMS 12 static const WidgetType preBlend[] = { Slider, IndicatorOn, IndicatorOff, ExIndicatorOn, ExIndicatorOff, HScrollDeco, VScrollDeco, HScrollDecoDown, VScrollDecoDown, ComboDeco, ComboDecoDown, CheckMark }; int i; TQString tmpStr; TQString pixnames[ WIDGETS ]; // used for duplicate check TQString brdnames[ WIDGETS ]; bool loaded[ WIDGETS ]; // used for preloading for CopyWidget TQSettings config; if (configDirName.isEmpty() || configDirName == ".") { KStyleDirs::dirs()->addToSearch( "themerc", config ); } else config.insertSearchPath( TQSettings::Unix, configDirName ); applyConfigFile( config ); d->contrast = config.readNumEntry( configFileName + "KDE/contrast", 7 ); for ( i = 0; i < INHERIT_ITEMS; ++i ) applyResourceGroup( &config, i ); for ( ; i < INHERIT_ITEMS*2; ++i ) { if ( config.entryList( configFileName + widgetEntries[ i ] ).size() ) applyResourceGroup( &config, i ); #ifndef Q_WS_QWS //FIXME else { Prop& copyProp = d->props[ widgetEntries[ i ] ]; copyProp[ "CopyWidget" ] = TQString( widgetEntries[ i - INHERIT_ITEMS ] ); } #endif } for ( ; i < WIDGETS; ++i ) applyResourceGroup( &config, i ); applyMiscResourceGroup( &config ); // initialize defaults that may not be read for ( i = 0; i < WIDGETS; ++i ) loaded[ i ] = false; btnXShift = btnYShift = focus3DOffset = 0; aTabLine = iTabLine = true; roundedButton = roundedCombo = roundedSlider = focus3D = false; splitterWidth = 10; //Handle the rotated background separately.. d->props[ widgetEntries[ RotSliderGroove ] ] = d->props[ widgetEntries[ SliderGroove ] ]; d->props[ widgetEntries[ RotInactiveTab ] ] = d->props[ widgetEntries[ InactiveTab ] ]; d->props[ widgetEntries[ RotActiveTab ] ] = d->props[ widgetEntries[ ActiveTab ] ]; // misc items readMiscResourceGroup(); for ( i = 0; i < WIDGETS; ++i ) readResourceGroup( i, pixnames, brdnames, loaded ); if ( pixmaps[ RotSliderGroove ] ) { TQWMatrix r270; //TODO: 90 if reverse? r270.rotate( 270 ); KThemePixmap* bf = new KThemePixmap( pixmaps[ RotSliderGroove ], pixmaps[ RotSliderGroove ] ->xForm( r270 ) ); // pixmaps[ RotSliderGroove ] = bf; if ( images[ RotSliderGroove ] ) { delete images[ RotSliderGroove ]; images[ RotSliderGroove ] = new TQImage( bf->convertToImage() ); } } if ( pixmaps[ RotActiveTab ] ) { TQWMatrix r180; r180.rotate( 180 ); KThemePixmap* bf = new KThemePixmap( pixmaps[ RotActiveTab ], pixmaps[ RotActiveTab ] ->xForm( r180 ) ); pixmaps[ RotActiveTab ] = bf; if ( images[ RotActiveTab ] ) { delete images[ RotActiveTab ]; images[ RotActiveTab ] = new TQImage( bf->convertToImage() ); } } if ( pixmaps[ RotInactiveTab ] ) { TQWMatrix r180; r180.rotate( 180 ); KThemePixmap* bf = new KThemePixmap( pixmaps[ RotInactiveTab ], pixmaps[ RotInactiveTab ] ->xForm( r180 ) ); pixmaps[ RotInactiveTab ] = bf; if ( images[ RotInactiveTab ] ) { delete images[ RotInactiveTab ]; images[ RotInactiveTab ] = new TQImage( bf->convertToImage() ); } } // Handle preblend items for ( i = 0; i < PREBLEND_ITEMS; ++i ) { if ( pixmaps[ preBlend[ i ] ] != NULL && blends[ preBlend[ i ] ] != 0.0 ) blend( preBlend[ i ] ); } d->props.clear(); } KThemeBase::KThemeBase( const TQString& dir, const TQString & configFile ) : KStyle( FilledFrameWorkaround ), configFileName( configFile ) { d = new KThemeBasePrivate; if ( configFileName.isEmpty() ) configFileName = "kstylerc"; configDirName = dir; //Strip of rc from the configFileName if ( configFileName.endsWith( "rc" ) ) { configFileName.truncate( configFileName.length() - 2 ); //Get rid of rc.. } //else SCREAM!! configFileName = "/" + configFileName + "/"; readConfig( Qt::WindowsStyle ); cache = new KThemeCache( cacheSize ); switch ( scrollBarLayout() ) { case SBBottomLeft: setScrollBarType( NextStyleScrollBar ); break; case SBBottomRight: setScrollBarType( PlatinumStyleScrollBar ); break; case SBOpposite: break; //Do nothing, this type already set.. } ; } void KThemeBase::applyConfigFile( TQSettings& config ) { TQStringList keys = config.entryList( configFileName ); if ( keys.contains( "foreground" ) ) { d->overrideForeground = true; d->overrideForegroundCol = readColorEntry( &config, ( configFileName + "foreground" ).latin1(), 0 ); } else d->overrideForeground = false; if ( keys.contains( "background" ) ) { d->overrideBackground = true; d->overrideBackgroundCol = readColorEntry( &config, ( configFileName + "background" ).latin1(), 0 ); } else d->overrideBackground = false; if ( keys.contains( "selectForeground" ) ) { d->overrideSelectForeground = true; d->overrideSelectForegroundCol = readColorEntry( &config, ( configFileName + "selectForeground" ).latin1(), 0 ); } else d->overrideSelectForeground = false; if ( keys.contains( "selectBackground" ) ) { d->overrideSelectBackground = true; d->overrideSelectBackgroundCol = readColorEntry( &config, ( configFileName + "selectBackground" ).latin1(), 0 ); } else d->overrideSelectBackground = false; if ( keys.contains( "windowBackground" ) ) { d->overrideWindowBackground = true; d->overrideWindowBackgroundCol = readColorEntry( &config, ( configFileName + "windowBackground" ).latin1(), 0 ); } else d->overrideWindowBackground = false; if ( keys.contains( "windowForeground" ) ) { d->overrideWindowForeground = true; d->overrideWindowForegroundCol = readColorEntry( &config, ( configFileName + "windowForeground" ).latin1(), 0 ); } else d->overrideWindowForeground = false; #ifndef Q_WS_QWS //FIXME for ( int input = 0; input < WIDGETS; ++input ) { d->props.erase( widgetEntries[ input ] ); } d->props.erase( "Misc" ); #endif } KThemeBase::~KThemeBase() { int i; for ( i = 0; i < WIDGETS; ++i ) { if ( !duplicate[ i ] ) { if ( images[ i ] ) delete images[ i ]; if ( pixmaps[ i ] ) delete pixmaps[ i ]; } if ( !pbDuplicate[ i ] && pbPixmaps[ i ] ) delete pbPixmaps[ i ]; if ( colors[ i ] ) delete( colors[ i ] ); if ( grLowColors[ i ] ) delete( grLowColors[ i ] ); if ( grHighColors[ i ] ) delete( grHighColors[ i ] ); } KStyleDirs::release(); delete cache; delete d; } TQImage* KThemeBase::loadImage( const TQString &name ) { TQImage * image = new TQImage; TQString path = KStyleDirs::dirs()->findResource( "themepixmap",name ); image->load( path ); if ( !image->isNull() ) return ( image ); qWarning( "KThemeBase: Unable to load image %s\n", name.latin1() ); delete image; return ( NULL ); } KThemePixmap* KThemeBase::loadPixmap( const TQString &name ) { KThemePixmap * pixmap = new KThemePixmap( false ); TQString path = KStyleDirs::dirs()->findResource( "themepixmap", name ); pixmap->load( path ); if ( !pixmap->isNull() ) return pixmap; qWarning( "KThemeBase: Unable to load pixmap %s\n", name.latin1() ); delete pixmap; return ( NULL ); } KThemePixmap* KThemeBase::scale( int w, int h, WidgetType widget ) const { if ( scaleHints[ widget ] == FullScale ) { if ( !pixmaps[ widget ] || pixmaps[ widget ] ->width() != w || pixmaps[ widget ] ->height() != h ) { KThemePixmap * cachePix = cache->pixmap( w, h, widget ); if ( cachePix ) { cachePix = new KThemePixmap( *cachePix ); if ( pixmaps[ widget ] ) cache->insert( pixmaps[ widget ], KThemeCache::FullScale, widget ); else qWarning( "We would have inserted a null pixmap!\n" ); pixmaps[ widget ] = cachePix; } else { cache->insert( pixmaps[ widget ], KThemeCache::FullScale, widget ); TQImage tmpImg = images[ widget ] ->smoothScale( w, h ); pixmaps[ widget ] = new KThemePixmap; pixmaps[ widget ] ->convertFromImage( tmpImg ); if ( blends[ widget ] != 0.0 ) blend( widget ); } } } else if ( scaleHints[ widget ] == HorizontalScale ) { if ( pixmaps[ widget ] ->width() != w ) { KThemePixmap * cachePix = cache->horizontalPixmap( w, widget ); if ( cachePix ) { cachePix = new KThemePixmap( *cachePix ); if ( pixmaps[ widget ] ) cache->insert( pixmaps[ widget ], KThemeCache::HorizontalScale, widget ); else qWarning( "We would have inserted a null pixmap!\n" ); pixmaps[ widget ] = cachePix; } else { cache->insert( pixmaps[ widget ], KThemeCache::HorizontalScale, widget ); TQImage tmpImg = images[ widget ] -> smoothScale( w, images[ widget ] ->height() ); pixmaps[ widget ] = new KThemePixmap; pixmaps[ widget ] ->convertFromImage( tmpImg ); if ( blends[ widget ] != 0.0 ) blend( widget ); } } } else if ( scaleHints[ widget ] == VerticalScale ) { if ( pixmaps[ widget ] ->height() != h ) { KThemePixmap * cachePix = cache->verticalPixmap( w, widget ); if ( cachePix ) { cachePix = new KThemePixmap( *cachePix ); if ( pixmaps[ widget ] ) cache->insert( pixmaps[ widget ], KThemeCache::VerticalScale, widget ); else qWarning( "We would have inserted a null pixmap!\n" ); pixmaps[ widget ] = cachePix; } else { cache->insert( pixmaps[ widget ], KThemeCache::VerticalScale, widget ); TQImage tmpImg = images[ widget ] ->smoothScale( images[ widget ] ->width(), h ); pixmaps[ widget ] = new KThemePixmap; pixmaps[ widget ] ->convertFromImage( tmpImg ); if ( blends[ widget ] != 0.0 ) blend( widget ); } } } // If blended tile here so the blend is scaled properly else if ( scaleHints[ widget ] == TileScale && blends[ widget ] != 0.0 ) { if ( !pixmaps[ widget ] || pixmaps[ widget ] ->width() != w || pixmaps[ widget ] ->height() != h ) { KThemePixmap * cachePix = cache->pixmap( w, h, widget ); if ( cachePix ) { cachePix = new KThemePixmap( *cachePix ); cache->insert( pixmaps[ widget ], KThemeCache::FullScale, widget ); pixmaps[ widget ] = cachePix; } else { cache->insert( pixmaps[ widget ], KThemeCache::FullScale, widget ); TQPixmap tile; tile.convertFromImage( *images[ widget ] ); pixmaps[ widget ] = new KThemePixmap; pixmaps[ widget ] ->resize( w, h ); TQPainter p( pixmaps[ widget ] ); p.drawTiledPixmap( 0, 0, w, h, tile ); if ( blends[ widget ] != 0.0 ) blend( widget ); } } } return ( pixmaps[ widget ] ); } KThemePixmap* KThemeBase::scaleBorder( int w, int h, WidgetType widget ) const { KThemePixmap * pixmap = NULL; if ( !pbPixmaps[ widget ] && !pbWidth[ widget ] ) return ( NULL ); pixmap = cache->pixmap( w, h, widget, true ); if ( pixmap ) { pixmap = new KThemePixmap( *pixmap ); } else { pixmap = new KThemePixmap(); pixmap->resize( w, h ); TQBitmap mask; mask.resize( w, h ); mask.fill( color0 ); TQPainter mPainter; mPainter.begin( &mask ); TQPixmap *tmp = borderPixmap( widget ) ->border( KThemePixmap::TopLeft ); const TQBitmap *srcMask = tmp->mask(); int bdWidth = tmp->width(); bitBlt( pixmap, 0, 0, tmp, 0, 0, bdWidth, bdWidth, Qt::CopyROP, false ); if ( srcMask ) bitBlt( &mask, 0, 0, srcMask, 0, 0, bdWidth, bdWidth, Qt::CopyROP, false ); else mPainter.fillRect( 0, 0, bdWidth, bdWidth, color1 ); tmp = borderPixmap( widget ) ->border( KThemePixmap::TopRight ); srcMask = tmp->mask(); bitBlt( pixmap, w - bdWidth, 0, tmp, 0, 0, bdWidth, bdWidth, Qt::CopyROP, false ); if ( srcMask ) bitBlt( &mask, w - bdWidth, 0, srcMask, 0, 0, bdWidth, bdWidth, Qt::CopyROP, false ); else mPainter.fillRect( w - bdWidth, 0, bdWidth, bdWidth, color1 ); tmp = borderPixmap( widget ) ->border( KThemePixmap::BottomLeft ); srcMask = tmp->mask(); bitBlt( pixmap, 0, h - bdWidth, tmp, 0, 0, bdWidth, bdWidth, Qt::CopyROP, false ); if ( srcMask ) bitBlt( &mask, 0, h - bdWidth, srcMask, 0, 0, bdWidth, bdWidth, Qt::CopyROP, false ); else mPainter.fillRect( 0, h - bdWidth, bdWidth, bdWidth, color1 ); tmp = borderPixmap( widget ) ->border( KThemePixmap::BottomRight ); srcMask = tmp->mask(); bitBlt( pixmap, w - bdWidth, h - bdWidth, tmp, 0, 0, bdWidth, bdWidth, Qt::CopyROP, false ); if ( srcMask ) bitBlt( &mask, w - bdWidth, h - bdWidth, srcMask, 0, 0, bdWidth, bdWidth, Qt::CopyROP, false ); else mPainter.fillRect( w - bdWidth, h - bdWidth, bdWidth, bdWidth, color1 ); TQPainter p; p.begin( pixmap ); if ( w - bdWidth * 2 > 0 ) { tmp = borderPixmap( widget ) ->border( KThemePixmap::Top ); srcMask = tmp->mask(); p.drawTiledPixmap( bdWidth, 0, w - bdWidth * 2, bdWidth, *tmp ); if ( srcMask ) bitBlt( &mask, bdWidth, 0, srcMask, 0, 0, w - bdWidth * 2, bdWidth, Qt::CopyROP, false ); else mPainter.fillRect( bdWidth, 0, w - bdWidth * 2, bdWidth, color1 ); tmp = borderPixmap( widget ) ->border( KThemePixmap::Bottom ); srcMask = tmp->mask(); p.drawTiledPixmap( bdWidth, h - bdWidth, w - bdWidth * 2, bdWidth, *tmp ); if ( srcMask ) bitBlt( &mask, bdWidth, h - bdWidth, srcMask, 0, 0, w - bdWidth * 2, bdWidth, Qt::CopyROP, false ); else mPainter.fillRect( bdWidth, h - bdWidth, w - bdWidth * 2, bdWidth, color1 ); } if ( h - bdWidth * 2 > 0 ) { tmp = borderPixmap( widget ) ->border( KThemePixmap::Left ); srcMask = tmp->mask(); p.drawTiledPixmap( 0, bdWidth, bdWidth, h - bdWidth * 2, *tmp ); if ( srcMask ) bitBlt( &mask, 0, bdWidth, srcMask, 0, 0, bdWidth, h - bdWidth * 2, Qt::CopyROP, false ); else mPainter.fillRect( 0, bdWidth, bdWidth, h - bdWidth * 2, color1 ); tmp = borderPixmap( widget ) ->border( KThemePixmap::Right ); srcMask = tmp->mask(); p.drawTiledPixmap( w - bdWidth, bdWidth, bdWidth, h - bdWidth * 2, *tmp ); if ( srcMask ) bitBlt( &mask, w - bdWidth, bdWidth, srcMask, 0, 0, bdWidth, h - bdWidth * 2, Qt::CopyROP, false ); else mPainter.fillRect( w - bdWidth, bdWidth, bdWidth, h - bdWidth * 2, color1 ); } p.end(); mPainter.end(); pixmap->setMask( mask ); cache->insert( pixmap, KThemeCache::FullScale, widget, true ); if ( !pixmap->mask() ) qWarning( "No mask for border pixmap!\n" ); } return ( pixmap ); } KThemePixmap* KThemeBase::blend( WidgetType widget ) const { KPixmapEffect::GradientType g; switch ( gradients[ widget ] ) { case GrHorizontal: g = KPixmapEffect::HorizontalGradient; break; case GrVertical: g = KPixmapEffect::VerticalGradient; break; case GrPyramid: g = KPixmapEffect::PyramidGradient; break; case GrRectangle: g = KPixmapEffect::RectangleGradient; break; case GrElliptic: g = KPixmapEffect::EllipticGradient; break; default: g = KPixmapEffect::DiagonalGradient; break; } KPixmapEffect::blend( *pixmaps[ widget ], blends[ widget ], *grLowColors[ widget ], g, false ); return ( pixmaps[ widget ] ); } KThemePixmap* KThemeBase::gradient( int w, int h, WidgetType widget ) const { if ( gradients[ widget ] == GrVertical ) { if ( !pixmaps[ widget ] || pixmaps[ widget ] ->height() != h ) { KThemePixmap * cachePix = cache->verticalPixmap( h, widget ); if ( cachePix ) { cachePix = new KThemePixmap( *cachePix ); if ( pixmaps[ widget ] ) cache->insert( pixmaps[ widget ], KThemeCache::VerticalScale, widget ); pixmaps[ widget ] = cachePix; } else { if ( pixmaps[ widget ] ) cache->insert( pixmaps[ widget ], KThemeCache::VerticalScale, widget ); pixmaps[ widget ] = new KThemePixmap; pixmaps[ widget ] ->resize( w, h ); KPixmapEffect::gradient( *pixmaps[ widget ], *grHighColors[ widget ], *grLowColors[ widget ], KPixmapEffect::VerticalGradient ); } } } else if ( gradients[ widget ] == GrHorizontal ) { if ( !pixmaps[ widget ] || pixmaps[ widget ] ->width() != w ) { KThemePixmap * cachePix = cache->horizontalPixmap( w, widget ); if ( cachePix ) { cachePix = new KThemePixmap( *cachePix ); if ( pixmaps[ widget ] ) cache->insert( pixmaps[ widget ], KThemeCache::HorizontalScale, widget ); pixmaps[ widget ] = cachePix; } else { if ( pixmaps[ widget ] ) cache->insert( pixmaps[ widget ], KThemeCache::HorizontalScale, widget ); pixmaps[ widget ] = new KThemePixmap; pixmaps[ widget ] ->resize( w, h ); KPixmapEffect::gradient( *pixmaps[ widget ], *grHighColors[ widget ], *grLowColors[ widget ], KPixmapEffect::HorizontalGradient ); } } } else if ( gradients[ widget ] == GrReverseBevel ) { if ( !pixmaps[ widget ] || pixmaps[ widget ] ->width() != w || pixmaps[ widget ] ->height() != h ) { KThemePixmap * cachePix = cache->pixmap( w, h, widget ); if ( cachePix ) { cachePix = new KThemePixmap( *cachePix ); if ( pixmaps[ widget ] ) cache->insert( pixmaps[ widget ], KThemeCache::FullScale, widget ); pixmaps[ widget ] = cachePix; } else { if ( pixmaps[ widget ] ) cache->insert( pixmaps[ widget ], KThemeCache::FullScale, widget ); pixmaps[ widget ] = new KThemePixmap; pixmaps[ widget ] ->resize( w, h ); KPixmap s; int offset = decoWidth( widget ); s.resize( w - offset * 2, h - offset * 2 ); TQColor lc( *grLowColors[ widget ] ); TQColor hc( *grHighColors[ widget ] ); if ( bevelContrast( widget ) ) { int bc = bevelContrast( widget ); // want single increments, not factors like light()/dark() lc.setRgb( lc.red() - bc, lc.green() - bc, lc.blue() - bc ); hc.setRgb( hc.red() + bc, hc.green() + bc, hc.blue() + bc ); } KPixmapEffect::gradient( *pixmaps[ widget ], lc, hc, KPixmapEffect::DiagonalGradient ); KPixmapEffect::gradient( s, *grHighColors[ widget ], *grLowColors[ widget ], KPixmapEffect::DiagonalGradient ); bitBlt( pixmaps[ widget ], offset, offset, &s, 0, 0, w - offset * 2, h - offset * 2, Qt::CopyROP ); } } } else { KPixmapEffect::GradientType g; switch ( gradients[ widget ] ) { case GrPyramid: g = KPixmapEffect::PyramidGradient; break; case GrRectangle: g = KPixmapEffect::RectangleGradient; break; case GrElliptic: g = KPixmapEffect::EllipticGradient; break; default: g = KPixmapEffect::DiagonalGradient; break; } if ( !pixmaps[ widget ] || pixmaps[ widget ] ->width() != w || pixmaps[ widget ] ->height() != h ) { KThemePixmap * cachePix = cache->pixmap( w, h, widget ); if ( cachePix ) { cachePix = new KThemePixmap( *cachePix ); if ( pixmaps[ widget ] ) cache->insert( pixmaps[ widget ], KThemeCache::FullScale, widget ); pixmaps[ widget ] = cachePix; } else { if ( pixmaps[ widget ] ) cache->insert( pixmaps[ widget ], KThemeCache::FullScale, widget ); pixmaps[ widget ] = new KThemePixmap; pixmaps[ widget ] ->resize( w, h ); KPixmapEffect::gradient( *pixmaps[ widget ], *grHighColors[ widget ], *grLowColors[ widget ], g ); } } } return ( pixmaps[ widget ] ); } KThemePixmap* KThemeBase::scalePixmap( int w, int h, WidgetType widget ) const { if ( gradients[ widget ] && blends[ widget ] == 0.0 ) return ( gradient( w, h, widget ) ); return ( scale( w, h, widget ) ); } TQColorGroup* KThemeBase::makeColorGroup( const TQColor &fg, const TQColor &bg, Qt::GUIStyle ) { if ( shading == Motif ) { int highlightVal, lowlightVal; highlightVal = 100 + ( 2 * d->contrast + 4 ) * 16 / 10; lowlightVal = 100 + ( ( 2 * d->contrast + 4 ) * 10 ); return ( new TQColorGroup( fg, bg, bg.light( highlightVal ), bg.dark( lowlightVal ), bg.dark( 120 ), fg, TQApplication::palette().active().base() ) ); } else return ( new TQColorGroup( fg, bg, bg.light( 150 ), bg.dark(), bg.dark( 120 ), fg, TQApplication::palette().active().base() ) ); } void KThemeBase::applyMiscResourceGroup( TQSettings *config ) { #ifndef Q_WS_QWS //FIXME d->props.erase( "Misc" ); // clear the old property TQString base = configFileName + "Misc/"; Prop& prop = d->props[ "Misc" ]; TQString tmpStr; tmpStr = config->readEntry( base + "SButtonPosition" ); if ( tmpStr == "BottomLeft" ) prop[ "SButtonPosition" ] = TQString::number( ( int ) SBBottomLeft ); else if ( tmpStr == "BottomRight" ) prop[ "SButtonPosition" ] = TQString::number( ( int ) SBBottomRight ); else { if ( tmpStr != "Opposite" && !tmpStr.isEmpty() ) qWarning( "KThemeBase: Unrecognized sb button option %s, using Opposite.\n", tmpStr.latin1() ); ; prop[ "SButtonPosition" ] = TQString::number( ( int ) SBOpposite ); } tmpStr = config->readEntry( base + "ArrowType" ); if ( tmpStr == "Small" ) prop[ "ArrowType" ] = TQString::number( ( int ) SmallArrow ); else if ( tmpStr == "3D" ) prop[ "ArrowType" ] = TQString::number( ( int ) MotifArrow ); else { if ( tmpStr != "Normal" && !tmpStr.isEmpty() ) qWarning( "KThemeBase: Unrecognized arrow option %s, using Normal.\n", tmpStr.latin1() ); prop[ "ArrowType" ] = TQString::number( ( int ) LargeArrow ); } tmpStr = config->readEntry( base + "ShadeStyle" ); if ( tmpStr == "Motif" ) prop[ "ShadeStyle" ] = TQString::number( ( int ) Motif ); else if ( tmpStr == "Next" ) prop[ "ShadeStyle" ] = TQString::number( ( int ) Next ); else if ( tmpStr == "KDE" ) prop[ "ShadeStyle" ] = TQString::number( ( int ) KDE ); else prop[ "ShadeStyle" ] = TQString::number( ( int ) Windows ); prop[ "FrameWidth" ] = TQString::number( config->readNumEntry( base + "FrameWidth", 2 ) ); prop[ "Cache" ] = TQString::number( config->readNumEntry( base + "Cache", 1024 ) ); prop[ "ScrollBarExtent" ] = TQString::number( config->readNumEntry( base + "ScrollBarExtent", 16 ) ); #endif } static int readNumEntry( Prop& prop, TQString setting, int def ) { bool ok; TQString s_val = prop[ setting ]; int val = s_val.toInt( &ok ); if ( ok ) return val; return def; } static TQColor readColorEntry( Prop& prop, TQString setting, const TQColor& def ) { TQString s_val = prop[ setting ]; if ( !s_val.isEmpty() ) { TQColor c( s_val ); return c; } return def; } void KThemeBase::readMiscResourceGroup() { #ifndef Q_WS_QWS //FIXME Prop & prop = d->props[ "Misc" ]; sbPlacement = ( SButton ) readNumEntry( prop, "SButtonPosition", ( int ) SBOpposite ); arrowStyle = ( ArrowStyle ) readNumEntry( prop, "ArrowType", ( int ) LargeArrow ); shading = ( ShadeStyle ) readNumEntry( prop, "ShadeStyle", ( int ) Windows ); defaultFrame = readNumEntry( prop, "FrameWidth", 2 ); cacheSize = readNumEntry( prop, "Cache", 1024 ); sbExtent = readNumEntry( prop, "ScrollBarExtent", 16 ); #endif } void KThemeBase::applyResourceGroup( TQSettings *config, int i ) { #ifndef Q_WS_QWS //FIXME TQString tmpStr; int tmpVal; // clear the old property d->props.erase( widgetEntries[ i ] ); TQString base = configFileName + widgetEntries[ i ] + "/"; Prop& prop = d->props[ widgetEntries[ i ] ]; tmpStr = config->readEntry( base + "CopyWidget", "" ); prop[ "CopyWidget" ] = tmpStr; if ( !tmpStr.isEmpty() ) { return ; } tmpStr = config->readEntry( base + "Scale" ); if ( tmpStr == "Full" ) tmpVal = ( int ) FullScale; else if ( tmpStr == "Horizontal" ) tmpVal = ( int ) HorizontalScale; else if ( tmpStr == "Vertical" ) tmpVal = ( int ) VerticalScale; else { if ( tmpStr != "Tile" && !tmpStr.isEmpty() ) qWarning( "KThemeBase: Unrecognized scale option %s, using Tile.\n", tmpStr.latin1() ); tmpVal = ( int ) TileScale; } prop[ "ScaleHint" ] = TQString::number( tmpVal ); // Gradient type tmpStr = config->readEntry( base + "Gradient" ); if ( tmpStr == "Diagonal" ) tmpVal = ( int ) GrDiagonal; else if ( tmpStr == "Horizontal" ) tmpVal = ( int ) GrHorizontal; else if ( tmpStr == "Vertical" ) tmpVal = ( int ) GrVertical; else if ( tmpStr == "Pyramid" ) tmpVal = ( int ) GrPyramid; else if ( tmpStr == "Rectangle" ) tmpVal = ( int ) GrRectangle; else if ( tmpStr == "Elliptic" ) tmpVal = ( int ) GrElliptic; else if ( tmpStr == "ReverseBevel" ) tmpVal = ( int ) GrReverseBevel; else { if ( tmpStr != "None" && !tmpStr.isEmpty() ) qWarning( "KThemeBase: Unrecognized gradient option %s, using None.\n", tmpStr.latin1() ); tmpVal = ( int ) GrNone; } prop[ "Gradient" ] = TQString::number( tmpVal ); // Blend intensity tmpStr.setNum( config->readDoubleEntry( base + "BlendIntensity", 0.0 ) ); prop[ "Blend" ] = tmpStr; // Bevel contrast prop[ "BContrast" ] = TQString::number( config->readNumEntry( base + "BevelContrast", 0 ) ); // Border width prop[ "Border" ] = TQString::number( config->readNumEntry( base + "Border", 1 ) ); // Highlight width prop[ "Highlight" ] = TQString::number( config->readNumEntry( base + "Highlight", 1 ) ); TQStringList keys = config->entryList( base ); // Gradient low color or blend background if ( keys.contains( "GradientLow" ) ) prop[ "GrLow" ] = readColorEntry( config, TQString( base + "GradientLow" ).latin1(), &TQApplication::palette().active().background() ).name(); // Gradient high color if ( keys.contains( "GradientHigh" ) ) prop[ "GrHigh" ] = readColorEntry( config, TQString( base + "GradientHigh" ).latin1(), &TQApplication::palette().active().foreground() ).name(); // Extended color attributes if ( keys.contains( "Foreground" ) || keys.contains( "Background" ) ) { TQColor fg, bg; if ( keys.contains( "Background" ) ) bg = readColorEntry( config, TQString( base + "Background" ).latin1(), &bg ); if ( keys.contains( "Foreground" ) ) fg = readColorEntry( config, TQString( base + "Foreground" ).latin1(), &fg ); prop[ "Foreground" ] = fg.name(); prop[ "Background" ] = bg.name(); } else colors[ i ] = NULL; // Pixmap tmpStr = config->readEntry( base + "Pixmap", "" ); if ( !tmpStr.isEmpty() ) prop[ "Pixmap" ] = tmpStr; // Pixmap border tmpStr = config->readEntry( base + "PixmapBorder", "" ); if ( !tmpStr.isEmpty() ) { prop[ "PixmapBorder" ] = tmpStr; prop[ "PixmapBWidth" ] = TQString::number( config->readNumEntry( base + "PixmapBWidth", 0 ) ); } // Various widget specific settings. This was more efficient when bunched // together in the misc group, but this makes an easier to read config. if ( i == SliderGroove ) prop[ "SmallGroove" ] = TQString::number( config->readBoolEntry( base + "SmallGroove", false ) ); else if ( i == ActiveTab || i == InactiveTab ) prop[ "BottomLine" ] = TQString::number( config->readBoolEntry( base + "BottomLine", true ) ); else if ( i == Splitter ) prop[ "Width" ] = TQString::number( config->readNumEntry( base + "Width", 10 ) ); else if ( i == ComboBox || i == ComboBoxDown ) { if ( keys.contains( "Round" ) ) prop[ "Round" ] = TQString::number( config->readBoolEntry( base + "Round", false ) ); else prop[ "Round" ] = "5000"; // invalid, used w/multiple groups } else if ( i == PushButton || i == PushButtonDown ) { if ( keys.contains( "XShift" ) ) prop[ "XShift" ] = TQString::number( config->readNumEntry( base + "XShift", 0 ) ); else prop[ "XShift" ] = "5000"; if ( keys.contains( "YShift" ) ) prop[ "YShift" ] = TQString::number( config->readNumEntry( base + "YShift", 0 ) ); else prop[ "YShift" ] = "5000"; if ( keys.contains( "3DFocusRect" ) ) prop[ "3DFRect" ] = TQString::number( config-> readBoolEntry( base + "3DFocusRect", false ) ); else prop[ "3DFRect" ] = "5000"; if ( keys.contains( "3DFocusOffset" ) ) prop[ "3DFOffset" ] = TQString::number( config-> readBoolEntry( base + "3DFocusOffset", 0 ) ); else prop[ "3DFOffset" ] = "5000"; if ( keys.contains( "Round" ) ) prop[ "Round" ] = TQString::number( config->readBoolEntry( base + "Round", false ) ); else prop[ "Round" ] = "5000"; } #endif } void KThemeBase::readResourceGroup( int i, TQString *pixnames, TQString *brdnames, bool *loadArray ) { #ifndef Q_WS_QWS //FIXME if ( loadArray[ i ] == true ) { return ; // already been preloaded. } int tmpVal; Prop prop = d->props[ widgetEntries[ i ] ]; TQString tmpStr; tmpStr = prop[ "CopyWidget" ]; if ( !tmpStr.isEmpty() ) { // Duplicate another widget's config int sIndex; loadArray[ i ] = true; for ( sIndex = 0; sIndex < WIDGETS; ++sIndex ) { if ( tmpStr == widgetEntries[ sIndex ] ) { if ( !loadArray[ sIndex ] ) // hasn't been loaded yet readResourceGroup( sIndex, pixnames, brdnames, loadArray ); break; } } if ( loadArray[ sIndex ] ) { copyWidgetConfig( sIndex, i, pixnames, brdnames ); } else qWarning( "KThemeBase: Unable to identify source widget for %s\n", widgetEntries[ i ] ); return ; } // special inheritance for disabled arrows (these are tri-state unlike // the rest of what we handle). for ( tmpVal = DisArrowUp; tmpVal <= DisArrowRight; ++tmpVal ) { if ( tmpVal == i ) { tmpStr = prop[ "Pixmap" ]; if ( tmpStr.isEmpty() ) { copyWidgetConfig( ArrowUp + ( tmpVal - DisArrowUp ), i, pixnames, brdnames ); return ; } } } // Scale hint scaleHints[ i ] = ( ScaleHint ) readNumEntry( prop, "ScaleHint", ( int ) TileScale ); gradients[ i ] = ( Gradient ) readNumEntry( prop, "Gradient", ( int ) GrNone ); // Blend intensity tmpStr = prop[ "Blend" ]; if ( tmpStr.isEmpty() ) tmpStr = TQString::fromLatin1( "0.0" ); blends[ i ] = tmpStr.toFloat(); // Bevel contrast bContrasts[ i ] = readNumEntry( prop, "BContrast", 0 ); // Border width borders[ i ] = readNumEntry( prop, "Border", 1 ); // Highlight width highlights[ i ] = readNumEntry( prop, "Highlight", 1 ); // Gradient low color or blend background if ( gradients[ i ] != GrNone || blends[ i ] != 0.0 ) grLowColors[ i ] = new TQColor( readColorEntry( prop, "GrLow", TQApplication::palette().active(). background() ) ); else grLowColors[ i ] = NULL; // Gradient high color if ( gradients[ i ] != GrNone ) grHighColors[ i ] = new TQColor( readColorEntry( prop, "GrHigh", TQApplication::palette().active(). background() ) ); else grHighColors[ i ] = NULL; // Extended color attributes TQColor fg, bg; fg = readColorEntry( prop, "Foreground", fg ); bg = readColorEntry( prop, "Background", bg ); if ( fg.isValid() || bg.isValid() ) { if ( !fg.isValid() ) fg = TQApplication::palette().active().foreground(); if ( !bg.isValid() ) bg = TQApplication::palette().active().background(); colors[ i ] = makeColorGroup( fg, bg, Qt::WindowsStyle ); } else colors[ i ] = NULL; // Pixmap int existing; tmpStr = prop[ "Pixmap" ]; pixnames[ i ] = tmpStr; duplicate[ i ] = false; pixmaps[ i ] = NULL; images[ i ] = NULL; // Scan for duplicate pixmaps(two identical pixmaps, tile scale, no blend, // no pixmapped border) if ( !tmpStr.isEmpty() ) { for ( existing = 0; existing < i; ++existing ) { if ( tmpStr == pixnames[ existing ] && scaleHints[ i ] == TileScale && scaleHints[ existing ] == TileScale && blends[ existing ] == 0.0 && blends[ i ] == 0.0 ) { pixmaps[ i ] = pixmaps[ existing ]; duplicate[ i ] = true; break; } } } // load if ( !duplicate[ i ] && !tmpStr.isEmpty() ) { pixmaps[ i ] = loadPixmap( tmpStr ); // load and save images for scaled/blended widgets for speed. if ( scaleHints[ i ] == TileScale && blends[ i ] == 0.0 ) images[ i ] = NULL; else images[ i ] = loadImage( tmpStr ); } // Pixmap border tmpStr = prop[ "PixmapBorder" ]; brdnames[ i ] = tmpStr; pbDuplicate[ i ] = false; pbPixmaps[ i ] = NULL; pbWidth[ i ] = 0; if ( !tmpStr.isEmpty() ) { pbWidth[ i ] = readNumEntry( prop, "PixmapBWidth", 0 ); if ( pbWidth[ i ] == 0 ) { qWarning( "KThemeBase: No border width specified for pixmapped border widget %s\n", widgetEntries[ i ] ); qWarning( "KThemeBase: Using default of 2.\n" ); pbWidth[ i ] = 2; } // duplicate check for ( existing = 0; existing < i; ++existing ) { if ( tmpStr == brdnames[ existing ] ) { pbPixmaps[ i ] = pbPixmaps[ existing ]; pbDuplicate[ i ] = true; break; } } } // load if ( !pbDuplicate[ i ] && !tmpStr.isEmpty() ) pbPixmaps[ i ] = loadPixmap( tmpStr ); if ( pbPixmaps[ i ] && !pbDuplicate[ i ] ) generateBorderPix( i ); // Various widget specific settings. This was more efficient when bunched // together in the misc group, but this makes an easier to read config. if ( i == SliderGroove ) roundedSlider = readNumEntry( prop, "SmallGroove", false ); else if ( i == ActiveTab ) aTabLine = readNumEntry( prop, "BottomLine", true ); else if ( i == InactiveTab ) iTabLine = readNumEntry( prop, "BottomLine", true ); else if ( i == Splitter ) splitterWidth = readNumEntry( prop, "Width", 10 ); else if ( i == ComboBox || i == ComboBoxDown ) { tmpVal = readNumEntry( prop, "Round", 5000 ); if ( tmpVal != 5000 ) roundedCombo = tmpVal; } else if ( i == PushButton || i == PushButtonDown ) { tmpVal = readNumEntry( prop, "XShift", 0 ); if ( tmpVal != 5000 ) btnXShift = tmpVal; tmpVal = readNumEntry( prop, "YShift", 0 ); if ( tmpVal != 5000 ) btnYShift = tmpVal; tmpVal = readNumEntry( prop, "3DFRect", false ); if ( tmpVal != 5000 ) focus3D = tmpVal; tmpVal = readNumEntry( prop, "3DFOffset", 0 ); if ( tmpVal != 5000 ) focus3DOffset = tmpVal; tmpVal = readNumEntry( prop, "Round", false ); if ( tmpVal != 5000 ) roundedButton = tmpVal; } loadArray[ i ] = true; #endif } TQPalette KThemeBase::overridePalette( const TQPalette& pal ) { //Read current settings for colors.. TQColor background = pal.active().background(); TQColor foreground = pal.active().foreground(); TQColor button = background; //CHECKME TQColor highlight = pal.active().highlight(); TQColor highlightedText = pal.active().highlightedText(); //CHECKME TQColor base = pal.active().base(); //config->readColorEntry( "windowBackground", &white ); TQColor baseText = pal.active().text(); //CHECKME //See whether there are any immediate overrides. if ( d->overrideBackground ) background = d->overrideBackgroundCol; if ( d->overrideForeground ) foreground = d->overrideForegroundCol; if ( d->overrideSelectBackground ) highlight = d->overrideSelectBackgroundCol; if ( d->overrideSelectForeground ) highlightedText = d->overrideSelectForegroundCol; if ( d->overrideWindowBackground ) base = d->overrideWindowBackgroundCol; if ( d->overrideWindowForeground ) baseText = d->overrideWindowForegroundCol; //Now, try to get the button color from the pixmap if ( uncached( Bevel ) ) button = d->pixmapAveColor( uncached( Bevel ) ); TQColor buttonText = foreground; int highlightVal, lowlightVal; highlightVal = 100 + ( 2 * d->contrast + 4 ) * 16 / 10; lowlightVal = 100 + ( 2 * d->contrast + 4 ) * 10; if ( isPixmap( Background ) || isColor( Background ) ) { if ( isColor( Background ) ) { background = colorGroup( pal.active(), Background ) ->background(); } if ( isPixmap( Background ) ) { background = d->pixmapAveColor( uncached( Background ) ); } TQColorGroup pre( foreground, button, background.light( highlightVal ), background.dark( lowlightVal ), background.dark( 120 ), baseText, buttonText /*CHECKME: BrightText*/, base, background ); buttonText = colorGroup( pre, PushButton ) ->foreground(); } TQColor disfg = foreground; int h, s, v; disfg.hsv( &h, &s, &v ); if ( v > 128 ) // dark bg, light fg - need a darker disabled fg disfg = disfg.dark( lowlightVal ); else if ( disfg != black ) // light bg, dark fg - need a lighter disabled fg - but only if !black disfg = disfg.light( highlightVal ); else // black fg - use darkgray disabled fg disfg = Qt::darkGray; TQColorGroup disabledgrp( disfg, background, //TODO:Convert this to the new ctor. background.light( highlightVal ), background.dark( lowlightVal ), background.dark( 120 ), background.dark( 120 ), base ); TQColorGroup colgrp( foreground, button, background.light( highlightVal ), background.dark( lowlightVal ), background.dark( 120 ), baseText, buttonText /*CHECKME: BrightText*/, base, background ); colgrp.setColor( TQColorGroup::Highlight, highlight ); colgrp.setColor( TQColorGroup::HighlightedText, highlightedText ); colgrp.setColor( TQColorGroup::ButtonText, buttonText ); colgrp.setColor( TQColorGroup::Midlight, button.light( 110 ) ); disabledgrp.setColor( TQColorGroup::Base, base ); disabledgrp.setColor( TQColorGroup::Button, button ); disabledgrp.setColor( TQColorGroup::ButtonText, buttonText ); disabledgrp.setColor( TQColorGroup::Midlight, button.light( 110 ) ); TQPalette newPal( colgrp, disabledgrp, colgrp ); return newPal; } KThemePixmap::KThemePixmap( bool timer ) : KPixmap() { if ( timer ) { t = new TQTime; t->start(); } else t = NULL; int i; for ( i = 0; i < 8; ++i ) b[ i ] = NULL; } KThemePixmap::KThemePixmap( const KThemePixmap &p ) : KPixmap( p ) { if ( p.t ) { t = new TQTime; t->start(); } else t = NULL; int i; for ( i = 0; i < 8; ++i ) if ( p.b[ i ] ) b[ i ] = new TQPixmap( *p.b[ i ] ); else b[ i ] = NULL; } KThemePixmap::KThemePixmap( const KThemePixmap &p, const TQPixmap &p2 ) : KPixmap( p2 ) { if ( p.t ) { t = new TQTime; t->start(); } else t = NULL; int i; for ( i = 0; i < 8; ++i ) if ( p.b[ i ] ) b[ i ] = new TQPixmap( *p.b[ i ] ); else b[ i ] = NULL; } KThemePixmap::~KThemePixmap() { if ( t ) delete t; int i; for ( i = 0; i < 8; ++i ) if ( b[ i ] ) delete b[ i ]; } KThemeCache::KThemeCache( int maxSize, TQObject *parent, const char *name ) : TQObject( parent, name ) { cache.setMaxCost( maxSize * 1024 ); cache.setAutoDelete( true ); flushTimer.start( 300000 ); // 5 minutes connect( &flushTimer, TQT_SIGNAL( timeout() ), TQT_SLOT( flushTimeout() ) ); } void KThemeCache::flushTimeout() { TQIntCacheIterator it( cache ); while ( it.current() ) { if ( it.current() ->isOld() ) cache.remove( it.currentKey() ); else ++it; } } KThemePixmap* KThemeCache::pixmap( int w, int h, int widgetID, bool border, bool mask ) { kthemeKey key; key.cacheKey = 0; // shut up, gcc key.data.id = widgetID; key.data.width = w; key.data.height = h; key.data.border = border; key.data.mask = mask; KThemePixmap *pix = cache.find( ( unsigned long ) key.cacheKey ); if ( pix ) pix->updateAccessed(); return ( pix ); } KThemePixmap* KThemeCache::horizontalPixmap( int w, int widgetID ) { kthemeKey key; key.cacheKey = 0; // shut up, gcc key.data.id = widgetID; key.data.width = w; key.data.height = 0; key.data.border = false; key.data.mask = false; KThemePixmap *pix = cache.find( ( unsigned long ) key.cacheKey ); if ( pix ) pix->updateAccessed(); return ( pix ); } KThemePixmap* KThemeCache::verticalPixmap( int h, int widgetID ) { kthemeKey key; key.cacheKey = 0; // shut up, gcc key.data.id = widgetID; key.data.width = 0; key.data.height = h; key.data.border = false; key.data.mask = false; KThemePixmap *pix = cache.find( ( unsigned long ) key.cacheKey ); if ( pix ) pix->updateAccessed(); return ( pix ); } bool KThemeCache::insert( KThemePixmap *pixmap, ScaleHint scale, int widgetID, bool border, bool mask ) { kthemeKey key; key.cacheKey = 0; // shut up, gcc key.data.id = widgetID; key.data.width = ( scale == FullScale || scale == HorizontalScale ) ? pixmap->width() : 0; key.data.height = ( scale == FullScale || scale == VerticalScale ) ? pixmap->height() : 0; key.data.border = border; key.data.mask = mask; if ( cache.find( ( unsigned long ) key.cacheKey, true ) != NULL ) { return ( true ); // a pixmap of this scale is already in there } return ( cache.insert( ( unsigned long ) key.cacheKey, pixmap, pixmap->width() * pixmap->height() * pixmap->depth() / 8 ) ); } #include "kthemebase.moc"