diff --git a/src/modules/locale/CMakeLists.txt b/src/modules/locale/CMakeLists.txt index 7e7fd359f..7778400b1 100644 --- a/src/modules/locale/CMakeLists.txt +++ b/src/modules/locale/CMakeLists.txt @@ -6,6 +6,7 @@ calamares_add_plugin( locale SOURCES LocaleViewStep.cpp LocalePage.cpp + QtWaitingSpinner.cpp timezonewidget/timezonewidget.cpp timezonewidget/localeglobal.cpp UI diff --git a/src/modules/locale/LocaleViewStep.cpp b/src/modules/locale/LocaleViewStep.cpp index ebce74445..efc1d47ec 100644 --- a/src/modules/locale/LocaleViewStep.cpp +++ b/src/modules/locale/LocaleViewStep.cpp @@ -19,6 +19,7 @@ #include "LocaleViewStep.h" #include "LocalePage.h" +#include "QtWaitingSpinner.h" #include "timezonewidget/localeglobal.h" #include "utils/CalamaresUtilsGui.h" @@ -37,16 +38,45 @@ LocaleViewStep::LocaleViewStep( QObject* parent ) m_widget->setLayout( mainLayout ); CalamaresUtils::unmarginLayout( mainLayout ); - QLabel* waitingLabel = new QLabel( "Loading location data..." ); - waitingLabel->setAlignment( Qt::AlignCenter ); - mainLayout->addWidget( waitingLabel ); + QWidget* waitingWidget = new QWidget; + { + QBoxLayout* waitingLayout = new QVBoxLayout; + waitingWidget->setLayout( waitingLayout ); + waitingLayout->addStretch(); + QBoxLayout* pbLayout = new QHBoxLayout; + waitingLayout->addLayout( pbLayout ); + pbLayout->addStretch(); + + QtWaitingSpinner* spnr = new QtWaitingSpinner(); + pbLayout->addWidget( spnr ); + + pbLayout->addStretch(); + + QLabel* waitingLabel = new QLabel( "Loading location data..." ); + + int spnrSize = waitingLabel->fontMetrics().height() * 4; + spnr->setFixedSize( spnrSize, spnrSize ); + spnr->setRadius( spnrSize / 2 ); + spnr->setLength( spnrSize / 2 ); + spnr->setWidth( spnrSize / 8 ); + spnr->start(); + + waitingLabel->setAlignment( Qt::AlignCenter); + waitingLayout->addSpacing( spnrSize / 2 ); + waitingLayout->addWidget( waitingLabel ); + waitingLayout->addStretch(); + + mainLayout->addWidget( waitingWidget ); + + CalamaresUtils::unmarginLayout( waitingLayout ); + } connect( &m_initWatcher, &QFutureWatcher< void >::finished, [=] { m_actualWidget->init(); - m_widget->layout()->removeWidget( waitingLabel ); - waitingLabel->deleteLater(); + m_widget->layout()->removeWidget( waitingWidget ); + waitingWidget->deleteLater(); m_widget->layout()->addWidget( m_actualWidget ); m_nextEnabled = true; emit nextStatusChanged( m_nextEnabled ); diff --git a/src/modules/locale/QtWaitingSpinner.cpp b/src/modules/locale/QtWaitingSpinner.cpp new file mode 100644 index 000000000..834c91c1f --- /dev/null +++ b/src/modules/locale/QtWaitingSpinner.cpp @@ -0,0 +1,176 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014, Teo Mrnjavac + * + * Originally from https://github.com/snowwlex/QtWaitingSpinner + * Copyright 2012, Alex Turkin + * + * Calamares is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Calamares 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Calamares. If not, see . + */ + +#include +#include + +#include + +#include "QtWaitingSpinner.h" + +QtWaitingSpinner::QtWaitingSpinner(int linesNumber, int length, int width, int radius, QWidget *parent) : QWidget(parent), + myLinesNumber(linesNumber), + myLength(length + width), + myWidth(width), + myRadius(radius), + myRoundness(70.0), + myColor(Qt::black), + mySpeed(1), + myTrail(70), + myOpacity(15) +{ + myCurrentCounter = 0; + myTimer = new QTimer(this); + connect(myTimer,SIGNAL(timeout()), this, SLOT(rotate())); + updateSize(); + updateTimer(); + this->hide(); +} + +void QtWaitingSpinner::paintEvent(QPaintEvent */*ev*/) { + QPainter painter(this); + painter.fillRect(this->rect(), Qt::transparent); + painter.setRenderHint(QPainter::Antialiasing, true); + + if (myCurrentCounter >= myLinesNumber) { + myCurrentCounter = 0; + } + painter.setPen(Qt::NoPen); + for (int i = 0; i < myLinesNumber; ++i) { + painter.save(); + painter.translate(myRadius + myLength, myRadius + myLength); + qreal rotateAngle = (qreal)360 * qreal(i) / qreal(myLinesNumber); + painter.rotate(rotateAngle); + painter.translate(myRadius, 0); + int distance = lineDistance(i, myCurrentCounter, myLinesNumber); + QColor color = countTrailColor(distance, myLinesNumber, myTrail, myOpacity, myColor); + painter.setBrush(color); + //TODO improve the way rounded rect is painted + painter.drawRoundedRect(QRect(0, -myWidth/2, myLength, myWidth), myRoundness, myRoundness, Qt::RelativeSize); + painter.restore(); + } +} + +void QtWaitingSpinner::start() { + this->show(); + if (!myTimer->isActive()) { + myTimer->start(); + myCurrentCounter = 0; + } +} + +void QtWaitingSpinner::finish() { + this->hide(); + if (myTimer->isActive()) { + myTimer->stop(); + myCurrentCounter = 0; + } +} + +void QtWaitingSpinner::setLinesNumber(int linesNumber) { + myLinesNumber = linesNumber; + myCurrentCounter = 0; + updateTimer(); +} + +void QtWaitingSpinner::setLength(int length){ + myLength = length; + updateSize(); +} + +void QtWaitingSpinner::setWidth(int width) { + myWidth = width; + updateSize(); +} + +void QtWaitingSpinner::setRadius(int radius) { + myRadius = radius; + updateSize(); +} + +void QtWaitingSpinner::setRoundness(qreal roundness) { + myRoundness = std::max(0.0, std::min(100.0, roundness)); +} + +void QtWaitingSpinner::setColor(QColor color) { + myColor = color; +} + +void QtWaitingSpinner::setSpeed(qreal speed) { + mySpeed = speed; + updateTimer(); +} + +void QtWaitingSpinner::setTrail(int trail) { + myTrail = trail; +} + +void QtWaitingSpinner::setOpacity(int minOpacity) { + myOpacity = minOpacity; +} + +void QtWaitingSpinner::rotate() { + ++myCurrentCounter; + if (myCurrentCounter >= myLinesNumber) { + myCurrentCounter = 0; + } + update(); +} + +void QtWaitingSpinner::updateSize() { + int size = (myRadius + myLength) * 2; + setFixedSize(size, size); +} + +void QtWaitingSpinner::updateTimer() { + myTimer->setInterval(countTimeout(myLinesNumber, mySpeed)); +} + +int QtWaitingSpinner::countTimeout(int lines, qreal speed) { + return 1000 / (lines * speed); +} + +int QtWaitingSpinner::lineDistance(int from, int to, int lines) { + int result = to - from; + if (result < 0) { + result += lines; + } + return result; +} + +QColor QtWaitingSpinner::countTrailColor(int distance, int lines, int trail, int minOpacity, QColor color) { + if (distance == 0) { + return color; + } + const qreal minAlphaF = (qreal)minOpacity / 100; + int distanceThreshold = ceil( (lines - 1) * (qreal)trail / 100); + if (distance > distanceThreshold) { + color.setAlphaF(minAlphaF); + return color; + } + qreal alphaDiff = color.alphaF() - (qreal)minAlphaF; + qreal gradation = alphaDiff / (qreal)(distanceThreshold + 1); + qreal resultAlpha = color.alphaF() - gradation * distance; + resultAlpha = std::min(1.0, std::max(0.0, resultAlpha)); //if alpha is out of bound, force it to bounds + color.setAlphaF(resultAlpha); + return color; +} + diff --git a/src/modules/locale/QtWaitingSpinner.h b/src/modules/locale/QtWaitingSpinner.h new file mode 100644 index 000000000..5ab1ec808 --- /dev/null +++ b/src/modules/locale/QtWaitingSpinner.h @@ -0,0 +1,80 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014, Teo Mrnjavac + * + * Originally from https://github.com/snowwlex/QtWaitingSpinner + * Copyright 2012, Alex Turkin + * + * Calamares is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Calamares 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Calamares. If not, see . + */ + +#ifndef QTWAITINGSPINNER_H +#define QTWAITINGSPINNER_H + +#include + +#include +#include + +class QtWaitingSpinner : public QWidget { + Q_OBJECT + +public: + explicit QtWaitingSpinner(int linesNumber = 12, int length = 7, int width = 5, int radius = 10, QWidget *parent = 0); + +public Q_SLOTS: + void start(); + void finish(); + +public: + void setLinesNumber(int linesNumber); + void setLength(int length); + void setWidth(int width); + void setRadius(int radius); + void setRoundness(qreal roundness); + void setColor(QColor color); + void setSpeed(qreal speed); + void setTrail(int trail); + void setOpacity(int minOpacity); + +private Q_SLOTS: + void rotate(); + void updateSize(); + void updateTimer(); + +protected: + void paintEvent(QPaintEvent *ev); + +private: + static int countTimeout(int lines, qreal speed); + static int lineDistance(int from, int to, int lines); + static QColor countTrailColor(int distance, int lines, int trail, int minOpacity, QColor color); + +private: + int myLinesNumber; + int myLength; + int myWidth; + int myRadius; + qreal myRoundness; //0..100 + QColor myColor; + qreal mySpeed; // in rounds per second + int myTrail; + int myOpacity; + +private: + QTimer *myTimer; + int myCurrentCounter; +}; + +#endif // QTWAITINGSPINNER_H