|
Packit |
8e9c33 |
//////////////////////////////////////////////////////////////////////////////
|
|
Packit |
8e9c33 |
// adwaitatransitionwidget.cpp
|
|
Packit |
8e9c33 |
// stores event filters and maps widgets to transitions for transitions
|
|
Packit |
8e9c33 |
// -------------------
|
|
Packit |
8e9c33 |
//
|
|
Packit |
8e9c33 |
// Copyright (c) 2009 Hugo Pereira Da Costa <hugo.pereira@free.fr>
|
|
Packit |
8e9c33 |
//
|
|
Packit |
8e9c33 |
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
Packit |
8e9c33 |
// of this software and associated documentation files (the "Software"), to
|
|
Packit |
8e9c33 |
// deal in the Software without restriction, including without limitation the
|
|
Packit |
8e9c33 |
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
Packit |
8e9c33 |
// sell copies of the Software, and to permit persons to whom the Software is
|
|
Packit |
8e9c33 |
// furnished to do so, subject to the following conditions:
|
|
Packit |
8e9c33 |
//
|
|
Packit |
8e9c33 |
// The above copyright notice and this permission notice shall be included in
|
|
Packit |
8e9c33 |
// all copies or substantial portions of the Software.
|
|
Packit |
8e9c33 |
//
|
|
Packit |
8e9c33 |
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
Packit |
8e9c33 |
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
Packit |
8e9c33 |
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
Packit |
8e9c33 |
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
Packit |
8e9c33 |
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
Packit |
8e9c33 |
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
Packit |
8e9c33 |
// IN THE SOFTWARE.
|
|
Packit |
8e9c33 |
//////////////////////////////////////////////////////////////////////////////
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
#include "adwaitatransitionwidget.h"
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
#include <QPainter>
|
|
Packit |
8e9c33 |
#include <QPaintEvent>
|
|
Packit |
8e9c33 |
#include <QStyleOption>
|
|
Packit |
8e9c33 |
#include <QTextStream>
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
namespace Adwaita
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
//________________________________________________
|
|
Packit |
8e9c33 |
bool TransitionWidget::_paintEnabled = true;
|
|
Packit |
8e9c33 |
bool TransitionWidget::paintEnabled( void )
|
|
Packit |
8e9c33 |
{ return _paintEnabled; }
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
int TransitionWidget::_steps = 0;
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
//________________________________________________
|
|
Packit |
8e9c33 |
TransitionWidget::TransitionWidget( QWidget* parent, int duration ):
|
|
Packit |
8e9c33 |
QWidget( parent ),
|
|
Packit |
8e9c33 |
_animation( new Animation( duration, this ) )
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// background flags
|
|
Packit |
8e9c33 |
setAttribute( Qt::WA_NoSystemBackground );
|
|
Packit |
8e9c33 |
setAutoFillBackground( false );
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// setup animation
|
|
Packit |
8e9c33 |
_animation.data()->setStartValue( 0 );
|
|
Packit |
8e9c33 |
_animation.data()->setEndValue( 1.0 );
|
|
Packit |
8e9c33 |
_animation.data()->setTargetObject( this );
|
|
Packit |
8e9c33 |
_animation.data()->setPropertyName( "opacity" );
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// hide when animation is finished
|
|
Packit |
8e9c33 |
connect( _animation.data(), SIGNAL(finished()), SLOT(hide()) );
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
//________________________________________________
|
|
Packit |
8e9c33 |
QPixmap TransitionWidget::grab( QWidget* widget, QRect rect )
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// change rect
|
|
Packit |
8e9c33 |
if( !rect.isValid() ) rect = widget->rect();
|
|
Packit |
8e9c33 |
if( !rect.isValid() ) return QPixmap();
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// initialize pixmap
|
|
Packit |
8e9c33 |
QPixmap out( rect.size() );
|
|
Packit |
8e9c33 |
out.fill( Qt::transparent );
|
|
Packit |
8e9c33 |
_paintEnabled = false;
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
if( testFlag( GrabFromWindow ) )
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
rect = rect.translated( widget->mapTo( widget->window(), widget->rect().topLeft() ) );
|
|
Packit |
8e9c33 |
widget = widget->window();
|
|
Packit |
8e9c33 |
#if QT_VERSION < 0x050000
|
|
Packit |
8e9c33 |
out = QPixmap::grabWidget( widget, rect );
|
|
Packit |
8e9c33 |
#else
|
|
Packit |
8e9c33 |
out = widget->grab( rect );
|
|
Packit |
8e9c33 |
#endif
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
} else {
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
if( !testFlag( Transparent ) ) { grabBackground( out, widget, rect ); }
|
|
Packit |
8e9c33 |
grabWidget( out, widget, rect );
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
_paintEnabled = true;
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
return out;
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
//________________________________________________
|
|
Packit |
8e9c33 |
bool TransitionWidget::event( QEvent* event )
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
switch( event->type() )
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
case QEvent::MouseButtonPress:
|
|
Packit |
8e9c33 |
case QEvent::MouseButtonRelease:
|
|
Packit |
8e9c33 |
case QEvent::KeyPress:
|
|
Packit |
8e9c33 |
case QEvent::KeyRelease:
|
|
Packit |
8e9c33 |
endAnimation();
|
|
Packit |
8e9c33 |
hide();
|
|
Packit |
8e9c33 |
event->ignore();
|
|
Packit |
8e9c33 |
return false;
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
default: return QWidget::event( event );
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
//________________________________________________
|
|
Packit |
8e9c33 |
void TransitionWidget::paintEvent( QPaintEvent* event )
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// fully transparent case
|
|
Packit |
8e9c33 |
if( opacity() >= 1.0 && endPixmap().isNull() ) return;
|
|
Packit |
8e9c33 |
if( !_paintEnabled ) return;
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// get rect
|
|
Packit |
8e9c33 |
QRect rect = event->rect();
|
|
Packit |
8e9c33 |
if( !rect.isValid() ) rect = this->rect();
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// local pixmap
|
|
Packit |
8e9c33 |
bool paintOnWidget( testFlag( PaintOnWidget ) && !testFlag( Transparent ) );
|
|
Packit |
8e9c33 |
if( !paintOnWidget )
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
if( _currentPixmap.isNull() || _currentPixmap.size() != size() )
|
|
Packit |
8e9c33 |
{ _currentPixmap = QPixmap( size() ); }
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// fill
|
|
Packit |
8e9c33 |
_currentPixmap.fill( Qt::transparent );
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// copy local pixmap to current
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
QPainter p;
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// draw end pixmap first, provided that opacity is small enough
|
|
Packit |
8e9c33 |
if( opacity() >= 0.004 && !_endPixmap.isNull() )
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// faded endPixmap if parent target is transparent and opacity is
|
|
Packit |
8e9c33 |
if( opacity() <= 0.996 && testFlag( Transparent ) )
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
fade( _endPixmap, _currentPixmap, opacity(), rect );
|
|
Packit |
8e9c33 |
p.begin( &_currentPixmap );
|
|
Packit |
8e9c33 |
p.setClipRect( event->rect() );
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
} else {
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
if( paintOnWidget ) p.begin( this );
|
|
Packit |
8e9c33 |
else p.begin( &_currentPixmap );
|
|
Packit |
8e9c33 |
p.setClipRect( event->rect() );
|
|
Packit |
8e9c33 |
p.drawPixmap( QPoint(), _endPixmap );
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
} else {
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
if( paintOnWidget ) p.begin( this );
|
|
Packit |
8e9c33 |
else p.begin( &_currentPixmap );
|
|
Packit |
8e9c33 |
p.setClipRect( event->rect() );
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// draw fading start pixmap
|
|
Packit |
8e9c33 |
if( opacity() <= 0.996 && !_startPixmap.isNull() )
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
if( opacity() >= 0.004 )
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
fade( _startPixmap, _localStartPixmap, 1.0-opacity(), rect );
|
|
Packit |
8e9c33 |
p.drawPixmap( QPoint(), _localStartPixmap );
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
} else p.drawPixmap( QPoint(), _startPixmap );
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
p.end();
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// copy current pixmap on widget
|
|
Packit |
8e9c33 |
if( !paintOnWidget )
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
QPainter p( this );
|
|
Packit |
8e9c33 |
p.setClipRect( event->rect() );
|
|
Packit |
8e9c33 |
p.drawPixmap( QPoint(0,0), _currentPixmap );
|
|
Packit |
8e9c33 |
p.end();
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
//________________________________________________
|
|
Packit |
8e9c33 |
void TransitionWidget::grabBackground( QPixmap& pixmap, QWidget* widget, QRect& rect ) const
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
if( !widget ) return;
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
QWidgetList widgets;
|
|
Packit |
8e9c33 |
if( widget->autoFillBackground() )
|
|
Packit |
8e9c33 |
{ widgets.append( widget ); }
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
QWidget *parent(0);
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// get highest level parent
|
|
Packit |
8e9c33 |
for( parent = widget->parentWidget(); parent; parent = parent->parentWidget() )
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
if( !( parent->isVisible() && parent->rect().isValid() ) ) continue;
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// store in list
|
|
Packit |
8e9c33 |
widgets.append( parent );
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// stop at topLevel
|
|
Packit |
8e9c33 |
if( parent->isTopLevel() || parent->autoFillBackground() ) break;
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
if( !parent ) parent = widget;
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// painting
|
|
Packit |
8e9c33 |
QPainter p(&pixmap);
|
|
Packit |
8e9c33 |
p.setClipRect( rect );
|
|
Packit |
8e9c33 |
QBrush backgroundBrush = parent->palette().brush( parent->backgroundRole());
|
|
Packit |
8e9c33 |
if( backgroundBrush.style() == Qt::TexturePattern)
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
p.drawTiledPixmap( rect, backgroundBrush.texture(), widget->mapTo( parent, rect.topLeft() ) );
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
} else {
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
p.fillRect( pixmap.rect(), backgroundBrush );
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
if( parent->isTopLevel() && parent->testAttribute(Qt::WA_StyledBackground))
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
QStyleOption option;
|
|
Packit |
8e9c33 |
option.initFrom(parent);
|
|
Packit |
8e9c33 |
option.rect = rect;
|
|
Packit |
8e9c33 |
option.rect.translate( widget->mapTo( parent, rect.topLeft() ) );
|
|
Packit |
8e9c33 |
p.translate(-option.rect.topLeft());
|
|
Packit |
8e9c33 |
parent->style()->drawPrimitive ( QStyle::PE_Widget, &option, &p, parent );
|
|
Packit |
8e9c33 |
p.translate(option.rect.topLeft());
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// draw all widgets in parent list
|
|
Packit |
8e9c33 |
// backward
|
|
Packit |
8e9c33 |
QPaintEvent event(rect);
|
|
Packit |
8e9c33 |
for( int i = widgets.size() - 1; i>=0; i-- )
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
QWidget* w = widgets.at(i);
|
|
Packit |
8e9c33 |
w->render( &p, -widget->mapTo( w, rect.topLeft() ), rect, 0 );
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// end
|
|
Packit |
8e9c33 |
p.end();
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
//________________________________________________
|
|
Packit |
8e9c33 |
void TransitionWidget::grabWidget( QPixmap& pixmap, QWidget* widget, QRect& rect ) const
|
|
Packit |
8e9c33 |
{ widget->render( &pixmap, pixmap.rect().topLeft(), rect, QWidget::DrawChildren ); }
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
//________________________________________________
|
|
Packit |
8e9c33 |
void TransitionWidget::fade( const QPixmap& source, QPixmap& target, qreal opacity, const QRect& rect ) const
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
if( target.isNull() || target.size() != size() )
|
|
Packit |
8e9c33 |
{ target = QPixmap( size() ); }
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// erase target
|
|
Packit |
8e9c33 |
target.fill( Qt::transparent );
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// check opacity
|
|
Packit |
8e9c33 |
if( opacity*255 < 1 ) return;
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
QPainter p( &target );
|
|
Packit |
8e9c33 |
p.setClipRect( rect );
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// draw pixmap
|
|
Packit |
8e9c33 |
p.drawPixmap( QPoint(0,0), source );
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
// opacity mask (0.996 corresponds to 254/255)
|
|
Packit |
8e9c33 |
if( opacity <= 0.996 )
|
|
Packit |
8e9c33 |
{
|
|
Packit |
8e9c33 |
p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
|
|
Packit |
8e9c33 |
QColor color( Qt::black );
|
|
Packit |
8e9c33 |
color.setAlphaF( opacity );
|
|
Packit |
8e9c33 |
p.fillRect(rect, color );
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
p.end();
|
|
Packit |
8e9c33 |
return;
|
|
Packit |
8e9c33 |
}
|
|
Packit |
8e9c33 |
|
|
Packit |
8e9c33 |
}
|