Skip to content
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
3 changes: 2 additions & 1 deletion include/widgets/dfloatingmessage.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2019 - 2023 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 @@ -38,6 +38,7 @@ class DFloatingMessage : public DFloatingWidget

Q_SIGNALS:
void closeButtonClicked();
void messageClosed();

protected:
using DFloatingWidget::setWidget;
Expand Down
8 changes: 5 additions & 3 deletions include/widgets/dmessagemanager.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd.
// SPDX-FileCopyrightText: 2022 - 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later

#ifndef DMESSAGEMANAGER_H
#define DMESSAGEMANAGER_H

#include <QObject>
#include <DObject>
#include <QWidget>
#include <dtkwidget_global.h>
#include <dtkgui_global.h>
Expand All @@ -16,9 +16,11 @@ DGUI_END_NAMESPACE

DWIDGET_BEGIN_NAMESPACE
class DFloatingMessage;
class DMessageManager: public QObject
class DMessageManagerPrivate;
class DMessageManager: public QObject, public DCORE_NAMESPACE::DObject
{
Q_OBJECT
D_DECLARE_PRIVATE(DMessageManager)

private:
DMessageManager(); //构造函数是私有的
Expand Down
21 changes: 18 additions & 3 deletions src/widgets/dfloatingmessage.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2019 - 2023 UnionTech Software Technology Co., Ltd.
// SPDX-FileCopyrightText: 2019 - 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later

Expand All @@ -11,6 +11,7 @@
#include <QTimer>
#include <QLabel>
#include <QDebug>
#include <QGraphicsDropShadowEffect>

class MessageLabel : public QLabel
{
Expand Down Expand Up @@ -54,13 +55,17 @@ void DFloatingMessagePrivate::init()
iconButton->setIconSize(DSizeModeHelper::element(QSize(20, 20), QSize(30, 30)));

hBoxLayout->addWidget(iconButton);
hBoxLayout->addSpacing(10);
hBoxLayout->addWidget(labMessage);

if (notifyType == DFloatingMessage::MessageType::TransientType) { //临时消息
timer = new QTimer(q);
timer->setInterval(4000);
timer->setSingleShot(true);
q->connect(timer, &QTimer::timeout, q, &DFloatingMessage::close);
q->connect(timer, &QTimer::timeout, q, [q]() {
q->close();
Q_EMIT q->messageClosed();
});
} else { //常驻消息
content = nullptr;
closeButton = new DDialogCloseButton(q);
Expand All @@ -69,8 +74,18 @@ void DFloatingMessagePrivate::init()

hBoxLayout->addWidget(closeButton);
q->connect(closeButton, &DIconButton::clicked, q, &DFloatingMessage::closeButtonClicked);
q->connect(closeButton, &DIconButton::clicked, q, &DFloatingMessage::close);
q->connect(closeButton, &DIconButton::clicked, q, [q]() {
q->close();
Q_EMIT q->messageClosed();
});
}

auto effect = new QGraphicsDropShadowEffect(q);
effect->setColor(QColor(0, 0, 0, 0.1 * 255));
effect->setBlurRadius(20);
effect->setXOffset(0);
effect->setYOffset(2);
q->setGraphicsEffect(effect);
}

/*!
Expand Down
127 changes: 111 additions & 16 deletions src/widgets/dmessagemanager.cpp
Original file line number Diff line number Diff line change
@@ -1,19 +1,48 @@
// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd.
// SPDX-FileCopyrightText: 2022 - 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later

#include "dmessagemanager.h"
#include "private/dmessagemanager_p.h"

#include <DFloatingMessage>
#include <DDciIcon>

#include <QVBoxLayout>
#include <QEvent>
#include <QPainter>

#define D_MESSAGE_MANAGER_CONTENT "_d_message_manager_content"
const int MARGIN = 20;
const int MESSGAE_HEIGHT = 50;
const int ANIMATION_DURATION = 400;

Q_DECLARE_METATYPE(QMargins)

class ImageLabel : public QLabel {
Q_OBJECT
Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity)
public:
explicit ImageLabel(QWidget *parent=nullptr)
: QLabel (parent)
, m_opacity(0)
{
};
void setOpacity(qreal opac) { m_opacity = opac; }
qreal opacity() { return m_opacity ;}

protected:
void paintEvent(QPaintEvent *e) override
{
Q_UNUSED(e)
QPainter p(this);
p.setRenderHint(QPainter::Antialiasing);
p.setOpacity(m_opacity);
p.drawPixmap(rect().marginsRemoved(contentsMargins()), *pixmap());
};
private:
qreal m_opacity;
};

// 仅仅为了接口兼容, 符号不会减少, 如果使用了这个接口,实际调用走的有namespace的
class Q_DECL_EXPORT DMessageManager: public QObject
{
Expand Down Expand Up @@ -91,7 +120,30 @@ static void sendMessage_helper(DMessageManager *manager, QWidget *par, IconType
manager->sendMessage(par, floMsg);
}

DMessageManagerPrivate::DMessageManagerPrivate(DMessageManager *qq)
: DObjectPrivate(qq)
, m_aniGeometry(new QPropertyAnimation(qq))
, m_aniOpacity(new QPropertyAnimation(qq))
, m_aniGroup(new QParallelAnimationGroup(qq))
, m_label(new ImageLabel)
{
m_aniGeometry->setPropertyName("geometry");
m_aniGeometry->setDuration(ANIMATION_DURATION);
m_aniGeometry->setEasingCurve(QEasingCurve::OutCubic);

m_aniOpacity->setPropertyName("opacity");
m_aniOpacity->setDuration(ANIMATION_DURATION);
m_aniOpacity->setEasingCurve(QEasingCurve::OutCubic);
m_aniOpacity->setTargetObject(m_label);
m_aniOpacity->setStartValue(0);
m_aniOpacity->setEndValue(1);

m_aniGroup->addAnimation(m_aniGeometry);
m_aniGroup->addAnimation(m_aniOpacity);
}

DMessageManager::DMessageManager() //私有静态构造函数
: DObject(*new DMessageManagerPrivate(this))
{
}

Expand All @@ -114,6 +166,7 @@ DMessageManager *DMessageManager::instance() //公有静态函数
*/
void DMessageManager::sendMessage(QWidget *par, DFloatingMessage *floMsg)
{
D_D(DMessageManager);
QWidget *content = par->findChild<QWidget *>(D_MESSAGE_MANAGER_CONTENT, Qt::FindDirectChildrenOnly);

if (!content) {
Expand All @@ -125,18 +178,68 @@ void DMessageManager::sendMessage(QWidget *par, DFloatingMessage *floMsg)
if (par->property("_d_margins").isValid())
content->setContentsMargins(magins);
else
content->setContentsMargins(QMargins(20, 0, 20, 0));
content->setContentsMargins(QMargins(MARGIN, 0, MARGIN, 0));

content->installEventFilter(this);
par->installEventFilter(this);
QVBoxLayout *layout = new QVBoxLayout(content);
layout->setSpacing(0);
layout->setContentsMargins(0, 0, 0, 0);
layout->setDirection(QBoxLayout::BottomToTop);
content->show();
}

if (content->layout()->count() >= 1) {
content->layout()->itemAt(content->layout()->count() - 1)->widget()->hide();
delete content->layout()->takeAt(content->layout()->count() - 1);
}

static_cast<QBoxLayout*>(content->layout())->addWidget(floMsg, 0, Qt::AlignHCenter);

// 限制通知消息的最大宽度
for (DFloatingMessage *message : content->findChildren<DFloatingMessage*>(QString(), Qt::FindDirectChildrenOnly)) {
message->setMaximumWidth(par->rect().marginsRemoved(content->contentsMargins()).width());
message->setMinimumHeight(message->sizeHint().height());
}

QRect geometry(QPoint(0, 0), floMsg->sizeHint() + QSize(MARGIN * 2, 0));
geometry.moveCenter(par->rect().center());
geometry.moveBottom(par->rect().bottom() - MESSGAE_HEIGHT);

content->setGeometry(geometry);
content->hide();

if (d->m_aniGeometry->state() == QPropertyAnimation::State::Running)
return;

d->m_label->setParent(par);
d->m_label->setAlignment(Qt::AlignCenter);
d->m_label->setContentsMargins(MARGIN, 0, MARGIN, 0);
d->m_label->setPixmap(floMsg->grab());
d->m_label->setScaledContents(true);
d->m_label->show();
d->m_aniGeometry->setTargetObject(d->m_label);
d->m_aniOpacity->setTargetObject(d->m_label);
d->m_aniGeometry->setStartValue(QRect(par->rect().center().x(), par->rect().bottom(), 0, 0));
d->m_aniGeometry->setEndValue(content->geometry());
d->m_aniGroup->start();
connect(d->m_aniGroup, &QPropertyAnimation::finished, this, [d, content]() {
if (d->m_aniGroup->direction() == QAbstractAnimation::Backward) {
d->m_aniGroup->setDirection(QAbstractAnimation::Forward);
} else {
content->show();
}
d->m_label->hide();
});

connect(floMsg, &DFloatingMessage::messageClosed, [=, this]() {
d->m_aniGeometry->setStartValue(QRect(par->rect().center().x(), par->rect().bottom(), 0, 0));
d->m_aniGeometry->setEndValue(content->geometry());
d->m_label->setPixmap(floMsg->grab());

d->m_aniGroup->setDirection(QAbstractAnimation::Backward);
d->m_label->show();
d->m_aniGroup->start();
});
}

/*!
Expand Down Expand Up @@ -184,27 +287,19 @@ bool DMessageManager::setContentMargens(QWidget *par, const QMargins &margins)
*/
bool DMessageManager::eventFilter(QObject *watched, QEvent *event)
{
if (event->type() == QEvent::LayoutRequest || event->type() == QEvent::Resize) {
if (QWidget *widget = qobject_cast<QWidget *>(watched)) {
QWidget *content;

if (widget->objectName() == D_MESSAGE_MANAGER_CONTENT) {
content = widget;
} else {
content = widget->findChild<QWidget*>(D_MESSAGE_MANAGER_CONTENT, Qt::FindDirectChildrenOnly);
}
if (event->type() == QEvent::Resize) {
if (auto content = watched->findChild<QWidget *>(D_MESSAGE_MANAGER_CONTENT, Qt::FindDirectChildrenOnly)) {

QWidget *par = content->parentWidget();
auto par = qobject_cast<QWidget *>(watched);

// 限制通知消息的最大宽度
for (DFloatingMessage *message : content->findChildren<DFloatingMessage*>(QString(), Qt::FindDirectChildrenOnly)) {
message->setMaximumWidth(par->rect().marginsRemoved(content->contentsMargins()).width());
message->setMinimumHeight(message->sizeHint().height());
}

QRect geometry(QPoint(0, 0), content->sizeHint());
geometry.moveCenter(par->rect().center());
geometry.moveBottom(par->rect().bottom());
geometry.moveBottom(par->rect().bottom() - MESSGAE_HEIGHT);
content->setGeometry(geometry);
}
} else if (event->type() == QEvent::ChildRemoved) {
Expand Down
11 changes: 10 additions & 1 deletion src/widgets/dstyle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1339,9 +1339,18 @@ void DStyle::drawPrimitive(const QStyle *style, DStyle::PrimitiveElement pe, con
//先绘画阴影
DDrawUtils::drawShadow(p, btn->rect + shadow_margin, frameRadius, frameRadius, QColor(0, 0, 0, 0.25 * 255), shadowRadius, QPoint(offsetX, offsetY));
//再绘画上面的待显示区域
p->setPen(QPen(btn->dpalette.frameShadowBorder(), 1));
p->setPen(Qt::NoPen);
p->setBrush(btn->noBackground ? Qt::NoBrush : p->background());
p->drawRoundedRect(opt->rect, frameRadius, frameRadius);

p->setBrush(Qt::NoBrush);
QPen pen;
pen.setWidth(1);
pen.setColor(DGuiApplicationHelper::instance()->themeType() == DGuiApplicationHelper::DarkType
? QColor(255, 255, 255, int(0.1 * 255))
: QColor(0, 0, 0, int(0.12 * 255)));
p->setPen(pen);
p->drawRoundedRect(opt->rect, frameRadius, frameRadius);
}
break;
}
Expand Down
33 changes: 33 additions & 0 deletions src/widgets/private/dmessagemanager_p.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later

#ifndef DABOUTDIALOG_P_H
#define DABOUTDIALOG_P_H

#include "dmessagemanager.h"

#include <DObjectPrivate>

#include <QLabel>
#include <QPropertyAnimation>
#include <QParallelAnimationGroup>

DWIDGET_BEGIN_NAMESPACE

class DMessageManagerPrivate : public DCORE_NAMESPACE::DObjectPrivate
{
public:
DMessageManagerPrivate(DMessageManager *qq);

QPropertyAnimation *m_aniGeometry;
QPropertyAnimation *m_aniOpacity;;
QParallelAnimationGroup *m_aniGroup;
QLabel *m_label;

D_DECLARE_PUBLIC(DMessageManager);
};

DWIDGET_END_NAMESPACE

#endif // DABOUTDIALOG_P_H