Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sync: from linuxdeepin/dtkwidget #71

Merged
merged 1 commit into from
Sep 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions examples/collections/progressbarexample.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <DWaterProgress>
#include <QPropertyAnimation>
#include <DColoredProgressBar>
#include <DIndeterminateProgressbar>
#include "progressbarexample.h"

DWIDGET_USE_NAMESPACE
Expand All @@ -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)
Expand Down Expand Up @@ -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;
}
12 changes: 12 additions & 0 deletions examples/collections/progressbarexample.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
1 change: 1 addition & 0 deletions include/DWidget/DIndeterminateProgressbar
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#include "dindeterminateprogressbar.h"
7 changes: 6 additions & 1 deletion include/widgets/dbuttonbox.h
Original file line number Diff line number Diff line change
@@ -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

Expand Down Expand Up @@ -47,6 +47,8 @@ class DButtonBoxButton : public QAbstractButton, public DCORE_NAMESPACE::DObject
void paintEvent(QPaintEvent *e) override;
void keyPressEvent(QKeyEvent *event) override;
bool event(QEvent *e) override;

friend class DButtonBox;
};

class DButtonBoxPrivate;
Expand Down Expand Up @@ -78,6 +80,9 @@ class DButtonBox : public QWidget, public DCORE_NAMESPACE::DObject
void buttonReleased(QAbstractButton *);
void buttonToggled(QAbstractButton *, bool);

protected:
bool eventFilter(QObject *o, QEvent *e) override;

private:
void paintEvent(QPaintEvent *e) override;

Expand Down
26 changes: 26 additions & 0 deletions include/widgets/dindeterminateprogressbar.h
Original file line number Diff line number Diff line change
@@ -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 <DObject>
#include <QWidget>

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
182 changes: 178 additions & 4 deletions src/widgets/dbuttonbox.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
// 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 "dbuttonbox.h"
#include "private/dbuttonbox_p.h"
#include <private/qabstractbutton_p.h>
#include "dstyleoption.h"
#include "dstyle.h"

Expand All @@ -12,10 +13,17 @@
#include <QHBoxLayout>
#include <QStyleOptionButton>
#include <QStylePainter>
#include <private/qabstractbutton_p.h>
#include <QVariantAnimation>

#include <DGuiApplicationHelper>

DWIDGET_BEGIN_NAMESPACE

constexpr int HOVER_ANI_DURATION = 150;
constexpr int CHECK_ANI_DURATION = 200;
constexpr qreal HOVER_BACKGROUND_SCALE = 0.8;
constexpr int SHADOW_HEIGHT = 2;

class DButtonBoxButtonPrivate : public DCORE_NAMESPACE::DObjectPrivate
{
public:
Expand Down Expand Up @@ -291,6 +299,7 @@
DStylePainter p(this);
DStyleOptionButtonBoxButton option;
initStyleOption(&option);
option.palette.setColor(QPalette::HighlightedText, this->palette().highlight().color());
p.drawControl(DStyle::CE_ButtonBoxButton, option);
}

Expand Down Expand Up @@ -349,8 +358,13 @@
return QAbstractButton::event(e);
}

DButtonBoxPrivate::DButtonBoxPrivate(DButtonBox *qq)

Check warning on line 361 in src/widgets/dbuttonbox.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Member variable 'DButtonBoxPrivate::group' is not initialized in the constructor.

Check warning on line 361 in src/widgets/dbuttonbox.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Member variable 'DButtonBoxPrivate::layout' is not initialized in the constructor.
: DObjectPrivate(qq)
, m_hoverId(-1)
, m_checkedId(-1)
, m_pressId(-1)
, m_hoverAnimation(new QVariantAnimation(qq))
, m_checkMoveAnimation(new QVariantAnimation(qq))
{

}
Expand All @@ -366,9 +380,17 @@
q->connect(group, SIGNAL(buttonPressed(QAbstractButton*)), q, SIGNAL(buttonPressed(QAbstractButton*)));
q->connect(group, SIGNAL(buttonReleased(QAbstractButton*)), q, SIGNAL(buttonReleased(QAbstractButton*)));
q->connect(group, SIGNAL(buttonToggled(QAbstractButton*, bool)), q, SIGNAL(buttonToggled(QAbstractButton*, bool)));
q->connect(m_hoverAnimation, &QVariantAnimation::valueChanged, q, [q]() {
q->update();
});
q->connect(m_checkMoveAnimation, &QVariantAnimation::valueChanged, q, [q]() {
q->update();
});
m_hoverAnimation->setDuration(HOVER_ANI_DURATION);
m_checkMoveAnimation->setDuration(CHECK_ANI_DURATION);

layout = new QHBoxLayout(q);
layout->setContentsMargins(0,0,0,0);
layout->setContentsMargins(0, 0, 0, 0);
layout->setSpacing(0);
}

Expand Down Expand Up @@ -484,6 +506,7 @@
d->group->addButton(button);

button->setCheckable(checkable);
button->installEventFilter(this);
}
}

Expand Down Expand Up @@ -575,9 +598,11 @@
void DButtonBox::paintEvent(QPaintEvent *e)
{
Q_UNUSED(e)
D_D(DButtonBox);

QStylePainter p(this);
QStyleOptionButton opt;
p.setRenderHint(QPainter::Antialiasing);
opt.state = QStyle::State_None;
opt.rect = rect();
opt.direction = layoutDirection();
Expand All @@ -591,7 +616,156 @@
opt.state |= QStyle::State_Active;
}

p.drawControl(QStyle::CE_PushButtonBevel, opt);
bool isDarkType = DGuiApplicationHelper::instance()->themeType() == DGuiApplicationHelper::DarkType;
int radius = DStyle::pixelMetric(style(), DStyle::PM_FrameRadius);
QColor background;
if (d->m_hoverId >= 0 && d->m_hoverId < buttonList().size()) {
if (isDarkType) {
background = "#141414";
background.setAlphaF(0.2);
} else {
background = Qt::black;
background.setAlphaF(0.1);
}

p.setPen(Qt::NoPen);
p.setBrush(background);

auto rect = d->m_hoverAnimation->currentValue().toRect();
p.drawRoundedRect(rect, radius, radius);

if (isDarkType) { // 深色模式需要绘制上下阴影
QPainterPath rectPath;
rectPath.addRoundedRect(rect, radius, radius);

QRect excludeRect = rect;
excludeRect.setHeight(rect.height() - SHADOW_HEIGHT);
QPainterPath bottomShadowPath;
bottomShadowPath.addRoundedRect(excludeRect, radius, radius);
bottomShadowPath = rectPath.subtracted(bottomShadowPath);

background.setAlphaF(0.5);
p.setBrush(background);
p.drawPath(bottomShadowPath); // 下阴影

excludeRect.moveBottom(rect.bottom());
QPainterPath topShadowPath;
topShadowPath.addRoundedRect(excludeRect, radius, radius);
topShadowPath = rectPath.subtracted(topShadowPath);

background = Qt::white;
background.setAlphaF(0.1);
p.setBrush(background);
p.drawPath(topShadowPath); // 上阴影
}
}

if (d->m_pressId >= 0 && d->m_pressId < buttonList().size()) {
background = Qt::black;
background.setAlphaF(isDarkType ? 0.15 : 0.2);

p.setBrush(background);
p.setPen(Qt::NoPen);
p.drawRoundedRect(d->m_hoverAnimation->currentValue().toRect(), radius, radius);
}

if (d->m_checkedId >= 0 && d->m_checkedId < buttonList().size()) {
background = Qt::black;
background.setAlphaF(isDarkType ? 0.3 : 0.1);
p.setBrush(background);
p.setPen(Qt::NoPen);

QRect rect;
if (d->m_checkMoveAnimation->currentValue().toRect().isValid())
rect = d->m_checkMoveAnimation->currentValue().toRect();
else
rect = buttonList().at(d->m_checkedId)->geometry();
p.drawRoundedRect(rect, radius, radius);

p.setPen(Qt::NoPen);
QColor shadowColor = Qt::black;
shadowColor.setAlphaF(0.2);
p.setBrush(shadowColor);

QPainterPath rectPath;
rectPath.addRoundedRect(rect, radius, radius);

QRect excludeRect = rect;
excludeRect.setHeight(rect.height() - SHADOW_HEIGHT);
QPainterPath shadowPath;
shadowPath.addRoundedRect(excludeRect, radius, radius);
shadowPath = rectPath.subtracted(shadowPath);

if (isDarkType) {
background.setAlphaF(0.5);
p.setBrush(background);
}
p.drawPath(shadowPath);
}
}

bool DButtonBox::eventFilter(QObject *o, QEvent *e)
{
D_D(DButtonBox);
for (int i = 0; i < buttonList().size(); ++i) {
if (o == buttonList().at(i)) {
DStyleOptionButtonBoxButton option;
dynamic_cast<DButtonBoxButton *>(o)->initStyleOption(&option);
if (option.state.testFlag(QStyle::State_On)) {
if (d->m_checkedId == i)
return false;

if (d->m_checkedId >= 0 && d->m_checkedId < buttonList().size()) {
d->m_checkMoveAnimation->setStartValue(buttonList().at(d->m_checkedId)->geometry());
d->m_checkedId = i;
d->m_checkMoveAnimation->setEndValue(buttonList().at(d->m_checkedId)->geometry());
} else {
d->m_checkedId = i;
d->m_checkMoveAnimation->setStartValue(0);
d->m_checkMoveAnimation->setEndValue(0);
}
d->m_checkMoveAnimation->start();
update();
}
if (e->type() == QEvent::HoverEnter) {
if (d->m_hoverId == i)
return false;

d->m_hoverId = i;

if (d->m_hoverId < 0 || d->m_hoverId >= buttonList().size())
return false;

QRect smallRect = buttonList().at(d->m_hoverId)->geometry();
smallRect.setSize(QSize(smallRect.width() * HOVER_BACKGROUND_SCALE, smallRect.height() * HOVER_BACKGROUND_SCALE));
smallRect.moveCenter(buttonList().at(d->m_hoverId)->geometry().center());
d->m_hoverAnimation->setStartValue(smallRect);
d->m_hoverAnimation->setEndValue(buttonList().at(d->m_hoverId)->geometry());
d->m_hoverAnimation->start();
update();
} else if (e->type() == QEvent::HoverLeave) {
d->m_hoverId = -1;
update();
} else if (e->type() == QEvent::MouseButtonPress) {
if (d->m_pressId == i)
return false;

d->m_pressId = i;
d->m_hoverId = -1;
update();
} else if (e->type() == QEvent::MouseButtonRelease) {
d->m_pressId = -1;
update();
} else if (e->type() == QEvent::Resize) {
d->m_hoverId = -1;
if (d->m_checkedId >= 0 && d->m_checkedId < buttonList().size()) {
d->m_checkMoveAnimation->setStartValue(buttonList().at(d->m_checkedId)->geometry());
d->m_checkMoveAnimation->setEndValue(buttonList().at(d->m_checkedId)->geometry());
}
}
}
}
return QWidget::eventFilter(o, e);
}

DWIDGET_END_NAMESPACE
Loading
Loading