~ubuntu-branches/ubuntu/utopic/kde-workspace/utopic-proposed

« back to all changes in this revision

Viewing changes to kstyles/oxygen/transitions/oxygentransitionwidget.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michał Zając
  • Date: 2011-07-09 08:31:15 UTC
  • Revision ID: james.westby@ubuntu.com-20110709083115-ohyxn6z93mily9fc
Tags: upstream-4.6.90
Import upstream version 4.6.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//////////////////////////////////////////////////////////////////////////////
 
2
// oxygentransitionwidget.cpp
 
3
// stores event filters and maps widgets to transitions for transitions
 
4
// -------------------
 
5
//
 
6
// Copyright (c) 2009 Hugo Pereira Da Costa <hugo.pereira@free.fr>
 
7
//
 
8
// Permission is hereby granted, free of charge, to any person obtaining a copy
 
9
// of this software and associated documentation files (the "Software"), to
 
10
// deal in the Software without restriction, including without limitation the
 
11
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 
12
// sell copies of the Software, and to permit persons to whom the Software is
 
13
// furnished to do so, subject to the following conditions:
 
14
//
 
15
// The above copyright notice and this permission notice shall be included in
 
16
// all copies or substantial portions of the Software.
 
17
//
 
18
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
19
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
20
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 
21
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
22
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 
23
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 
24
// IN THE SOFTWARE.
 
25
//////////////////////////////////////////////////////////////////////////////
 
26
 
 
27
#include "oxygentransitionwidget.h"
 
28
#include "oxygentransitionwidget.moc"
 
29
 
 
30
#include <cassert>
 
31
#include <QtGui/QPainter>
 
32
#include <QtGui/QPaintEvent>
 
33
#include <QtGui/QStyleOption>
 
34
#include <QtCore/QCoreApplication>
 
35
#include <QtCore/QTextStream>
 
36
 
 
37
namespace Oxygen
 
38
{
 
39
 
 
40
    //________________________________________________
 
41
    bool TransitionWidget::_paintEnabled = true;
 
42
    bool TransitionWidget::paintEnabled( void )
 
43
    { return _paintEnabled; }
 
44
 
 
45
    int TransitionWidget::_steps = 0;
 
46
 
 
47
    //________________________________________________
 
48
    TransitionWidget::TransitionWidget( QWidget* parent, int duration ):
 
49
        QWidget( parent ),
 
50
        _flags( None ),
 
51
        _animation( new Animation( duration, this ) ),
 
52
        _opacity( 0 )
 
53
    {
 
54
 
 
55
        // background flags
 
56
        setAttribute(Qt::WA_NoSystemBackground );
 
57
        setAutoFillBackground( false );
 
58
 
 
59
        // setup animation
 
60
        _animation.data()->setStartValue( 0 );
 
61
        _animation.data()->setEndValue( 1.0 );
 
62
        _animation.data()->setTargetObject( this );
 
63
        _animation.data()->setPropertyName( "opacity" );
 
64
 
 
65
        // setup connections
 
66
        connect( _animation.data(), SIGNAL( finished( void ) ), SIGNAL( finished( void ) ) );
 
67
 
 
68
    }
 
69
 
 
70
    //________________________________________________
 
71
    QPixmap TransitionWidget::grab( QWidget* widget, QRect rect )
 
72
    {
 
73
 
 
74
        // change rect
 
75
        if( !rect.isValid() ) rect = widget->rect();
 
76
        if( !rect.isValid() ) return QPixmap();
 
77
 
 
78
        // initialize pixmap
 
79
        QPixmap out( rect.size() );
 
80
        out.fill( Qt::transparent );
 
81
        _paintEnabled = false;
 
82
 
 
83
        if( testFlag( GrabFromWindow ) )
 
84
        {
 
85
 
 
86
            rect = rect.translated( widget->mapTo( widget->window(), widget->rect().topLeft() ) );
 
87
            widget = widget->window();
 
88
            out = QPixmap::grabWidget( widget, rect );
 
89
 
 
90
        } else {
 
91
 
 
92
            if( !testFlag( Transparent ) ) { grabBackground( out, widget, rect ); }
 
93
            grabWidget( out, widget, rect );
 
94
 
 
95
        }
 
96
 
 
97
        _paintEnabled = true;
 
98
 
 
99
        return out;
 
100
 
 
101
    }
 
102
 
 
103
    //________________________________________________
 
104
    void TransitionWidget::paintEvent( QPaintEvent* event )
 
105
    {
 
106
 
 
107
        // fully transparent case
 
108
        if( opacity() >= 1.0 && endPixmap().isNull() ) return;
 
109
        if( !_paintEnabled ) return;
 
110
 
 
111
        // get rect
 
112
        QRect rect = event->rect();
 
113
        if( !rect.isValid() ) rect = this->rect();
 
114
 
 
115
        // local pixmap
 
116
        const bool paintOnWidget( testFlag( PaintOnWidget ) && !testFlag( Transparent ) );
 
117
        if( !paintOnWidget )
 
118
        {
 
119
 
 
120
            if( _currentPixmap.isNull() || _currentPixmap.size() != size() )
 
121
            { _currentPixmap = QPixmap( size() ); }
 
122
 
 
123
        }
 
124
 
 
125
        // fill
 
126
        _currentPixmap.fill( Qt::transparent );
 
127
 
 
128
        // copy local pixmap to current
 
129
        {
 
130
 
 
131
            QPainter p;
 
132
 
 
133
            // draw end pixmap first, provided that opacity is small enough
 
134
            if( opacity() >= 0.004 && !_endPixmap.isNull() )
 
135
            {
 
136
 
 
137
                // faded endPixmap if parent target is transparent and opacity is
 
138
                if( opacity() <= 0.996 && testFlag( Transparent ) )
 
139
                {
 
140
 
 
141
                    fade( _endPixmap, _currentPixmap, opacity(), rect );
 
142
                    p.begin( &_currentPixmap );
 
143
                    p.setClipRect( event->rect() );
 
144
 
 
145
                } else {
 
146
 
 
147
                    if( paintOnWidget ) p.begin( this );
 
148
                    else p.begin( &_currentPixmap );
 
149
                    p.setClipRect( event->rect() );
 
150
                    p.drawPixmap( QPoint(), _endPixmap );
 
151
 
 
152
                }
 
153
 
 
154
            } else {
 
155
 
 
156
                if( paintOnWidget ) p.begin( this );
 
157
                else p.begin( &_currentPixmap );
 
158
                p.setClipRect( event->rect() );
 
159
 
 
160
            }
 
161
 
 
162
            // draw fading start pixmap
 
163
            if( opacity() <= 0.996 && !_startPixmap.isNull() )
 
164
            {
 
165
                if( opacity() >= 0.004 )
 
166
                {
 
167
 
 
168
                    fade( _startPixmap, _localStartPixmap, 1.0-opacity(), rect );
 
169
                    p.drawPixmap( QPoint(), _localStartPixmap );
 
170
 
 
171
                } else p.drawPixmap( QPoint(), _startPixmap );
 
172
 
 
173
            }
 
174
 
 
175
            p.end();
 
176
        }
 
177
 
 
178
        // copy current pixmap on widget
 
179
        if( !paintOnWidget )
 
180
        {
 
181
            QPainter p( this );
 
182
            p.setClipRect( event->rect() );
 
183
            p.drawPixmap( QPoint(0,0), _currentPixmap );
 
184
            p.end();
 
185
        }
 
186
    }
 
187
 
 
188
    //________________________________________________
 
189
    void TransitionWidget::grabBackground( QPixmap& pixmap, QWidget* widget, QRect& rect ) const
 
190
    {
 
191
        if( !widget ) return;
 
192
 
 
193
        QWidgetList widgets;
 
194
        if( widget->autoFillBackground() )
 
195
        { widgets.push_back( widget ); }
 
196
 
 
197
        QWidget *parent(0);
 
198
 
 
199
        // get highest level parent
 
200
        for( parent = widget->parentWidget(); parent; parent = parent->parentWidget() )
 
201
        {
 
202
 
 
203
            if( !( parent->isVisible() && parent->rect().isValid() ) ) continue;
 
204
 
 
205
            // store in list
 
206
            widgets.push_back( parent );
 
207
 
 
208
            // stop at topLevel
 
209
            if( parent->isTopLevel() || parent->autoFillBackground() ) break;
 
210
 
 
211
        }
 
212
 
 
213
        if( !parent ) parent = widget;
 
214
 
 
215
        // painting
 
216
        QPainter p(&pixmap);
 
217
        p.setClipRect( rect );
 
218
        const QBrush backgroundBrush = parent->palette().brush( parent->backgroundRole());
 
219
        if( backgroundBrush.style() == Qt::TexturePattern)
 
220
        {
 
221
 
 
222
            p.drawTiledPixmap( rect, backgroundBrush.texture(), widget->mapTo( parent, rect.topLeft() ) );
 
223
 
 
224
        } else {
 
225
 
 
226
            p.fillRect( pixmap.rect(), backgroundBrush );
 
227
 
 
228
        }
 
229
 
 
230
        if( parent->isTopLevel() && parent->testAttribute(Qt::WA_StyledBackground))
 
231
        {
 
232
            QStyleOption option;
 
233
            option.initFrom(parent);
 
234
            option.rect = rect;
 
235
            option.rect.translate( widget->mapTo( parent, rect.topLeft() ) );
 
236
            p.translate(-option.rect.topLeft());
 
237
            parent->style()->drawPrimitive ( QStyle::PE_Widget, &option, &p, parent );
 
238
        }
 
239
 
 
240
        p.end();
 
241
 
 
242
        // draw all widgets in parent list
 
243
        // backward
 
244
        QPaintEvent event(rect);
 
245
        for( int i = widgets.size() - 1; i>=0; i-- )
 
246
        {
 
247
            QWidget* w = widgets.at(i);
 
248
            QPainter::setRedirected( w, &pixmap, widget->mapTo(w, rect.topLeft() ) );
 
249
            event = QPaintEvent(QRect( QPoint(), rect.size()));
 
250
            QCoreApplication::sendEvent(w, &event);
 
251
            QPainter::restoreRedirected(w);
 
252
        }
 
253
 
 
254
    }
 
255
 
 
256
    //________________________________________________
 
257
    void TransitionWidget::grabWidget( QPixmap& pixmap, QWidget* widget, QRect& rect ) const
 
258
    { widget->render( &pixmap, pixmap.rect().topLeft(), rect, QWidget::DrawChildren ); }
 
259
 
 
260
    //________________________________________________
 
261
    void TransitionWidget::fade( const QPixmap& source, QPixmap& target, qreal opacity, const QRect& rect ) const
 
262
    {
 
263
 
 
264
        if( target.isNull() || target.size() != size() )
 
265
        { target = QPixmap( size() ); }
 
266
 
 
267
        // erase target
 
268
        target.fill( Qt::transparent );
 
269
 
 
270
        // check opacity
 
271
        if( opacity*255 < 1 ) return;
 
272
 
 
273
        QPainter p( &target );
 
274
        p.setClipRect( rect );
 
275
 
 
276
        // draw pixmap
 
277
        p.drawPixmap( QPoint(0,0), source );
 
278
 
 
279
        // opacity mask (0.996 corresponds to 254/255)
 
280
        if( opacity <= 0.996 )
 
281
        {
 
282
            p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
 
283
            QColor color( Qt::black );
 
284
            color.setAlphaF( opacity );
 
285
            p.fillRect(rect, color );
 
286
        }
 
287
 
 
288
        p.end();
 
289
        return;
 
290
    }
 
291
 
 
292
}