Skip to content

Commit

Permalink
sync: from linuxdeepin/dtkwidget
Browse files Browse the repository at this point in the history
Synchronize source files from linuxdeepin/dtkwidget.

Source-pull-request: linuxdeepin/dtkwidget#597
  • Loading branch information
deepin-ci-robot committed Aug 13, 2024
1 parent c8b8148 commit 3486a7d
Show file tree
Hide file tree
Showing 9 changed files with 285 additions and 10 deletions.
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"
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
137 changes: 137 additions & 0 deletions src/widgets/dindeterminateprogressbar.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later

#include "private/dindeterminateprogressbar_p.h"

#include <DStyle>
#include <DGuiApplicationHelper>

#include <QPainter>
#include <QTimer>
#include <QPropertyAnimation>
#include <QDebug>
#include <QPainterPath>

DGUI_USE_NAMESPACE

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);
update();
});
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);

bool isDarkType = DGuiApplicationHelper::instance()->themeType() == DGuiApplicationHelper::DarkType;
p.setBrush(isDarkType ? QColor(255, 255, 255, int(0.1 * 255)) : QColor(0, 0, 0, int(0.1 * 255)));
p.setPen(Qt::NoPen);

p.drawRoundedRect(rect(), radius, radius);

QPen pen;
pen.setWidth(1);
pen.setColor(isDarkType ? QColor(255, 255, 255, int(0.1 * 255)) : QColor(0, 0, 0, int(0.1 * 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);

QColor highLightColor(palette().highlight().color());
auto borderColor = isDarkType ? DGuiApplicationHelper::adjustColor(highLightColor, 0, 0, +10, 0, 0, 0, 0)
: DGuiApplicationHelper::adjustColor(highLightColor, 0, 0, -20, 0, 0, 0, -20);
pen.setColor(borderColor);
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 spotColor = DGuiApplicationHelper::adjustColor(highLightColor, 0, 0, +30, 0, 0, 0, 0);

QLinearGradient linear(pointStart, pointEnd);
linear.setColorAt(0, highLightColor);
linear.setColorAt(0.5, spotColor);
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().marginsRemoved(QMargins(2, 2, 2, 2)), radius, radius);
p.setClipPath(clipPath);
p.setClipping(true);
p.drawRoundedRect(d->m_spotWidget->geometry(), radius, radius);
p.setClipping(false);
}
55 changes: 46 additions & 9 deletions src/widgets/dsearchedit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ DWIDGET_BEGIN_NAMESPACE
DCORE_USE_NAMESPACE
DGUI_USE_NAMESPACE

constexpr int ANI_DURATION = 200;
constexpr int HIDE_CURSOR_MARGIN = -4;

#ifdef ENABLE_AI
class VoiceDevice : public QIODevice
{
Expand Down Expand Up @@ -270,7 +273,11 @@ DSearchEditPrivate::DSearchEditPrivate(DSearchEdit *q)
, action(nullptr)
, iconWidget(nullptr)
, label(nullptr)
, animation(new QPropertyAnimation)
{
animation->setPropertyName("pos");
animation->setEasingCurve(QEasingCurve::OutCubic);
animation->setDuration(ANI_DURATION);
}

DSearchEditPrivate::~DSearchEditPrivate()
Expand Down Expand Up @@ -377,15 +384,31 @@ void DSearchEditPrivate::_q_toEditMode(bool focus)
{
D_Q(DSearchEdit);

if (focus || !q->lineEdit()->text().isEmpty()) {
action->setVisible(true);
iconWidget->setVisible(false);
lineEdit->setPlaceholderText(placeholderText);
} else {
action->setVisible(false);
iconWidget->setVisible(true);
lineEdit->setPlaceholderText(QString());
}
if (animation->state() == QPropertyAnimation::Running)
return;

auto textMargins = q->lineEdit()->textMargins();
QMargins marginsInAnimation(HIDE_CURSOR_MARGIN, 0, 0, 0);

if (!animation->parent())
animation->setParent(iconWidget);

animation->setTargetObject(iconWidget);
animation->setStartValue(QPoint(q->lineEdit()->geometry().center().x() - iconWidget->width() / 2, iconWidget->pos().y()));
animation->setEndValue(QPoint(0, iconWidget->pos().y()));

q->connect(animation, &QPropertyAnimation::finished, q, [q, this, textMargins]() {
q->lineEdit()->setTextMargins(textMargins);
if (animation->direction() == QPropertyAnimation::Direction::Forward) {
action->setVisible(true);
iconWidget->setVisible(false);
lineEdit->setPlaceholderText(placeholderText);
} else {
iconWidget->setVisible(true);
lineEdit->setPlaceholderText(QString());
iconWidget->move(QPoint(q->lineEdit()->geometry().center().x() - iconWidget->width() / 2, iconWidget->pos().y()));
}
});

#ifdef ENABLE_AI
//Focus disappears, clear voice check
Expand All @@ -394,6 +417,20 @@ void DSearchEditPrivate::_q_toEditMode(bool focus)
_q_onVoiceActionTrigger(false);
}
#endif

if (!q->lineEdit()->text().isEmpty())
return;

if (focus) {
animation->setDirection(QPropertyAnimation::Direction::Forward);
} else {
action->setVisible(false);
animation->setDirection(QPropertyAnimation::Direction::Backward);
}

iconWidget->setVisible(true);
q->lineEdit()->setTextMargins(marginsInAnimation);
animation->start();
}

void DSearchEditPrivate::_q_onVoiceActionTrigger(bool checked)

Check warning on line 436 in src/widgets/dsearchedit.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function '_q_onVoiceActionTrigger' is never used.
Expand Down
2 changes: 1 addition & 1 deletion src/widgets/dtitlebar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -775,7 +775,7 @@ void DTitlebarPrivate::setIconVisible(bool visible)
return;

if (visible) {
if (auto spacerItem = dynamic_cast<QSpacerItem *>(leftLayout->takeAt(0)))
if (dynamic_cast<QSpacerItem *>(leftLayout->itemAt(0)))
delete leftLayout->takeAt(0);

leftLayout->insertSpacing(0, 10);
Expand Down
29 changes: 29 additions & 0 deletions src/widgets/private/dindeterminateprogressbar_p.h
Original file line number Diff line number Diff line change
@@ -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 <DObjectPrivate>
#include <DIndeterminateProgressbar>

#include <QTimer>

class QPropertyAnimation;
class DIndeterminateProgressbarPrivate : public DTK_CORE_NAMESPACE::DObjectPrivate
{
public:
DIndeterminateProgressbarPrivate(DIndeterminateProgressbar *qq);

Check warning on line 17 in src/widgets/private/dindeterminateprogressbar_p.h

View workflow job for this annotation

GitHub Actions / cppcheck

Class 'DIndeterminateProgressbarPrivate' has a constructor with 1 argument that is not explicit. Such constructors should in general be explicit for type safety reasons. Using the explicit keyword in the constructor means some mistakes when using the class can be avoided.

QWidget *m_sliderWidget;
QTimer *m_timer;
bool m_leftToRight;
QWidget *m_spotWidget;
QPropertyAnimation *m_animation;

Check warning on line 23 in src/widgets/private/dindeterminateprogressbar_p.h

View workflow job for this annotation

GitHub Actions / cppcheck

The class 'DIndeterminateProgressbarPrivate' is unsafe, wrong usage can cause memory/resource leaks for 'DIndeterminateProgressbarPrivate::m_animation'. This can for instance be fixed by adding proper cleanup in the destructor.

private:
D_DECLARE_PUBLIC(DIndeterminateProgressbar)
};

#endif // DINDETERMINATEPROGRESSBAR_P_H
2 changes: 2 additions & 0 deletions src/widgets/private/dsearchedit_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <DSearchEdit>

#include <QLabel>
#include <QPropertyAnimation>

QT_BEGIN_NAMESPACE
class QAudioInput;
Expand Down Expand Up @@ -37,6 +38,7 @@ class DSearchEditPrivate : DLineEditPrivate

QWidget *iconWidget;
QLabel *label;
QPropertyAnimation *animation;

#ifdef ENABLE_AI
QAction *voiceAction = nullptr;
Expand Down

0 comments on commit 3486a7d

Please sign in to comment.