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