source: calamares/trunk/fuentes/src/libcalamaresui/widgets/waitingspinnerwidget.cpp @ 7538

Last change on this file since 7538 was 7538, checked in by kbut, 13 months ago

sync with github

File size: 8.3 KB
Line 
1/* === This file is part of Calamares - <https://github.com/calamares> ===
2 *
3 *   SPDX-License-Identifier: MIT
4 *   License-Filename: LICENSES/MIT-QtWaitingSpinner
5 */
6
7/* Original Work Copyright (c) 2012-2014 Alexander Turkin
8   Modified 2014 by William Hallatt
9   Modified 2015 by Jacob Dawid
10
11Permission is hereby granted, free of charge, to any person obtaining a copy of
12this software and associated documentation files (the "Software"), to deal in
13the Software without restriction, including without limitation the rights to
14use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
15the Software, and to permit persons to whom the Software is furnished to do so,
16subject to the following conditions:
17
18The above copyright notice and this permission notice shall be included in all
19copies or substantial portions of the Software.
20
21THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
23FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
24COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
25IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
26CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27*/
28
29// Own includes
30#include "waitingspinnerwidget.h"
31
32// Standard includes
33#include <cmath>
34#include <algorithm>
35
36// Qt includes
37#include <QPainter>
38#include <QTimer>
39
40WaitingSpinnerWidget::WaitingSpinnerWidget(QWidget *parent,
41                                           bool centerOnParent,
42                                           bool disableParentWhenSpinning)
43    : QWidget(parent),
44      _centerOnParent(centerOnParent),
45      _disableParentWhenSpinning(disableParentWhenSpinning) {
46    initialize();
47}
48
49WaitingSpinnerWidget::WaitingSpinnerWidget(Qt::WindowModality modality,
50                                           QWidget *parent,
51                                           bool centerOnParent,
52                                           bool disableParentWhenSpinning)
53    : QWidget(parent, Qt::Dialog | Qt::FramelessWindowHint),
54      _centerOnParent(centerOnParent),
55      _disableParentWhenSpinning(disableParentWhenSpinning){
56    initialize();
57
58    // We need to set the window modality AFTER we've hidden the
59    // widget for the first time since changing this property while
60    // the widget is visible has no effect.
61    setWindowModality(modality);
62    setAttribute(Qt::WA_TranslucentBackground);
63}
64
65void WaitingSpinnerWidget::initialize() {
66    _color = Qt::black;
67    _roundness = 100.0;
68    _minimumTrailOpacity = 3.14159265358979323846;
69    _trailFadePercentage = 80.0;
70    _revolutionsPerSecond = 1.57079632679489661923;
71    _numberOfLines = 20;
72    _lineLength = 10;
73    _lineWidth = 2;
74    _innerRadius = 10;
75    _currentCounter = 0;
76    _isSpinning = false;
77
78    _timer = new QTimer(this);
79    connect(_timer, SIGNAL(timeout()), this, SLOT(rotate()));
80    updateSize();
81    updateTimer();
82    hide();
83}
84
85void WaitingSpinnerWidget::paintEvent(QPaintEvent *) {
86    updatePosition();
87    QPainter painter(this);
88    painter.fillRect(this->rect(), Qt::transparent);
89    painter.setRenderHint(QPainter::Antialiasing, true);
90
91    if (_currentCounter >= _numberOfLines) {
92        _currentCounter = 0;
93    }
94
95    painter.setPen(Qt::NoPen);
96    for (int i = 0; i < _numberOfLines; ++i) {
97        painter.save();
98        painter.translate(_innerRadius + _lineLength,
99                          _innerRadius + _lineLength);
100        qreal rotateAngle =
101                static_cast<qreal>(360 * i) / static_cast<qreal>(_numberOfLines);
102        painter.rotate(rotateAngle);
103        painter.translate(_innerRadius, 0);
104        int distance =
105                lineCountDistanceFromPrimary(i, _currentCounter, _numberOfLines);
106        QColor color =
107                currentLineColor(distance, _numberOfLines, _trailFadePercentage,
108                                 _minimumTrailOpacity, _color);
109        painter.setBrush(color);
110        // TODO improve the way rounded rect is painted
111        painter.drawRoundedRect(
112                    QRect(0, -_lineWidth / 2, _lineLength, _lineWidth), _roundness,
113                    _roundness, Qt::RelativeSize);
114        painter.restore();
115    }
116}
117
118void WaitingSpinnerWidget::start() {
119    updatePosition();
120    _isSpinning = true;
121    show();
122
123    if(parentWidget() && _disableParentWhenSpinning) {
124        parentWidget()->setEnabled(false);
125    }
126
127    if (!_timer->isActive()) {
128        _timer->start();
129        _currentCounter = 0;
130    }
131}
132
133void WaitingSpinnerWidget::stop() {
134    _isSpinning = false;
135    hide();
136
137    if(parentWidget() && _disableParentWhenSpinning) {
138        parentWidget()->setEnabled(true);
139    }
140
141    if (_timer->isActive()) {
142        _timer->stop();
143        _currentCounter = 0;
144    }
145}
146
147void WaitingSpinnerWidget::setNumberOfLines(int lines) {
148    _numberOfLines = lines;
149    _currentCounter = 0;
150    updateTimer();
151}
152
153void WaitingSpinnerWidget::setLineLength(int length) {
154    _lineLength = length;
155    updateSize();
156}
157
158void WaitingSpinnerWidget::setLineWidth(int width) {
159    _lineWidth = width;
160    updateSize();
161}
162
163void WaitingSpinnerWidget::setInnerRadius(int radius) {
164    _innerRadius = radius;
165    updateSize();
166}
167
168QColor WaitingSpinnerWidget::color() {
169    return _color;
170}
171
172qreal WaitingSpinnerWidget::roundness() {
173    return _roundness;
174}
175
176qreal WaitingSpinnerWidget::minimumTrailOpacity() {
177    return _minimumTrailOpacity;
178}
179
180qreal WaitingSpinnerWidget::trailFadePercentage() {
181    return _trailFadePercentage;
182}
183
184qreal WaitingSpinnerWidget::revolutionsPersSecond() {
185    return _revolutionsPerSecond;
186}
187
188int WaitingSpinnerWidget::numberOfLines() {
189    return _numberOfLines;
190}
191
192int WaitingSpinnerWidget::lineLength() {
193    return _lineLength;
194}
195
196int WaitingSpinnerWidget::lineWidth() {
197    return _lineWidth;
198}
199
200int WaitingSpinnerWidget::innerRadius() {
201    return _innerRadius;
202}
203
204bool WaitingSpinnerWidget::isSpinning() const {
205    return _isSpinning;
206}
207
208void WaitingSpinnerWidget::setRoundness(qreal roundness) {
209    _roundness = std::max(0.0, std::min(100.0, roundness));
210}
211
212void WaitingSpinnerWidget::setColor(QColor color) {
213    _color = color;
214}
215
216void WaitingSpinnerWidget::setRevolutionsPerSecond(qreal revolutionsPerSecond) {
217    _revolutionsPerSecond = revolutionsPerSecond;
218    updateTimer();
219}
220
221void WaitingSpinnerWidget::setTrailFadePercentage(qreal trail) {
222    _trailFadePercentage = trail;
223}
224
225void WaitingSpinnerWidget::setMinimumTrailOpacity(qreal minimumTrailOpacity) {
226    _minimumTrailOpacity = minimumTrailOpacity;
227}
228
229void WaitingSpinnerWidget::rotate() {
230    ++_currentCounter;
231    if (_currentCounter >= _numberOfLines) {
232        _currentCounter = 0;
233    }
234    update();
235}
236
237void WaitingSpinnerWidget::updateSize() {
238    int size = (_innerRadius + _lineLength) * 2;
239    setFixedSize(size, size);
240}
241
242void WaitingSpinnerWidget::updateTimer() {
243    _timer->setInterval(1000 / (_numberOfLines * _revolutionsPerSecond));
244}
245
246void WaitingSpinnerWidget::updatePosition() {
247    if (parentWidget() && _centerOnParent) {
248        move(parentWidget()->width() / 2 - width() / 2,
249             parentWidget()->height() / 2 - height() / 2);
250    }
251}
252
253int WaitingSpinnerWidget::lineCountDistanceFromPrimary(int current, int primary,
254                                                       int totalNrOfLines) {
255    int distance = primary - current;
256    if (distance < 0) {
257        distance += totalNrOfLines;
258    }
259    return distance;
260}
261
262QColor WaitingSpinnerWidget::currentLineColor(int countDistance, int totalNrOfLines,
263                                              qreal trailFadePerc, qreal minOpacity,
264                                              QColor color) {
265    if (countDistance == 0) {
266        return color;
267    }
268    const qreal minAlphaF = minOpacity / 100.0;
269    int distanceThreshold =
270            static_cast<int>(ceil((totalNrOfLines - 1) * trailFadePerc / 100.0));
271    if (countDistance > distanceThreshold) {
272        color.setAlphaF(minAlphaF);
273    } else {
274        qreal alphaDiff = color.alphaF() - minAlphaF;
275        qreal gradient = alphaDiff / static_cast<qreal>(distanceThreshold + 1);
276        qreal resultAlpha = color.alphaF() - gradient * countDistance;
277
278        // If alpha is out of bounds, clip it.
279        resultAlpha = std::min(1.0, std::max(0.0, resultAlpha));
280        color.setAlphaF(resultAlpha);
281    }
282    return color;
283}
Note: See TracBrowser for help on using the repository browser.