From 9dcea566826c8d485e4572611357974d211c34ee Mon Sep 17 00:00:00 2001 From: deepin-ci-robot Date: Mon, 12 Aug 2024 02:42:10 +0000 Subject: [PATCH] sync: from linuxdeepin/dtkwidget Synchronize source files from linuxdeepin/dtkwidget. Source-pull-request: https://github.com/linuxdeepin/dtkwidget/pull/596 --- examples/collections/progressbarexample.cpp | 31 ++++ examples/collections/progressbarexample.h | 12 ++ include/DWidget/DBounceAnimation | 1 + include/DWidget/DIndeterminateProgressbar | 1 + include/widgets/dbounceanimation.h | 31 ++++ include/widgets/dindeterminateprogressbar.h | 26 ++++ src/widgets/dbounceanimation.cpp | 107 ++++++++++++++ src/widgets/dindeterminateprogressbar.cpp | 133 ++++++++++++++++++ src/widgets/dlistview.cpp | 7 + src/widgets/dtitlebar.cpp | 2 +- src/widgets/private/dbounceanimation_p.h | 23 +++ .../private/dindeterminateprogressbar_p.h | 29 ++++ 12 files changed, 402 insertions(+), 1 deletion(-) create mode 100644 include/DWidget/DBounceAnimation create mode 100644 include/DWidget/DIndeterminateProgressbar create mode 100644 include/widgets/dbounceanimation.h create mode 100644 include/widgets/dindeterminateprogressbar.h create mode 100644 src/widgets/dbounceanimation.cpp create mode 100644 src/widgets/dindeterminateprogressbar.cpp create mode 100644 src/widgets/private/dbounceanimation_p.h create mode 100644 src/widgets/private/dindeterminateprogressbar_p.h diff --git a/examples/collections/progressbarexample.cpp b/examples/collections/progressbarexample.cpp index 8c7010c9e..a79dfe507 100644 --- a/examples/collections/progressbarexample.cpp +++ b/examples/collections/progressbarexample.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include "progressbarexample.h" DWIDGET_USE_NAMESPACE @@ -28,6 +29,7 @@ ProgressBarExampleWindow::ProgressBarExampleWindow(QWidget *parent) addExampleWindow(new DProgressBarExample(this)); addExampleWindow(new DWaterProgressExample(this)); addExampleWindow(new DColoredProgressBarExample(this)); + addExampleWindow(new DIndeterminateProgressBarExample(this)); } DProgressBarExample::DProgressBarExample(QWidget *parent) @@ -181,3 +183,32 @@ int DColoredProgressBarExample::getFixedHeight() const { return 200; } + +DIndeterminateProgressBarExample::DIndeterminateProgressBarExample(QWidget *parent) + : ExampleWindowInterface(parent) +{ + auto mainLayout = new QVBoxLayout(this); + auto indeterBar = new DIndeterminateProgressbar(); + indeterBar->setFixedSize(500, 35); + mainLayout->addWidget(indeterBar, 0, Qt::AlignCenter); + setLayout(mainLayout); +} + +QString DIndeterminateProgressBarExample::getTitleName() const +{ + return "DIndeterminateProgressbar"; +} + +QString DIndeterminateProgressBarExample::getDescriptionInfo() const +{ + return QString("一个模糊进度条,不展示具体进度值,\n" + "用于等待时间不确定的情况。主要用\n" + "在小工具主窗口内部,作为一个中间状态\n" + "展示给用户,最终的结果往往会跟随成功\n" + "或者失败的图标。"); +} + +int DIndeterminateProgressBarExample::getFixedHeight() const +{ + return 200; +} diff --git a/examples/collections/progressbarexample.h b/examples/collections/progressbarexample.h index fb71257c5..c22ee1319 100644 --- a/examples/collections/progressbarexample.h +++ b/examples/collections/progressbarexample.h @@ -53,4 +53,16 @@ class DColoredProgressBarExample : public ExampleWindowInterface int getFixedHeight() const override; }; +class DIndeterminateProgressBarExample : public ExampleWindowInterface +{ + Q_OBJECT + +public: + explicit DIndeterminateProgressBarExample(QWidget *parent = nullptr); + + QString getTitleName() const override; + QString getDescriptionInfo() const override; + int getFixedHeight() const override; +}; + #endif // PROGRESSBAREXAMPLE_H diff --git a/include/DWidget/DBounceAnimation b/include/DWidget/DBounceAnimation new file mode 100644 index 000000000..b088a7338 --- /dev/null +++ b/include/DWidget/DBounceAnimation @@ -0,0 +1 @@ +#include "dbounceanimation.h" 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/dbounceanimation.h b/include/widgets/dbounceanimation.h new file mode 100644 index 000000000..b5ff98fa5 --- /dev/null +++ b/include/widgets/dbounceanimation.h @@ -0,0 +1,31 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later +#ifndef DBOUNCEANIMATION_H +#define DBOUNCEANIMATION_H + +#include +#include + +class QPropertyAnimation; +class QAbstractScrollArea; +class DBounceAnimationPrivate; +class DBounceAnimation : public QObject, public DTK_CORE_NAMESPACE::DObject +{ + Q_OBJECT +public: + explicit DBounceAnimation(QObject *parent = nullptr); + + void setAnimationTarget(QAbstractScrollArea *w); + void setAniMationEnable(bool enable); + +protected: + bool eventFilter(QObject *o, QEvent *e) override; + void bounceBack(Qt::Orientation orientation); + +private: + D_DECLARE_PRIVATE(DBounceAnimation) + +}; + +#endif // DBOUNCEANIMATION_H diff --git a/include/widgets/dindeterminateprogressbar.h b/include/widgets/dindeterminateprogressbar.h new file mode 100644 index 000000000..7883b1bea --- /dev/null +++ b/include/widgets/dindeterminateprogressbar.h @@ -0,0 +1,26 @@ +// SPDX-FileCopyrightText: 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/src/widgets/dbounceanimation.cpp b/src/widgets/dbounceanimation.cpp new file mode 100644 index 000000000..d574375a7 --- /dev/null +++ b/src/widgets/dbounceanimation.cpp @@ -0,0 +1,107 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later +#include "private/dbounceanimation_p.h" +#include +#include +#include +#include +#include +#include +#include + +DBounceAnimationPrivate::DBounceAnimationPrivate(DBounceAnimation *qq) + : DObjectPrivate (qq) + , m_animation(nullptr) + , m_animationTarget(nullptr) + , m_deltaSum(0) +{ +} + +DBounceAnimation::DBounceAnimation(QObject *parent) + : QObject(parent) + , DObject(*new DBounceAnimationPrivate(this)) +{ +} + +void DBounceAnimation::setAnimationTarget(QAbstractScrollArea *w) +{ + D_D(DBounceAnimation); + if (!w) + return; + + if (d->m_animationTarget == w) + return; + + d->m_animationTarget = w; +} + +void DBounceAnimation::setAniMationEnable(bool enable) +{ + D_D(DBounceAnimation); + enable ? d->m_animationTarget->installEventFilter(this) + : d->m_animationTarget->removeEventFilter(this); +} + +bool DBounceAnimation::eventFilter(QObject *o, QEvent *e) +{ + D_D(DBounceAnimation); + if (e->type() == QEvent::Wheel) { + if (auto absscroll = dynamic_cast(o)) { + if (auto wheelEvent = dynamic_cast(e)) { + if (absscroll->verticalScrollBar()->value() <= 0 || absscroll->verticalScrollBar()->value() >= absscroll->verticalScrollBar()->maximum()) { + d->m_deltaSum += wheelEvent->delta(); + bounceBack(wheelEvent->angleDelta().x() == 0 ? Qt::Vertical : Qt::Horizontal); + } + } + } + } + + return false; +} + +void DBounceAnimation::bounceBack(Qt::Orientation orientation) +{ + D_D(DBounceAnimation); + if (d->m_animation) + return; + + if (orientation & Qt::Vertical && d->m_animationTarget->verticalScrollBar()->maximum() == d->m_animationTarget->verticalScrollBar()->minimum()) + return; + + if (orientation & Qt::Horizontal && d->m_animationTarget->horizontalScrollBar()->maximum() == d->m_animationTarget->horizontalScrollBar()->minimum()) + return; + + d->m_animation = new QPropertyAnimation(this); + d->m_animation->setTargetObject(d->m_animationTarget->viewport()); + d->m_animation->setPropertyName("pos"); + d->m_animation->setDuration(100); + d->m_animation->setEasingCurve(QEasingCurve::InQuart); + d->m_animation->setStartValue(QPoint(d->m_animationTarget->viewport()->x(), d->m_animationTarget->viewport()->y())); + + QTimer::singleShot(100, this, [this, d, orientation]() { + + if (orientation & Qt::Vertical) { + d->m_animation->setEndValue( + QPoint(d->m_animationTarget->viewport()->x(), d->m_animationTarget->viewport()->y() + d->m_deltaSum / 16)); + } else { + d->m_animation->setEndValue( + QPoint(d->m_animationTarget->viewport()->x() + d->m_deltaSum / 16, d->m_animationTarget->viewport()->y())); + } + + d->m_animation->start(); + + connect(d->m_animation, &QPropertyAnimation::finished, this, [d]() { + if (d->m_animation->direction() == QPropertyAnimation::Backward) { + delete d->m_animation; + d->m_animation = nullptr; + return; + } + + d->m_animation->setDirection(QPropertyAnimation::Direction::Backward); + d->m_animation->setDuration(1000); + d->m_animation->start(QPropertyAnimation::DeleteWhenStopped); + d->m_deltaSum = 0; + }); + }); +} diff --git a/src/widgets/dindeterminateprogressbar.cpp b/src/widgets/dindeterminateprogressbar.cpp new file mode 100644 index 000000000..bb0713140 --- /dev/null +++ b/src/widgets/dindeterminateprogressbar.cpp @@ -0,0 +1,133 @@ +// SPDX-FileCopyrightText: 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(1); + 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/dlistview.cpp b/src/widgets/dlistview.cpp index 16672ba05..8b7bff3d6 100644 --- a/src/widgets/dlistview.cpp +++ b/src/widgets/dlistview.cpp @@ -13,6 +13,8 @@ #include "dstyleditemdelegate.h" #include "dstyle.h" +#include + DWIDGET_BEGIN_NAMESPACE DVariantListModel::DVariantListModel(QObject *parent) : @@ -196,6 +198,11 @@ DListView::DListView(QWidget *parent) : DObject(*new DListViewPrivate(this)) { d_func()->init(); + if (!qEnvironmentVariableIsSet("DTK_DISABLE_LISTVIEW_ANIMATION")) { + auto ani = new DBounceAnimation(this); + ani->setAnimationTarget(this); + ani->setAniMationEnable(true); + } } /*! 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/dbounceanimation_p.h b/src/widgets/private/dbounceanimation_p.h new file mode 100644 index 000000000..09e2d5b3b --- /dev/null +++ b/src/widgets/private/dbounceanimation_p.h @@ -0,0 +1,23 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later +#ifndef DBOUNCEANIMATION_P_H +#define DBOUNCEANIMATION_P_H + +#include "dbounceanimation.h" +#include + +class DBounceAnimationPrivate : public DTK_CORE_NAMESPACE::DObjectPrivate +{ +public: + DBounceAnimationPrivate(DBounceAnimation *qq); + + QPropertyAnimation *m_animation; + QAbstractScrollArea *m_animationTarget; + int m_deltaSum; + +private: + D_DECLARE_PUBLIC(DBounceAnimation) +}; + +#endif // DBOUNCEANIMATION_P_H diff --git a/src/widgets/private/dindeterminateprogressbar_p.h b/src/widgets/private/dindeterminateprogressbar_p.h new file mode 100644 index 000000000..330504358 --- /dev/null +++ b/src/widgets/private/dindeterminateprogressbar_p.h @@ -0,0 +1,29 @@ +// SPDX-FileCopyrightText: 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