354 lines
7.6 KiB
C++
354 lines
7.6 KiB
C++
#include <QPropertyAnimation>
|
|
#include <QParallelAnimationGroup>
|
|
#include <QPainter>
|
|
#include <QHBoxLayout>
|
|
#include <QTimer>
|
|
#include "waitwidget.h"
|
|
CircularProgress::CircularProgress(QWidget* parent)
|
|
: QProgressBar(parent)
|
|
{
|
|
init();
|
|
}
|
|
|
|
CircularProgress::~CircularProgress()
|
|
{
|
|
}
|
|
|
|
void CircularProgress::setProgressType(ProgressType type)
|
|
{
|
|
m_progressType = type;
|
|
update();
|
|
}
|
|
|
|
CircularProgress::ProgressType CircularProgress::progressType() const
|
|
{
|
|
return m_progressType;
|
|
}
|
|
|
|
void CircularProgress::setUseThemeColors(bool value)
|
|
{
|
|
if (m_useThemeColors == value) {
|
|
return;
|
|
}
|
|
|
|
m_useThemeColors = value;
|
|
update();
|
|
}
|
|
|
|
bool CircularProgress::useThemeColors() const
|
|
{
|
|
return m_useThemeColors;
|
|
}
|
|
|
|
void CircularProgress::setLineWidth(qreal width)
|
|
{
|
|
m_penWidth = width;
|
|
update();
|
|
updateGeometry();
|
|
}
|
|
|
|
qreal CircularProgress::lineWidth() const
|
|
{
|
|
return m_penWidth;
|
|
}
|
|
|
|
void CircularProgress::setSize(int size)
|
|
{
|
|
m_size = size;
|
|
update();
|
|
updateGeometry();
|
|
}
|
|
|
|
int CircularProgress::size() const
|
|
{
|
|
return m_size;
|
|
}
|
|
|
|
void CircularProgress::setColor(const QColor& color)
|
|
{
|
|
m_color = color;
|
|
update();
|
|
}
|
|
|
|
QColor CircularProgress::color() const
|
|
{
|
|
if (m_useThemeColors || !m_color.isValid()) {
|
|
return QColor(37, 177, 218);
|
|
}
|
|
else {
|
|
return m_color;
|
|
}
|
|
}
|
|
|
|
QSize CircularProgress::sizeHint() const
|
|
{
|
|
const qreal s = m_size + m_penWidth + 8;
|
|
return QSize(s, s);
|
|
}
|
|
|
|
void CircularProgress::paintEvent(QPaintEvent* event)
|
|
{
|
|
Q_UNUSED(event)
|
|
|
|
QPainter painter(this);
|
|
painter.setRenderHint(QPainter::Antialiasing);
|
|
|
|
if (!isEnabled()) {
|
|
QPen pen;
|
|
pen.setCapStyle(Qt::RoundCap);
|
|
pen.setWidthF(m_penWidth);
|
|
pen.setColor(QColor(186, 186, 186));
|
|
painter.setPen(pen);
|
|
painter.drawLine(rect().center() - QPointF(20, 20), rect().center() + QPointF(20, 20));
|
|
painter.drawLine(rect().center() + QPointF(20, -20), rect().center() - QPointF(20, -20));
|
|
return;
|
|
}
|
|
|
|
if (IndeterminateProgress == m_progressType) {
|
|
painter.translate(width() / 2, height() / 2);
|
|
painter.rotate(m_delegate->angle());
|
|
}
|
|
|
|
QPen pen;
|
|
pen.setCapStyle(Qt::RoundCap);
|
|
pen.setWidthF(m_penWidth);
|
|
|
|
// 绘制底部环
|
|
pen.setColor(QColor(165, 165, 165));
|
|
painter.setPen(pen);
|
|
painter.drawEllipse(QPoint(0, 0), m_size / 2, m_size / 2);
|
|
|
|
pen.setColor(color());
|
|
|
|
if (IndeterminateProgress == m_progressType) {
|
|
QVector<qreal> pattern;
|
|
pattern << m_delegate->dashLength() * m_size / 50 << 30 * m_size / 50;
|
|
|
|
pen.setDashOffset(m_delegate->dashOffset() * m_size / 50);
|
|
pen.setDashPattern(pattern);
|
|
|
|
painter.setPen(pen);
|
|
|
|
painter.drawEllipse(QPoint(0, 0), m_size / 2, m_size / 2);
|
|
}
|
|
else
|
|
{
|
|
painter.setPen(pen);
|
|
|
|
const qreal x = (width() - m_size) / 2;
|
|
const qreal y = (height() - m_size) / 2;
|
|
|
|
const qreal a = 360 * (value() - minimum()) / (maximum() - minimum());
|
|
|
|
QPainterPath path;
|
|
path.arcMoveTo(x, y, m_size, m_size, 0);
|
|
path.arcTo(x, y, m_size, m_size, 0, a);
|
|
|
|
painter.drawPath(path);
|
|
}
|
|
}
|
|
|
|
void CircularProgress::init()
|
|
{
|
|
m_delegate = new CircularProgressDelegate(this);
|
|
m_progressType = IndeterminateProgress;
|
|
m_penWidth = 6.25;
|
|
m_size = 64;
|
|
m_useThemeColors = true;
|
|
|
|
setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding,
|
|
QSizePolicy::MinimumExpanding));
|
|
|
|
QParallelAnimationGroup* group = new QParallelAnimationGroup(this);
|
|
group->setLoopCount(-1);
|
|
|
|
QPropertyAnimation* animation;
|
|
animation = new QPropertyAnimation(this);
|
|
animation->setPropertyName("dashLength");
|
|
animation->setTargetObject(m_delegate);
|
|
animation->setEasingCurve(QEasingCurve::InOutQuad);
|
|
animation->setStartValue(0.1);
|
|
animation->setKeyValueAt(0.15, 0.2);
|
|
animation->setKeyValueAt(0.6, 20);
|
|
animation->setKeyValueAt(0.7, 20);
|
|
animation->setEndValue(20);
|
|
animation->setDuration(2050);
|
|
|
|
group->addAnimation(animation);
|
|
|
|
animation = new QPropertyAnimation(this);
|
|
animation->setPropertyName("dashOffset");
|
|
animation->setTargetObject(m_delegate);
|
|
animation->setEasingCurve(QEasingCurve::InOutSine);
|
|
animation->setStartValue(0);
|
|
animation->setKeyValueAt(0.15, 0);
|
|
animation->setKeyValueAt(0.6, -7);
|
|
animation->setKeyValueAt(0.7, -7);
|
|
animation->setEndValue(-25);
|
|
animation->setDuration(2050);
|
|
|
|
group->addAnimation(animation);
|
|
|
|
animation = new QPropertyAnimation(this);
|
|
animation->setPropertyName("angle");
|
|
animation->setTargetObject(m_delegate);
|
|
animation->setStartValue(0);
|
|
animation->setEndValue(719);
|
|
animation->setDuration(2050);
|
|
|
|
group->addAnimation(animation);
|
|
|
|
group->start();
|
|
}
|
|
|
|
|
|
CircularProgressDelegate::CircularProgressDelegate(CircularProgress* parent)
|
|
: QObject(parent),
|
|
m_progress(parent),
|
|
m_dashOffset(0),
|
|
m_dashLength(89),
|
|
m_angle(0)
|
|
{
|
|
Q_ASSERT(parent);
|
|
}
|
|
|
|
CircularProgressDelegate::~CircularProgressDelegate()
|
|
{
|
|
}
|
|
|
|
void CircularProgressDelegate::setDashOffset(qreal offset)
|
|
{
|
|
m_dashOffset = offset;
|
|
m_progress->update();
|
|
}
|
|
|
|
qreal CircularProgressDelegate::dashOffset() const
|
|
{
|
|
return m_dashOffset;
|
|
}
|
|
|
|
void CircularProgressDelegate::setDashLength(qreal length)
|
|
{
|
|
m_dashLength = length;
|
|
m_progress->update();
|
|
}
|
|
|
|
qreal CircularProgressDelegate::dashLength() const
|
|
{
|
|
return m_dashLength;
|
|
}
|
|
|
|
void CircularProgressDelegate::setAngle(int angle)
|
|
{
|
|
m_angle = angle;
|
|
m_progress->update();
|
|
}
|
|
|
|
int CircularProgressDelegate::angle() const
|
|
{
|
|
return m_angle;
|
|
}
|
|
|
|
|
|
|
|
WaitProgressWidget::WaitProgressWidget(QWidget* parent)
|
|
: QWidget(parent)
|
|
, m_parentWidget(parent)
|
|
{
|
|
m_progress = new CircularProgress(this);
|
|
|
|
this->setAutoFillBackground(true);
|
|
this->hide();
|
|
|
|
QColor color(165, 165, 165);
|
|
color.setAlphaF(0.6);
|
|
this->setBgColor(color);
|
|
|
|
auto waitBgLayout = new QHBoxLayout(this);
|
|
waitBgLayout->addWidget(m_progress);
|
|
waitBgLayout->setAlignment(m_progress, Qt::AlignCenter);
|
|
|
|
parent->installEventFilter(this);
|
|
|
|
m_timer = new QTimer(this);
|
|
connect(m_timer, &QTimer::timeout, this, [this]() {
|
|
if (!this->isHidden()) {
|
|
stop(false);
|
|
}
|
|
});
|
|
connect(this, &WaitProgressWidget::sig_finished, [this](bool isok) {
|
|
if (isok) {
|
|
if (!this->isHidden()) {
|
|
stop(false);
|
|
}
|
|
}
|
|
else {
|
|
if (this->isHidden()) {
|
|
start();
|
|
}
|
|
}
|
|
|
|
});
|
|
}
|
|
|
|
WaitProgressWidget::~WaitProgressWidget()
|
|
{
|
|
stop(true);
|
|
|
|
if (m_timer) {
|
|
|
|
delete m_timer;
|
|
m_timer = NULL;
|
|
}
|
|
}
|
|
|
|
void WaitProgressWidget::setBgColor(QColor color)
|
|
{
|
|
QPalette palette;
|
|
palette.setColor(QPalette::Background, color);
|
|
this->setPalette(palette);
|
|
update();
|
|
}
|
|
|
|
bool WaitProgressWidget::eventFilter(QObject* obj, QEvent* ev)
|
|
{
|
|
if (obj == m_parentWidget && ev->type() == QEvent::Resize) {
|
|
if (!this->isHidden()) {
|
|
this->setFixedSize(m_parentWidget->size());
|
|
this->raise();
|
|
}
|
|
}
|
|
return QWidget::eventFilter(obj, ev);
|
|
}
|
|
|
|
void WaitProgressWidget::showEvent(QShowEvent* ev)
|
|
{
|
|
Q_UNUSED(ev);// 屏蔽鼠标事件
|
|
|
|
this->setFixedSize(m_parentWidget->size());
|
|
this->raise();
|
|
}
|
|
|
|
void WaitProgressWidget::start(int msecs)
|
|
{
|
|
m_timer->start(msecs);
|
|
this->show();
|
|
}
|
|
|
|
void WaitProgressWidget::stop(bool isOk)
|
|
{
|
|
m_timer->stop();
|
|
this->hide();
|
|
emit sig_finished(isOk);
|
|
}
|
|
|
|
void WaitProgressWidget::show()
|
|
{
|
|
QWidget::show();
|
|
}
|
|
|
|
void WaitProgressWidget::hide()
|
|
{
|
|
QWidget::hide();
|
|
}
|