|
|
|
@ -0,0 +1,304 @@
|
|
|
|
|
#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;"
|
|
|
|
|
"}";
|
|
|
|
|
}
|