Warning, file /frameworks/kdelibs4support/src/kdeui/kfadewidgeteffect.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*  This file is part of the KDE project
0002     Copyright (C) 2008 Matthias Kretz <kretz@kde.org>
0003     Copyright (C) 2008 Rafael Fernández López <ereslibre@kde.org>
0004 
0005     This program is free software; you can redistribute it and/or
0006     modify it under the terms of the GNU Library General Public
0007     License as published by the Free Software Foundation; either
0008     version 2 of the License, or (at your option) version 3.
0009 
0010     This library is distributed in the hope that it will be useful,
0011     but WITHOUT ANY WARRANTY; without even the implied warranty of
0012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013     Library General Public License for more details.
0014 
0015     You should have received a copy of the GNU Library General Public License
0016     along with this library; see the file COPYING.LIB.  If not, write to
0017     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0018     Boston, MA 02110-1301, USA.
0019 
0020 */
0021 
0022 #include "kfadewidgeteffect.h"
0023 #include "kfadewidgeteffect_p.h"
0024 
0025 #include <QEvent>
0026 #include <QPaintEngine>
0027 #include <QPainter>
0028 #include <QStyle>
0029 
0030 KFadeWidgetEffectPrivate::KFadeWidgetEffectPrivate(QWidget *_destWidget)
0031     : destWidget(_destWidget), disabled(false)
0032 {
0033 }
0034 
0035 // Code from KFileItemDelegate (Author: Frederik Höglund)
0036 // Fast transitions. Read:
0037 // http://techbase.kde.org/Development/Tutorials/Graphics/Performance
0038 // for further information on why not use setOpacity.
0039 QPixmap KFadeWidgetEffectPrivate::transition(const QPixmap &from, const QPixmap &to, qreal amount) const
0040 {
0041     const int value = int(0xff * amount);
0042 
0043     if (value == 0) {
0044         return from;
0045     }
0046 
0047     if (value == 1) {
0048         return to;
0049     }
0050 
0051     QColor color;
0052     color.setAlphaF(amount);
0053 
0054     // If the native paint engine supports Porter/Duff compositing and CompositionMode_Plus
0055     if (from.paintEngine()->hasFeature(QPaintEngine::PorterDuff) &&
0056             from.paintEngine()->hasFeature(QPaintEngine::BlendModes)) {
0057         QPixmap under = from;
0058         QPixmap over  = to;
0059 
0060         QPainter p;
0061         p.begin(&over);
0062         p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
0063         p.fillRect(over.rect(), color);
0064         p.end();
0065 
0066         p.begin(&under);
0067         p.setCompositionMode(QPainter::CompositionMode_DestinationOut);
0068         p.fillRect(under.rect(), color);
0069         p.setCompositionMode(QPainter::CompositionMode_Plus);
0070         p.drawPixmap(0, 0, over);
0071         p.end();
0072 
0073         return under;
0074     } else {
0075         // Fall back to using QRasterPaintEngine to do the transition.
0076         QImage under = from.toImage();
0077         QImage over  = to.toImage();
0078 
0079         QPainter p;
0080         p.begin(&over);
0081         p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
0082         p.fillRect(over.rect(), color);
0083         p.end();
0084 
0085         p.begin(&under);
0086         p.setCompositionMode(QPainter::CompositionMode_DestinationOut);
0087         p.fillRect(under.rect(), color);
0088         p.setCompositionMode(QPainter::CompositionMode_Plus);
0089         p.drawImage(0, 0, over);
0090         p.end();
0091 
0092         return QPixmap::fromImage(under);
0093     }
0094 }
0095 
0096 KFadeWidgetEffect::KFadeWidgetEffect(QWidget *destWidget)
0097     : QWidget(destWidget ? destWidget->parentWidget() : nullptr),
0098       d_ptr(new KFadeWidgetEffectPrivate(destWidget))
0099 {
0100     Q_D(KFadeWidgetEffect);
0101     d->q_ptr = this;
0102     Q_ASSERT(destWidget && destWidget->parentWidget());
0103     if (!destWidget || !destWidget->parentWidget() || !destWidget->isVisible() ||
0104             !style()->styleHint(QStyle::SH_Widget_Animate, nullptr, this)) {
0105         d->disabled = true;
0106         hide();
0107         return;
0108     }
0109     setGeometry(QRect(destWidget->mapTo(parentWidget(), QPoint(0, 0)), destWidget->size()));
0110     d->oldPixmap = destWidget->grab();
0111     d->timeLine.setFrameRange(0, 255);
0112     d->timeLine.setCurveShape(QTimeLine::EaseOutCurve);
0113     connect(&d->timeLine, SIGNAL(finished()), SLOT(finished()));
0114     connect(&d->timeLine, SIGNAL(frameChanged(int)), SLOT(repaint()));
0115     show();
0116 }
0117 
0118 KFadeWidgetEffect::~KFadeWidgetEffect()
0119 {
0120     delete d_ptr;
0121 }
0122 
0123 void KFadeWidgetEffectPrivate::finished()
0124 {
0125     Q_Q(KFadeWidgetEffect);
0126     destWidget->setUpdatesEnabled(false);
0127     q->hide();
0128     q->deleteLater();
0129     destWidget->setUpdatesEnabled(true);
0130 }
0131 
0132 void KFadeWidgetEffect::start(int duration)
0133 {
0134     Q_D(KFadeWidgetEffect);
0135     if (d->disabled) {
0136         deleteLater();
0137         return;
0138     }
0139     d->newPixmap = d->destWidget->grab();
0140     d->timeLine.setDuration(duration);
0141     d->timeLine.start();
0142 }
0143 
0144 void KFadeWidgetEffect::paintEvent(QPaintEvent *)
0145 {
0146     Q_D(KFadeWidgetEffect);
0147     QPainter p(this);
0148     p.drawPixmap(rect(), d->transition(d->oldPixmap, d->newPixmap, d->timeLine.currentValue()));
0149     p.end();
0150 }
0151 
0152 #include "moc_kfadewidgeteffect.cpp"