-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathToastWidget.cpp
More file actions
130 lines (110 loc) · 4 KB
/
Copy pathToastWidget.cpp
File metadata and controls
130 lines (110 loc) · 4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include "ToastWidget.hpp"
#include <QFontMetrics>
#include <QHBoxLayout>
#include <QPixmap>
#include <QTimer>
ToastWidget::ToastWidget(QWidget *parent)
: QFrame(parent), level(ToastLevel::Info) {
setWindowFlags(Qt::FramelessWindowHint | Qt::SubWindow);
setAttribute(Qt::WA_TransparentForMouseEvents, false);
setAttribute(Qt::WA_ShowWithoutActivating);
setAttribute(Qt::WA_DeleteOnClose);
}
void ToastWidget::showToast(QWidget *parent, const QString &message,
ToastLevel level, int durationMs) {
if (!parent)
return;
// 关闭父窗口中所有已有的 toast,避免堆积
const auto children = parent->findChildren<ToastWidget *>();
for (auto *child : children) {
child->close();
}
auto *toast = new ToastWidget(parent);
toast->setupUi(level, message, durationMs);
toast->QWidget::show();
}
void ToastWidget::showInfo(QWidget *parent, const QString &message,
int durationMs) {
showToast(parent, message, ToastLevel::Info, durationMs);
}
void ToastWidget::showWarning(QWidget *parent, const QString &message,
int durationMs) {
showToast(parent, message, ToastLevel::Warning, durationMs);
}
void ToastWidget::showError(QWidget *parent, const QString &message,
int durationMs) {
showToast(parent, message, ToastLevel::Error, durationMs);
}
void ToastWidget::setupUi(ToastLevel level, const QString &message,
int durationMs) {
this->level = level;
QColor color;
QString iconPath;
switch (level) {
case ToastLevel::Info:
color = QColor(0x07, 0x7A, 0xFF); // 蓝色
iconPath = QStringLiteral(":/toast_info.png");
break;
case ToastLevel::Warning:
color = QColor(0xFF, 0x98, 0x00); // 橙色
iconPath = QStringLiteral(":/toast_warning.png");
break;
case ToastLevel::Error:
color = QColor(0xE5, 0x39, 0x35); // 红色
iconPath = QStringLiteral(":/toast_error.png");
break;
}
setStyleSheet(QString("QFrame { border: 2px solid %1; border-radius: 6px; "
"background: white; }")
.arg(color.name()));
auto *layout = new QHBoxLayout(this);
layout->setContentsMargins(12, 10, 12, 10);
layout->setSpacing(10);
// 图标
iconLabelPtr = new QLabel(this);
iconLabelPtr->setFixedSize(24, 24);
iconLabelPtr->setScaledContents(true);
iconLabelPtr->setPixmap(QPixmap(iconPath).scaled(24, 24, Qt::KeepAspectRatio,
Qt::SmoothTransformation));
iconLabelPtr->setStyleSheet(
QString("QLabel { background: transparent; border: none; }"));
layout->addWidget(iconLabelPtr);
// 消息文本
messageLabelPtr = new QLabel(message, this);
messageLabelPtr->setWordWrap(true);
messageLabelPtr->setStyleSheet(
QString("QLabel { color: %1; font-size: 13px; background: transparent; "
"border: none; }")
.arg(color.name()));
messageLabelPtr->setSizePolicy(QSizePolicy::Expanding,
QSizePolicy::Preferred);
layout->addWidget(messageLabelPtr);
// 自适应宽度:边距(12+12) + 图标(24) + 间距(10) = 58px
{
constexpr int kFixedOverhead = 58;
QFont font;
font.setPixelSize(13);
const QFontMetrics fm(font);
const int textWidth = fm.horizontalAdvance(message);
const int idealWidth = textWidth + kFixedOverhead;
const int clampedWidth =
qBound(TOAST_MIN_WIDTH, idealWidth, TOAST_MAX_WIDTH);
setFixedWidth(clampedWidth);
}
adjustSize();
reposition();
// 自动消失定时器
dismissTimerPtr = new QTimer(this);
dismissTimerPtr->setSingleShot(true);
connect(dismissTimerPtr, &QTimer::timeout, this, &QWidget::close);
dismissTimerPtr->start(durationMs);
}
void ToastWidget::reposition() {
if (!parentWidget())
return;
const int parentW = parentWidget()->width();
const int parentH = parentWidget()->height();
const int x = (parentW - width()) / 2;
const int y = (parentH - height()) / 2;
move(x, y);
}