You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
PayloadAPP/3rdparty/QNotify/include/NotifyManager.cpp

305 lines
9.4 KiB
C++

#include "NotifyManager.h"
#include "NotifyWidget.h" // NotifyWidget.h没有放到NotifyManager.h文件是因为NotifyWidget.cpp也include了NotifyManager.h为了能互相include才这么做
NotifyManager::NotifyManager(QWidget *widget, QObject *parent)
: m_parentWidget(widget), QObject(parent) {
m_maxCount = 5; // 可见的最大通知数目设置为5
m_displayTime =
3000; // 显示时间默认设置为3秒通知显示出来过了10秒之后隐藏并自动销毁
m_animateTime = 300; // 动画时间设置为300ms
m_spacing = 10; // 通知框之间的间距设置为10
m_notifyWndSize = QSize(300, 40); // 通知框大小
m_defaultIcon = ":/message1.png"; // 默认图标
initStyleSheet();
m_isShowQueueCount = true; // 默认显示队列的通知数目
// 传入边距以设置最下面的通知的右下角坐标
this->setCornerMargins(10, 10);
// 初始化队列的剩余通知数目界面
m_notifyCount = new NotifyCountWidget(this, m_parentWidget);
}
// 弹出通知框
void NotifyManager::notify(const QString &title, const QString &body, int type,
int displayTime, const QVariantMap &data) {
// 将标题栏和内容数据添加到队列中
QVariantMap tmp = data;
tmp.insert("title", title);
tmp.insert("body", body);
// tmp.insert("type", type);
switch (type) {
case NotificationType::SUCCESS:
m_defaultIcon = ":/success.png";
tmp.insert("theme", "success");
break;
case NotificationType::WARNING:
m_defaultIcon = ":/warning.png";
tmp.insert("theme", "warn");
break;
case NotificationType::ERROR:
m_defaultIcon = ":/error.png";
tmp.insert("theme", "error");
break;
default:
break;
}
setDisplayTime(displayTime);
m_dataQueue.enqueue(tmp);
// 显示下一条通知
showNext();
}
// 设置通知框的最大数目
void NotifyManager::setMaxCount(int count) {
m_maxCount = count;
}
// 获取通知框显示时间
int NotifyManager::displayTime() const {
return m_displayTime;
}
// 设置通知框显示时间
void NotifyManager::setDisplayTime(int displayTime) {
m_displayTime = displayTime;
}
// 获取动画时间
int NotifyManager::animateTime() const {
return m_animateTime;
}
// 设置动画时间
void NotifyManager::setAnimateTime(int animateTime) {
m_animateTime = animateTime;
}
// 获取通知栏之间的间距
int NotifyManager::spacing() const {
return m_spacing;
}
// 设置通知栏之间的间距
void NotifyManager::setSpacing(int spacing) {
m_spacing = spacing;
}
// 获取最下面的通知的右下角坐标
QPoint NotifyManager::cornerPos() {
QScreen *screen = QGuiApplication::primaryScreen();
QRect screenGeometry = screen->availableGeometry();
qreal dpiScale = screen->devicePixelRatio();
QRect widgetGeometry = m_parentWidget->geometry();
QPoint pt = widgetGeometry.topLeft();
m_cornerPos.setX((pt.x() + m_parentWidget->width() / 2));
m_cornerPos.setY(widgetGeometry.top() - m_notifyWndSize.height());
return m_cornerPos;
}
// 传入边距以设置最下面的通知的右下角坐标
void NotifyManager::setCornerMargins(int right, int bottom) {
// QRect desktopRect = QApplication::primaryScreen()->availableGeometry();
// QPoint bottomRignt = desktopRect.bottomRight();
// m_cornerPos = QPoint(bottomRignt.x() - right, bottomRignt.y() - bottom);
// 获取当前屏幕的DPI和缩放比例
QScreen *screen = QGuiApplication::primaryScreen();
QRect screenGeometry = screen->availableGeometry();
qreal dpiScale = screen->devicePixelRatio();
QPoint bottomRignt;
QPoint pt;
QRect widgetGeometry = m_parentWidget->geometry();
int y = widgetGeometry.top();
QPoint lpt = widgetGeometry.topLeft();
pt = m_parentWidget->mapToGlobal(lpt);
bottomRignt.setX((screenGeometry.width() - m_parentWidget->width()) / 2);
bottomRignt.setY((screenGeometry.height()) / 2);
m_cornerPos =
QPoint(bottomRignt.x() * dpiScale, bottomRignt.y() * dpiScale);
}
// 获取通知框的尺寸
QSize NotifyManager::notifyWndSize() const {
return m_notifyWndSize;
}
// 设置通知框的尺寸
void NotifyManager::setNotifyWndSize(int width, int height) {
m_notifyWndSize = QSize(width, height);
}
// 获取默认图标的路径
QString NotifyManager::defaultIcon() const {
return m_defaultIcon;
}
// 设置默认图标
void NotifyManager::setDefaultIcon(const QString &defaultIcon) {
m_defaultIcon = defaultIcon;
}
// 获取指定theme的样式
QString NotifyManager::styleSheet(const QString &theme) const {
if (!m_styleSheets.contains(theme)) return m_styleSheets.value("default");
return m_styleSheets.value(theme);
}
// 设置指定theme的样式
void NotifyManager::setStyleSheet(const QString &styleSheet,
const QString &theme) {
m_styleSheets[theme] = styleSheet;
}
// 设置是否显示队列的通知数目
void NotifyManager::setShowQueueCount(bool isShowQueueCount) {
m_isShowQueueCount = isShowQueueCount;
if (!m_isShowQueueCount) m_notifyCount->showArranged(0);
}
// 显示下一条通知
void NotifyManager::showNext() {
// 如果通知数目超出限制,则显示"通知当前数目界面"
if (m_notifyList.size() >= m_maxCount || m_dataQueue.isEmpty()) {
showQueueCount();
return;
}
// 创建并显示新的通知框
NotifyWidget *notifyWidget =
new NotifyWidget(this); // 将管理员自身传给notifyWidget的m_manager
m_notifyList.append(notifyWidget); // 添加到通知框列表
notifyWidget->showArranged(m_notifyList.size()); // 设置新通知的显示位置
notifyWidget->setData(
m_dataQueue
.dequeue()); // 设置数据队列的第一个数据(dequeue删除队列第一个元素并返回这个元素)
showQueueCount(); // 显示队列的剩余通知数目
// 通知过了displayTime时间之后隐藏之后销毁然后触发下面槽函数
connect(notifyWidget, &QObject::destroyed, this, [notifyWidget, this]() {
// 找到被销毁的通知在队列中的索引,然后移除该通知
int index = m_notifyList.indexOf(notifyWidget);
m_notifyList.removeAt(index);
// 旧消息被移出后,就要显示通知队列中的下一个新消息,并排序
for (; index < m_notifyList.size(); index++)
m_notifyList[index]->showArranged(index + 1);
// 这里是为了实现周期提示功能,一般不用到,可以注释
QTimer::singleShot(m_animateTime, this, [this]() {
showNext();
});
});
}
// 显示队列的剩余通知数目
void NotifyManager::showQueueCount() {
// 判断是否允许显示队列的剩余通知数目
if (!m_isShowQueueCount) return;
// 数据队列大于0说明还有未显示的剩余通知则显示数目否则隐藏"剩余通知数目"
if (!m_dataQueue.isEmpty()) {
m_notifyCount->showArranged(m_maxCount + 1);
m_notifyCount->setCount(m_dataQueue.size());
} else {
m_notifyCount->showArranged(0);
}
}
void NotifyManager::initStyleSheet() {
m_styleSheets["default"] =
"#notify-background {"
"background: white;"
"border-radius: 6px;"
"}"
"#notify-title{"
"font-weight: bold;"
"font-size: 14px;"
"color: #333333;"
"}"
"#notify-body{"
"font-size: 12px;"
"color: #444444;"
"}"
"#notify-close-btn{ "
"border: 0;"
"color: #999999;"
"}"
"#notify-close-btn:hover{ "
"background: #cccccc;"
"}";
m_styleSheets["success"] =
"#notify-background {"
"background: rgba(236, 253, 245, 0.95);"
"border-radius: 6px;"
"border: 1px solid #A7F3D0;"
"}"
"#notify-title{"
"font-weight: bold;"
"font-size: 14px;"
"color: #059669;"
"}"
"#notify-body{"
"font-size: 12px;"
"color: #059669;"
"}"
"#notify-close-btn{ "
"border: 0;"
"color: #059669;"
"}"
"#notify-close-btn:hover{ "
"background: #D1FAE5;"
"}";
m_styleSheets["warn"] =
"#notify-background {"
"background: rgba(254, 252, 232, 0.95);"
"border-radius: 6px;"
"border: 1px solid #FEF08A;"
"}"
"#notify-title{"
"font-weight: bold;"
"font-size: 14px;"
"color: #D97706;"
"}"
"#notify-body{"
"font-size: 12px;"
"color: #D97706;"
"}"
"#notify-close-btn{ "
"border: 0;"
"color: #D97706;"
"}"
"#notify-close-btn:hover{ "
"background: #FEF9C3;"
"}";
m_styleSheets["error"] =
"#notify-background {"
"background: rgba(254, 242, 242, 0.95);"
"border-radius: 6px;"
"border: 1px solid #FECACA;"
"}"
"#notify-title{"
"font-weight: bold;"
"font-size: 14px;"
"color: #DC2626;"
"}"
"#notify-body{"
"font-size: 12px;"
"color: #DC2626;"
"}"
"#notify-close-btn{ "
"border: 0;"
"color: #DC2626;"
"}"
"#notify-close-btn:hover{ "
"background: #FEE2E2;"
"}";
}