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