1
/***************************************************************************
2
* notificationstack.cpp *
3
* Copyright (C) 2010 Marco Martin <notmart@gmail.com> *
5
* This program is free software; you can redistribute it and/or modify *
6
* it under the terms of the GNU General Public License as published by *
7
* the Free Software Foundation; either version 2 of the License, or *
8
* (at your option) any later version. *
10
* This program is distributed in the hope that it will be useful, *
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13
* GNU General Public License for more details. *
15
* You should have received a copy of the GNU General Public License *
16
* along with this program; if not, write to the *
17
* Free Software Foundation, Inc., *
18
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
19
***************************************************************************/
21
#include "notificationstack.h"
22
#include "../core/notification.h"
23
#include "notificationwidget.h"
25
#include <QGraphicsLinearLayout>
29
#include <KGlobalSettings>
31
#include <Plasma/FrameSvg>
32
#include <Plasma/Dialog>
34
NotificationStack::NotificationStack(QGraphicsItem *parent)
35
: QGraphicsWidget(parent),
39
m_mainLayout = new QGraphicsLinearLayout(Qt::Vertical, this);
40
m_canDismissTimer = new QTimer(this);
41
m_canDismissTimer->setSingleShot(true);
43
m_delayedRemoveTimer = new QTimer(this);
44
m_delayedRemoveTimer->setSingleShot(true);
45
connect(m_delayedRemoveTimer, SIGNAL(timeout()), this, SLOT(popNotification()));
47
setAcceptsHoverEvents(true);
50
NotificationStack::~NotificationStack()
54
void NotificationStack::addNotification(Notification *notification)
56
m_canDismissTimer->start(1000);
57
connect(notification, SIGNAL(notificationDestroyed(Notification *)), this, SLOT(removeNotification(Notification *)), Qt::UniqueConnection);
58
connect(notification, SIGNAL(expired(Notification *)), this, SLOT(delayedRemoveNotification(Notification *)), Qt::UniqueConnection);
59
connect(notification, SIGNAL(changed(Notification *)), this, SLOT(notificationChanged(Notification *)), Qt::UniqueConnection);
61
NotificationWidget *notificationWidget = new NotificationWidget(notification, this);
62
notificationWidget->installEventFilter(this);
63
notificationWidget->setAcceptsHoverEvents(this);
64
connect(notificationWidget, SIGNAL(actionTriggered(Notification *)), this, SLOT(removeNotification(Notification *)));
66
m_notificationWidgets[notification] = notificationWidget;
67
m_notifications.append(notification);
69
if (m_notifications.size() > 1) {
70
notificationWidget->setCollapsed(true, false);
72
m_currentNotificationWidget = notificationWidget;
75
if (m_notifications.size() > m_size) {
78
//try to kill the oldest notification of the same app
79
foreach (Notification *notif, m_notifications) {
80
if (notif->applicationName() == notification->applicationName()) {
81
m_notificationWidgets[notif]->deleteLater();
82
m_notificationWidgets.remove(notif);
83
m_notifications.removeAll(notif);
88
//or kill the oldest one
90
Notification *notif = m_notifications.first();
91
m_notificationWidgets[notif]->deleteLater();
92
m_notificationWidgets.remove(notif);
93
m_notifications.pop_front();
97
m_mainLayout->insertItem(0, notificationWidget);
98
m_mainLayout->activate();
100
resize(size().width(), effectiveSizeHint(Qt::MinimumSize).height());
101
emit updateRequested();
104
void NotificationStack::notificationChanged(Notification *notification)
106
//if it was gone away put in on the stack again
107
if (!m_notificationWidgets.contains(notification)) {
108
addNotification(notification);
110
emit showRequested();
113
void NotificationStack::removeNotification(Notification *notification)
115
NotificationWidget *nw = m_notificationWidgets.value(notification);
119
m_mainLayout->removeItem(nw);
120
m_notificationWidgets.remove(notification);
121
m_notifications.removeAll(notification);
123
if (m_notifications.count() > 0) {
124
setCurrentNotification(m_notifications.first());
127
if (m_notifications.count() == 0) {
132
resize(size().width(), sizeHint(Qt::MinimumSize, QSizeF()).height());
133
emit updateRequested();
136
void NotificationStack::delayedRemoveNotification(Notification *notification)
138
m_notificationsToRemove.append(notification);
140
m_delayedRemoveTimer->start(1000);
144
void NotificationStack::setCurrentNotification(Notification *notification)
146
if (m_notificationWidgets.contains(notification)) {
147
if (m_currentNotificationWidget) {
148
m_currentNotificationWidget.data()->setCollapsed(true);
150
m_currentNotificationWidget = m_notificationWidgets.value(notification);
151
m_currentNotificationWidget.data()->setCollapsed(false);
155
void NotificationStack::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
160
m_delayedRemoveTimer->stop();
163
void NotificationStack::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
167
m_underMouse = false;
168
m_delayedRemoveTimer->start(1000);
171
void NotificationStack::mousePressEvent(QGraphicsSceneMouseEvent *event)
176
void NotificationStack::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
180
if (!m_canDismissTimer->isActive() &&
181
QPointF(event->buttonDownScenePos(event->button()) - event->scenePos()).manhattanLength() < KGlobalSettings::dndEventDelay()) {
182
emit hideRequested();
186
NotificationWidget *NotificationStack::currentNotificationWidget() const
188
if (m_currentNotificationWidget) {
189
return m_currentNotificationWidget.data();
197
bool NotificationStack::eventFilter(QObject *watched, QEvent *event)
199
NotificationWidget *nw = qobject_cast<NotificationWidget *>(watched);
205
if (event->type() == QEvent::GraphicsSceneHoverEnter) {
206
if (m_currentNotificationWidget && m_currentNotificationWidget.data() == nw) {
208
} else if (m_currentNotificationWidget) {
209
m_currentNotificationWidget.data()->setCollapsed(true);
211
nw->setCollapsed(false);
212
m_currentNotificationWidget = nw;
213
m_canDismissTimer->start(1000);
214
} else if (event->type() == QEvent::GraphicsSceneMove) {
215
emit updateRequested();
222
void NotificationStack::popNotification()
224
if (m_notificationsToRemove.isEmpty()) {
228
Notification *notif = m_notificationsToRemove.first();
229
removeNotification(notif);
230
m_notificationsToRemove.pop_front();
231
m_delayedRemoveTimer->start(1000);
235
#include "notificationstack.moc"