/* This file is part of the KDE libraries Copyright (C) 2005-2006 Olivier Goffart code from KNotify/KNotifyClient Copyright (c) 1997 Christian Esken (esken@kde.org) 2000 Charles Samuels (charles@kde.org) 2000 Stefan Schimanski (1Stein@gmx.de) 2000 Matthias Ettrich (ettrich@kde.org) 2000 Waldo Bastian 2000-2003 Carsten Pfeiffer 2005 Allan Sandfeld Jensen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "knotification.h" #include "knotificationmanager_p.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct KNotification::Private { QString eventId; int id; int ref; QWidget *widget; QString title; QString text; QStringList actions; QPixmap pixmap; ContextList contexts; NotificationFlags flags; KComponentData componentData; QTimer updateTimer; bool needUpdate; Private() : id(0), ref(1), widget(0l), needUpdate(false) {} /** * recursive function that raise the widget. @p w * * @see raiseWidget() */ static void raiseWidget(QWidget *w); }; KNotification::KNotification(const QString& eventId, QWidget *parent, const NotificationFlags& flags) : QObject(parent) , d(new Private) { d->eventId=eventId; d->flags=flags; setWidget(parent); connect(&d->updateTimer,SIGNAL(timeout()), this, SLOT(update())); d->updateTimer.setSingleShot(true); d->updateTimer.setInterval(100); } KNotification::KNotification( const QString& eventId, const NotificationFlags& flags, QObject *parent) : QObject(parent), d(new Private) { d->eventId=eventId; d->flags=flags; connect(&d->updateTimer,SIGNAL(timeout()), this, SLOT(update())); d->updateTimer.setSingleShot(true); d->updateTimer.setInterval(100); } KNotification::~KNotification() { if(d ->id > 0) KNotificationManager::self()->close( d->id ); delete d; } QString KNotification::eventId() const { return d->eventId; } QString KNotification::title() const { return d->title; } QString KNotification::text() const { return d->text; } QWidget *KNotification::widget() const { return d->widget; } void KNotification::setWidget(QWidget *wid) { d->widget = wid; setParent(wid); if ( wid && d->flags & CloseWhenWidgetActivated ) { wid->installEventFilter(this); } } void KNotification::setTitle(const QString &title) { d->needUpdate = true; d->title = title; if(d->id > 0) d->updateTimer.start(); } void KNotification::setText(const QString &text) { d->needUpdate = true; d->text=text; if(d->id > 0) d->updateTimer.start(); } QPixmap KNotification::pixmap() const { return d->pixmap; } void KNotification::setPixmap(const QPixmap &pix) { d->needUpdate = true; d->pixmap=pix; if(d->id > 0) d->updateTimer.start(); } QStringList KNotification::actions() const { return d->actions; } void KNotification::setActions(const QStringList& as ) { d->needUpdate = true; d->actions=as; if(d->id > 0) d->updateTimer.start(); } KNotification::ContextList KNotification::contexts() const { return d->contexts; } void KNotification::setContexts( const KNotification::ContextList &contexts) { d->contexts=contexts; } void KNotification::addContext( const KNotification::Context & context) { d->contexts << context; } void KNotification::addContext( const QString & context_key, const QString & context_value ) { d->contexts << qMakePair( context_key , context_value ); } KNotification::NotificationFlags KNotification::flags() const { return d->flags; } void KNotification::setFlags(const NotificationFlags & flags) { d->flags=flags; } void KNotification::setComponentData(const KComponentData &c) { d->componentData = c; } void KNotification::activate(unsigned int action) { switch (action) { case 0: emit activated(); break; case 1: emit action1Activated(); break; case 2: emit action2Activated(); break; case 3: emit action3Activated(); break; } emit activated(action); if(d->id != -1) deleteLater(); d->id = -2; } void KNotification::close() { if(d->id >= 0) KNotificationManager::self()->close( d->id ); if(d->id != -1) //=-1 mean still waiting for receiving the id deleteLater(); d->id = -2; emit closed(); } void KNotification::raiseWidget() { if ( !d->widget ) { return; } Private::raiseWidget( d->widget ); } void KNotification::Private::raiseWidget(QWidget *w) { //TODO this function is far from finished. if(w->isTopLevel()) { w->raise(); KWindowSystem::activateWindow( w->winId() ); } else { QWidget *pw=w->parentWidget(); raiseWidget(pw); if( QTabWidget *tab_widget=qobject_cast(pw)) { tab_widget->setCurrentIndex(tab_widget->indexOf(w)); } } } KNotification *KNotification::event( const QString& eventid , const QString& title, const QString& text, const QPixmap& pixmap, QWidget *widget, const NotificationFlags &flags, const KComponentData &componentData) { KNotification *notify=new KNotification(eventid, widget, flags); notify->setTitle(title); notify->setText(text); notify->setPixmap(pixmap); notify->setComponentData(componentData); QTimer::singleShot(0,notify,SLOT(sendEvent())); return notify; } KNotification *KNotification::event( const QString& eventid , const QString& text, const QPixmap& pixmap, QWidget *widget, const NotificationFlags &flags, const KComponentData &componentData) { return event( eventid, QString(), text, pixmap, widget, flags, componentData ); } KNotification *KNotification::event( StandardEvent eventid , const QString& title, const QString& text, const QPixmap& pixmap, QWidget *widget, const NotificationFlags &flags) { QString message; switch ( eventid ) { case Warning: message = QLatin1String("warning"); break; case Error: message = QLatin1String("fatalerror"); break; case Catastrophe: message = QLatin1String("catastrophe"); break; case Notification: // fall through default: message = QLatin1String("notification"); break; } return event( message, title, text, pixmap, widget , flags | DefaultEvent ); } KNotification *KNotification::event( StandardEvent eventid , const QString& text, const QPixmap& pixmap, QWidget *widget, const NotificationFlags &flags) { return event( eventid, QString(), text, pixmap, widget , flags ); } void KNotification::ref() { d->ref++; } void KNotification::deref() { d->ref--; if(d->ref==0) close(); } void KNotification::beep( const QString & reason, QWidget * widget ) { event( QLatin1String("beep"), reason, QPixmap(), widget , CloseOnTimeout | DefaultEvent ); } void KNotification::sendEvent() { d->needUpdate = false; if(d->id == 0) { QString appname; if(d->flags & DefaultEvent) appname = QLatin1String("kde"); else if(d->componentData.isValid()) { appname = d->componentData.componentName(); } else { appname = KGlobal::mainComponent().componentName(); } if (KNotificationManager::self()->notify( this , d->pixmap , d->actions , d->contexts , appname )) d->id = -1; } else if(d->id > 0) { KNotificationManager::self()->reemit(this , d->id ); } else if(d->id == -1) { //schedule an update. d->needUpdate = true; } } void KNotification::slotReceivedId(int id) { if(d->id == -2) //we are already closed { KNotificationManager::self()->close( id, /*force=*/ true ); deleteLater(); return; } d->id=id; if(d->id>0) { KNotificationManager::self()->insert(this,d->id); if (d->needUpdate) sendEvent(); } else { //if there is no presentation, delete the object QTimer::singleShot(0, this, SLOT(deref())); } } void KNotification::slotReceivedIdError(const QDBusError& error) { if(d->id == -2) //we are already closed { deleteLater(); return; } kWarning(299) << "Error while contacting notify daemon" << error.message(); d->id = -3; QTimer::singleShot(0, this, SLOT(deref())); } void KNotification::update() { KNotificationManager::self()->update(this, d->id); } bool KNotification::eventFilter( QObject * watched, QEvent * event ) { if( watched == d->widget ) { if( event->type() == QEvent::WindowActivate ) { if( d->flags & CloseWhenWidgetActivated ) QTimer::singleShot(500, this, SLOT(close())); } //kDebug(299) << event->type(); } return false; } #include "moc_knotification.cpp"