fix tricky regression noticed by Vyacheslav Tokarev on Google Reader.
[kdelibs.git] / kdeui / util / knotification.cpp
blobb06def463c0168405a8c4df47d7b030afb130158
1 /* This file is part of the KDE libraries
2 Copyright (C) 2005-2006 Olivier Goffart <ogoffart at kde.org>
4 code from KNotify/KNotifyClient
5 Copyright (c) 1997 Christian Esken (esken@kde.org)
6 2000 Charles Samuels (charles@kde.org)
7 2000 Stefan Schimanski (1Stein@gmx.de)
8 2000 Matthias Ettrich (ettrich@kde.org)
9 2000 Waldo Bastian <bastian@kde.org>
10 2000-2003 Carsten Pfeiffer <pfeiffer@kde.org>
11 2005 Allan Sandfeld Jensen <kde@carewolf.com>
13 This library is free software; you can redistribute it and/or
14 modify it under the terms of the GNU Library General Public
15 License version 2 as published by the Free Software Foundation.
17 This library is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 Library General Public License for more details.
22 You should have received a copy of the GNU Library General Public License
23 along with this library; see the file COPYING.LIB. If not, write to
24 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25 Boston, MA 02110-1301, USA.
28 #include "knotification.h"
29 #include "knotificationmanager_p.h"
31 #include <kmessagebox.h>
32 #include <klocale.h>
33 #include <kiconloader.h>
34 #include <kconfig.h>
35 #include <kpassivepopup.h>
36 #include <kdialog.h>
37 #include <kmacroexpander.h>
38 #include <kwindowsystem.h>
39 #include <kdebug.h>
40 #include <kvbox.h>
41 #include <kapplication.h>
43 #include <QMap>
44 #include <QPixmap>
45 #include <QPointer>
46 #include <QLabel>
47 #include <QTimer>
48 #include <QTabWidget>
49 #include <QFile>
50 #include <QStringList>
51 #include <QTextStream>
52 #include <QDateTime>
53 #include <QDBusError>
55 struct KNotification::Private
57 QString eventId;
58 int id;
59 int ref;
61 QWidget *widget;
62 QString text;
63 QStringList actions;
64 QPixmap pixmap;
65 ContextList contexts;
66 NotificationFlags flags;
67 KComponentData componentData;
69 QTimer updateTimer;
71 Private() : id(0), ref(1), widget(0l) {}
72 /**
73 * recursive function that raise the widget. @p w
75 * @see raiseWidget()
77 static void raiseWidget(QWidget *w);
80 KNotification::KNotification(const QString& eventId, QWidget *parent, const NotificationFlags& flags) :
81 QObject(parent) , d(new Private)
83 d->eventId=eventId;
84 d->flags=flags;
85 setWidget(parent);
86 connect(&d->updateTimer,SIGNAL(timeout()), this, SLOT(update()));
87 d->updateTimer.setSingleShot(true);
88 d->updateTimer.setInterval(100);
91 KNotification::~KNotification()
93 kDebug( 299 ) << d->id;
94 if(d ->id > 0)
95 KNotificationManager::self()->close( d->id );
96 delete d;
99 QString KNotification::eventId() const
101 return d->eventId;
104 QString KNotification::text() const
106 return d->text;
109 QWidget *KNotification::widget() const
111 return d->widget;
114 void KNotification::setWidget(QWidget *wid)
116 d->widget = wid;
117 setParent(wid);
118 if ( wid && d->flags & CloseWhenWidgetActivated ) {
119 wid->installEventFilter(this);
123 void KNotification::setText(const QString &text)
125 d->text=text;
126 if(d->id > 0)
127 d->updateTimer.start();
130 QPixmap KNotification::pixmap() const
132 return d->pixmap;
135 void KNotification::setPixmap(const QPixmap &pix)
137 d->pixmap=pix;
138 if(d->id > 0)
139 d->updateTimer.start();
142 QStringList KNotification::actions() const
144 return d->actions;
147 void KNotification::setActions(const QStringList& as )
149 d->actions=as;
150 if(d->id > 0)
151 d->updateTimer.start();
154 KNotification::ContextList KNotification::contexts() const
156 return d->contexts;
159 void KNotification::setContexts( const KNotification::ContextList &contexts)
161 d->contexts=contexts;
164 void KNotification::addContext( const KNotification::Context & context)
166 d->contexts << context;
169 void KNotification::addContext( const QString & context_key, const QString & context_value )
171 d->contexts << qMakePair( context_key , context_value );
174 KNotification::NotificationFlags KNotification::flags() const
176 return d->flags;
179 void KNotification::setFlags(const NotificationFlags & flags)
181 d->flags=flags;
185 void KNotification::setComponentData(const KComponentData &c)
187 d->componentData = c;
190 void KNotification::activate(unsigned int action)
192 switch (action)
194 case 0:
195 emit activated();
196 break;
197 case 1:
198 emit action1Activated();
199 break;
200 case 2:
201 emit action2Activated();
202 break;
203 case 3:
204 emit action3Activated();
205 break;
207 emit activated(action);
208 if(d->id != -1)
209 deleteLater();
210 d->id = -2;
214 void KNotification::close()
216 kDebug( 299 ) << d->id;
217 if(d->id >= 0)
218 KNotificationManager::self()->close( d->id );
219 if(d->id != -1) //=-1 mean still waiting for receiving the id
220 deleteLater();
221 d->id = -2;
222 emit closed();
226 void KNotification::raiseWidget()
228 if ( !d->widget ) {
229 return;
232 Private::raiseWidget( d->widget );
236 void KNotification::Private::raiseWidget(QWidget *w)
238 //TODO this function is far from finished.
239 if(w->isTopLevel())
241 w->raise();
242 #if defined(Q_WS_WIN) || defined(Q_WS_MAC)
243 w->activateWindow();
244 #else
245 KWindowSystem::activateWindow( w->winId() );
246 #endif
248 else
250 QWidget *pw=w->parentWidget();
251 raiseWidget(pw);
253 if( QTabWidget *tab_widget=qobject_cast<QTabWidget*>(pw))
255 tab_widget->setCurrentIndex(tab_widget->indexOf(w));
261 KNotification *KNotification::event( const QString& eventid , const QString& text,
262 const QPixmap& pixmap, QWidget *widget, const NotificationFlags &flags, const KComponentData &componentData)
264 KNotification *notify=new KNotification(eventid, widget, flags);
265 notify->setText(text);
266 notify->setPixmap(pixmap);
267 notify->setComponentData(componentData);
269 QTimer::singleShot(0,notify,SLOT(sendEvent()));
271 return notify;
275 KNotification *KNotification::event( StandardEvent eventid , const QString& text,
276 const QPixmap& pixmap, QWidget *widget, const NotificationFlags &flags)
278 QString message;
279 switch ( eventid ) {
280 case Warning:
281 message = QLatin1String("warning");
282 break;
283 case Error:
284 message = QLatin1String("fatalerror");
285 break;
286 case Catastrophe:
287 message = QLatin1String("catastrophe");
288 break;
289 case Notification: // fall through
290 default:
291 message = QLatin1String("notification");
292 break;
294 return event( message, text, pixmap, widget , flags | DefaultEvent );
297 void KNotification::ref()
299 d->ref++;
302 void KNotification::deref()
304 d->ref--;
305 if(d->ref==0)
306 close();
309 void KNotification::beep( const QString & reason, QWidget * widget )
311 event( QLatin1String("beep"), reason, QPixmap(), widget , CloseOnTimeout | DefaultEvent );
314 void KNotification::sendEvent()
316 if(d->id<=0)
318 QString appname;
320 if(d->flags & DefaultEvent)
321 appname = QLatin1String("kde");
322 else if(d->componentData.isValid()) {
323 appname = d->componentData.componentName();
324 } else {
325 appname = KGlobal::mainComponent().componentName();
328 if(!(d->flags & Persistent))
330 QTimer::singleShot(6*1000, this, SLOT(close()));
332 if (KNotificationManager::self()->notify( this , d->pixmap , d->actions , d->contexts , appname ))
333 d->id = -1;
335 else
337 KNotificationManager::self()->reemit(this , d->id );
341 void KNotification::slotReceivedId(int id)
343 if(d->id == -2) //we are already closed
345 KNotificationManager::self()->close( id, /*force=*/ true );
346 deleteLater();
347 return;
349 d->id=id;
350 kDebug(299) << id;
351 if(d->id>0)
353 KNotificationManager::self()->insert(this,d->id);
355 else
357 //if there is no presentation, delete the object
358 QTimer::singleShot(0, this, SLOT(deref()));
363 void KNotification::slotReceivedIdError(const QDBusError& error)
365 if(d->id == -2) //we are already closed
367 deleteLater();
368 return;
370 kWarning(299) << "Error while contacting notify daemon" << error.message();
371 d->id = -3;
372 QTimer::singleShot(0, this, SLOT(deref()));
376 void KNotification::update()
378 KNotificationManager::self()->update(this, d->id);
381 bool KNotification::eventFilter( QObject * watched, QEvent * event )
383 if( watched == d->widget )
385 if( event->type() == QEvent::WindowActivate )
387 if( d->flags & CloseWhenWidgetActivated )
388 QTimer::singleShot(500, this, SLOT(close()));
390 //kDebug(299) << event->type();
393 return false;
397 #include "knotification.moc"