Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qeffects.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qapplication.h"
5#include "qdebug.h"
6#include "qeffects_p.h"
7#include "qelapsedtimer.h"
8#include "qevent.h"
9#include "qimage.h"
10#include "qpainter.h"
11#include "qscreen.h"
12#include "qpixmap.h"
13#include "qpointer.h"
14#include "qtimer.h"
15#include "qwidget.h"
16#include "private/qwidget_p.h"
17#include "qwindow.h"
18
19
21
22/*
23 Internal class QAlphaWidget.
24
25 The QAlphaWidget is shown while the animation lasts
26 and displays the pixmap resulting from the alpha blending.
27*/
28
29class QAlphaWidget: public QWidget, private QEffects
30{
32public:
33 QAlphaWidget(QWidget* w, Qt::WindowFlags f = { });
35
36 void run(int time);
37
38protected:
39 void paintEvent(QPaintEvent* e) override;
40 void closeEvent(QCloseEvent*) override;
41 void alphaBlend();
42 bool eventFilter(QObject *, QEvent *) override;
43
44protected slots:
45 void render();
46
47private:
48 QPixmap pm;
49 double alpha;
50 QImage backImage;
51 QImage frontImage;
52 QImage mixedImage;
53 QPointer<QWidget> widget;
54 int duration;
55 int elapsed;
56 bool showWidget;
57 QTimer anim;
58 QElapsedTimer checkTime;
59};
60
61static QAlphaWidget* q_blend = nullptr;
62
63/*
64 Constructs a QAlphaWidget.
65*/
67 : QWidget(nullptr, f)
68{
69 QWidgetPrivate::get(this)->setScreen(w->screen());
70#ifndef Q_OS_WIN
71 setEnabled(false);
72#endif
74 widget = w;
75 alpha = 0;
76}
77
79{
80#if defined(Q_OS_WIN)
81 // Restore user-defined opacity value
82 if (widget)
83 widget->setWindowOpacity(1);
84#endif
85}
86
87/*
88 \reimp
89*/
91{
92 QPainter p(this);
93 p.drawPixmap(0, 0, pm);
94}
95
96/*
97 Starts the alphablending animation.
98 The animation will take about \a time ms
99*/
101{
102 duration = time;
103
104 if (duration < 0)
105 duration = 150;
106
107 if (!widget)
108 return;
109
110 elapsed = 0;
111 checkTime.start();
112
113 showWidget = true;
114#if defined(Q_OS_WIN)
115 qApp->installEventFilter(this);
116 widget->setWindowOpacity(0.0);
117 widget->show();
118 connect(&anim, SIGNAL(timeout()), this, SLOT(render()));
119 anim.start(1);
120#else
121 //This is roughly equivalent to calling setVisible(true) without actually showing the widget
123 widget->setAttribute(Qt::WA_WState_Hidden, false);
124
125 qApp->installEventFilter(this);
126
127 move(widget->geometry().x(),widget->geometry().y());
128 resize(widget->size().width(), widget->size().height());
129
130 frontImage = widget->grab().toImage();
132 widget->geometry().x(), widget->geometry().y(),
133 widget->geometry().width(), widget->geometry().height()).toImage();
134
135 if (!backImage.isNull() && checkTime.elapsed() < duration / 2) {
136 mixedImage = backImage.copy();
137 pm = QPixmap::fromImage(mixedImage);
138 show();
139 setEnabled(false);
140
141 connect(&anim, SIGNAL(timeout()), this, SLOT(render()));
142 anim.start(1);
143 } else {
144 duration = 0;
145 render();
146 }
147#endif
148}
149
150/*
151 \reimp
152*/
154{
155 switch (e->type()) {
156 case QEvent::Move:
157 if (o != widget)
158 break;
159 move(widget->geometry().x(),widget->geometry().y());
160 update();
161 break;
162 case QEvent::Hide:
163 case QEvent::Close:
164 if (o != widget)
165 break;
169 showWidget = false;
170 render();
171 break;
172 case QEvent::KeyPress: {
173#ifndef QT_NO_SHORTCUT
174 QKeyEvent *ke = static_cast<QKeyEvent *>(e);
175 if (ke->matches(QKeySequence::Cancel)) {
176 showWidget = false;
177 } else
178#endif
179 {
180 duration = 0;
181 }
182 render();
183 break;
184 }
185 default:
186 break;
187 }
188 return QWidget::eventFilter(o, e);
189}
190
191/*
192 \reimp
193*/
195{
196 e->accept();
197 if (!q_blend)
198 return;
199
200 showWidget = false;
201 render();
202
204}
205
206/*
207 Render alphablending for the time elapsed.
208
209 Show the blended widget and free all allocated source
210 if the blending is finished.
211*/
213{
214 int tempel = checkTime.elapsed();
215 if (elapsed >= tempel)
216 elapsed++;
217 else
218 elapsed = tempel;
219
220 if (duration != 0)
221 alpha = tempel / double(duration);
222 else
223 alpha = 1;
224
225#if defined(Q_OS_WIN)
226 if (alpha >= 1 || !showWidget) {
227 anim.stop();
228 qApp->removeEventFilter(this);
229 widget->setWindowOpacity(1);
230 q_blend = 0;
231 deleteLater();
232 } else {
233 widget->setWindowOpacity(alpha);
234 }
235#else
236 if (alpha >= 1 || !showWidget) {
237 anim.stop();
238 qApp->removeEventFilter(this);
239
240 if (widget) {
241 if (!showWidget) {
242 widget->hide();
243 } else {
244 //Since we are faking the visibility of the widget
245 //we need to unset the hidden state on it before calling show
246 widget->setAttribute(Qt::WA_WState_Hidden, true);
247 widget->show();
248 lower();
249 }
250 }
251 q_blend = nullptr;
252 deleteLater();
253 } else {
254 alphaBlend();
255 pm = QPixmap::fromImage(mixedImage);
256 repaint();
257 }
258#endif // defined(Q_OS_WIN)
259}
260
261/*
262 Calculate an alphablended image.
263*/
265{
266 const int a = qRound(alpha*256);
267 const int ia = 256 - a;
268
269 const int sw = frontImage.width();
270 const int sh = frontImage.height();
271 const qsizetype bpl = frontImage.bytesPerLine();
272 switch(frontImage.depth()) {
273 case 32:
274 {
275 uchar *mixed_data = mixedImage.bits();
276 const uchar *back_data = backImage.bits();
277 const uchar *front_data = frontImage.bits();
278
279 for (int sy = 0; sy < sh; sy++) {
280 quint32* mixed = (quint32*)mixed_data;
281 const quint32* back = (const quint32*)back_data;
282 const quint32* front = (const quint32*)front_data;
283 for (int sx = 0; sx < sw; sx++) {
284 quint32 bp = back[sx];
285 quint32 fp = front[sx];
286
287 mixed[sx] = qRgb((qRed(bp)*ia + qRed(fp)*a)>>8,
288 (qGreen(bp)*ia + qGreen(fp)*a)>>8,
289 (qBlue(bp)*ia + qBlue(fp)*a)>>8);
290 }
291 mixed_data += bpl;
292 back_data += bpl;
293 front_data += bpl;
294 }
295 }
296 default:
297 break;
298 }
299}
300
301/*
302 Internal class QRollEffect
303
304 The QRollEffect widget is shown while the animation lasts
305 and displays a scrolling pixmap.
306*/
307
308class QRollEffect : public QWidget, private QEffects
309{
311public:
312 QRollEffect(QWidget* w, Qt::WindowFlags f, DirFlags orient);
313
314 void run(int time);
315
316protected:
317 void paintEvent(QPaintEvent*) override;
318 void closeEvent(QCloseEvent*) override;
319
320private slots:
321 void scroll();
322
323private:
324 QPointer<QWidget> widget;
325
326 int currentHeight;
327 int currentWidth;
328 int totalHeight;
329 int totalWidth;
330
331 int duration;
332 int elapsed;
333 bool done;
334 bool showWidget;
335 int orientation;
336
337 QTimer anim;
338 QElapsedTimer checkTime;
339
340 QPixmap pm;
341};
342
343static QRollEffect* q_roll = nullptr;
344
345/*
346 Construct a QRollEffect widget.
347*/
348QRollEffect::QRollEffect(QWidget* w, Qt::WindowFlags f, DirFlags orient)
349 : QWidget(nullptr, f), orientation(orient)
350{
351 QWidgetPrivate::get(this)->setScreen(w->screen());
352#ifndef Q_OS_WIN
353 setEnabled(false);
354#endif
355
356 widget = w;
357 Q_ASSERT(widget);
358
360
361 if (widget->testAttribute(Qt::WA_Resized)) {
362 totalWidth = widget->width();
363 totalHeight = widget->height();
364 } else {
365 totalWidth = widget->sizeHint().width();
366 totalHeight = widget->sizeHint().height();
367 }
368
369 currentHeight = totalHeight;
370 currentWidth = totalWidth;
371
372 if (orientation & (RightScroll|LeftScroll))
373 currentWidth = 0;
374 if (orientation & (DownScroll|UpScroll))
375 currentHeight = 0;
376
377 pm = widget->grab();
378}
379
380/*
381 \reimp
382*/
384{
385 int x = orientation & RightScroll ? qMin(0, currentWidth - totalWidth) : 0;
386 int y = orientation & DownScroll ? qMin(0, currentHeight - totalHeight) : 0;
387
388 QPainter p(this);
389 p.drawPixmap(x, y, pm);
390}
391
392/*
393 \reimp
394*/
396{
397 e->accept();
398 if (done)
399 return;
400
401 showWidget = false;
402 done = true;
403 scroll();
404
406}
407
408/*
409 Start the animation.
410
411 The animation will take about \a time ms, or is
412 calculated if \a time is negative
413*/
415{
416 if (!widget)
417 return;
418
419 duration = time;
420 elapsed = 0;
421
422 if (duration < 0) {
423 int dist = 0;
424 if (orientation & (RightScroll|LeftScroll))
425 dist += totalWidth - currentWidth;
426 if (orientation & (DownScroll|UpScroll))
427 dist += totalHeight - currentHeight;
428 duration = qMin(qMax(dist/3, 50), 120);
429 }
430
431 connect(&anim, SIGNAL(timeout()), this, SLOT(scroll()));
432
433 move(widget->geometry().x(),widget->geometry().y());
434 resize(qMin(currentWidth, totalWidth), qMin(currentHeight, totalHeight));
435
436 //This is roughly equivalent to calling setVisible(true) without actually showing the widget
438 widget->setAttribute(Qt::WA_WState_Hidden, false);
439
440 show();
441 setEnabled(false);
442
443 showWidget = true;
444 done = false;
445 anim.start(1);
446 checkTime.start();
447}
448
449/*
450 Roll according to the time elapsed.
451*/
452void QRollEffect::scroll()
453{
454 if (!done && widget) {
455 int tempel = checkTime.elapsed();
456 if (elapsed >= tempel)
457 elapsed++;
458 else
459 elapsed = tempel;
460
461 if (currentWidth != totalWidth) {
462 currentWidth = totalWidth * (elapsed/duration)
463 + (2 * totalWidth * (elapsed%duration) + duration)
464 / (2 * duration);
465 // equiv. to int((totalWidth*elapsed) / duration + 0.5)
466 }
467 if (currentHeight != totalHeight) {
468 currentHeight = totalHeight * (elapsed/duration)
469 + (2 * totalHeight * (elapsed%duration) + duration)
470 / (2 * duration);
471 // equiv. to int((totalHeight*elapsed) / duration + 0.5)
472 }
473 done = (currentHeight >= totalHeight) &&
474 (currentWidth >= totalWidth);
475
476 int w = totalWidth;
477 int h = totalHeight;
478 int x = widget->geometry().x();
479 int y = widget->geometry().y();
480
481 if (orientation & RightScroll || orientation & LeftScroll)
482 w = qMin(currentWidth, totalWidth);
483 if (orientation & DownScroll || orientation & UpScroll)
484 h = qMin(currentHeight, totalHeight);
485
486 setUpdatesEnabled(false);
487 if (orientation & UpScroll)
488 y = widget->geometry().y() + qMax(0, totalHeight - currentHeight);
489 if (orientation & LeftScroll)
490 x = widget->geometry().x() + qMax(0, totalWidth - currentWidth);
491 if (orientation & UpScroll || orientation & LeftScroll)
492 move(x, y);
493
494 resize(w, h);
495 setUpdatesEnabled(true);
496 repaint();
497 }
498 if (done || !widget) {
499 anim.stop();
500 if (widget) {
501 if (!showWidget) {
502#ifdef Q_OS_WIN
503 setEnabled(true);
504 setFocus();
505#endif
506 widget->hide();
507 } else {
508 //Since we are faking the visibility of the widget
509 //we need to unset the hidden state on it before calling show
510 widget->setAttribute(Qt::WA_WState_Hidden, true);
511 widget->show();
512 lower();
513 }
514 }
515 q_roll = nullptr;
516 deleteLater();
517 }
518}
519
520/*
521 Scroll widget \a w in \a time ms. \a orient may be 1 (vertical), 2
522 (horizontal) or 3 (diagonal).
523*/
525{
526 if (q_roll) {
528 q_roll = nullptr;
529 }
530
531 if (!w)
532 return;
533
536 Qt::WindowFlags flags = Qt::ToolTip;
537
538 // those can be popups - they would steal the focus, but are disabled
539 q_roll = new QRollEffect(w, flags, orient);
540 q_roll->run(time);
541}
542
543/*
544 Fade in widget \a w in \a time ms.
545*/
547{
548 if (q_blend) {
550 q_blend = nullptr;
551 }
552
553 if (!w)
554 return;
555
558
559 Qt::WindowFlags flags = Qt::ToolTip;
560
561 // those can be popups - they would steal the focus, but are disabled
562 q_blend = new QAlphaWidget(w, flags);
563
564 q_blend->run(time);
565}
566
568
569/*
570 Delete this after timeout
571*/
572
573#include "qeffects.moc"
void paintEvent(QPaintEvent *e) override
This event handler can be reimplemented in a subclass to receive paint events passed in event.
Definition qeffects.cpp:90
bool eventFilter(QObject *, QEvent *) override
Filters events if this object has been installed as an event filter for the watched object.
Definition qeffects.cpp:153
void alphaBlend()
Definition qeffects.cpp:264
QAlphaWidget(QWidget *w, Qt::WindowFlags f={ })
Definition qeffects.cpp:66
void closeEvent(QCloseEvent *) override
This event handler is called with the given event when Qt receives a window close request for a top-l...
Definition qeffects.cpp:194
void run(int time)
Definition qeffects.cpp:100
void render()
Definition qeffects.cpp:212
The QCloseEvent class contains parameters that describe a close event.
Definition qevent.h:561
static void sendPostedEvents(QObject *receiver=nullptr, int event_type=0)
Immediately dispatches all events which have been previously queued with QCoreApplication::postEvent(...
\inmodule QtCore
qint64 elapsed() const noexcept
Returns the number of milliseconds since this QElapsedTimer was last started.
void start() noexcept
Starts this timer.
\inmodule QtCore
Definition qcoreevent.h:45
@ KeyPress
Definition qcoreevent.h:64
@ MouseButtonPress
Definition qcoreevent.h:60
@ MouseButtonDblClick
Definition qcoreevent.h:62
QScreen * primaryScreen
the primary (or default) screen of the application.
\inmodule QtGui
Definition qimage.h:37
qsizetype bytesPerLine() const
Returns the number of bytes per image scanline.
Definition qimage.cpp:1538
QImage copy(const QRect &rect=QRect()) const
Returns a sub-area of the image as a new image.
int width() const
Returns the width of the image.
uchar * bits()
Returns a pointer to the first pixel data.
Definition qimage.cpp:1677
bool isNull() const
Returns true if it is a null image, otherwise returns false.
Definition qimage.cpp:1197
int height() const
Returns the height of the image.
int depth() const
The QKeyEvent class describes a key event.
Definition qevent.h:423
\inmodule QtCore
Definition qobject.h:90
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2823
virtual bool eventFilter(QObject *watched, QEvent *event)
Filters events if this object has been installed as an event filter for the watched object.
Definition qobject.cpp:1518
void deleteLater()
\threadsafe
Definition qobject.cpp:2352
The QPaintEvent class contains event parameters for paint events.
Definition qevent.h:485
The QPainter class performs low-level painting on widgets and other paint devices.
Definition qpainter.h:46
Returns a copy of the pixmap that is transformed using the given transformation transform and transfo...
Definition qpixmap.h:27
QImage toImage() const
Converts the pixmap to a QImage.
Definition qpixmap.cpp:412
static QPixmap fromImage(const QImage &image, Qt::ImageConversionFlags flags=Qt::AutoColor)
Converts the given image to a pixmap using the specified flags to control the conversion.
Definition qpixmap.cpp:1445
\inmodule QtCore
Definition qpointer.h:18
constexpr int height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:238
constexpr int x() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:184
constexpr int width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:235
constexpr int y() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:187
void paintEvent(QPaintEvent *) override
This event handler can be reimplemented in a subclass to receive paint events passed in event.
Definition qeffects.cpp:383
void run(int time)
Definition qeffects.cpp:414
QRollEffect(QWidget *w, Qt::WindowFlags f, DirFlags orient)
Definition qeffects.cpp:348
void closeEvent(QCloseEvent *) override
This event handler is called with the given event when Qt receives a window close request for a top-l...
Definition qeffects.cpp:395
QPixmap grabWindow(WId window=0, int x=0, int y=0, int w=-1, int h=-1)
Creates and returns a pixmap constructed by grabbing the contents of the given window restricted by Q...
Definition qscreen.cpp:685
constexpr int height() const noexcept
Returns the height.
Definition qsize.h:132
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:129
\inmodule QtCore
Definition qtimer.h:20
void start(int msec)
Starts or restarts the timer with a timeout interval of msec milliseconds.
Definition qtimer.cpp:208
void stop()
Stops the timer.
Definition qtimer.cpp:226
bool setScreen(QScreen *screen)
Definition qwidget.cpp:2427
static QWidgetPrivate * get(QWidget *w)
Definition qwidget_p.h:211
The QWidget class is the base class of all user interface objects.
Definition qwidget.h:99
void setAttribute(Qt::WidgetAttribute, bool on=true)
Sets the attribute attribute on this widget if on is true; otherwise clears the attribute.
void repaint()
Repaints the widget directly by calling paintEvent() immediately, unless updates are disabled or the ...
void setUpdatesEnabled(bool enable)
Definition qwidget.cpp:7940
Q_INVOKABLE QPixmap grab(const QRect &rectangle=QRect(QPoint(0, 0), QSize(-1, -1)))
Definition qwidget.cpp:5219
virtual void closeEvent(QCloseEvent *event)
This event handler is called with the given event when Qt receives a window close request for a top-l...
Definition qwidget.cpp:9902
QSize size
the size of the widget excluding any window frame
Definition qwidget.h:113
void setEnabled(bool)
Definition qwidget.cpp:3365
void setWindowOpacity(qreal level)
QRect geometry
the geometry of the widget relative to its parent and excluding the window frame
Definition qwidget.h:106
int width
the width of the widget excluding any window frame
Definition qwidget.h:114
void move(int x, int y)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qwidget.h:880
void hide()
Hides the widget.
Definition qwidget.cpp:8209
int height
the height of the widget excluding any window frame
Definition qwidget.h:115
void setFocus()
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qwidget.h:423
void show()
Shows the widget and its child widgets.
Definition qwidget.cpp:7956
void lower()
Lowers the widget to the bottom of the parent widget's stack.
void update()
Updates the widget unless updates are disabled or the widget is hidden.
QSize sizeHint
the recommended size for the widget
Definition qwidget.h:148
void resize(int w, int h)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qwidget.h:883
bool testAttribute(Qt::WidgetAttribute) const
Returns true if attribute attribute is set on this widget; otherwise returns false.
Definition qwidget.h:910
double e
Combined button and popup list for selecting options.
@ WA_WState_ExplicitShowHide
Definition qnamespace.h:334
@ WA_Resized
Definition qnamespace.h:307
@ WA_WState_Hidden
Definition qnamespace.h:296
@ WA_NoSystemBackground
Definition qnamespace.h:290
@ ToolTip
Definition qnamespace.h:212
#define Q_FALLTHROUGH()
#define qApp
static QRollEffect * q_roll
Definition qeffects.cpp:343
static QAlphaWidget * q_blend
Definition qeffects.cpp:61
void qScrollEffect(QWidget *w, QEffects::DirFlags orient, int time)
Definition qeffects.cpp:524
void qFadeEffect(QWidget *w, int time)
Definition qeffects.cpp:546
int qRound(qfloat16 d) noexcept
Definition qfloat16.h:281
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
#define SLOT(a)
Definition qobjectdefs.h:51
#define SIGNAL(a)
Definition qobjectdefs.h:52
GLint GLint GLint GLint GLint x
[0]
GLfloat GLfloat GLfloat w
[0]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLbitfield GLuint64 timeout
[4]
GLfloat GLfloat f
GLbitfield flags
GLint y
GLfloat GLfloat GLfloat GLfloat h
GLfloat GLfloat p
[1]
GLfloat GLfloat GLfloat alpha
Definition qopenglext.h:418
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
constexpr QRgb qRgb(int r, int g, int b)
Definition qrgb.h:30
constexpr int qRed(QRgb rgb)
Definition qrgb.h:18
constexpr int qGreen(QRgb rgb)
Definition qrgb.h:21
constexpr int qBlue(QRgb rgb)
Definition qrgb.h:24
#define fp
#define Q_OBJECT
#define slots
unsigned int quint32
Definition qtypes.h:45
unsigned char uchar
Definition qtypes.h:27
ptrdiff_t qsizetype
Definition qtypes.h:70
std::uniform_real_distribution dist(1, 2.5)
[2]
QObject::connect nullptr
@ RightScroll
Definition qeffects_p.h:32
uint DirFlags
Definition qeffects_p.h:37