KWidgetsAddons

kpixmapsequenceoverlaypainter.cpp
1 /*
2  SPDX-FileCopyrightText: 2009 Sebastian Trueg <[email protected]>
3 
4  SPDX-License-Identifier: LGPL-2.1-or-later
5 */
6 
7 #include "kpixmapsequenceoverlaypainter.h"
8 #include "kpixmapsequence.h"
9 
10 #include <QWidget>
11 #include <QPoint>
12 #include <QRect>
13 #include <QPainter>
14 #include <QTimer>
15 #include <QEvent>
16 #include <QPointer>
17 #include <QCoreApplication>
18 
19 class Q_DECL_HIDDEN KPixmapSequenceOverlayPainter::Private
20 {
21 public:
23  void _k_timeout();
24  void paintFrame();
25 
26  KPixmapSequence &sequence();
27 
28  QRect pixmapRect();
29 
30  KPixmapSequence m_sequence;
31  QPointer<QWidget> m_widget;
32  Qt::Alignment m_alignment;
33  QPoint m_offset;
34  QRect m_rect;
35 
36  QTimer m_timer;
37  int m_counter;
38 
39  bool m_started;
40 
42 };
43 
44 void KPixmapSequenceOverlayPainter::Private::init(KPixmapSequenceOverlayPainter *p)
45 {
46  q = p;
47  m_widget = nullptr;
48  m_alignment = Qt::AlignCenter;
49  m_started = false;
50  q->setInterval(200);
51  connect(&m_timer, SIGNAL(timeout()), q, SLOT(_k_timeout()));
52 }
53 
54 void KPixmapSequenceOverlayPainter::Private::_k_timeout()
55 {
56  if (sequence().isEmpty()) {
57  return;
58  }
59  ++m_counter;
60  m_counter %= sequence().frameCount();
61  if (m_widget) {
62  m_widget->update(pixmapRect());
63  }
64 }
65 
66 void KPixmapSequenceOverlayPainter::Private::paintFrame()
67 {
68  if (m_counter >= sequence().frameCount()) {
69  return;
70  }
71  QPainter p(m_widget);
72  p.drawPixmap(pixmapRect(), sequence().frameAt(m_counter), QRect(QPoint(0, 0), sequence().frameSize()));
73 }
74 
75 KPixmapSequence &KPixmapSequenceOverlayPainter::Private::sequence()
76 {
77  return m_sequence;
78 }
79 
80 QRect KPixmapSequenceOverlayPainter::Private::pixmapRect()
81 {
82  QRect rect(m_rect);
83  if (!rect.isValid()) {
84  rect = m_widget->rect();
85  }
86 
87  QPoint pos(rect.topLeft());
88  if (m_alignment & Qt::AlignHCenter) {
89  pos.setX(rect.center().x() - (sequence().frameSize().width() / 2));
90  } else if (m_alignment & Qt::AlignRight) {
91  pos.setX(rect.right() - sequence().frameSize().width());
92  }
93 
94  if (m_alignment & Qt::AlignVCenter) {
95  pos.setY(rect.center().y() - (sequence().frameSize().height() / 2));
96  } else if (m_alignment & Qt::AlignBottom) {
97  pos.setY(rect.bottom() - sequence().frameSize().height());
98  }
99 
100  pos += m_offset;
101 
102  return QRect(pos, sequence().frameSize());
103 }
104 
106  : QObject(parent),
107  d(new Private)
108 {
109  d->init(this);
110 }
111 
113  : QObject(parent),
114  d(new Private)
115 {
116  d->init(this);
117  d->m_sequence = seq;
118 }
119 
121 {
122  stop();
123  delete d;
124 }
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 
233 bool 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...
240  QCoreApplication::sendEvent(obj, event);
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"
int interval() const
The interval between frames.
Loads and gives access to the frames of a typical multi-row pixmap as often used for spinners...
QEvent::Type type() const const
QRect rect() const
The optional rect to draw the pixmaps in.
Qt::Alignment alignment() const
The alignment of the pixmaps in the rect.
typedef Alignment
void setRect(const QRect &rect)
Set the rect in which to place the sequence.
virtual bool event(QEvent *e)
void setWidget(QWidget *w)
Set the widget to draw the overlay on.
void setInterval(int msecs)
Set the interval between frames.
QPoint offset() const
The optional offset within the rect.
void installEventFilter(QObject *filterObj)
void setOffset(const QPoint &offset)
Set the offset relative to the placement determined by alignment and rect.
bool sendEvent(QObject *receiver, QEvent *event)
QCA_EXPORT void init()
void setAlignment(Qt::Alignment align)
Set the alignment of the sequence in rect.
void start()
Start drawing the sequence.
QObject(QObject *parent)
void stop()
Stop drawing the overlay.
void setSequence(const KPixmapSequence &seq)
Set the sequence to be used.
void setX(int x)
Paints a KPixmapSequence on top of any widget at any position.
QObject * parent() const const
KPixmapSequence sequence() const
The sequence used to draw the overlay.
KPixmapSequenceOverlayPainter(QObject *parent=nullptr)
Constructor.
void removeEventFilter(QObject *obj)
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Wed Aug 5 2020 22:42:24 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.