├── .gitignore ├── LICENSE ├── README.md ├── img ├── message.png └── screeshot.png ├── main.cpp ├── mainwindow.cpp ├── mainwindow.h ├── notify.cpp ├── notify.h ├── notifymanager.cpp ├── notifymanager.h ├── qtnotify.pro └── res.qrc /.gitignore: -------------------------------------------------------------------------------- 1 | # C++ objects and libs 2 | 3 | *.slo 4 | *.lo 5 | *.o 6 | *.a 7 | *.la 8 | *.lai 9 | *.so 10 | *.dll 11 | *.dylib 12 | 13 | # Qt-es 14 | 15 | /.qmake.cache 16 | /.qmake.stash 17 | *.pro.user 18 | *.pro.user.* 19 | *.qbs.user 20 | *.qbs.user.* 21 | *.moc 22 | moc_*.cpp 23 | qrc_*.cpp 24 | ui_*.h 25 | Makefile* 26 | *build-* 27 | 28 | # QtCreator 29 | 30 | *.autosave 31 | 32 | # QtCtreator Qml 33 | *.qmlproject.user 34 | *.qmlproject.user.* 35 | 36 | # QtCtreator CMake 37 | CMakeLists.txt.user 38 | 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 panxin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # qt-notify 2 | Simple notifications for qt apps 3 | 4 | ![](./img/screeshot.png) 5 | 6 | ```c++ 7 | NotifyManager *manager = new NotifyManager(this); 8 | manager->notify(title, body, icon, url); 9 | ``` -------------------------------------------------------------------------------- /img/message.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pansinm/qt-notify/a20a47a815c040f0bf5c903cc17e54519a59840f/img/message.png -------------------------------------------------------------------------------- /img/screeshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pansinm/qt-notify/a20a47a815c040f0bf5c903cc17e54519a59840f/img/screeshot.png -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "mainwindow.h" 4 | 5 | int main(int argc, char *argv[]) 6 | { 7 | QApplication app(argc, argv); 8 | MainWindow window; 9 | window.show(); 10 | return app.exec(); 11 | } 12 | -------------------------------------------------------------------------------- /mainwindow.cpp: -------------------------------------------------------------------------------- 1 | #include "mainwindow.h" 2 | #include "notifymanager.h" 3 | #include 4 | 5 | MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) 6 | { 7 | 8 | QPushButton * button = new QPushButton("弹窗", this); 9 | NotifyManager *manager = new NotifyManager(this); 10 | 11 | connect(button, &QPushButton::clicked, manager, [manager]{ 12 | manager->notify("新消息", "新消息新消息新消息新消息", "://img/message.png", "http://www.github.com"); 13 | }); 14 | } 15 | -------------------------------------------------------------------------------- /mainwindow.h: -------------------------------------------------------------------------------- 1 | #ifndef MAINWINDOW_H 2 | #define MAINWINDOW_H 3 | 4 | #include 5 | 6 | class MainWindow : public QMainWindow 7 | { 8 | Q_OBJECT 9 | public: 10 | explicit MainWindow(QWidget *parent = 0); 11 | 12 | Q_SIGNALS: 13 | 14 | public Q_SLOTS: 15 | }; 16 | 17 | #endif // MAINWINDOW_H 18 | 19 | -------------------------------------------------------------------------------- /notify.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "notify.h" 12 | 13 | Notify::Notify (int displayTime, QWidget *parent) : QWidget(parent), 14 | displayTime(displayTime) 15 | { 16 | 17 | this->setWindowFlags(Qt::FramelessWindowHint|Qt::WindowSystemMenuHint| Qt::Tool | Qt::WindowStaysOnTopHint); 18 | this->setAttribute(Qt::WA_NoSystemBackground, true); 19 | this->setAttribute(Qt::WA_TranslucentBackground,true); 20 | 21 | backgroundLabel = new QLabel(this); 22 | backgroundLabel->move(0, 0); 23 | backgroundLabel->setObjectName("notify-background"); 24 | 25 | 26 | QHBoxLayout *mainLayout = new QHBoxLayout(backgroundLabel); 27 | QVBoxLayout *contentLayout = new QVBoxLayout(); 28 | 29 | iconLabel = new QLabel(backgroundLabel); 30 | iconLabel->setFixedWidth(40); 31 | iconLabel->setAlignment(Qt::AlignCenter); 32 | 33 | titleLabel = new QLabel(backgroundLabel); 34 | titleLabel->setObjectName("notify-title"); 35 | 36 | bodyLabel = new QLabel(backgroundLabel); 37 | bodyLabel->setObjectName("notify-body"); 38 | QFont font = bodyLabel->font(); 39 | font.setPixelSize(12); 40 | bodyLabel->setFont(font); 41 | 42 | contentLayout->addWidget(titleLabel); 43 | contentLayout->addWidget(bodyLabel); 44 | 45 | mainLayout->addWidget(iconLabel); 46 | mainLayout->addSpacing(5); 47 | mainLayout->addLayout(contentLayout); 48 | 49 | 50 | closeBtn = new QPushButton("×", backgroundLabel); 51 | closeBtn->setObjectName("notify-close-btn"); 52 | closeBtn->setFixedSize(24, 24); 53 | connect(closeBtn, &QPushButton::clicked, this, [this]{ 54 | Q_EMIT disappeared(); 55 | }); 56 | 57 | this->setStyleSheet("#notify-background {" 58 | "border: 1px solid #ccc;" 59 | "background:white;" 60 | "border-radius: 4px;" 61 | "} " 62 | "#notify-title{" 63 | "font-weight: bold;" 64 | "color: #333;" 65 | "font-size: 14px;" 66 | "}" 67 | "#notify-body{" 68 | "color: #444;" 69 | "}" 70 | "#notify-close-btn{ " 71 | "border: 0;" 72 | "color: #999;" 73 | "}" 74 | "#notify-close-btn:hover{ " 75 | "background: #ccc;" 76 | "}"); 77 | 78 | } 79 | 80 | 81 | void Notify::showGriant() 82 | { 83 | this->show(); 84 | 85 | titleLabel->setText(title); 86 | QPixmap tempPix = QPixmap(this->icon); 87 | tempPix = tempPix.scaled(QSize(30, 30), Qt::KeepAspectRatio); 88 | iconLabel->setPixmap(tempPix); 89 | 90 | backgroundLabel->setFixedSize(this->size()); 91 | closeBtn->move(backgroundLabel->width() - closeBtn->width(), 0); 92 | 93 | // 超过长度省略号 94 | QFontMetrics elidfont(bodyLabel->font()); 95 | QString text = elidfont.elidedText(this->body, Qt::ElideRight, bodyLabel->width() - 5); 96 | bodyLabel->setText(text); 97 | 98 | QPropertyAnimation *animation = new QPropertyAnimation(this, "windowOpacity", this); 99 | animation->setStartValue(0); 100 | animation->setEndValue(1); 101 | animation->setDuration(200); 102 | animation->start(); 103 | 104 | connect(animation, &QPropertyAnimation::finished, this, [animation, this](){ 105 | animation->deleteLater(); 106 | QTimer::singleShot(displayTime, this, [this](){ 107 | this->hideGriant(); 108 | }); 109 | }); 110 | } 111 | 112 | void Notify::hideGriant() 113 | { 114 | QPropertyAnimation *animation = new QPropertyAnimation(this, "windowOpacity", this); 115 | animation->setStartValue(this->windowOpacity()); 116 | animation->setEndValue(0); 117 | animation->setDuration(200); 118 | animation->start(); 119 | 120 | connect(animation, &QPropertyAnimation::finished, this, [animation, this](){ 121 | this->hide(); 122 | animation->deleteLater(); 123 | Q_EMIT disappeared(); 124 | }); 125 | } 126 | 127 | void Notify::mousePressEvent(QMouseEvent *event) 128 | { 129 | if(event->button() == Qt::LeftButton) { 130 | if(!url.isEmpty()){ 131 | QDesktopServices::openUrl(url); 132 | } 133 | hideGriant(); 134 | } 135 | } 136 | 137 | void Notify::setUrl(const QString &value) 138 | { 139 | url = value; 140 | } 141 | 142 | 143 | void Notify::setBody(const QString &value) 144 | { 145 | body = value; 146 | } 147 | 148 | void Notify::setTitle(const QString &value) 149 | { 150 | title = value; 151 | } 152 | 153 | void Notify::setIcon(const QString &value) 154 | { 155 | icon = value; 156 | } 157 | -------------------------------------------------------------------------------- /notify.h: -------------------------------------------------------------------------------- 1 | #ifndef NOTIFY_H 2 | #define NOTIFY_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class Notify : public QWidget 10 | { 11 | Q_OBJECT 12 | public: 13 | explicit Notify(int displayTime, QWidget *parent = 0); 14 | 15 | void setIcon(const QString &value); 16 | 17 | void setTitle(const QString &value); 18 | 19 | void setBody(const QString &value); 20 | 21 | void setUrl(const QString &value); 22 | 23 | void showGriant(); 24 | 25 | Q_SIGNALS: 26 | void disappeared(); 27 | 28 | private: 29 | 30 | int displayTime; 31 | 32 | QString icon; 33 | QString title; 34 | QString body; 35 | QString url; 36 | 37 | QLabel *backgroundLabel; 38 | QLabel *iconLabel; 39 | QLabel *titleLabel; 40 | QLabel *bodyLabel; 41 | 42 | QPushButton *closeBtn; 43 | 44 | void hideGriant(); 45 | 46 | void mousePressEvent(QMouseEvent *event); 47 | }; 48 | 49 | #endif // NOTIFY_H 50 | -------------------------------------------------------------------------------- /notifymanager.cpp: -------------------------------------------------------------------------------- 1 |  2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "notifymanager.h" 9 | 10 | const int RIGHT = 10; 11 | const int BOTTOM = 10; 12 | 13 | const int HEIGHT = 60; 14 | const int WIDTH = 300; 15 | 16 | const int SPACE = 20; 17 | 18 | NotifyManager::NotifyManager(QObject *parent): QObject(parent), 19 | maxCount(6), 20 | displayTime(10 * 1000) 21 | { 22 | 23 | } 24 | 25 | void NotifyManager::notify(const QString &title, const QString &body, const QString &icon, const QString url) 26 | { 27 | dataQueue.enqueue(NotifyData(icon, title, body, url)); 28 | showNext(); 29 | } 30 | 31 | void NotifyManager::setMaxCount(int count) 32 | { 33 | maxCount = count; 34 | } 35 | 36 | void NotifyManager::setDisplayTime(int ms) 37 | { 38 | displayTime = ms; 39 | } 40 | 41 | // 调整所有提醒框的位置 42 | void NotifyManager::rearrange() 43 | { 44 | QDesktopWidget *desktop = QApplication::desktop(); 45 | QRect desktopRect = desktop->availableGeometry(); 46 | QPoint bottomRignt = desktopRect.bottomRight(); 47 | 48 | QList::iterator i; 49 | for (i = notifyList.begin(); i != notifyList.end(); ++i) { 50 | int index = notifyList.indexOf((*i)); 51 | 52 | QPoint pos = bottomRignt - QPoint(WIDTH + RIGHT, (HEIGHT + SPACE) * (index + 1) - SPACE + BOTTOM); 53 | QPropertyAnimation *animation = new QPropertyAnimation((*i), "pos", this); 54 | animation->setStartValue((*i)->pos()); 55 | animation->setEndValue(pos); 56 | animation->setDuration(300); 57 | animation->start(); 58 | 59 | connect(animation, &QPropertyAnimation::finished, this, [animation, this](){ 60 | animation->deleteLater(); 61 | }); 62 | } 63 | } 64 | 65 | 66 | void NotifyManager::showNext() 67 | { 68 | if(notifyList.size() >= maxCount || dataQueue.isEmpty()) { 69 | return; 70 | } 71 | 72 | NotifyData data = dataQueue.dequeue(); 73 | Notify *notify = new Notify(this->displayTime); 74 | notify->setIcon(data.icon); 75 | notify->setTitle(data.title); 76 | notify->setBody(data.body); 77 | notify->setUrl(data.url); 78 | 79 | notify->setFixedSize(WIDTH, HEIGHT); 80 | 81 | QDesktopWidget *desktop = QApplication::desktop(); 82 | QRect desktopRect = desktop->availableGeometry(); 83 | 84 | // 计算提醒框的位置 85 | QPoint bottomRignt = desktopRect.bottomRight(); 86 | QPoint pos = bottomRignt - QPoint(notify->width() + RIGHT, (HEIGHT + SPACE) * (notifyList.size() + 1) - SPACE + BOTTOM); 87 | 88 | 89 | notify->move(pos); 90 | notify->showGriant(); 91 | notifyList.append(notify); 92 | 93 | connect(notify, &Notify::disappeared, this, [notify, this](){ 94 | this->notifyList.removeAll(notify); 95 | this->rearrange(); 96 | 97 | // 如果列表是满的,重排完成后显示 98 | if(this->notifyList.size() == this->maxCount - 1){ 99 | QTimer::singleShot(300, this, [this]{ 100 | this->showNext(); 101 | }); 102 | } else { 103 | this->showNext(); 104 | } 105 | notify->deleteLater(); 106 | }); 107 | } 108 | 109 | -------------------------------------------------------------------------------- /notifymanager.h: -------------------------------------------------------------------------------- 1 | #ifndef NOTIFYMANAGER_H 2 | #define NOTIFYMANAGER_H 3 | 4 | #include 5 | #include 6 | 7 | #include "notify.h" 8 | 9 | class NotifyManager : public QObject 10 | { 11 | Q_OBJECT 12 | public: 13 | explicit NotifyManager( QObject *parent = 0); 14 | 15 | void notify(const QString &title, const QString &body, const QString &icon, const QString url); 16 | void setMaxCount(int count); 17 | void setDisplayTime(int ms); 18 | 19 | private: 20 | class NotifyData { 21 | public: 22 | NotifyData(const QString &icon, const QString &title, const QString &body, const QString url): 23 | icon(icon), 24 | title(title), 25 | body(body), 26 | url(url) 27 | { 28 | } 29 | 30 | QString icon; 31 | QString title; 32 | QString body; 33 | QString url; 34 | }; 35 | 36 | void rearrange(); 37 | void showNext(); 38 | 39 | QQueue dataQueue; 40 | QList notifyList; 41 | int maxCount; 42 | int displayTime; 43 | }; 44 | 45 | #endif // NOTIFYMANAGER_H 46 | -------------------------------------------------------------------------------- /qtnotify.pro: -------------------------------------------------------------------------------- 1 | QT += core gui 2 | 3 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 4 | 5 | TARGET = qtnotify 6 | TEMPLATE = app 7 | 8 | CONFIG+=no_keywords 9 | CONFIG+=c++11 10 | 11 | HEADERS += \ 12 | notify.h \ 13 | notifymanager.h \ 14 | mainwindow.h 15 | 16 | SOURCES += \ 17 | notify.cpp \ 18 | notifymanager.cpp \ 19 | main.cpp \ 20 | mainwindow.cpp 21 | 22 | RESOURCES += \ 23 | res.qrc 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /res.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | img/message.png 4 | 5 | 6 | --------------------------------------------------------------------------------