1 /****************************************************************************
3 ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the QtGui module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
40 ****************************************************************************/
42 #include "qapplication.h"
44 #include "qdesktopwidget.h"
45 #include "qeffects_p.h"
52 #include "qelapsedtimer.h"
58 Internal class QAlphaWidget.
60 The QAlphaWidget is shown while the animation lasts
61 and displays the pixmap resulting from the alpha blending.
64 class QAlphaWidget: public QWidget, private QEffects
68 QAlphaWidget(QWidget* w, Qt::WindowFlags f = 0);
74 void paintEvent(QPaintEvent* e);
75 void closeEvent(QCloseEvent*);
77 bool eventFilter(QObject *, QEvent *);
88 QPointer<QWidget> widget;
93 QElapsedTimer checkTime;
96 static QAlphaWidget* q_blend = 0;
99 Constructs a QAlphaWidget.
101 QAlphaWidget::QAlphaWidget(QWidget* w, Qt::WindowFlags f)
102 : QWidget(QApplication::desktop()->screen(QApplication::desktop()->screenNumber(w)), f)
107 setAttribute(Qt::WA_NoSystemBackground, true);
112 QAlphaWidget::~QAlphaWidget()
114 #if defined(Q_WS_WIN) && !defined(Q_WS_WINCE)
115 // Restore user-defined opacity value
117 widget->setWindowOpacity(1);
124 void QAlphaWidget::paintEvent(QPaintEvent*)
127 p.drawPixmap(0, 0, pm);
131 Starts the alphablending animation.
132 The animation will take about \a time ms
134 void QAlphaWidget::run(int time)
148 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
149 qApp->installEventFilter(this);
150 widget->setWindowOpacity(0.0);
152 connect(&anim, SIGNAL(timeout()), this, SLOT(render()));
155 //This is roughly equivalent to calling setVisible(true) without actually showing the widget
156 widget->setAttribute(Qt::WA_WState_ExplicitShowHide, true);
157 widget->setAttribute(Qt::WA_WState_Hidden, false);
159 qApp->installEventFilter(this);
161 move(widget->geometry().x(),widget->geometry().y());
162 resize(widget->size().width(), widget->size().height());
164 frontImage = QPixmap::grabWidget(widget).toImage();
165 backImage = QPixmap::grabWindow(QApplication::desktop()->winId(),
166 widget->geometry().x(), widget->geometry().y(),
167 widget->geometry().width(), widget->geometry().height()).toImage();
169 if (!backImage.isNull() && checkTime.elapsed() < duration / 2) {
170 mixedImage = backImage.copy();
171 pm = QPixmap::fromImage(mixedImage);
175 connect(&anim, SIGNAL(timeout()), this, SLOT(render()));
187 bool QAlphaWidget::eventFilter(QObject *o, QEvent *e)
193 move(widget->geometry().x(),widget->geometry().y());
200 case QEvent::MouseButtonPress:
201 case QEvent::MouseButtonDblClick:
205 case QEvent::KeyPress: {
206 QKeyEvent *ke = (QKeyEvent*)e;
207 if (ke->key() == Qt::Key_Escape) {
218 return QWidget::eventFilter(o, e);
224 void QAlphaWidget::closeEvent(QCloseEvent *e)
233 QWidget::closeEvent(e);
237 Render alphablending for the time elapsed.
239 Show the blended widget and free all allocated source
240 if the blending is finished.
242 void QAlphaWidget::render()
244 int tempel = checkTime.elapsed();
245 if (elapsed >= tempel)
251 alpha = tempel / double(duration);
255 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
256 if (alpha >= 1 || !showWidget) {
258 qApp->removeEventFilter(this);
259 widget->setWindowOpacity(1);
263 widget->setWindowOpacity(alpha);
266 if (alpha >= 1 || !showWidget) {
268 qApp->removeEventFilter(this);
278 //Since we are faking the visibility of the widget
279 //we need to unset the hidden state on it before calling show
280 widget->setAttribute(Qt::WA_WState_Hidden, true);
289 pm = QPixmap::fromImage(mixedImage);
292 #endif // defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
296 Calculate an alphablended image.
298 void QAlphaWidget::alphaBlend()
300 const int a = qRound(alpha*256);
301 const int ia = 256 - a;
303 const int sw = frontImage.width();
304 const int sh = frontImage.height();
305 const int bpl = frontImage.bytesPerLine();
306 switch(frontImage.depth()) {
309 uchar *mixed_data = mixedImage.bits();
310 const uchar *back_data = backImage.bits();
311 const uchar *front_data = frontImage.bits();
313 for (int sy = 0; sy < sh; sy++) {
314 quint32* mixed = (quint32*)mixed_data;
315 const quint32* back = (const quint32*)back_data;
316 const quint32* front = (const quint32*)front_data;
317 for (int sx = 0; sx < sw; sx++) {
318 quint32 bp = back[sx];
319 quint32 fp = front[sx];
321 mixed[sx] = qRgb((qRed(bp)*ia + qRed(fp)*a)>>8,
322 (qGreen(bp)*ia + qGreen(fp)*a)>>8,
323 (qBlue(bp)*ia + qBlue(fp)*a)>>8);
336 Internal class QRollEffect
338 The QRollEffect widget is shown while the animation lasts
339 and displays a scrolling pixmap.
342 class QRollEffect : public QWidget, private QEffects
346 QRollEffect(QWidget* w, Qt::WindowFlags f, DirFlags orient);
351 void paintEvent(QPaintEvent*);
352 void closeEvent(QCloseEvent*);
358 QPointer<QWidget> widget;
372 QElapsedTimer checkTime;
377 static QRollEffect* q_roll = 0;
380 Construct a QRollEffect widget.
382 QRollEffect::QRollEffect(QWidget* w, Qt::WindowFlags f, DirFlags orient)
383 : QWidget(0, f), orientation(orient)
392 setAttribute(Qt::WA_NoSystemBackground, true);
394 if (widget->testAttribute(Qt::WA_Resized)) {
395 totalWidth = widget->width();
396 totalHeight = widget->height();
398 totalWidth = widget->sizeHint().width();
399 totalHeight = widget->sizeHint().height();
402 currentHeight = totalHeight;
403 currentWidth = totalWidth;
405 if (orientation & (RightScroll|LeftScroll))
407 if (orientation & (DownScroll|UpScroll))
410 pm = QPixmap::grabWidget(widget);
416 void QRollEffect::paintEvent(QPaintEvent*)
418 int x = orientation & RightScroll ? qMin(0, currentWidth - totalWidth) : 0;
419 int y = orientation & DownScroll ? qMin(0, currentHeight - totalHeight) : 0;
422 p.drawPixmap(x, y, pm);
428 void QRollEffect::closeEvent(QCloseEvent *e)
438 QWidget::closeEvent(e);
444 The animation will take about \a time ms, or is
445 calculated if \a time is negative
447 void QRollEffect::run(int time)
457 if (orientation & (RightScroll|LeftScroll))
458 dist += totalWidth - currentWidth;
459 if (orientation & (DownScroll|UpScroll))
460 dist += totalHeight - currentHeight;
461 duration = qMin(qMax(dist/3, 50), 120);
464 connect(&anim, SIGNAL(timeout()), this, SLOT(scroll()));
466 move(widget->geometry().x(),widget->geometry().y());
467 resize(qMin(currentWidth, totalWidth), qMin(currentHeight, totalHeight));
469 //This is roughly equivalent to calling setVisible(true) without actually showing the widget
470 widget->setAttribute(Qt::WA_WState_ExplicitShowHide, true);
471 widget->setAttribute(Qt::WA_WState_Hidden, false);
476 qApp->installEventFilter(this);
485 Roll according to the time elapsed.
487 void QRollEffect::scroll()
489 if (!done && widget) {
490 int tempel = checkTime.elapsed();
491 if (elapsed >= tempel)
496 if (currentWidth != totalWidth) {
497 currentWidth = totalWidth * (elapsed/duration)
498 + (2 * totalWidth * (elapsed%duration) + duration)
500 // equiv. to int((totalWidth*elapsed) / duration + 0.5)
501 done = (currentWidth >= totalWidth);
503 if (currentHeight != totalHeight) {
504 currentHeight = totalHeight * (elapsed/duration)
505 + (2 * totalHeight * (elapsed%duration) + duration)
507 // equiv. to int((totalHeight*elapsed) / duration + 0.5)
508 done = (currentHeight >= totalHeight);
510 done = (currentHeight >= totalHeight) &&
511 (currentWidth >= totalWidth);
515 int x = widget->geometry().x();
516 int y = widget->geometry().y();
518 if (orientation & RightScroll || orientation & LeftScroll)
519 w = qMin(currentWidth, totalWidth);
520 if (orientation & DownScroll || orientation & UpScroll)
521 h = qMin(currentHeight, totalHeight);
523 setUpdatesEnabled(false);
524 if (orientation & UpScroll)
525 y = widget->geometry().y() + qMax(0, totalHeight - currentHeight);
526 if (orientation & LeftScroll)
527 x = widget->geometry().x() + qMax(0, totalWidth - currentWidth);
528 if (orientation & UpScroll || orientation & LeftScroll)
532 setUpdatesEnabled(true);
535 if (done || !widget) {
537 qApp->removeEventFilter(this);
546 //Since we are faking the visibility of the widget
547 //we need to unset the hidden state on it before calling show
548 widget->setAttribute(Qt::WA_WState_Hidden, true);
559 Scroll widget \a w in \a time ms. \a orient may be 1 (vertical), 2
560 (horizontal) or 3 (diagonal).
562 void qScrollEffect(QWidget* w, QEffects::DirFlags orient, int time)
565 q_roll->deleteLater();
572 QApplication::sendPostedEvents(w, QEvent::Move);
573 QApplication::sendPostedEvents(w, QEvent::Resize);
574 Qt::WindowFlags flags = Qt::ToolTip;
576 // those can be popups - they would steal the focus, but are disabled
577 q_roll = new QRollEffect(w, flags, orient);
582 Fade in widget \a w in \a time ms.
584 void qFadeEffect(QWidget* w, int time)
587 q_blend->deleteLater();
594 QApplication::sendPostedEvents(w, QEvent::Move);
595 QApplication::sendPostedEvents(w, QEvent::Resize);
597 Qt::WindowFlags flags = Qt::ToolTip;
599 // those can be popups - they would steal the focus, but are disabled
600 q_blend = new QAlphaWidget(w, flags);
608 Delete this after timeout
611 #include "qeffects.moc"
613 #endif //QT_NO_EFFECTS