File indexing completed on 2024-05-12 16:39:55
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 "KexiFadeWidgetEffect.h" 0023 #include "KexiFadeWidgetEffect_p.h" 0024 0025 #include <QtCore/QEvent> 0026 #include <QPaintEngine> 0027 #include <QPainter> 0028 #include <QStyle> 0029 0030 KexiFadeWidgetEffectPrivate::KexiFadeWidgetEffectPrivate(QWidget *_destWidget) 0031 : destWidget(_destWidget), disabled(false), defaultDuration(0) 0032 { 0033 } 0034 0035 // Code from KFileItemDelegate (Author: Frederik Höglund) 0036 // Fast transitions. Read: 0037 // https://techbase.kde.org/Development/Tutorials/Graphics/Performance 0038 // for further information on why not use setOpacity. 0039 QPixmap KexiFadeWidgetEffectPrivate::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 KexiFadeWidgetEffect::KexiFadeWidgetEffect(QWidget *destWidget, int defaultDuration) 0097 : QWidget(destWidget ? destWidget->parentWidget() : 0), 0098 d(new KexiFadeWidgetEffectPrivate(destWidget)) 0099 { 0100 d->defaultDuration = defaultDuration; 0101 Q_ASSERT(destWidget && destWidget->parentWidget()); 0102 if (!destWidget || !destWidget->parentWidget() || !destWidget->isVisible() || 0103 !style()->styleHint(QStyle::SH_Widget_Animate, 0, this)) { 0104 d->disabled = true; 0105 hide(); 0106 return; 0107 } 0108 setGeometry(QRect(destWidget->mapTo(parentWidget(), QPoint(0, 0)), destWidget->size())); 0109 d->oldPixmap = destWidget->grab(); 0110 d->timeLine.setFrameRange(0, 255); 0111 d->timeLine.setCurveShape(QTimeLine::EaseOutCurve); 0112 connect(&d->timeLine, SIGNAL(finished()), SLOT(finished())); 0113 connect(&d->timeLine, SIGNAL(frameChanged(int)), SLOT(repaint())); 0114 show(); 0115 } 0116 0117 KexiFadeWidgetEffect::~KexiFadeWidgetEffect() 0118 { 0119 delete d; 0120 } 0121 0122 void KexiFadeWidgetEffect::finished() 0123 { 0124 d->destWidget->setUpdatesEnabled(false); 0125 hide(); 0126 deleteLater(); 0127 d->destWidget->setUpdatesEnabled(true); 0128 } 0129 0130 void KexiFadeWidgetEffect::start(int duration) 0131 { 0132 if (d->disabled) { 0133 deleteLater(); 0134 return; 0135 } 0136 d->newPixmap = d->destWidget->grab(); 0137 d->timeLine.setDuration(duration); 0138 d->timeLine.start(); 0139 } 0140 0141 void KexiFadeWidgetEffect::start() 0142 { 0143 start(d->defaultDuration); 0144 } 0145 0146 void KexiFadeWidgetEffect::paintEvent(QPaintEvent *) 0147 { 0148 QPainter p(this); 0149 p.drawPixmap(rect(), d->transition(d->oldPixmap, d->newPixmap, d->timeLine.currentValue())); 0150 p.end(); 0151 }