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