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>
33 #include <kiconloader.h>
35 #include <kpassivepopup.h>
36 #include <kactivelabel.h>
39 #include <kmacroexpander.h>
46 #include <dcopclient.h>
50 #include <qtabwidget.h>
51 #include <kapplication.h>
53 #include <qtextstream.h>
55 #include <QMetaObject>
58 //TODO, make the KNotification aware of the systemtray.
59 #include "kopeteuiglobal.h"
60 static WId
checkWinId( const QString
&/*appName*/, WId senderWinId
)
63 senderWinId
=Kopete::UI::Global::sysTrayWId();
69 struct KNotification::Private
81 Private() : widget(0l) , id(0), ref(1) {}
84 KNotification::KNotification(QObject
*parent
) :
85 QObject(parent
) , d(new Private
)
89 KNotification::~KNotification()
92 KNotificationManager::self()->remove( d
->id
);
96 QString
KNotification::eventId() const
101 QString
KNotification::text() const
106 QString
KNotification::title() const
111 QWidget
*KNotification::widget() const
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
136 p
.start(KProcess::DontCare
);
143 void KNotification::notifyByMessagebox()
145 // ignore empty messages
146 if ( d
->text
.isEmpty() )
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
158 KMessageBox::sorryWId( winId
, d
->text
, i18n( "Warning" ) , false );
161 KMessageBox::errorWId( winId
, d
->text
, i18n( "Error" ) , false );
164 KMessageBox::errorWId( winId
, d
->text
, i18n( "Catastrophe!" ) , false );
168 KMessageBox::informationWId( winId
, d
->text
, i18n( "Notification" ) , 0 , false );
174 { //we may show the specific action button
176 QPointer
<KNotification
> _this
=this; //this can be deleted
181 result
= KMessageBox::questionYesNo(d
->widget
, d
->text
, i18n( "Notification" ), actions
[0], KStdGuiItem::cancel(), QString::null
, false );
184 result
= KMessageBox::warningYesNo( d
->widget
, d
->text
, i18n( "Warning" ), actions
[0], KStdGuiItem::cancel(), QString::null
, false );
187 result
= KMessageBox::warningYesNo( d
->widget
, d
->text
, i18n( "Error" ), actions
[0], KStdGuiItem::cancel(), QString::null
, false );
190 result
= KMessageBox::warningYesNo( d
->widget
, d
->text
, i18n( "Catastrophe!" ), actions
[0], KStdGuiItem::cancel(), QString::null
, false );
193 if(result
==KMessageBox::Yes
&& _this
)
200 void KNotification::notifyByPassivePopup(const QPixmap
&pix
, const QString
& sound
)
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() )
214 // open file in append mode
216 if ( !logFile
.open(QIODevice::WriteOnly
| QIODevice::Append
) )
220 QTextStream
strm( &logFile
);
221 strm
<< "- KNotify " << QDateTime::currentDateTime().toString() << ": ";
222 strm
<< text
<< endl
;
229 bool KNotification::notifyByStderr(const QString
&text
)
231 // ignore empty messages
232 if ( text
.isEmpty() )
235 // open stderr for output
236 QTextStream
strm( stderr
, QIODevice::WriteOnly
);
239 strm
<< "KNotify " << QDateTime::currentDateTime().toString() << ": ";
240 strm
<< text
<< endl
;
245 bool KNotification::notifyByTaskbar( WId win
)
249 KWin::demandAttention( win
);
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();
272 void KNotification::activate(unsigned int action
)
276 emit
activated(action
);
277 kdDebug() << k_funcinfo
<< d
->id
<< " " << action
<< endl
;
282 void KNotification::close()
285 KNotificationManager::self()->close( d
->id
);
291 void KNotification::raiseWidget()
296 raiseWidget(d
->widget
);
300 void KNotification::raiseWidget(QWidget
*w
)
302 //TODO this funciton is far from finished.
306 KWin::activateWindow( w
->winId() );
310 QWidget
*pw
=w
->parentWidget();
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
324 //this is temporary code
328 KConfig eventsfile
,configfile
;
329 KNotification::ContextList contexts
;
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
;
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
;
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
;
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;
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() );
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()));
446 QDataStream
ds(&qbd
, QIODevice::WriteOnly
);
447 ds
<< event
<< fromApp
<< text
<< sound
<< file
<< present
<< level
449 emitDCOPSignal("notifySignal(QString,QString,QString,QString,QString,int,int,int,int)", qbd
);
455 void KNotification::ref()
460 void KNotification::deref()
467 #include "knotification.moc"