|
|
|
/* This file is part of the KDE project
|
|
|
|
Copyright (C) 2005 Christian Nitschkowski <segfault_ii@web.de>
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU Library General Public
|
|
|
|
License as published by the Free Software Foundation; either
|
|
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This program 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 program; see the file COPYING. If not, write to
|
|
|
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
* Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <tqapplication.h>
|
|
|
|
#include <tqbitmap.h>
|
|
|
|
#include <tqimage.h>
|
|
|
|
#include <tqobjectlist.h>
|
|
|
|
#include <tqpainter.h>
|
|
|
|
#include <tqstyle.h>
|
|
|
|
|
|
|
|
#include <kimageeffect.h>
|
|
|
|
#include <kpixmap.h>
|
|
|
|
|
|
|
|
#include "kexigradientwidget.h"
|
|
|
|
|
|
|
|
KexiGradientWidget::KexiGradientWidget( TQWidget *parent, const char *name, WFlags f )
|
|
|
|
: TQWidget( parent, name, f ), p_displayMode( NoGradient ),
|
|
|
|
p_gradientType( VerticalGradient ),
|
|
|
|
p_color1( TQt::white ), p_color2( TQt::blue ), p_currentChild( 0 ),
|
|
|
|
p_opacity( 0.5 ), p_cacheDirty( true )
|
|
|
|
{
|
|
|
|
p_customBackgroundWidgets.setAutoDelete( false );
|
|
|
|
p_knownWidgets.setAutoDelete( false );
|
|
|
|
|
|
|
|
p_backgroundColor = TQWidget::paletteBackgroundColor();
|
|
|
|
|
|
|
|
connect ( &p_rebuildDelayTimer, TQT_SIGNAL( timeout() ), this, TQT_SLOT( setCacheDirty() ) );
|
|
|
|
|
|
|
|
installEventFilter( this );
|
|
|
|
}
|
|
|
|
|
|
|
|
KexiGradientWidget::~KexiGradientWidget()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KexiGradientWidget::isValidChildWidget( TQObject* child ) {
|
|
|
|
const TQWidget* wgt = dynamic_cast<TQWidget*>( child );
|
|
|
|
|
|
|
|
if ( wgt == 0L )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if ( wgt->inherits( "TQScrollView" ) )
|
|
|
|
return false;
|
|
|
|
if ( wgt->inherits( "TQComboBox" ) )
|
|
|
|
return false;
|
|
|
|
if ( wgt->inherits( "TQLineEdit" ) )
|
|
|
|
return false;
|
|
|
|
if ( wgt->inherits( "KexiDBForm" ) )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KexiGradientWidget::buildChildrenList( WidgetList& list, TQWidget* p ) {
|
|
|
|
TQObjectList* objects = p->queryList( "TQWidget", 0, false, false );
|
|
|
|
|
|
|
|
for ( TQObjectList::Iterator it = objects->begin(); it != objects->end(); ++it ) {
|
|
|
|
if ( isValidChildWidget( ( *it ) ) == false )
|
|
|
|
continue;
|
|
|
|
list.append( dynamic_cast<TQWidget*>( ( *it ) ) );
|
|
|
|
buildChildrenList( list, dynamic_cast<TQWidget*>( ( *it ) ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
delete objects;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KexiGradientWidget::rebuildCache( void ) {
|
|
|
|
WidgetList childWidgetList;
|
|
|
|
buildChildrenList( childWidgetList, this );
|
|
|
|
|
|
|
|
/**
|
|
|
|
Disable the effect and behave like a normal TQWidget.
|
|
|
|
*/
|
|
|
|
if ( p_displayMode == NoGradient ) {
|
|
|
|
// if ( p_backgroundPixmap.isNull() ) {
|
|
|
|
//unsetPalette();
|
|
|
|
//} else {
|
|
|
|
TQWidget::setPaletteBackgroundPixmap( p_backgroundPixmap );
|
|
|
|
//}
|
|
|
|
TQWidget::setPaletteBackgroundColor( p_backgroundColor );
|
|
|
|
|
|
|
|
for ( WidgetList::Iterator it = childWidgetList.begin();
|
|
|
|
it != childWidgetList.end(); ++it ) {
|
|
|
|
|
|
|
|
if ( p_customBackgroundWidgets.contains( ( *it ) ) == false ) {
|
|
|
|
( *it )->unsetPalette();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
The cache is now in a current state.
|
|
|
|
*/
|
|
|
|
p_cacheDirty = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
KPixmap tempPixmap;
|
|
|
|
TQImage gradientImage;
|
|
|
|
TQImage bgImage;
|
|
|
|
|
|
|
|
/**
|
|
|
|
Draw the gradient
|
|
|
|
*/
|
|
|
|
gradientImage = KImageEffect::gradient( size(), p_color1, p_color2,
|
|
|
|
(KImageEffect::GradientType)p_gradientType );
|
|
|
|
|
|
|
|
/**
|
|
|
|
Draw the widget-background in a pixmap and fade it with the gradient.
|
|
|
|
*/
|
|
|
|
if ( p_displayMode == FadedGradient ) {
|
|
|
|
tempPixmap.resize( size() );
|
|
|
|
TQPainter p( &tempPixmap, this );
|
|
|
|
|
|
|
|
if ( p_backgroundPixmap.isNull() ) {
|
|
|
|
/*
|
|
|
|
Need to unset the palette, otherwise the old gradient
|
|
|
|
will be used as a background, not the widget's default bg.
|
|
|
|
*/
|
|
|
|
unsetPalette();
|
|
|
|
p.fillRect( 0, 0, width(), height(), palette().brush(
|
|
|
|
isEnabled() ? TQPalette::Active : TQPalette::Disabled,
|
|
|
|
TQColorGroup::Background ) );
|
|
|
|
} else {
|
|
|
|
p.drawTiledPixmap( 0, 0, width(), height(), p_backgroundPixmap );
|
|
|
|
}
|
|
|
|
|
|
|
|
p.end();
|
|
|
|
|
|
|
|
bgImage = tempPixmap;
|
|
|
|
|
|
|
|
KImageEffect::blend( gradientImage, bgImage, (float)p_opacity );
|
|
|
|
|
|
|
|
tempPixmap.convertFromImage( bgImage );
|
|
|
|
} else if ( p_displayMode == SimpleGradient ) {
|
|
|
|
/**
|
|
|
|
Use the gradient as the final background-pixmap
|
|
|
|
if displaymode is set to SimpleGradient.
|
|
|
|
*/
|
|
|
|
tempPixmap.convertFromImage( gradientImage );
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
All children need to have our background set.
|
|
|
|
*/
|
|
|
|
KPixmap partPixmap;
|
|
|
|
TQRect area;
|
|
|
|
TQWidget* childWidget = 0;
|
|
|
|
const TQPoint topLeft( 0, 0 );
|
|
|
|
|
|
|
|
for ( WidgetList::Iterator it = childWidgetList.begin();
|
|
|
|
it != childWidgetList.end(); ++it ) {
|
|
|
|
|
|
|
|
childWidget = ( *it );
|
|
|
|
|
|
|
|
/**
|
|
|
|
Exclude widgets with a custom palette.
|
|
|
|
*/
|
|
|
|
if ( p_customBackgroundWidgets.contains( childWidget ) ) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
partPixmap.resize( childWidget->size() );
|
|
|
|
/**
|
|
|
|
Get the part of the tempPixmap that is
|
|
|
|
under the current child-widget.
|
|
|
|
*/
|
|
|
|
if ( childWidget->parent() == this ) {
|
|
|
|
area = childWidget->geometry();
|
|
|
|
} else {
|
|
|
|
area.setTopLeft( childWidget->mapTo( this,
|
|
|
|
childWidget->clipRegion().boundingRect().topLeft() ) );
|
|
|
|
area.setSize( childWidget->size() );
|
|
|
|
}
|
|
|
|
bitBlt( &partPixmap, topLeft, &tempPixmap, area );
|
|
|
|
|
|
|
|
p_currentChild = childWidget;
|
|
|
|
childWidget->setPaletteBackgroundPixmap( partPixmap );
|
|
|
|
}
|
|
|
|
|
|
|
|
TQWidget::setPaletteBackgroundPixmap( tempPixmap );
|
|
|
|
/**
|
|
|
|
Unset the dirty-flag at the end of the method.
|
|
|
|
TQWidget::setPaletteBackgroundPixmap() causes this
|
|
|
|
to get set to true again, so set it to false
|
|
|
|
right after setting the pixmap.
|
|
|
|
*/
|
|
|
|
p_cacheDirty = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KexiGradientWidget::paintEvent( TQPaintEvent* e ) {
|
|
|
|
/**
|
|
|
|
Rebuild the background-pixmap if necessary.
|
|
|
|
*/
|
|
|
|
if ( p_cacheDirty == true ) {
|
|
|
|
rebuildCache();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Draw the widget as usual
|
|
|
|
*/
|
|
|
|
TQWidget::paintEvent( e );
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KexiGradientWidget::eventFilter( TQObject* object, TQEvent* event ) {
|
|
|
|
TQWidget* child = dynamic_cast<TQWidget*>( object );
|
|
|
|
|
|
|
|
/**
|
|
|
|
Manage list of child-widgets.
|
|
|
|
*/
|
|
|
|
if ( object == this ) {
|
|
|
|
if ( event->type() == TQEvent::ChildInserted ) {
|
|
|
|
child = dynamic_cast<TQWidget*>( dynamic_cast<TQChildEvent*>( event )->child() );
|
|
|
|
if ( isValidChildWidget( TQT_TQOBJECT(child) ) == false ) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
Add the new child-widget to our list of known widgets.
|
|
|
|
*/
|
|
|
|
p_knownWidgets.append( child );
|
|
|
|
/**
|
|
|
|
... and install 'this' as the child's event-filter.
|
|
|
|
*/
|
|
|
|
child->installEventFilter( this );
|
|
|
|
} else if ( event->type() == TQEvent::ChildRemoved ) {
|
|
|
|
/**
|
|
|
|
Remove the child-widget from the list of known widgets.
|
|
|
|
*/
|
|
|
|
p_knownWidgets.remove( dynamic_cast<TQWidget*>( dynamic_cast<TQChildEvent*>( event )->child() ) );
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Manage custombackground-list.
|
|
|
|
*/
|
|
|
|
if ( event->type() == TQEvent::PaletteChange ) {
|
|
|
|
/**
|
|
|
|
p_currentChild will be == 0L, when the user
|
|
|
|
sets it's palette manually.
|
|
|
|
In this case, it has to be added to the customBackground-list.
|
|
|
|
*/
|
|
|
|
if ( p_currentChild == 0L && child != 0L ) {
|
|
|
|
if ( p_customBackgroundWidgets.contains( child ) == false ) {
|
|
|
|
p_customBackgroundWidgets.append( child );
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
Check if the widget whose PaletteChange-event we handle
|
|
|
|
isn't the widget we set the background in rebuildCache().
|
|
|
|
*/
|
|
|
|
if ( child != p_currentChild && child != 0L ) {
|
|
|
|
/**
|
|
|
|
Add the new child to the list of widgets, we don't set
|
|
|
|
the background ourselves if it isn't in the list.
|
|
|
|
*/
|
|
|
|
if ( p_customBackgroundWidgets.contains( child ) == false ) {
|
|
|
|
if ( child->paletteBackgroundPixmap() != 0L ) {
|
|
|
|
p_customBackgroundWidgets.append( child );
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/**
|
|
|
|
If the palette is now the default-palette again,
|
|
|
|
remove it from the "don't set background in rebuildCache()"-list
|
|
|
|
and rebuild the cache, so it again will get the gradient background.
|
|
|
|
*/
|
|
|
|
if ( child->paletteBackgroundPixmap() == 0L ) {
|
|
|
|
p_customBackgroundWidgets.remove( child );
|
|
|
|
if ( p_displayMode != NoGradient ) {
|
|
|
|
p_cacheDirty = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
p_currentChild = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( event->type() == TQEvent::Move ) {
|
|
|
|
if ( p_customBackgroundWidgets.contains( child ) == false ) {
|
|
|
|
updateChildBackground( child );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KexiGradientWidget::updateChildBackground( TQWidget* childWidget )
|
|
|
|
{
|
|
|
|
KPixmap partPixmap;
|
|
|
|
KPixmap bgPixmap;
|
|
|
|
TQRect area;
|
|
|
|
const TQPoint topLeft( 0, 0 );
|
|
|
|
|
|
|
|
bgPixmap = paletteBackgroundPixmap() ? (*paletteBackgroundPixmap()) : TQPixmap();
|
|
|
|
if ( bgPixmap.isNull() )
|
|
|
|
return;
|
|
|
|
|
|
|
|
/**
|
|
|
|
Exclude widgtes that don't have a parent.
|
|
|
|
This happens when children are removed
|
|
|
|
which are in the knownWidgets-list.
|
|
|
|
*/
|
|
|
|
if ( childWidget->parent() == 0L )
|
|
|
|
return;
|
|
|
|
|
|
|
|
/**
|
|
|
|
Exclude widgets with a custom palette.
|
|
|
|
*/
|
|
|
|
if ( p_customBackgroundWidgets.contains( childWidget ) ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
partPixmap.resize( childWidget->size() );
|
|
|
|
/**
|
|
|
|
Get the part of the tempPixmap that is
|
|
|
|
under the current child-widget.
|
|
|
|
*/
|
|
|
|
if ( childWidget->parent() == this ) {
|
|
|
|
area = childWidget->geometry();
|
|
|
|
} else {
|
|
|
|
area.setTopLeft( childWidget->mapTo( this,
|
|
|
|
childWidget->clipRegion().boundingRect().topLeft() ) );
|
|
|
|
area.setSize( childWidget->size() );
|
|
|
|
}
|
|
|
|
bitBlt( &partPixmap, topLeft, &bgPixmap, area );
|
|
|
|
|
|
|
|
p_currentChild = childWidget;
|
|
|
|
childWidget->setPaletteBackgroundPixmap( partPixmap );
|
|
|
|
}
|
|
|
|
|
|
|
|
void KexiGradientWidget::setPaletteBackgroundColor( const TQColor& color )
|
|
|
|
{
|
|
|
|
p_backgroundColor = color;
|
|
|
|
if ( p_displayMode == NoGradient ) {
|
|
|
|
TQWidget::setPaletteBackgroundColor( p_backgroundColor );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const TQColor& KexiGradientWidget::paletteBackgroundColor() const
|
|
|
|
{
|
|
|
|
return p_backgroundColor;
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "kexigradientwidget.moc"
|