Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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();
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
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 break;
296 }
297 default:
298 break;
299 }
300}
301
302/*
303 Internal class QRollEffect
304
305 The QRollEffect widget is shown while the animation lasts
306 and displays a scrolling pixmap.
307*/
308
309class QRollEffect : public QWidget, private QEffects
310{
312public:
313 QRollEffect(QWidget* w, Qt::WindowFlags f, DirFlags orient);
314
315 void run(int time);
316
317protected:
318 void paintEvent(QPaintEvent*) override;
319 void closeEvent(QCloseEvent*) override;
320
321private slots:
322 void scroll();
323
324private:
325 QPointer<QWidget> widget;
326
327 int currentHeight;
328 int currentWidth;
329 int totalHeight;
330 int totalWidth;
331
332 int duration;
333 int elapsed;
334 bool done;
335 bool showWidget;
336 int orientation;
337
338 QTimer anim;
339 QElapsedTimer checkTime;
340
341 QPixmap pm;
342};
343
344static QRollEffect* q_roll = nullptr;
345
346/*
347 Construct a QRollEffect widget.
348*/
349QRollEffect::QRollEffect(QWidget* w, Qt::WindowFlags f, DirFlags orient)
350 : QWidget(nullptr, f), orientation(orient)
351{
352 QWidgetPrivate::get(this)->setScreen(w->screen());
353#ifndef Q_OS_WIN
354 setEnabled(false);
355#endif
356
357 widget = w;
358 Q_ASSERT(widget);
359
361
362 if (widget->testAttribute(Qt::WA_Resized)) {
363 totalWidth = widget->width();
364 totalHeight = widget->height();
365 } else {
366 totalWidth = widget->sizeHint().width();
367 totalHeight = widget->sizeHint().height();
368 }
369
370 currentHeight = totalHeight;
371 currentWidth = totalWidth;
372
373 if (orientation & (RightScroll|LeftScroll))
374 currentWidth = 0;
375 if (orientation & (DownScroll|UpScroll))
376 currentHeight = 0;
377
378 pm = widget->grab();
379}
380
381/*
382 \reimp
383*/
385{
386 int x = orientation & RightScroll ? qMin(0, currentWidth - totalWidth) : 0;
387 int y = orientation & DownScroll ? qMin(0, currentHeight - totalHeight) : 0;
388
389 QPainter p(this);
390 p.drawPixmap(x, y, pm);
391}
392
393/*
394 \reimp
395*/
397{
398 e->accept();
399 if (done)
400 return;
401
402 showWidget = false;
403 done = true;
404 scroll();
405
407}
408
409/*
410 Start the animation.
411
412 The animation will take about \a time ms, or is
413 calculated if \a time is negative
414*/
416{
417 if (!widget)
418 return;
419
420 duration = time;
421 elapsed = 0;
422
423 if (duration < 0) {
424 int dist = 0;
425 if (orientation & (RightScroll|LeftScroll))
426 dist += totalWidth - currentWidth;
427 if (orientation & (DownScroll|UpScroll))
428 dist += totalHeight - currentHeight;
429 duration = qMin(qMax(dist/3, 50), 120);
430 }
431
432 connect(&anim, &QTimer::timeout, this, &QRollEffect::scroll);
433
434 move(widget->geometry().x(),widget->geometry().y());
435 resize(qMin(currentWidth, totalWidth), qMin(currentHeight, totalHeight));
436
437 //This is roughly equivalent to calling setVisible(true) without actually showing the widget
439 widget->setAttribute(Qt::WA_WState_Hidden, false);
440
441 show();
442 setEnabled(false);
443
444 showWidget = true;
445 done = false;
446 anim.start(1);
447 checkTime.start();
448}
449
450/*
451 Roll according to the time elapsed.
452*/
453void QRollEffect::scroll()
454{
455 if (!done && widget) {
456 int tempel = checkTime.elapsed();
457 if (elapsed >= tempel)
458 elapsed++;
459 else
460 elapsed = tempel;
461
462 if (currentWidth != totalWidth) {
463 currentWidth = totalWidth * (elapsed/duration)
464 + (2 * totalWidth * (elapsed%duration) + duration)
465 / (2 * duration);
466 // equiv. to int((totalWidth*elapsed) / duration + 0.5)
467 }
468 if (currentHeight != totalHeight) {
469 currentHeight = totalHeight * (elapsed/duration)
470 + (2 * totalHeight * (elapsed%duration) + duration)
471 / (2 * duration);
472 // equiv. to int((totalHeight*elapsed) / duration + 0.5)
473 }
474 done = (currentHeight >= totalHeight) &&
475 (currentWidth >= totalWidth);
476
477 int w = totalWidth;
478 int h = totalHeight;
479 int x = widget->geometry().x();
480 int y = widget->geometry().y();
481
482 if (orientation & RightScroll || orientation & LeftScroll)
483 w = qMin(currentWidth, totalWidth);
484 if (orientation & DownScroll || orientation & UpScroll)
485 h = qMin(currentHeight, totalHeight);
486
487 setUpdatesEnabled(false);
488 if (orientation & UpScroll)
489 y = widget->geometry().y() + qMax(0, totalHeight - currentHeight);
490 if (orientation & LeftScroll)
491 x = widget->geometry().x() + qMax(0, totalWidth - currentWidth);
492 if (orientation & UpScroll || orientation & LeftScroll)
493 move(x, y);
494
495 resize(w, h);
496 setUpdatesEnabled(true);
497 repaint();
498 }
499 if (done || !widget) {
500 anim.stop();
501 if (widget) {
502 if (!showWidget) {
503#ifdef Q_OS_WIN
504 setEnabled(true);
505 setFocus();
506#endif
507 widget->hide();
508 } else {
509 //Since we are faking the visibility of the widget
510 //we need to unset the hidden state on it before calling show
511 widget->setAttribute(Qt::WA_WState_Hidden, true);
512 widget->show();
513 lower();
514 }
515 }
516 q_roll = nullptr;
517 deleteLater();
518 }
519}
520
521/*
522 Scroll widget \a w in \a time ms. \a orient may be 1 (vertical), 2
523 (horizontal) or 3 (diagonal).
524*/
526{
527 if (q_roll) {
528 q_roll->deleteLater();
529 q_roll = nullptr;
530 }
531
532 if (!w)
533 return;
534
537 Qt::WindowFlags flags = Qt::ToolTip;
538
539 // those can be popups - they would steal the focus, but are disabled
540 q_roll = new QRollEffect(w, flags, orient);
541 q_roll->run(time);
542}
543
544/*
545 Fade in widget \a w in \a time ms.
546*/
548{
549 if (q_blend) {
550 q_blend->deleteLater();
551 q_blend = nullptr;
552 }
553
554 if (!w)
555 return;
556
559
560 Qt::WindowFlags flags = Qt::ToolTip;
561
562 // those can be popups - they would steal the focus, but are disabled
563 q_blend = new QAlphaWidget(w, flags);
564
565 q_blend->run(time);
566}
567
569
570/*
571 Delete this after timeout
572*/
573
574#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:562
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
\typealias QElapsedTimer::Duration Synonym for std::chrono::nanoseconds.
\inmodule QtCore
Definition qcoreevent.h:45
@ KeyPress
Definition qcoreevent.h:64
@ MouseButtonPress
Definition qcoreevent.h:60
@ MouseButtonDblClick
Definition qcoreevent.h:62
Type type() const
Returns the event type.
Definition qcoreevent.h:304
void accept()
Sets the accept flag of the event object, the equivalent of calling setAccepted(true).
Definition qcoreevent.h:310
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:1560
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:1698
bool isNull() const
Returns true if it is a null image, otherwise returns false.
Definition qimage.cpp:1222
int height() const
Returns the height of the image.
int depth() const
The QKeyEvent class describes a key event.
Definition qevent.h:424
\inmodule QtCore
Definition qobject.h:103
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
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:1555
void deleteLater()
\threadsafe
Definition qobject.cpp:2435
The QPaintEvent class contains event parameters for paint events.
Definition qevent.h:486
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:408
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:1437
constexpr int height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:239
constexpr int x() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:185
constexpr int width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:236
constexpr int y() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:188
void paintEvent(QPaintEvent *) override
This event handler can be reimplemented in a subclass to receive paint events passed in event.
Definition qeffects.cpp:384
void run(int time)
Definition qeffects.cpp:415
QRollEffect(QWidget *w, Qt::WindowFlags f, DirFlags orient)
Definition qeffects.cpp:349
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:396
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:133
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:130
\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:241
void stop()
Stops the timer.
Definition qtimer.cpp:267
void timeout(QPrivateSignal)
This signal is emitted when the timer times out.
static QWidgetPrivate * get(QWidget *w)
Definition qwidget_p.h:212
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:7858
Q_INVOKABLE QPixmap grab(const QRect &rectangle=QRect(QPoint(0, 0), QSize(-1, -1)))
Definition qwidget.cpp:5215
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:9856
QSize size
the size of the widget excluding any window frame
Definition qwidget.h:113
void setEnabled(bool)
Definition qwidget.cpp:3358
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:8135
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:7875
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
Combined button and popup list for selecting options.
@ WA_WState_ExplicitShowHide
Definition qnamespace.h:335
@ WA_Resized
Definition qnamespace.h:308
@ WA_WState_Hidden
Definition qnamespace.h:297
@ WA_NoSystemBackground
Definition qnamespace.h:291
@ ToolTip
Definition qnamespace.h:213
#define Q_FALLTHROUGH()
#define qApp
static QRollEffect * q_roll
Definition qeffects.cpp:344
static QAlphaWidget * q_blend
Definition qeffects.cpp:61
void qScrollEffect(QWidget *w, QEffects::DirFlags orient, int time)
Definition qeffects.cpp:525
void qFadeEffect(QWidget *w, int time)
Definition qeffects.cpp:547
int qRound(qfloat16 d) noexcept
Definition qfloat16.h:327
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
GLint GLint GLint GLint GLint x
[0]
GLfloat GLfloat GLfloat w
[0]
GLboolean GLboolean GLboolean GLboolean a
[7]
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:50
unsigned char uchar
Definition qtypes.h:32
ptrdiff_t qsizetype
Definition qtypes.h:165
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