kexi

kexigradientwidget.cpp

00001 /* This file is part of the KDE project
00002    Copyright (C) 2005 Christian Nitschkowski <segfault_ii@web.de>
00003 
00004    This program is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This program is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this program; see the file COPYING.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  * Boston, MA 02110-1301, USA.
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 //      if ( p_backgroundPixmap.isNull() ) {
00092             //unsetPalette();
00093         //} else {
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             Need to unset the palette, otherwise the old gradient
00132             will be used as a background, not the widget's default bg.
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"
KDE Home | KDE Accessibility Home | Description of Access Keys