less Q3 (remove a lot of unused Q3 headers, port small things)
[kdenetwork.git] / kopete / libkopete / knotification.cpp
blob064b96cea60a4545388ae0c6e7ebbdf693e51ebd
1 /* This file is part of the KDE libraries
2 Copyright (C) 2005 Olivier Goffart <ogoffart @ 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., 59 Temple Place - Suite 330,
25 Boston, MA 02111-1307, USA.
28 #include "knotification.h"
29 #include "knotificationmanager.h"
31 #include <kmessagebox.h>
32 #include <klocale.h>
33 #include <kiconloader.h>
34 #include <kconfig.h>
35 #include <kpassivepopup.h>
36 #include <kactivelabel.h>
37 #include <kprocess.h>
38 #include <kdialog.h>
39 #include <kmacroexpander.h>
40 #include <kwin.h>
41 #include <kdebug.h>
43 #include <kvbox.h>
44 #include <QMap>
45 #include <QPixmap>
46 #include <dcopclient.h>
47 #include <qpointer.h>
48 #include <qlabel.h>
49 #include <qtimer.h>
50 #include <qtabwidget.h>
51 #include <kapplication.h>
52 #include <qfile.h>
53 #include <qtextstream.h>
54 #include <QDateTime>
55 #include <QMetaObject>
56 #include <QMetaEnum>
58 //TODO, make the KNotification aware of the systemtray.
59 #include "kopeteuiglobal.h"
60 static WId checkWinId( const QString &/*appName*/, WId senderWinId )
62 if(senderWinId==0)
63 senderWinId=Kopete::UI::Global::sysTrayWId();
65 return senderWinId;
69 struct KNotification::Private
71 QWidget *widget;
72 QString text;
73 QStringList actions;
74 int level;
75 QString eventId;
76 QString title;
77 unsigned int id;
79 int ref;
81 Private() : widget(0l) , id(0), ref(1) {}
84 KNotification::KNotification(QObject *parent) :
85 QObject(parent) , d(new Private)
89 KNotification::~KNotification()
91 if(d ->id != 0)
92 KNotificationManager::self()->remove( d->id );
93 delete d;
96 QString KNotification::eventId() const
98 return d->eventId;
101 QString KNotification::text() const
103 return d->text;
106 QString KNotification::title() const
108 return d->title;
111 QWidget *KNotification::widget() const
113 return d->widget;
117 void KNotification::notifyByExecute(const QString &command, const QString& event,
118 const QString& fromApp, const QString& text,
119 int winId, int eventId)
121 if (!command.isEmpty()) {
122 // kdDebug() << "executing command '" << command << "'" << endl;
123 QHash<QChar,QString> subst;
124 subst.insert( 'e', event );
125 subst.insert( 'a', fromApp );
126 subst.insert( 's', text );
127 subst.insert( 'w', QString::number( winId ));
128 subst.insert( 'i', QString::number( eventId ));
129 QString execLine = KMacroExpander::expandMacrosShellQuote( command, subst );
130 if ( execLine.isEmpty() )
131 execLine = command; // fallback
133 KProcess p;
134 p.setUseShell(true);
135 p << execLine;
136 p.start(KProcess::DontCare);
137 // return true;
139 // return false;
143 void KNotification::notifyByMessagebox()
145 // ignore empty messages
146 if ( d->text.isEmpty() )
147 return;
149 QStringList actions=d->actions;
150 WId winId=d->widget ? d->widget->topLevelWidget()->winId() : 0;
152 if( actions.count() == 0)
154 // display message box for specified event level
155 switch( d->level )
157 case Warning:
158 KMessageBox::sorryWId( winId, d->text, i18n( "Warning" ) , false );
159 break;
160 case Error:
161 KMessageBox::errorWId( winId, d->text, i18n( "Error" ) , false );
162 break;
163 case Catastrophe:
164 KMessageBox::errorWId( winId, d->text, i18n( "Catastrophe!" ) , false );
165 break;
166 default:
167 case Notification:
168 KMessageBox::informationWId( winId, d->text, i18n( "Notification" ) , 0 , false );
169 break;
173 else
174 { //we may show the specific action button
175 int result=0;
176 QPointer<KNotification> _this=this; //this can be deleted
177 switch( d->level )
179 default:
180 case Notification:
181 result = KMessageBox::questionYesNo(d->widget, d->text, i18n( "Notification" ), actions[0], KStdGuiItem::cancel(), QString::null, false );
182 break;
183 case Warning:
184 result = KMessageBox::warningYesNo( d->widget, d->text, i18n( "Warning" ), actions[0], KStdGuiItem::cancel(), QString::null, false );
185 break;
186 case Error:
187 result = KMessageBox::warningYesNo( d->widget, d->text, i18n( "Error" ), actions[0], KStdGuiItem::cancel(), QString::null, false );
188 break;
189 case Catastrophe:
190 result = KMessageBox::warningYesNo( d->widget, d->text, i18n( "Catastrophe!" ), actions[0], KStdGuiItem::cancel(), QString::null, false );
191 break;
193 if(result==KMessageBox::Yes && _this)
195 activate(0);
200 void KNotification::notifyByPassivePopup(const QPixmap &pix, const QString& sound )
202 ref();
203 d->id=KNotificationManager::self()->notify( this , pix , d->actions , sound );
204 kdDebug() << k_funcinfo << d->id << endl;
208 bool KNotification::notifyByLogfile(const QString &text, const QString &file)
210 // ignore empty messages
211 if ( text.isEmpty() )
212 return true;
214 // open file in append mode
215 QFile logFile(file);
216 if ( !logFile.open(QIODevice::WriteOnly | QIODevice::Append) )
217 return false;
219 // append msg
220 QTextStream strm( &logFile );
221 strm << "- KNotify " << QDateTime::currentDateTime().toString() << ": ";
222 strm << text << endl;
224 // close file
225 logFile.close();
226 return true;
229 bool KNotification::notifyByStderr(const QString &text)
231 // ignore empty messages
232 if ( text.isEmpty() )
233 return true;
235 // open stderr for output
236 QTextStream strm( stderr, QIODevice::WriteOnly );
238 // output msg
239 strm << "KNotify " << QDateTime::currentDateTime().toString() << ": ";
240 strm << text << endl;
242 return true;
245 bool KNotification::notifyByTaskbar( WId win )
247 if( win == 0 )
248 return false;
249 KWin::demandAttention( win );
250 return true;
255 bool KNotification::notifyBySound( const QString &sound, const QString &appname, int eventId )
257 return KNotificationManager::self()->notifyBySound( sound, appname, eventId );
261 void KNotification::slotPopupLinkClicked(const QString &adr)
263 unsigned int action=adr.toUInt();
264 if(action==0)
265 return;
267 activate(action);
272 void KNotification::activate(unsigned int action)
274 if(action==0)
275 emit activated();
276 emit activated(action);
277 kdDebug() << k_funcinfo << d->id << " " << action << endl;
278 deleteLater();
282 void KNotification::close()
284 if(d->id != 0)
285 KNotificationManager::self()->close( d->id );
286 emit closed();
287 deleteLater();
291 void KNotification::raiseWidget()
293 if(!d->widget)
294 return;
296 raiseWidget(d->widget);
300 void KNotification::raiseWidget(QWidget *w)
302 //TODO this funciton is far from finished.
303 if(w->isTopLevel())
305 w->raise();
306 KWin::activateWindow( w->winId() );
308 else
310 QWidget *pw=w->parentWidget();
311 raiseWidget(pw);
313 if( QTabWidget *tab_widget=dynamic_cast<QTabWidget*>(pw))
315 tab_widget->showPage(w);
321 //to workaround the fact that , i not allowed in a macro
322 #define VIRGULE ,
324 //this is temporary code
325 class ConfigHelper
327 public:
328 KConfig eventsfile,configfile;
329 KNotification::ContextList contexts;
330 QString eventid;
331 ConfigHelper(const QString &appname, const KNotification::ContextList &_contexts , const QString &_eventid)
332 : eventsfile( appname+QString::fromAscii( "/eventsrc" ), true, false, "data"),
333 configfile( appname+QString::fromAscii( ".eventsrc" ), true, false),
334 contexts(_contexts) , eventid(_eventid)
337 QString readEntry(const QString& entry , bool path=false)
339 foreach( QPair<QString VIRGULE QString> context , contexts )
341 const QString group="Event/" + eventid + "/" + context.first + "/" + context.second;
342 if(configfile.hasGroup( group ) )
344 configfile.setGroup(group);
345 QString p=path ? configfile.readPathEntry(entry) : configfile.readEntry(entry);
346 kdDebug() << k_funcinfo << "group=" << group << " value=" << p << " isNull=" << p.isNull() << endl;
347 if(!p.isNull())
348 return p;
351 const QString group="Event/" + eventid ;
352 kdDebug() << k_funcinfo << "group=" << group << endl;
353 if(configfile.hasGroup( group ) )
355 configfile.setGroup(group);
356 QString p=path ? configfile.readPathEntry(entry) : configfile.readEntry(entry);
357 kdDebug() << k_funcinfo << "bib group=" << group << " value=" << p << " isNull=" << p.isNull() << endl;
358 if(!p.isNull())
359 return p;
361 if(eventsfile.hasGroup( group ) )
363 eventsfile.setGroup(group);
364 QString p=path ? eventsfile.readPathEntry(entry) : eventsfile.readEntry(entry);
365 kdDebug() << k_funcinfo << "bob group=" << group << " value=" << p << " isNull=" << p.isNull() << endl;
366 if(!p.isNull())
367 return p;
369 return QString::null;
376 KNotification *KNotification::event( const QString& eventid , const QString& text,
377 const QPixmap& pixmap, QWidget *widget, const QStringList &actions,
378 ContextList contexts, unsigned int flags)
380 int level=Notification;
381 QString appname = QString::fromAscii(kapp->instanceName());
382 KNotification *notify=new KNotification(widget);
383 notify->d->widget=widget;
384 notify->d->text=text;
385 notify->d->actions=actions;
386 notify->d->level=level;
387 notify->d->eventId=eventid;
389 WId winId=widget ? widget->topLevelWidget()->winId() : 0;
391 // get config file
392 ConfigHelper config( appname, contexts, eventid );
393 config.eventsfile.setGroup("Global");
394 notify->d->title=config.eventsfile.readEntry( "Comment", appname );
396 int n = notify->metaObject()->indexOfEnumerator( "NotifyPresentation" );
397 QString presentstring=config.readEntry("Action");
398 int present= notify->metaObject()->enumerator(n).keysToValue( presentstring.toLatin1() );
399 if(present == -1)
400 present=0;
402 kdDebug() << k_funcinfo << "Action: " << presentstring << " - " << present << endl;
404 // get default event level
405 if( present & Messagebox )
406 level = config.readEntry( "level" ).toUInt();
408 if ( present & PassivePopup )
410 notify->notifyByPassivePopup( pixmap , (present & Sound) ? config.readEntry( "sound" , true) : QString::null );
412 else if ( present & Sound ) // && QFile(sound).isReadable()
413 notify->notifyBySound( config.readEntry( "sound" , true), kapp->instanceName(), 0 );
417 if ( present & Messagebox )
419 QTimer::singleShot(0,notify,SLOT(notifyByMessagebox()));
421 else //not a message box (because closing the event when a message box is there is suicide)
422 if(flags & CloseOnTimeout)
424 QTimer::singleShot(6*1000, notify, SLOT(close()));
426 if ( present & Execute )
428 notify->notifyByExecute(config.readEntry( "commandline" ), QString::null,appname,text, winId, 0 );
432 if ( present & Logfile ) // && QFile(file).isWritable()
433 notify->notifyByLogfile( text, config.readEntry( "logfile" , true) );
435 if ( present & Stderr )
436 notify->notifyByStderr( text );
438 if ( present & Taskbar )
439 notify->notifyByTaskbar( checkWinId( kapp->instanceName(), winId ));
441 //after a small timeout, the notification will be deleted if all presentation are finished
442 QTimer::singleShot(1000, notify, SLOT(deref()));
444 #if 0 //TODO
445 QByteArray qbd;
446 QDataStream ds(&qbd, QIODevice::WriteOnly);
447 ds << event << fromApp << text << sound << file << present << level
448 << winId << eventId;
449 emitDCOPSignal("notifySignal(QString,QString,QString,QString,QString,int,int,int,int)", qbd);
450 #endif
452 return notify;
455 void KNotification::ref()
457 d->ref++;
460 void KNotification::deref()
462 d->ref--;
463 if(d->ref==0)
464 close();
467 #include "knotification.moc"