KWidgetsAddons

kpixmapsequenceoverlaypainter.cpp
1/*
2 SPDX-FileCopyrightText: 2009 Sebastian Trueg <trueg@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.1-or-later
5*/
6
7#include "kpixmapsequenceoverlaypainter.h"
8#include "kpixmapsequence.h"
9
10#include <QCoreApplication>
11#include <QEvent>
12#include <QPainter>
13#include <QPointer>
14#include <QRect>
15#include <QTimer>
16#include <QWidget>
17
18class KPixmapSequenceOverlayPainterPrivate
19{
20public:
22 void timeout();
23 void paintFrame();
24
25 KPixmapSequence &sequence();
26
27 QRect pixmapRect();
28
29 KPixmapSequence m_sequence;
30 QPointer<QWidget> m_widget;
31 Qt::Alignment m_alignment;
32 QPoint m_offset;
33 QRect m_rect;
34
35 QTimer m_timer;
36 int m_counter;
37
38 bool m_started;
39
41};
42
43void KPixmapSequenceOverlayPainterPrivate::init(KPixmapSequenceOverlayPainter *p)
44{
45 q = p;
46 m_widget = nullptr;
47 m_alignment = Qt::AlignCenter;
48 m_started = false;
49 q->setInterval(200);
50 QObject::connect(&m_timer, &QTimer::timeout, q, [this]() {
51 timeout();
52 });
53}
54
55void KPixmapSequenceOverlayPainterPrivate::timeout()
56{
57 if (sequence().isEmpty()) {
58 return;
59 }
60 ++m_counter;
61 m_counter %= sequence().frameCount();
62 if (m_widget) {
63 m_widget->update(pixmapRect());
64 }
65}
66
67void KPixmapSequenceOverlayPainterPrivate::paintFrame()
68{
69 if (m_counter >= sequence().frameCount()) {
70 return;
71 }
72 QPainter p(m_widget);
73 p.drawPixmap(pixmapRect(), sequence().frameAt(m_counter), QRect(QPoint(0, 0), sequence().frameSize()));
74}
75
76KPixmapSequence &KPixmapSequenceOverlayPainterPrivate::sequence()
77{
78 return m_sequence;
79}
80
81QRect KPixmapSequenceOverlayPainterPrivate::pixmapRect()
82{
83 QRect rect(m_rect);
84 if (!rect.isValid()) {
85 rect = m_widget->rect();
86 }
87
88 QPoint pos(rect.topLeft());
89 if (m_alignment & Qt::AlignHCenter) {
90 pos.setX(rect.center().x() - (sequence().frameSize().width() / 2));
91 } else if (m_alignment & Qt::AlignRight) {
92 pos.setX(rect.right() - sequence().frameSize().width());
93 }
94
95 if (m_alignment & Qt::AlignVCenter) {
96 pos.setY(rect.center().y() - (sequence().frameSize().height() / 2));
97 } else if (m_alignment & Qt::AlignBottom) {
98 pos.setY(rect.bottom() - sequence().frameSize().height());
99 }
100
101 pos += m_offset;
102
103 return QRect(pos, sequence().frameSize());
104}
105
107 : QObject(parent)
108 , d(new KPixmapSequenceOverlayPainterPrivate)
109{
110 d->init(this);
111}
112
114 : QObject(parent)
115 , d(new KPixmapSequenceOverlayPainterPrivate)
116{
117 d->init(this);
118 d->m_sequence = seq;
119}
120
125
127{
128 return d->sequence();
129}
130
132{
133 return d->m_timer.interval();
134}
135
137{
138 if (d->m_rect.isValid()) {
139 return d->m_rect;
140 } else if (d->m_widget) {
141 return d->m_widget->rect();
142 } else {
143 return QRect();
144 }
145}
146
148{
149 return d->m_alignment;
150}
151
153{
154 return d->m_offset;
155}
156
158{
159 bool restart = d->m_started;
160 stop();
161 d->m_sequence = seq;
162 if (restart) {
163 start();
164 }
165}
166
168{
169 d->m_timer.setInterval(msecs);
170}
171
173{
174 stop();
175 d->m_widget = w;
176}
177
179{
180 bool restart = d->m_started;
181 stop();
182 d->m_rect = rect;
183 if (restart) {
184 start();
185 }
186}
187
189{
190 bool restart = d->m_started;
191 stop();
192 d->m_alignment = align;
193 if (restart) {
194 start();
195 }
196}
197
199{
200 bool restart = d->m_started;
201 stop();
202 d->m_offset = offset;
203 if (restart) {
204 start();
205 }
206}
207
209{
210 if (d->m_widget) {
211 stop();
212
213 d->m_counter = 0;
214 d->m_started = true;
215 d->m_widget->installEventFilter(this);
216 if (d->m_widget->isVisible()) {
217 d->m_timer.start();
218 d->m_widget->update(d->pixmapRect());
219 }
220 }
221}
222
224{
225 d->m_timer.stop();
226 if (d->m_widget && d->m_started) {
227 d->m_started = false;
228 d->m_widget->removeEventFilter(this);
229 d->m_widget->update(d->pixmapRect());
230 }
231}
232
233bool KPixmapSequenceOverlayPainter::eventFilter(QObject *obj, QEvent *event)
234{
235 if (obj == d->m_widget) {
236 switch (event->type()) {
237 case QEvent::Paint:
238 // make sure we paint after everyone else including other event filters
239 obj->removeEventFilter(this); // don't recourse...
241 d->paintFrame();
242 obj->installEventFilter(this); // catch on...
243 return true;
244 break;
245 case QEvent::Hide:
246 d->m_timer.stop();
247 break;
248 case QEvent::Show:
249 if (d->m_started) {
250 d->m_timer.start();
251 d->m_widget->update(d->pixmapRect());
252 }
253 break;
254 default:
255 break;
256 }
257 }
258
259 return false;
260}
261
262#include "moc_kpixmapsequenceoverlaypainter.cpp"
Paints a KPixmapSequence on top of any widget at any position.
void setOffset(const QPoint &offset)
Set the offset relative to the placement determined by alignment and rect.
QPoint offset() const
The optional offset within the rect.
KPixmapSequence sequence() const
The sequence used to draw the overlay.
int interval() const
The interval between frames.
void setSequence(const KPixmapSequence &seq)
Set the sequence to be used.
QRect rect() const
The optional rect to draw the pixmaps in.
void setAlignment(Qt::Alignment align)
Set the alignment of the sequence in rect.
Qt::Alignment alignment() const
The alignment of the pixmaps in the rect.
void setRect(const QRect &rect)
Set the rect in which to place the sequence.
KPixmapSequenceOverlayPainter(QObject *parent=nullptr)
Constructor.
void setInterval(int msecs)
Set the interval between frames.
void setWidget(QWidget *w)
Set the widget to draw the overlay on.
void start()
Start drawing the sequence.
Loads and gives access to the frames of a typical multi-row pixmap as often used for spinners.
int frameCount() const
The number of frames in this sequence.
bool sendEvent(QObject *receiver, QEvent *event)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
virtual bool event(QEvent *e)
T qobject_cast(QObject *object)
typedef Alignment
void timeout()
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:14:43 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.