00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
#include "knotifyclient.h"
00022
00023
#include <qdatastream.h>
00024
#include <qptrstack.h>
00025
00026
#include <kapplication.h>
00027
#include <kstandarddirs.h>
00028
#include <kapplication.h>
00029
#include <kconfig.h>
00030
#include <dcopclient.h>
00031
#include <kdebug.h>
00032
#include <kstaticdeleter.h>
00033
00034
static const char daemonName[] =
"knotify";
00035
00036
static bool canAvoidStartupEvent(
const QString& event,
const QString& appname,
int present )
00037 {
00038
static bool checkAvoid =
true;
00039
if( !checkAvoid )
00040
return false;
00041
if(( appname !=
"kwin" && appname !=
"ksmserver" ) || present > 0 ) {
00042 checkAvoid =
false;
00043
return false;
00044 }
00045
00046
static KConfig* configfile = appname !=
"ksmserver"
00047 ?
new KConfig( appname +
".eventsrc",
true,
false )
00048 : new
KConfig( "knotify.eventsrc", true, false );
00049
static KConfig* eventsfile = appname !=
"ksmserver"
00050 ?
new KConfig( appname +
"/eventsrc",
true,
false,
"data" )
00051 : new
KConfig( "knotify/eventsrc", true, false, "data" );
00052 configfile->
setGroup( event );
00053 eventsfile->
setGroup( event );
00054
int ev1 = configfile->
readNumEntry(
"presentation", -2 );
00055
int ev2 = eventsfile->
readNumEntry(
"default_presentation", -2 );
00056
if(( ev1 == -2 && ev2 == -2 )
00057 || ev1 > 0
00058 || ( ev1 == -2 && ev2 > 0 )) {
00059 checkAvoid =
false;
00060
return false;
00061 }
00062
return true;
00063 }
00064
00065
static int sendNotifyEvent(
const QString &message,
const QString &text,
00066
int present,
int level,
const QString &sound,
00067
const QString &file,
int winId )
00068 {
00069
if (!kapp)
return 0;
00070
00071
DCOPClient *client=kapp->dcopClient();
00072
if (!client->
isAttached())
00073 {
00074 client->
attach();
00075
if (!client->
isAttached())
00076
return 0;
00077 }
00078
00079
QString appname =
KNotifyClient::instance()->
instanceName();
00080
00081
if( canAvoidStartupEvent( message, appname, present ))
00082
return -1;
00083
00084
int uniqueId = kMax( 1, kapp->random() );
00085
00086
00087
QWidget* widget =
QWidget::find( (WId)winId );
00088
if( widget )
00089 winId = (
int)widget->
topLevelWidget()->winId();
00090
00091
QByteArray data;
00092
QDataStream ds(data, IO_WriteOnly);
00093 ds << message << appname << text << sound << file << present << level
00094 << winId << uniqueId;
00095
00096
if ( !
KNotifyClient::startDaemon() )
00097
return 0;
00098
00099
if ( client->
send(daemonName,
"Notify",
"notify(QString,QString,QString,QString,QString,int,int,int,int)", data) )
00100 {
00101
return uniqueId;
00102 }
00103
00104
return 0;
00105 }
00106
00107 int KNotifyClient::event( StandardEvent type,
const QString& text )
00108 {
00109
return event( 0, type, text );
00110 }
00111
00112 int KNotifyClient::event(
const QString &message,
const QString &text)
00113 {
00114
return event(0, message, text);
00115 }
00116
00117 int KNotifyClient::userEvent(
const QString &text,
int present,
int level,
00118
const QString &sound,
const QString &file)
00119 {
00120
return userEvent( 0, text, present, level, sound, file );
00121 }
00122
00123
00124 int KNotifyClient::event(
int winId, StandardEvent type,
const QString& text )
00125 {
00126
QString message;
00127
switch ( type ) {
00128
case cannotOpenFile:
00129 message = QString::fromLatin1(
"cannotopenfile");
00130
break;
00131
case warning:
00132 message = QString::fromLatin1(
"warning");
00133
break;
00134
case fatalError:
00135 message = QString::fromLatin1(
"fatalerror");
00136
break;
00137
case catastrophe:
00138 message = QString::fromLatin1(
"catastrophe");
00139
break;
00140
case notification:
00141
default:
00142 message = QString::fromLatin1(
"notification");
00143
break;
00144 }
00145
00146
return sendNotifyEvent( message, text, Default, Default,
00147 QString::null, QString::null, winId );
00148 }
00149
00150 int KNotifyClient::event(
int winId,
const QString &message,
00151
const QString &text)
00152 {
00153
return sendNotifyEvent(message, text, Default, Default, QString::null, QString::null, winId);
00154 }
00155
00156 int KNotifyClient::userEvent(
int winId,
const QString &text,
int present,
00157
int level,
00158
const QString &sound,
const QString &file)
00159 {
00160
return sendNotifyEvent(QString::null, text, present, level, sound, file, winId);
00161 }
00162
00163 int KNotifyClient::getPresentation(
const QString &eventname)
00164 {
00165
int present;
00166
if (eventname.
isEmpty())
return Default;
00167
00168
KConfig eventsfile( KNotifyClient::instance()->instanceName()+
".eventsrc",
true,
false);
00169 eventsfile.
setGroup(eventname);
00170
00171 present=eventsfile.
readNumEntry(
"presentation", -1);
00172
00173
return present;
00174 }
00175
00176 QString KNotifyClient::getFile(
const QString &eventname,
int present)
00177 {
00178
if (eventname.
isEmpty())
return QString::null;
00179
00180
KConfig eventsfile( KNotifyClient::instance()->instanceName()+
".eventsrc",
true,
false);
00181 eventsfile.
setGroup(eventname);
00182
00183
switch (present)
00184 {
00185
case (Sound):
00186
return eventsfile.
readPathEntry(
"soundfile");
00187
case (Logfile):
00188
return eventsfile.
readPathEntry(
"logfile");
00189 }
00190
00191
return QString::null;
00192 }
00193
00194 int KNotifyClient::getDefaultPresentation(
const QString &eventname)
00195 {
00196
int present;
00197
if (eventname.
isEmpty())
return Default;
00198
00199
KConfig eventsfile( KNotifyClient::instance()->instanceName()+
"/eventsrc",
true,
false,
"data");
00200 eventsfile.
setGroup(eventname);
00201
00202 present=eventsfile.
readNumEntry(
"default_presentation", -1);
00203
00204
return present;
00205 }
00206
00207 QString KNotifyClient::getDefaultFile(
const QString &eventname,
int present)
00208 {
00209
if (eventname.
isEmpty())
return QString::null;
00210
00211
KConfig eventsfile( KNotifyClient::instance()->instanceName()+
"/eventsrc",
true,
false,
"data");
00212 eventsfile.
setGroup(eventname);
00213
00214
switch (present)
00215 {
00216
case (Sound):
00217
return eventsfile.
readPathEntry(
"default_sound");
00218
case (Logfile):
00219
return eventsfile.
readPathEntry(
"default_logfile");
00220 }
00221
00222
return QString::null;
00223 }
00224
00225 bool KNotifyClient::startDaemon()
00226 {
00227
static bool firstTry =
true;
00228
if (!kapp->dcopClient()->isApplicationRegistered(daemonName)) {
00229
if( firstTry ) {
00230 firstTry =
false;
00231
return KApplication::startServiceByDesktopName(daemonName) == 0;
00232 }
00233
return false;
00234 }
00235
return true;
00236 }
00237
00238
00239 void KNotifyClient::beep(
const QString& reason)
00240 {
00241
if ( !kapp ||
KNotifyClient::Instance::currentInstance()->
useSystemBell() ) {
00242
QApplication::beep();
00243
return;
00244 }
00245
00246
DCOPClient *client=kapp->dcopClient();
00247
if (!client->
isAttached())
00248 {
00249 client->
attach();
00250
if (!client->
isAttached() || !client->
isApplicationRegistered(daemonName))
00251 {
00252
QApplication::beep();
00253
return;
00254 }
00255 }
00256
00257
if ( client->
isApplicationRegistered(
"kaccess" ) )
00258 {
00259
QApplication::beep();
00260
return;
00261 }
00262
00263
KNotifyClient::event(KNotifyClient::notification, reason);
00264 }
00265
00266
00267 KInstance *
KNotifyClient::instance() {
00268
return KNotifyClient::Instance::current();
00269 }
00270
00271
00272
class KNotifyClient::InstanceStack
00273 {
00274
public:
00275 InstanceStack() { m_defaultInstance = 0; }
00276
virtual ~InstanceStack() {
delete m_defaultInstance; }
00277
void push(Instance *instance) { m_instances.push(instance); }
00278
00279
void pop(Instance *instance)
00280 {
00281
if (m_instances.top() ==
instance)
00282 m_instances.pop();
00283
else if (!m_instances.isEmpty())
00284 {
00285 kdWarning(160) <<
"Tried to remove an Instance that is not the current," <<
endl;
00286 kdWarning(160) <<
"Resetting to the main KApplication." <<
endl;
00287 m_instances.clear();
00288 }
00289
else
00290 kdWarning(160) <<
"Tried to remove an Instance, but the stack was empty." <<
endl;
00291 }
00292
00293 Instance *currentInstance()
00294 {
00295
if (m_instances.isEmpty())
00296 {
00297 m_defaultInstance =
new Instance(kapp);
00298 }
00299
return m_instances.top();
00300 }
00301
00302
private:
00303
QPtrStack<Instance> m_instances;
00304 Instance *m_defaultInstance;
00305 };
00306
00307 KNotifyClient::InstanceStack * KNotifyClient::Instance::s_instances = 0L;
00308
static KStaticDeleter<KNotifyClient::InstanceStack > instancesDeleter;
00309
00310
struct KNotifyClient::InstancePrivate
00311 {
00312
KInstance *
instance;
00313
bool useSystemBell;
00314 };
00315
00316 KNotifyClient::Instance::Instance(
KInstance *instance)
00317 {
00318 d =
new InstancePrivate;
00319 d->instance =
instance;
00320 instances()->push(
this);
00321
00322
KConfig *config =
instance->
config();
00323
KConfigGroupSaver cs( config,
"General" );
00324 d->useSystemBell = config->
readBoolEntry(
"UseSystemBell",
false );
00325 }
00326
00327 KNotifyClient::Instance::~Instance()
00328 {
00329
if (s_instances)
00330 s_instances->pop(
this);
00331
delete d;
00332 }
00333
00334 KNotifyClient::InstanceStack *KNotifyClient::Instance::instances()
00335 {
00336
if (!s_instances)
00337 instancesDeleter.setObject(s_instances,
new InstanceStack);
00338
return s_instances;
00339 }
00340
00341 bool KNotifyClient::Instance::useSystemBell()
const
00342
{
00343
return d->useSystemBell;
00344 }
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355 KNotifyClient::Instance *
KNotifyClient::Instance::currentInstance()
00356 {
00357
return instances()->currentInstance();
00358 }
00359
00360 KInstance *
KNotifyClient::Instance::current()
00361 {
00362
return currentInstance()->
d->instance;
00363 }