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