diff --git a/include/DWidget/DIndeterminateProgressbar b/include/DWidget/DIndeterminateProgressbar new file mode 100644 index 000000000..1d45e0b4a --- /dev/null +++ b/include/DWidget/DIndeterminateProgressbar @@ -0,0 +1 @@ +#include "dindeterminateprogressbar.h" diff --git a/include/widgets/dindeterminateprogressbar.h b/include/widgets/dindeterminateprogressbar.h new file mode 100644 index 000000000..73e56fd3c --- /dev/null +++ b/include/widgets/dindeterminateprogressbar.h @@ -0,0 +1,26 @@ +// SPDX-FileCopyrightText: 2019 - 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef DINDETERMINATEPROGRESSBAR_H +#define DINDETERMINATEPROGRESSBAR_H + +#include +#include + +class DIndeterminateProgressbarPrivate; +class DIndeterminateProgressbar : public QWidget, public DTK_CORE_NAMESPACE::DObject +{ + Q_OBJECT +public: + explicit DIndeterminateProgressbar(QWidget *parent = nullptr); + +protected: + void paintEvent(QPaintEvent *e) override; + void resizeEvent(QResizeEvent *e) override; + +private: + D_DECLARE_PRIVATE(DIndeterminateProgressbar) +}; + +#endif // DINDETERMINATEPROGRESSBAR_H diff --git a/include/widgets/dprogressbar.h b/include/widgets/dprogressbar.h index f1fd20be3..4ce321322 100644 --- a/include/widgets/dprogressbar.h +++ b/include/widgets/dprogressbar.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2019 - 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2019 - 2024 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -8,9 +8,13 @@ #include #include #include +#include +#include +class QPropertyAnimation; DWIDGET_BEGIN_NAMESPACE +class DProgressBarPrivate; class DProgressBar : public QProgressBar, public DCORE_NAMESPACE::DObject { public: @@ -18,6 +22,13 @@ class DProgressBar : public QProgressBar, public DCORE_NAMESPACE::DObject QSize sizeHint() const override; QSize minimumSizeHint() const override; + +protected: + void resizeEvent(QResizeEvent *e) override; + void paintEvent(QPaintEvent *e) override; + +private: + D_DECLARE_PRIVATE(DProgressBar) }; DWIDGET_END_NAMESPACE diff --git a/src/widgets/dindeterminateprogressbar.cpp b/src/widgets/dindeterminateprogressbar.cpp new file mode 100644 index 000000000..5aee5875f --- /dev/null +++ b/src/widgets/dindeterminateprogressbar.cpp @@ -0,0 +1,133 @@ +// SPDX-FileCopyrightText: 2019 - 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "private/dindeterminateprogressbar_p.h" + +#include + +#include +#include +#include +#include +#include + +const int SPOT_WIDGET_WIDTH = 200; + +DIndeterminateProgressbarPrivate::DIndeterminateProgressbarPrivate(DIndeterminateProgressbar *qq) + : DObjectPrivate(qq) + , m_sliderWidget(new QWidget(qq)) + , m_timer(new QTimer(qq)) + , m_leftToRight(true) + , m_spotWidget(new QWidget(qq)) + , m_animation(new QPropertyAnimation(m_spotWidget, "pos", qq)) +{ +} + +DIndeterminateProgressbar::DIndeterminateProgressbar(QWidget *parent) + : QWidget(parent) + , DObject(*new DIndeterminateProgressbarPrivate(this)) +{ + D_D(DIndeterminateProgressbar); + d->m_spotWidget->setFixedSize(SPOT_WIDGET_WIDTH, height()); + d->m_spotWidget->move(-SPOT_WIDGET_WIDTH, 0); + + d->m_sliderWidget->setFixedWidth(150); + d->m_sliderWidget->move(0, 0); + + d->m_timer->setInterval(10); + static int step = 0; + connect(d->m_timer, &QTimer::timeout, this, [this, d]() { + if (d->m_sliderWidget->geometry().right() >= rect().right()) { + d->m_leftToRight = false; + } + + if (d->m_sliderWidget->geometry().left() <= rect().left()) { + d->m_leftToRight = true; + } + + d->m_leftToRight ? step += 2 : step -= 2; + d->m_sliderWidget->move(step, 0); + }); + d->m_timer->start(); +} + +void DIndeterminateProgressbar::resizeEvent(QResizeEvent *e) +{ + D_D(DIndeterminateProgressbar); + d->m_sliderWidget->setFixedHeight(height()); + d->m_spotWidget->setFixedSize(SPOT_WIDGET_WIDTH, height()); + + d->m_animation->setStartValue(QPoint(-SPOT_WIDGET_WIDTH, 0)); + d->m_animation->setEndValue(QPoint(rect().right(), 0)); + d->m_animation->setDuration(3000); + d->m_animation->setEasingCurve(QEasingCurve::InQuad); + d->m_animation->start(); + connect(d->m_animation, &QPropertyAnimation::finished, this, [d]() { + d->m_animation->start(); + }); + QWidget::resizeEvent(e); +} + +void DIndeterminateProgressbar::paintEvent(QPaintEvent *e) +{ + D_D(DIndeterminateProgressbar); + QWidget::paintEvent(e); + QPainter p(this); + + p.setRenderHint(QPainter::Antialiasing); + int radius; + this->height() <= DTK_WIDGET_NAMESPACE::DStyle::pixelMetric(style(), DTK_WIDGET_NAMESPACE::DStyle::PM_FrameRadius) * 2 + ? radius = height() / 2 + : radius = DTK_WIDGET_NAMESPACE::DStyle::pixelMetric(style(), DTK_WIDGET_NAMESPACE::DStyle::PM_FrameRadius); + + p.setBrush(QColor(0, 0, 0, int(0.1 * 255))); + p.setPen(Qt::NoPen); + + p.drawRoundedRect(rect(), radius, radius); + + QPen pen; + pen.setWidth(2); + pen.setColor(QColor(0, 0, 0, int(0.2 * 255))); + p.setBrush(Qt::NoBrush); + p.setPen(pen); + p.drawRoundedRect(rect().marginsRemoved(QMargins(1, 1, 1, 1)), radius, radius); + + p.setPen(Qt::NoPen); + p.setBrush(palette().highlight().color()); + p.drawRoundedRect(d->m_sliderWidget->geometry(), radius, radius); + + pen.setColor(QColor(0, 0, 0, int(0.3 * 255))); + p.setBrush(Qt::NoBrush); + p.setPen(pen); + p.drawRoundedRect(d->m_sliderWidget->geometry().marginsRemoved(QMargins(1, 1, 1, 1)), radius, radius); + + if (d->m_sliderWidget->width() < d->m_spotWidget->width() / 2) + return; + + QPointF pointStart(d->m_spotWidget->geometry().left(), d->m_spotWidget->geometry().center().y()); + QPointF pointEnd(d->m_spotWidget->geometry().right(), d->m_spotWidget->geometry().center().y()); + + QColor shadowColor(0, 0, 0, int(0.15 * 255)); + QColor spotColor(255, 255, 255, int(0.5 * 255)); + QColor highLightColor(palette().highlight().color()); + + QLinearGradient linear(pointStart, pointEnd); + linear.setColorAt(0, highLightColor); + linear.setColorAt(0.35, shadowColor); + linear.setColorAt(0.5, spotColor); + linear.setColorAt(0.65, shadowColor); + linear.setColorAt(1, highLightColor); + linear.setSpread(QGradient::PadSpread); + linear.setInterpolationMode(QLinearGradient::InterpolationMode::ColorInterpolation); + + p.setBrush(linear); + p.setPen(Qt::NoPen); + + QPainterPath clipPath; + clipPath.addRoundedRect(d->m_sliderWidget->geometry(), radius, radius); + p.setClipPath(clipPath); + p.setClipping(true); + p.drawRoundedRect(d->m_spotWidget->geometry().marginsRemoved(QMargins(2, 2, 2, 2)), radius, radius); + p.setClipping(false); +} diff --git a/src/widgets/dprogressbar.cpp b/src/widgets/dprogressbar.cpp index 1acf990fe..165656836 100644 --- a/src/widgets/dprogressbar.cpp +++ b/src/widgets/dprogressbar.cpp @@ -1,13 +1,28 @@ -// SPDX-FileCopyrightText: 2019 - 2022 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2019 - 2024 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later -#include "dprogressbar.h" +#include "private/dprogressbar_p.h" + +#include -#include #include +#include +#include +#include +#include +#include + +const int SPOT_WIDGET_WIDTH = 200; DWIDGET_BEGIN_NAMESPACE + +DProgressBarPrivate::DProgressBarPrivate(DProgressBar *qq) + : DObjectPrivate(qq) + , m_spotWidget(new QWidget(qq)) + , m_animation(new QPropertyAnimation(m_spotWidget, "pos", qq)) +{ +} /*! @~english @class Dtk::Widget::DProgressBar @@ -23,8 +38,11 @@ DWIDGET_BEGIN_NAMESPACE */ DProgressBar::DProgressBar(QWidget *parent) : QProgressBar(parent) + , DObject(*new DProgressBarPrivate(this)) { - + D_D(DProgressBar); + d->m_spotWidget->setFixedSize(SPOT_WIDGET_WIDTH, height()); + d->m_spotWidget->move(-SPOT_WIDGET_WIDTH, 0); } /*! @@ -57,4 +75,65 @@ QSize DProgressBar::minimumSizeHint() const return sizeHint(); } +void DProgressBar::resizeEvent(QResizeEvent *e) +{ + D_D(DProgressBar); + d->m_spotWidget->setFixedSize(SPOT_WIDGET_WIDTH, height()); + + d->m_animation->setStartValue(QPoint(-SPOT_WIDGET_WIDTH, 0)); + d->m_animation->setEndValue(QPoint(rect().right(), 0)); + d->m_animation->setDuration(2000); + d->m_animation->setEasingCurve(QEasingCurve::InQuad); + d->m_animation->start(); + connect(d->m_animation, &QPropertyAnimation::finished, this, [this, d]() { + // 动画之间需要间隔1s + QTimer::singleShot(1000, this, [this, d]() { + d->m_animation->start(); + }); + }); + QProgressBar::resizeEvent(e); +} + +void DProgressBar::paintEvent(QPaintEvent *e) +{ + D_D(DProgressBar); + QProgressBar::paintEvent(e); + + QPainter p(this); + + if (rect().right() * (qreal(value()) / qreal(maximum())) < d->m_spotWidget->width() / 2) + return; + + int radius; + this->height() <= DStyle::pixelMetric(style(), DStyle::PM_FrameRadius) * 2 + ? radius = height() / 2 + : radius = DStyle::pixelMetric(style(), DStyle::PM_FrameRadius); + + QPointF pointStart(d->m_spotWidget->geometry().left(), d->m_spotWidget->geometry().center().y()); + QPointF pointEnd(d->m_spotWidget->geometry().right(), d->m_spotWidget->geometry().center().y()); + + QColor shadowColor(0, 0, 0, int(0.15 * 255)); + QColor spotColor(255, 255, 255, int(0.5 * 255)); + QColor highLightColor(palette().highlight().color()); + + QLinearGradient linear(pointStart, pointEnd); + linear.setColorAt(0, highLightColor); + linear.setColorAt(0.35, shadowColor); + linear.setColorAt(0.5, spotColor); + linear.setColorAt(0.65, shadowColor); + linear.setColorAt(1, highLightColor); + linear.setSpread(QGradient::PadSpread); + linear.setInterpolationMode(QLinearGradient::InterpolationMode::ColorInterpolation); + + p.setBrush(linear); + p.setPen(Qt::NoPen); + int progressWidth = int(rect().right() * (qreal(value()) / qreal(maximum()))); + + QPainterPath clipPath; + clipPath.addRoundedRect(QRect(rect().x(), rect().y(), progressWidth, rect().height()), radius, radius); + p.setClipPath(clipPath); + p.setClipping(true); + p.drawRoundedRect(d->m_spotWidget->geometry().marginsRemoved(QMargins(2, 2, 2, 2)), radius, radius); + p.setClipping(false); +} DWIDGET_END_NAMESPACE diff --git a/src/widgets/dtitlebar.cpp b/src/widgets/dtitlebar.cpp index 23d604ad0..6c32eeaf1 100644 --- a/src/widgets/dtitlebar.cpp +++ b/src/widgets/dtitlebar.cpp @@ -775,7 +775,7 @@ void DTitlebarPrivate::setIconVisible(bool visible) return; if (visible) { - if (auto spacerItem = dynamic_cast(leftLayout->takeAt(0))) + if (dynamic_cast(leftLayout->itemAt(0))) delete leftLayout->takeAt(0); leftLayout->insertSpacing(0, 10); diff --git a/src/widgets/private/dindeterminateprogressbar_p.h b/src/widgets/private/dindeterminateprogressbar_p.h new file mode 100644 index 000000000..33cbcbc0a --- /dev/null +++ b/src/widgets/private/dindeterminateprogressbar_p.h @@ -0,0 +1,29 @@ +// SPDX-FileCopyrightText: 2017 - 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef DINDETERMINATEPROGRESSBAR_P_H +#define DINDETERMINATEPROGRESSBAR_P_H + +#include +#include + +#include + +class QPropertyAnimation; +class DIndeterminateProgressbarPrivate : public DTK_CORE_NAMESPACE::DObjectPrivate +{ +public: + DIndeterminateProgressbarPrivate(DIndeterminateProgressbar *qq); + + QWidget *m_sliderWidget; + QTimer *m_timer; + bool m_leftToRight; + QWidget *m_spotWidget; + QPropertyAnimation *m_animation; + +private: + D_DECLARE_PUBLIC(DIndeterminateProgressbar) +}; + +#endif // DINDETERMINATEPROGRESSBAR_P_H diff --git a/src/widgets/private/dprogressbar_p.h b/src/widgets/private/dprogressbar_p.h new file mode 100644 index 000000000..6b8c1c9e7 --- /dev/null +++ b/src/widgets/private/dprogressbar_p.h @@ -0,0 +1,27 @@ +// SPDX-FileCopyrightText: 2019 - 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef DPROGRESSBAR_P_H +#define DPROGRESSBAR_P_H + +#include "dprogressbar.h" +#include + +DWIDGET_BEGIN_NAMESPACE + +class DProgressBarPrivate : public DTK_CORE_NAMESPACE::DObjectPrivate +{ +public: + DProgressBarPrivate(DProgressBar *qq); + + QWidget *m_spotWidget; + QPropertyAnimation *m_animation; + +private: + D_DECLARE_PUBLIC(DProgressBar) +}; + +DWIDGET_END_NAMESPACE + +#endif // DPROGRESSBAR_P_H