File indexing completed on 2023-10-01 08:41:43

0001 /*
0002     Circular countdown widget
0003     Copyright (C) 2011  Martin Klapetek <martin.klapetek@gmail.com>
0004 
0005     This library is free software; you can redistribute it and/or
0006     modify it under the terms of the GNU Lesser General Public
0007     License as published by the Free Software Foundation; either
0008     version 2.1 of the License, or (at your option) any later version.
0009 
0010     This library is distributed in the hope that it will be useful,
0011     but WITHOUT ANY WARRANTY; without even the implied warranty of
0012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013     Lesser General Public License for more details.
0014 
0015     You should have received a copy of the GNU Lesser General Public
0016     License along with this library; if not, write to the Free Software
0017     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
0018 */
0019 
0020 #include "circular-countdown.h"
0021 
0022 #include <QPainter>
0023 #include <QPaintEvent>
0024 #include <QTimeLine>
0025 
0026 namespace KTp
0027 {
0028 
0029 class CircularCountdown::Private
0030 {
0031 public:
0032     Private(CircularCountdown *parent)
0033         : q(parent)
0034     {
0035 
0036     }
0037 
0038     CircularCountdown *q;
0039     QTimeLine *timeLine;
0040 };
0041 
0042 CircularCountdown::CircularCountdown(int msec, QWidget *parent)
0043     : QWidget(parent),
0044       d(new Private(this))
0045 {
0046     setAutoFillBackground(false);
0047 
0048     d->timeLine = new QTimeLine(msec, this);
0049     //circle has 360 degrees, for better smoothness we use 2x as much
0050     d->timeLine->setFrameRange(0, 720);
0051     //to paint the subtraction animation, we start from full circle to 0
0052     d->timeLine->setDirection(QTimeLine::Backward);
0053 
0054     //repaint on every frame change for smooth animation
0055     connect(d->timeLine, SIGNAL(frameChanged(int)), this, SLOT(repaint()));
0056 
0057     //repaint after animation is finished
0058     connect(d->timeLine, SIGNAL(finished()), this, SLOT(repaint()));
0059 
0060     //emit timeoutReached() when the timeout is reached
0061     connect(d->timeLine, SIGNAL(finished()), this, SIGNAL(timeout()));
0062 }
0063 
0064 CircularCountdown::~CircularCountdown()
0065 {
0066     delete d;
0067 }
0068 
0069 void CircularCountdown::paintEvent(QPaintEvent *event) {
0070     Q_UNUSED(event);
0071 
0072     if (d->timeLine->state() == QTimeLine::Running || d->timeLine->state() == QTimeLine::Paused) {
0073         QPainter painter(this);
0074         //always take parent widget's palette and use it's Base color
0075         painter.setBrush(QBrush(parentWidget()->palette().color(QPalette::Base), Qt::SolidPattern));
0076         painter.setRenderHint(QPainter::Antialiasing);
0077         /* drawPie always paints 1/16th of a degree, the total circle is 5760 (16 * 360)
0078          * the first argument is this widget size with 2px padding
0079          * second argument is start position, which is 3 o'clock by default,
0080          * to move it to 12 o'clock we need to start at 90 degrees, hence 90 * 16
0081          * third argument tells how much of the current circle is painted
0082          * the range is [0..720], hence the *8 (to get 5760 in total)
0083          * and it's minus because we want it to rotate in the other direction
0084          */
0085         painter.drawPie(this->rect().adjusted(2, 2, -2, -2), 90*16, -d->timeLine->currentFrame()*8);
0086     }
0087 }
0088 
0089 QSize CircularCountdown::sizeHint() const
0090 {
0091     return QSize(16, 16);
0092 }
0093 
0094 void CircularCountdown::setDuration(int msec) {
0095     d->timeLine->setDuration(msec);
0096 }
0097 
0098 int CircularCountdown::duration() const
0099 {
0100     return d->timeLine->duration();
0101 }
0102 
0103 void CircularCountdown::start() {
0104     d->timeLine->start();
0105 }
0106 
0107 void CircularCountdown::stop() {
0108     d->timeLine->stop();
0109 }
0110 
0111 void CircularCountdown::pause() {
0112     //no, there really is no ->pause() if you're thinking about that ;)
0113     d->timeLine->setPaused(true);
0114 }
0115 
0116 void CircularCountdown::resume() {
0117     d->timeLine->resume();
0118 }
0119 
0120 }