195 lines
6.3 KiB
C++
195 lines
6.3 KiB
C++
#include "ElaProgressRing.h"
|
|
|
|
#include "ElaProgressRingPrivate.h"
|
|
#include "ElaTheme.h"
|
|
#include <QPainter>
|
|
#include <QPainterPath>
|
|
#include <QPropertyAnimation>
|
|
#include <QtMath>
|
|
Q_PROPERTY_CREATE_Q_CPP(ElaProgressRing, bool, IsTransparent)
|
|
Q_PROPERTY_CREATE_Q_CPP(ElaProgressRing, bool, IsDisplayValue)
|
|
Q_PROPERTY_CREATE_Q_CPP(ElaProgressRing, ElaProgressRingType::ValueDisplayMode, ValueDisplayMode)
|
|
Q_PROPERTY_CREATE_Q_CPP(ElaProgressRing, int, ValuePixelSize)
|
|
ElaProgressRing::ElaProgressRing(QWidget *parent) : QWidget(parent), d_ptr(new ElaProgressRingPrivate()) {
|
|
Q_D(ElaProgressRing);
|
|
d->q_ptr = this;
|
|
d->_pIsDisplayValue = true;
|
|
d->_pValuePixelSize = 17;
|
|
d->_pValueDisplayMode = ElaProgressRingType::ValueDisplayMode::Actual;
|
|
d->_pMinimum = 0;
|
|
d->_pMaximum = 100;
|
|
d->_pValue = 0;
|
|
d->_pBusyIndex = 0xe100;
|
|
d->_pBusyingDurationTime = 1000;
|
|
d->_pBusyingWidth = 6;
|
|
d->_pBusyStartDeg = 0;
|
|
d->_pBusyContentDeg = 0;
|
|
d->_pIsBusying = false;
|
|
d->_pIsTransparent = false;
|
|
setFixedSize(70, 70);
|
|
setObjectName("ElaProgressRing");
|
|
setStyleSheet("#ElaProgressRing{background-color:transparent;}");
|
|
|
|
d->_busyStartDegAnimation = new QPropertyAnimation(d, "pBusyStartDeg");
|
|
connect(d->_busyStartDegAnimation, &QPropertyAnimation::valueChanged, this, [=]() { update(); });
|
|
d->_busyStartDegAnimation->setEasingCurve(QEasingCurve::Linear);
|
|
d->_busyStartDegAnimation->setDuration(1000);
|
|
d->_busyStartDegAnimation->setStartValue(0);
|
|
d->_busyStartDegAnimation->setEndValue(360);
|
|
d->_busyStartDegAnimation->setLoopCount(-1);
|
|
|
|
d->_busyContentDegAnimation = new QPropertyAnimation(d, "pBusyContentDeg");
|
|
d->_busyContentDegAnimation->setEasingCurve(QEasingCurve::Linear);
|
|
d->_busyContentDegAnimation->setDuration(1800);
|
|
d->_busyContentDegAnimation->setStartValue(10);
|
|
d->_busyContentDegAnimation->setKeyValueAt(0.5, 140);
|
|
d->_busyContentDegAnimation->setEndValue(10);
|
|
d->_busyContentDegAnimation->setLoopCount(-1);
|
|
|
|
d->_themeMode = eTheme->getThemeMode();
|
|
connect(eTheme, &ElaTheme::themeModeChanged, this, [=](ElaThemeType::ThemeMode themeMode) {
|
|
d->_themeMode = themeMode;
|
|
update();
|
|
});
|
|
}
|
|
|
|
ElaProgressRing::~ElaProgressRing() {}
|
|
|
|
void ElaProgressRing::setIsBusying(bool isBusying) {
|
|
Q_D(ElaProgressRing);
|
|
d->_pIsBusying = isBusying;
|
|
if (isBusying) {
|
|
d->_busyStartDegAnimation->start();
|
|
d->_busyContentDegAnimation->start();
|
|
} else {
|
|
d->_busyStartDegAnimation->stop();
|
|
d->_busyContentDegAnimation->stop();
|
|
}
|
|
update();
|
|
Q_EMIT pIsBusyingChanged();
|
|
}
|
|
|
|
bool ElaProgressRing::getIsBusying() const {
|
|
Q_D(const ElaProgressRing);
|
|
return d->_pIsBusying;
|
|
}
|
|
|
|
void ElaProgressRing::setBusyingWidth(int width) {
|
|
Q_D(ElaProgressRing);
|
|
d->_pBusyingWidth = width;
|
|
update();
|
|
Q_EMIT pBusyingWidthChanged();
|
|
}
|
|
|
|
int ElaProgressRing::getBusyingWidth() const {
|
|
Q_D(const ElaProgressRing);
|
|
return d->_pBusyingWidth;
|
|
}
|
|
|
|
void ElaProgressRing::setBusyingDurationTime(int busyingDurationTime) {
|
|
Q_D(ElaProgressRing);
|
|
d->_pBusyingDurationTime = busyingDurationTime;
|
|
d->_busyStartDegAnimation->setDuration(d->_pBusyingDurationTime);
|
|
Q_EMIT pBusyingDurationTimeChanged();
|
|
}
|
|
|
|
int ElaProgressRing::getBusyingDurationTime() const {
|
|
Q_D(const ElaProgressRing);
|
|
return d->_pBusyingDurationTime;
|
|
}
|
|
|
|
void ElaProgressRing::setMinimum(int minimum) {
|
|
Q_D(ElaProgressRing);
|
|
d->_pMinimum = minimum;
|
|
update();
|
|
Q_EMIT pMinimumChanged();
|
|
Q_EMIT rangeChanged(d->_pMinimum, d->_pMaximum);
|
|
}
|
|
|
|
int ElaProgressRing::getMinimum() const {
|
|
Q_D(const ElaProgressRing);
|
|
return d->_pMinimum;
|
|
}
|
|
|
|
void ElaProgressRing::setMaximum(int maximum) {
|
|
Q_D(ElaProgressRing);
|
|
d->_pMaximum = maximum;
|
|
update();
|
|
Q_EMIT pMaximumChanged();
|
|
Q_EMIT rangeChanged(d->_pMinimum, d->_pMaximum);
|
|
}
|
|
|
|
int ElaProgressRing::getMaximum() const {
|
|
Q_D(const ElaProgressRing);
|
|
return d->_pMaximum;
|
|
}
|
|
|
|
void ElaProgressRing::setValue(int value) {
|
|
Q_D(ElaProgressRing);
|
|
if (value < d->_pMinimum || value > d->_pMaximum) {
|
|
return;
|
|
}
|
|
d->_pValue = value;
|
|
update();
|
|
Q_EMIT pValueChanged();
|
|
}
|
|
|
|
int ElaProgressRing::getValue() const {
|
|
Q_D(const ElaProgressRing);
|
|
return d->_pValue;
|
|
}
|
|
|
|
void ElaProgressRing::setRange(int min, int max) {
|
|
Q_D(ElaProgressRing);
|
|
if (min < 0 || max < 0 || min > max) {
|
|
return;
|
|
}
|
|
d->_pMinimum = min;
|
|
d->_pMaximum = max;
|
|
update();
|
|
Q_EMIT pMinimumChanged();
|
|
Q_EMIT pMaximumChanged();
|
|
Q_EMIT rangeChanged(min, max);
|
|
}
|
|
|
|
void ElaProgressRing::paintEvent(QPaintEvent *event) {
|
|
Q_D(ElaProgressRing);
|
|
QPainter painter(this);
|
|
painter.save();
|
|
painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform | QPainter::TextAntialiasing);
|
|
// 文字绘制
|
|
if (d->_pIsDisplayValue && !d->_pIsBusying) {
|
|
painter.setPen(ElaThemeColor(d->_themeMode, BasicText));
|
|
QString valueText;
|
|
if (d->_pValueDisplayMode == ElaProgressRingType::ValueDisplayMode::Actual) {
|
|
valueText = QString::number(d->_pValue);
|
|
} else {
|
|
valueText = QString::number(d->_pValue / (qreal)(d->_pMaximum - d->_pMinimum) * 100) + "%";
|
|
}
|
|
painter.drawText(rect(), Qt::AlignCenter | Qt::TextSingleLine, valueText);
|
|
}
|
|
// Ring绘制
|
|
QRect ringRect = rect().adjusted(1, 1, -1, -1);
|
|
// 遮罩
|
|
QPainterPath basePath;
|
|
basePath.addEllipse(ringRect);
|
|
QPainterPath maskPath;
|
|
maskPath.addEllipse(ringRect.adjusted(d->_pBusyingWidth, d->_pBusyingWidth, -d->_pBusyingWidth, -d->_pBusyingWidth));
|
|
painter.setClipPath(basePath.subtracted(maskPath));
|
|
painter.setPen(Qt::NoPen);
|
|
// 底色
|
|
if (!d->_pIsTransparent) {
|
|
painter.setBrush(ElaThemeColor(d->_themeMode, BasicBaseDeep));
|
|
painter.drawEllipse(ringRect);
|
|
}
|
|
// 环
|
|
painter.setBrush(ElaThemeColor(d->_themeMode, PrimaryNormal));
|
|
if (d->_pIsBusying) {
|
|
painter.drawPie(ringRect, -d->_pBusyStartDeg * 16, d->_pBusyContentDeg * 16);
|
|
} else {
|
|
qreal valueDeg = d->_pValue / (qreal)(d->_pMaximum - d->_pMinimum) * 360;
|
|
painter.drawPie(ringRect, 90 * 16, -valueDeg * 16);
|
|
}
|
|
painter.restore();
|
|
}
|