File indexing completed on 2024-05-12 16:39:55

0001 /* This file is part of the KDE project
0002    Copyright (C) 2011 Jarosław Staniek <staniek@kde.org>
0003 
0004    This program is free software; you can redistribute it and/or
0005    modify it under the terms of the GNU Library General Public
0006    License as published by the Free Software Foundation; either
0007    version 2 of the License, or (at your option) any later version.
0008 
0009    This program is distributed in the hope that it will be useful,
0010    but WITHOUT ANY WARRANTY; without even the implied warranty of
0011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012    Library General Public License for more details.
0013 
0014    You should have received a copy of the GNU Library General Public License
0015    along with this program; see the file COPYING.  If not, write to
0016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0017  * Boston, MA 02110-1301, USA.
0018  */
0019 
0020 #include "KexiAnimatedLayout.h"
0021 #include "KexiAnimatedLayout_p.h"
0022 
0023 #include <kexiutils/utils.h>
0024 
0025 #include <QPainter>
0026 #include <QPaintEvent>
0027 #include <QDebug>
0028 
0029 KexiAnimatedLayout::Private::Private(KexiAnimatedLayout * qq)
0030  : QWidget(), q(qq), animation(this, "pos")
0031 {
0032     hide();
0033     setAttribute(Qt::WA_OpaquePaintEvent, true);
0034     animation.setEasingCurve(QEasingCurve::InOutQuart);
0035     animation.setDuration(500);
0036     connect(&animation, SIGNAL(finished()), this, SLOT(animationFinished()));
0037 }
0038 
0039 void KexiAnimatedLayout::Private::animateTo(QWidget* destination)
0040 {
0041     QWidget *from = q->currentWidget();
0042     Q_ASSERT(destination && from);
0043     destinationWidget = destination;
0044     if (from == destinationWidget)
0045         return;
0046     if (!(KexiUtils::graphicEffectsLevel() & KexiUtils::SimpleAnimationEffects))
0047     {
0048         // animations not allowed: switch to destination widget immediately
0049         animationFinished();
0050         return;
0051     }
0052     bool toRight = q->currentIndex() < q->indexOf(destinationWidget);
0053     hide();
0054     setParent(from);
0055     QSize s(from->parentWidget()->size());
0056     QPoint startPos(toRight ? QPoint(0, 0) : QPoint(s.width(), 0));
0057     QPoint endPos(toRight ? QPoint(s.width(), 0) : QPoint(0, 0));
0058     animation.setStartValue(-startPos);
0059     animation.setEndValue(-endPos);
0060     buffer = QPixmap(s.width() * 2, s.height());
0061     buffer.fill(Qt::white);
0062     from->render(&buffer, startPos);
0063     //qDebug() << s << from->geometry() << destinationWidget->geometry();
0064     destinationWidget->resize(from->size()); // needed because destination could
0065                                                // have been never displayed
0066     destinationWidget->render(&buffer, endPos);
0067     resize(buffer.size());
0068     move(animation.startValue().toPoint().x(), animation.startValue().toPoint().y());
0069     show();
0070     animation.start();
0071 }
0072 
0073 void KexiAnimatedLayout::Private::paintEvent(QPaintEvent* event)
0074 {
0075     if (buffer.isNull())
0076         return;
0077     QPainter p(this);
0078     p.drawPixmap(event->rect(), buffer, event->rect());
0079 }
0080 
0081 void KexiAnimatedLayout::Private::animationFinished()
0082 {
0083     if (destinationWidget) {
0084         static_cast<QStackedLayout*>(q)->setCurrentWidget(destinationWidget);
0085     }
0086     hide();
0087     destinationWidget = 0;
0088     buffer = QPixmap();
0089 }
0090 
0091 // ----
0092 
0093 KexiAnimatedLayout::KexiAnimatedLayout(QWidget* parent)
0094  : QStackedLayout(parent)
0095  , d(new Private(this))
0096 {
0097 }
0098 
0099 KexiAnimatedLayout::~KexiAnimatedLayout()
0100 {
0101     delete d;
0102 }
0103 
0104 void KexiAnimatedLayout::setCurrentWidget(QWidget* widget)
0105 {
0106     if (indexOf(widget) < 0) {
0107         return;
0108     }
0109     if (!currentWidget()) {
0110         QStackedLayout::setCurrentWidget(widget);
0111         return;
0112     }
0113     d->animateTo(widget);
0114 }
0115 
0116 void KexiAnimatedLayout::setCurrentIndex(int index)
0117 {
0118     QWidget *w = widget(index);
0119     if (!w)
0120         return;
0121 
0122     setCurrentWidget(w);
0123 }