/* Copyright 2009 Sebastian Trueg This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kpixmapsequenceoverlaypainter.h" #include "kpixmapsequence.h" #include #include #include #include #include #include #include #include #include class KPixmapSequenceOverlayPainter::Private { public: void _k_timeout(); void paintFrame(); QRect pixmapRect() const; KPixmapSequence m_sequence; QPointer m_widget; Qt::Alignment m_alignment; QPoint m_offset; QRect m_rect; QTimer m_timer; int m_counter; bool m_started; }; void KPixmapSequenceOverlayPainter::Private::_k_timeout() { if (m_sequence.isEmpty()) { return; } ++m_counter; m_counter %= m_sequence.frameCount(); if (m_widget) { m_widget->update(pixmapRect()); } } void KPixmapSequenceOverlayPainter::Private::paintFrame() { if (m_counter >= m_sequence.frameCount()) { return; } QPainter p(m_widget); p.drawPixmap(pixmapRect(), m_sequence.frameAt(m_counter), QRect(QPoint(0, 0), m_sequence.frameSize())); } QRect KPixmapSequenceOverlayPainter::Private::pixmapRect() const { QRect rect(m_rect); if (!rect.isValid()) { rect = m_widget->rect(); } QPoint pos(rect.topLeft()); if (m_alignment & Qt::AlignHCenter) { pos.setX(rect.center().x() - (m_sequence.frameSize().width() / 2)); } else if (m_alignment & Qt::AlignRight) { pos.setX(rect.right() - m_sequence.frameSize().width()); } if (m_alignment & Qt::AlignVCenter) { pos.setY(rect.center().y() - (m_sequence.frameSize().height() / 2)); } else if (m_alignment & Qt::AlignBottom) { pos.setY(rect.bottom() - m_sequence.frameSize().height()); } pos += m_offset; return QRect(pos, m_sequence.frameSize()); } KPixmapSequenceOverlayPainter::KPixmapSequenceOverlayPainter(QObject *parent) : QObject(parent), d(new Private()) { d->m_widget = 0; d->m_alignment = Qt::AlignCenter; d->m_counter = 0; d->m_started = false; // make sure we have a valid default sequence d->m_sequence = KPixmapSequence("process-working", 22); setInterval(200); connect(&d->m_timer, SIGNAL(timeout()), this, SLOT(_k_timeout())); } KPixmapSequenceOverlayPainter::~KPixmapSequenceOverlayPainter() { stop(); delete d; } KPixmapSequence KPixmapSequenceOverlayPainter::sequence() const { return d->m_sequence; } int KPixmapSequenceOverlayPainter::interval() const { return d->m_timer.interval(); } QRect KPixmapSequenceOverlayPainter::rect() const { if (d->m_rect.isValid()) { return d->m_rect; } else if(d->m_widget) { return d->m_widget->rect(); } return QRect(); } Qt::Alignment KPixmapSequenceOverlayPainter::alignment() const { return d->m_alignment; } QPoint KPixmapSequenceOverlayPainter::offset() const { return d->m_offset; } void KPixmapSequenceOverlayPainter::setSequence(const KPixmapSequence &seq) { bool restart = d->m_started; stop(); d->m_sequence = seq; if (d->m_sequence.isEmpty()) { d->m_sequence = KPixmapSequence("process-working", 22); } if (restart) { start(); } } void KPixmapSequenceOverlayPainter::setInterval(int msecs) { d->m_timer.setInterval(msecs); } void KPixmapSequenceOverlayPainter::setWidget(QWidget *w) { stop(); d->m_widget = w; } void KPixmapSequenceOverlayPainter::setRect(const QRect &rect) { bool restart = d->m_started; stop(); d->m_rect = rect; if (restart) { start(); } } void KPixmapSequenceOverlayPainter::setAlignment(Qt::Alignment align) { const bool restart = d->m_started; stop(); d->m_alignment = align; if (restart) { start(); } } void KPixmapSequenceOverlayPainter::setOffset(const QPoint &offset) { const bool restart = d->m_started; stop(); d->m_offset = offset; if (restart) { start(); } } void KPixmapSequenceOverlayPainter::start() { if (d->m_widget) { stop(); d->m_counter = 0; d->m_started = true; d->m_widget->installEventFilter(this); if (d->m_widget->isVisible()) { d->m_timer.start(); d->m_widget->update(d->pixmapRect()); } } } void KPixmapSequenceOverlayPainter::stop() { d->m_timer.stop(); if (d->m_widget) { d->m_started = false; d->m_widget->removeEventFilter(this); d->m_widget->update(d->pixmapRect()); } } bool KPixmapSequenceOverlayPainter::eventFilter(QObject *obj, QEvent *event) { if (obj == d->m_widget ) { switch (event->type()) { case QEvent::Paint: { // make sure we paint after everyone else including other event filters obj->removeEventFilter(this); // don't recurse... QCoreApplication::sendEvent(obj, event); d->paintFrame(); obj->installEventFilter(this); // catch on... return true; } case QEvent::Hide: { d->m_timer.stop(); break; } case QEvent::Show: { if(d->m_started) { d->m_timer.start(); d->m_widget->update(d->pixmapRect()); } break; } default: { break; } } } return false; } #include "moc_kpixmapsequenceoverlaypainter.cpp"