00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <qapplication.h>
00021 #include <qbitmap.h>
00022 #include <qimage.h>
00023 #include <qobjectlist.h>
00024 #include <qpainter.h>
00025 #include <qstyle.h>
00026
00027 #include <kimageeffect.h>
00028 #include <kpixmap.h>
00029
00030 #include "kexigradientwidget.h"
00031
00032 KexiGradientWidget::KexiGradientWidget( QWidget *parent, const char *name, WFlags f )
00033 : QWidget( parent, name, f ), p_displayMode( NoGradient ),
00034 p_gradientType( VerticalGradient ),
00035 p_color1( Qt::white ), p_color2( Qt::blue ), p_currentChild( 0 ),
00036 p_opacity( 0.5 ), p_cacheDirty( true )
00037 {
00038 p_customBackgroundWidgets.setAutoDelete( false );
00039 p_knownWidgets.setAutoDelete( false );
00040
00041 p_backgroundColor = QWidget::paletteBackgroundColor();
00042
00043 connect ( &p_rebuildDelayTimer, SIGNAL( timeout() ), this, SLOT( setCacheDirty() ) );
00044
00045 installEventFilter( this );
00046 }
00047
00048 KexiGradientWidget::~KexiGradientWidget()
00049 {
00050 }
00051
00052 bool KexiGradientWidget::isValidChildWidget( QObject* child ) {
00053 const QWidget* wgt = dynamic_cast<QWidget*>( child );
00054
00055 if ( wgt == 0L )
00056 return false;
00057
00058 if ( wgt->inherits( "QScrollView" ) )
00059 return false;
00060 if ( wgt->inherits( "QComboBox" ) )
00061 return false;
00062 if ( wgt->inherits( "QLineEdit" ) )
00063 return false;
00064 if ( wgt->inherits( "KexiDBForm" ) )
00065 return false;
00066
00067 return true;
00068 }
00069
00070 void KexiGradientWidget::buildChildrenList( WidgetList& list, QWidget* p ) {
00071 QObjectList* objects = p->queryList( "QWidget", 0, false, false );
00072
00073 for ( QObjectList::Iterator it = objects->begin(); it != objects->end(); ++it ) {
00074 if ( isValidChildWidget( ( *it ) ) == false )
00075 continue;
00076 list.append( dynamic_cast<QWidget*>( ( *it ) ) );
00077 buildChildrenList( list, dynamic_cast<QWidget*>( ( *it ) ) );
00078 }
00079
00080 delete objects;
00081 }
00082
00083 void KexiGradientWidget::rebuildCache( void ) {
00084 WidgetList childWidgetList;
00085 buildChildrenList( childWidgetList, this );
00086
00090 if ( p_displayMode == NoGradient ) {
00091
00092
00093
00094 QWidget::setPaletteBackgroundPixmap( p_backgroundPixmap );
00095
00096 QWidget::setPaletteBackgroundColor( p_backgroundColor );
00097
00098 for ( WidgetList::Iterator it = childWidgetList.begin();
00099 it != childWidgetList.end(); ++it ) {
00100
00101 if ( p_customBackgroundWidgets.contains( ( *it ) ) == false ) {
00102 ( *it )->unsetPalette();
00103 }
00104 }
00108 p_cacheDirty = false;
00109 return;
00110 }
00111
00112 KPixmap tempPixmap;
00113 QImage gradientImage;
00114 QImage bgImage;
00115
00119 gradientImage = KImageEffect::gradient( size(), p_color1, p_color2,
00120 (KImageEffect::GradientType)p_gradientType );
00121
00125 if ( p_displayMode == FadedGradient ) {
00126 tempPixmap.resize( size() );
00127 QPainter p( &tempPixmap, this );
00128
00129 if ( p_backgroundPixmap.isNull() ) {
00130
00131
00132
00133
00134 unsetPalette();
00135 p.fillRect( 0, 0, width(), height(), palette().brush(
00136 isEnabled() ? QPalette::Active : QPalette::Disabled,
00137 QColorGroup::Background ) );
00138 } else {
00139 p.drawTiledPixmap( 0, 0, width(), height(), p_backgroundPixmap );
00140 }
00141
00142 p.end();
00143
00144 bgImage = tempPixmap;
00145
00146 KImageEffect::blend( gradientImage, bgImage, (float)p_opacity );
00147
00148 tempPixmap.convertFromImage( bgImage );
00149 } else if ( p_displayMode == SimpleGradient ) {
00154 tempPixmap.convertFromImage( gradientImage );
00155 }
00156
00160 KPixmap partPixmap;
00161 QRect area;
00162 QWidget* childWidget = 0;
00163 const QPoint topLeft( 0, 0 );
00164
00165 for ( WidgetList::Iterator it = childWidgetList.begin();
00166 it != childWidgetList.end(); ++it ) {
00167
00168 childWidget = ( *it );
00169
00173 if ( p_customBackgroundWidgets.contains( childWidget ) ) {
00174 continue;
00175 }
00176
00177 partPixmap.resize( childWidget->size() );
00182 if ( childWidget->parent() == this ) {
00183 area = childWidget->geometry();
00184 } else {
00185 area.setTopLeft( childWidget->mapTo( this,
00186 childWidget->clipRegion().boundingRect().topLeft() ) );
00187 area.setSize( childWidget->size() );
00188 }
00189 bitBlt( &partPixmap, topLeft, &tempPixmap, area );
00190
00191 p_currentChild = childWidget;
00192 childWidget->setPaletteBackgroundPixmap( partPixmap );
00193 }
00194
00195 QWidget::setPaletteBackgroundPixmap( tempPixmap );
00202 p_cacheDirty = false;
00203 }
00204
00205 void KexiGradientWidget::paintEvent( QPaintEvent* e ) {
00209 if ( p_cacheDirty == true ) {
00210 rebuildCache();
00211 }
00212
00216 QWidget::paintEvent( e );
00217 }
00218
00219 bool KexiGradientWidget::eventFilter( QObject* object, QEvent* event ) {
00220 QWidget* child = dynamic_cast<QWidget*>( object );
00221
00225 if ( object == this ) {
00226 if ( event->type() == QEvent::ChildInserted ) {
00227 child = dynamic_cast<QWidget*>( dynamic_cast<QChildEvent*>( event )->child() );
00228 if ( isValidChildWidget( child ) == false ) {
00229 return false;
00230 }
00234 p_knownWidgets.append( child );
00238 child->installEventFilter( this );
00239 } else if ( event->type() == QEvent::ChildRemoved ) {
00243 p_knownWidgets.remove( dynamic_cast<QWidget*>( dynamic_cast<QChildEvent*>( event )->child() ) );
00244 }
00245 return false;
00246 }
00247
00251 if ( event->type() == QEvent::PaletteChange ) {
00257 if ( p_currentChild == 0L && child != 0L ) {
00258 if ( p_customBackgroundWidgets.contains( child ) == false ) {
00259 p_customBackgroundWidgets.append( child );
00260 return false;
00261 }
00262 }
00267 if ( child != p_currentChild && child != 0L ) {
00272 if ( p_customBackgroundWidgets.contains( child ) == false ) {
00273 if ( child->paletteBackgroundPixmap() != 0L ) {
00274 p_customBackgroundWidgets.append( child );
00275 }
00276 } else {
00282 if ( child->paletteBackgroundPixmap() == 0L ) {
00283 p_customBackgroundWidgets.remove( child );
00284 if ( p_displayMode != NoGradient ) {
00285 p_cacheDirty = true;
00286 }
00287 }
00288 }
00289 }
00290 p_currentChild = 0;
00291 }
00292
00293 if ( event->type() == QEvent::Move ) {
00294 if ( p_customBackgroundWidgets.contains( child ) == false ) {
00295 updateChildBackground( child );
00296 }
00297 }
00298 return false;
00299 }
00300
00301 void KexiGradientWidget::updateChildBackground( QWidget* childWidget )
00302 {
00303 KPixmap partPixmap;
00304 KPixmap bgPixmap;
00305 QRect area;
00306 const QPoint topLeft( 0, 0 );
00307
00308 bgPixmap = paletteBackgroundPixmap() ? (*paletteBackgroundPixmap()) : QPixmap();
00309 if ( bgPixmap.isNull() )
00310 return;
00311
00317 if ( childWidget->parent() == 0L )
00318 return;
00319
00323 if ( p_customBackgroundWidgets.contains( childWidget ) ) {
00324 return;
00325 }
00326
00327 partPixmap.resize( childWidget->size() );
00332 if ( childWidget->parent() == this ) {
00333 area = childWidget->geometry();
00334 } else {
00335 area.setTopLeft( childWidget->mapTo( this,
00336 childWidget->clipRegion().boundingRect().topLeft() ) );
00337 area.setSize( childWidget->size() );
00338 }
00339 bitBlt( &partPixmap, topLeft, &bgPixmap, area );
00340
00341 p_currentChild = childWidget;
00342 childWidget->setPaletteBackgroundPixmap( partPixmap );
00343 }
00344
00345 void KexiGradientWidget::setPaletteBackgroundColor( const QColor& color )
00346 {
00347 p_backgroundColor = color;
00348 if ( p_displayMode == NoGradient ) {
00349 QWidget::setPaletteBackgroundColor( p_backgroundColor );
00350 }
00351 }
00352
00353 const QColor& KexiGradientWidget::paletteBackgroundColor() const
00354 {
00355 return p_backgroundColor;
00356 }
00357
00358 #include "kexigradientwidget.moc"