daemon.cpp
00001 /* 00002 * daemon.cpp - interface with alarm daemon 00003 * Program: kalarm 00004 * Copyright © 2001-2007 by David Jarvie <software@astrojar.org.uk> 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License along 00017 * with this program; if not, write to the Free Software Foundation, Inc., 00018 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 */ 00020 00021 #include "kalarm.h" 00022 00023 #include <tqtimer.h> 00024 #include <tqiconset.h> 00025 00026 #include <kstandarddirs.h> 00027 #include <tdeconfig.h> 00028 #include <tdeaboutdata.h> 00029 #include <tdemessagebox.h> 00030 #include <dcopclient.h> 00031 #include <kdebug.h> 00032 00033 #include "kalarmd/kalarmd.h" 00034 #include "kalarmd/alarmdaemoniface.h" 00035 #include "kalarmd/alarmdaemoniface_stub.h" 00036 #include "kalarmd/alarmguiiface.h" 00037 00038 #include "alarmcalendar.h" 00039 #include "kalarmapp.h" 00040 #include "preferences.h" 00041 #include "daemon.moc" 00042 00043 00044 static const int REGISTER_TIMEOUT = 20; // seconds to wait before assuming registration with daemon has failed 00045 static const char* NOTIFY_DCOP_OBJECT = "notify"; // DCOP name of KAlarm's interface for notification by alarm daemon 00046 00047 static TQString expandURL(const TQString& urlString); 00048 00049 00050 /*============================================================================= 00051 = Class: NotificationHandler 00052 = Handles the the alarm daemon's client notification DCOP interface. 00053 =============================================================================*/ 00054 00055 class NotificationHandler : public TQObject, virtual public AlarmGuiIface 00056 { 00057 public: 00058 NotificationHandler(); 00059 private: 00060 // DCOP interface 00061 void alarmDaemonUpdate(int calendarStatus, const TQString& calendarURL); 00062 void handleEvent(const TQString& calendarURL, const TQString& eventID); 00063 void registered(bool reregister, int result, int version); 00064 }; 00065 00066 00067 Daemon* Daemon::mInstance = 0; 00068 NotificationHandler* Daemon::mDcopHandler = 0; 00069 TQValueList<TQString> Daemon::mQueuedEvents; 00070 TQValueList<TQString> Daemon::mSavingEvents; 00071 TQTimer* Daemon::mStartTimer = 0; 00072 TQTimer* Daemon::mRegisterTimer = 0; 00073 TQTimer* Daemon::mStatusTimer = 0; 00074 int Daemon::mStatusTimerCount = 0; 00075 int Daemon::mStatusTimerInterval; 00076 int Daemon::mStartTimeout = 0; 00077 Daemon::Status Daemon::mStatus = Daemon::STOPPED; 00078 bool Daemon::mRunning = false; 00079 bool Daemon::mCalendarDisabled = false; 00080 bool Daemon::mEnableCalPending = false; 00081 bool Daemon::mRegisterFailMsg = false; 00082 00083 // How frequently to check the daemon's status after starting it. 00084 // This is equal to the length of time we wait after the daemon is registered with DCOP 00085 // before we assume that it is ready to accept DCOP calls. 00086 static const int startCheckInterval = 500; // 500 milliseconds 00087 00088 00089 /****************************************************************************** 00090 * Initialise. 00091 * A Daemon instance needs to be constructed only in order for slots to work. 00092 * All external access is via static methods. 00093 */ 00094 void Daemon::initialise() 00095 { 00096 if (!mInstance) 00097 mInstance = new Daemon(); 00098 connect(AlarmCalendar::activeCalendar(), TQT_SIGNAL(calendarSaved(AlarmCalendar*)), mInstance, TQT_SLOT(slotCalendarSaved(AlarmCalendar*))); 00099 } 00100 00101 /****************************************************************************** 00102 * Initialise the daemon status timer. 00103 */ 00104 void Daemon::createDcopHandler() 00105 { 00106 if (mDcopHandler) 00107 return; 00108 mDcopHandler = new NotificationHandler(); 00109 // Check if the alarm daemon is running, but don't start it yet, since 00110 // the program is still initialising. 00111 mRunning = isRunning(false); 00112 00113 mStatusTimerInterval = Preferences::daemonTrayCheckInterval(); 00114 Preferences::connect(TQT_SIGNAL(preferencesChanged()), mInstance, TQT_SLOT(slotPreferencesChanged())); 00115 00116 mStatusTimer = new TQTimer(mInstance); 00117 connect(mStatusTimer, TQT_SIGNAL(timeout()), mInstance, TQT_SLOT(timerCheckIfRunning())); 00118 mStatusTimer->start(mStatusTimerInterval * 1000); // check regularly if daemon is running 00119 } 00120 00121 /****************************************************************************** 00122 * Start the alarm daemon if necessary, and register this application with it. 00123 * Reply = false if the daemon definitely couldn't be started or registered with. 00124 */ 00125 bool Daemon::start() 00126 { 00127 kdDebug(5950) << "Daemon::start()\n"; 00128 updateRegisteredStatus(); 00129 switch (mStatus) 00130 { 00131 case STOPPED: 00132 { 00133 if (mStartTimer) 00134 return true; // we're currently waiting for the daemon to start 00135 // Start the alarm daemon. It is a KUniqueApplication, which means that 00136 // there is automatically only one instance of the alarm daemon running. 00137 TQString execStr = locate("exe", TQString::fromLatin1(DAEMON_APP_NAME)); 00138 if (execStr.isEmpty()) 00139 { 00140 KMessageBox::error(0, i18n("Alarm daemon not found.")); 00141 kdError() << "Daemon::startApp(): " DAEMON_APP_NAME " not found" << endl; 00142 return false; 00143 } 00144 TDEApplication::tdeinitExec(execStr); 00145 kdDebug(5950) << "Daemon::start(): Alarm daemon started" << endl; 00146 mStartTimeout = 5000/startCheckInterval + 1; // check daemon status for 5 seconds before giving up 00147 mStartTimer = new TQTimer(mInstance); 00148 connect(mStartTimer, TQT_SIGNAL(timeout()), mInstance, TQT_SLOT(checkIfStarted())); 00149 mStartTimer->start(startCheckInterval); 00150 mInstance->checkIfStarted(); 00151 return true; 00152 } 00153 case RUNNING: 00154 return true; // we're waiting for the daemon to be completely ready 00155 case READY: 00156 // Daemon is ready. Register this application with it. 00157 if (!registerWith(false)) 00158 return false; 00159 break; 00160 case REGISTERED: 00161 break; 00162 } 00163 return true; 00164 } 00165 00166 /****************************************************************************** 00167 * Register this application with the alarm daemon, and tell it to load the 00168 * calendar. 00169 * Set 'reregister' true in order to notify the daemon of a change in the 00170 * 'disable alarms if stopped' setting. 00171 */ 00172 bool Daemon::registerWith(bool reregister) 00173 { 00174 if (mRegisterTimer) 00175 return true; 00176 switch (mStatus) 00177 { 00178 case STOPPED: 00179 case RUNNING: 00180 return false; 00181 case REGISTERED: 00182 if (!reregister) 00183 return true; 00184 break; 00185 case READY: 00186 break; 00187 } 00188 00189 bool disabledIfStopped = theApp()->alarmsDisabledIfStopped(); 00190 kdDebug(5950) << (reregister ? "Daemon::reregisterWith(): " : "Daemon::registerWith(): ") << (disabledIfStopped ? "NO_START" : "COMMAND_LINE") << endl; 00191 TQCString appname = kapp->aboutData()->appName(); 00192 AlarmDaemonIface_stub s(DAEMON_APP_NAME, DAEMON_DCOP_OBJECT); 00193 if (reregister) 00194 s.registerChange(appname, !disabledIfStopped); 00195 else 00196 s.registerApp(appname, kapp->aboutData()->programName(), TQCString(NOTIFY_DCOP_OBJECT), AlarmCalendar::activeCalendar()->urlString(), !disabledIfStopped); 00197 if (!s.ok()) 00198 { 00199 kdError(5950) << "Daemon::registerWith(" << reregister << "): DCOP error" << endl; 00200 registrationResult(reregister, KAlarmd::FAILURE); 00201 return false; 00202 } 00203 mRegisterTimer = new TQTimer(mInstance); 00204 connect(mRegisterTimer, TQT_SIGNAL(timeout()), mInstance, TQT_SLOT(registerTimerExpired())); 00205 mRegisterTimer->start(REGISTER_TIMEOUT * 1000); // wait for the reply 00206 return true; 00207 } 00208 00209 /****************************************************************************** 00210 * Called when the daemon has notified us of the result of the register() DCOP call. 00211 */ 00212 void Daemon::registrationResult(bool reregister, int result, int version) 00213 { 00214 kdDebug(5950) << "Daemon::registrationResult(" << reregister << ") version: " << version << endl; 00215 delete mRegisterTimer; 00216 mRegisterTimer = 0; 00217 bool failed = false; 00218 TQString errmsg; 00219 if (version && version != DAEMON_VERSION_NUM) 00220 { 00221 failed = true; 00222 kdError(5950) << "Daemon::registrationResult(" << reregister << "): kalarmd reports incompatible version " << version << endl; 00223 errmsg = i18n("Cannot enable alarms.\nInstallation or configuration error: Alarm Daemon (%1) version is incompatible.") 00224 .arg(TQString::fromLatin1(DAEMON_APP_NAME)); 00225 } 00226 else 00227 { 00228 switch (result) 00229 { 00230 case KAlarmd::SUCCESS: 00231 break; 00232 case KAlarmd::NOT_FOUND: 00233 // We've successfully registered with the daemon, but the daemon can't 00234 // find the KAlarm executable so won't be able to restart KAlarm if 00235 // KAlarm exits. 00236 kdError(5950) << "Daemon::registrationResult(" << reregister << "): registerApp dcop call: " << kapp->aboutData()->appName() << " not found\n"; 00237 KMessageBox::error(0, i18n("Alarms will be disabled if you stop KAlarm.\n" 00238 "(Installation or configuration error: %1 cannot locate %2 executable.)") 00239 .arg(TQString::fromLatin1(DAEMON_APP_NAME)) 00240 .arg(kapp->aboutData()->appName())); 00241 break; 00242 case KAlarmd::FAILURE: 00243 default: 00244 // Either the daemon reported an error in the registration DCOP call, 00245 // there was a DCOP error calling the daemon, or a timeout on the reply. 00246 kdError(5950) << "Daemon::registrationResult(" << reregister << "): registerApp dcop call failed -> " << result << endl; 00247 failed = true; 00248 if (!reregister) 00249 { 00250 errmsg = i18n("Cannot enable alarms:\nFailed to register with Alarm Daemon (%1)") 00251 .arg(TQString::fromLatin1(DAEMON_APP_NAME)); 00252 } 00253 break; 00254 } 00255 } 00256 00257 if (failed) 00258 { 00259 if (!errmsg.isEmpty()) 00260 { 00261 if (mStatus == REGISTERED) 00262 mStatus = READY; 00263 if (!mRegisterFailMsg) 00264 { 00265 mRegisterFailMsg = true; 00266 KMessageBox::error(0, errmsg); 00267 } 00268 } 00269 return; 00270 } 00271 00272 if (!reregister) 00273 { 00274 // The alarm daemon has loaded the calendar 00275 mStatus = REGISTERED; 00276 mRegisterFailMsg = false; 00277 kdDebug(5950) << "Daemon::start(): daemon startup complete" << endl; 00278 } 00279 } 00280 00281 /****************************************************************************** 00282 * Check whether the alarm daemon has started yet, and if so, register with it. 00283 */ 00284 void Daemon::checkIfStarted() 00285 { 00286 updateRegisteredStatus(); 00287 bool err = false; 00288 switch (mStatus) 00289 { 00290 case STOPPED: 00291 if (--mStartTimeout > 0) 00292 return; // wait a bit more to check again 00293 // Output error message, but delete timer first to prevent 00294 // multiple messages. 00295 err = true; 00296 break; 00297 case RUNNING: 00298 case READY: 00299 case REGISTERED: 00300 break; 00301 } 00302 delete mStartTimer; 00303 mStartTimer = 0; 00304 if (err) 00305 { 00306 kdError(5950) << "Daemon::checkIfStarted(): failed to start daemon" << endl; 00307 KMessageBox::error(0, i18n("Cannot enable alarms:\nFailed to start Alarm Daemon (%1)").arg(TQString::fromLatin1(DAEMON_APP_NAME))); 00308 } 00309 } 00310 00311 /****************************************************************************** 00312 * Check whether the alarm daemon has started yet, and if so, whether it is 00313 * ready to accept DCOP calls. 00314 */ 00315 void Daemon::updateRegisteredStatus(bool timeout) 00316 { 00317 if (!kapp->dcopClient()->isApplicationRegistered(DAEMON_APP_NAME)) 00318 { 00319 mStatus = STOPPED; 00320 mRegisterFailMsg = false; 00321 } 00322 else 00323 { 00324 switch (mStatus) 00325 { 00326 case STOPPED: 00327 // The daemon has newly been detected as registered with DCOP. 00328 // Wait for a short time to ensure that it is ready for DCOP calls. 00329 mStatus = RUNNING; 00330 TQTimer::singleShot(startCheckInterval, mInstance, TQT_SLOT(slotStarted())); 00331 break; 00332 case RUNNING: 00333 if (timeout) 00334 { 00335 mStatus = READY; 00336 start(); 00337 } 00338 break; 00339 case READY: 00340 case REGISTERED: 00341 break; 00342 } 00343 } 00344 kdDebug(5950) << "Daemon::updateRegisteredStatus() -> " << mStatus << endl; 00345 } 00346 00347 /****************************************************************************** 00348 * Stop the alarm daemon if it is running. 00349 */ 00350 bool Daemon::stop() 00351 { 00352 kdDebug(5950) << "Daemon::stop()" << endl; 00353 if (kapp->dcopClient()->isApplicationRegistered(DAEMON_APP_NAME)) 00354 { 00355 AlarmDaemonIface_stub s(DAEMON_APP_NAME, DAEMON_DCOP_OBJECT); 00356 s.quit(); 00357 if (!s.ok()) 00358 { 00359 kdError(5950) << "Daemon::stop(): dcop call failed" << endl; 00360 return false; 00361 } 00362 } 00363 return true; 00364 } 00365 00366 /****************************************************************************** 00367 * Reset the alarm daemon. 00368 * Reply = true if daemon was told to reset 00369 * = false if daemon is not running. 00370 */ 00371 bool Daemon::reset() 00372 { 00373 kdDebug(5950) << "Daemon::reset()" << endl; 00374 if (!kapp->dcopClient()->isApplicationRegistered(DAEMON_APP_NAME)) 00375 return false; 00376 AlarmDaemonIface_stub s(DAEMON_APP_NAME, DAEMON_DCOP_OBJECT); 00377 s.resetCalendar(TQCString(kapp->aboutData()->appName()), AlarmCalendar::activeCalendar()->urlString()); 00378 if (!s.ok()) 00379 kdError(5950) << "Daemon::reset(): resetCalendar dcop send failed" << endl; 00380 return true; 00381 } 00382 00383 /****************************************************************************** 00384 * Tell the alarm daemon to reread the calendar file. 00385 */ 00386 void Daemon::reload() 00387 { 00388 kdDebug(5950) << "Daemon::reload()\n"; 00389 AlarmDaemonIface_stub s(DAEMON_APP_NAME, DAEMON_DCOP_OBJECT); 00390 s.reloadCalendar(TQCString(kapp->aboutData()->appName()), AlarmCalendar::activeCalendar()->urlString()); 00391 if (!s.ok()) 00392 kdError(5950) << "Daemon::reload(): reloadCalendar dcop send failed" << endl; 00393 } 00394 00395 /****************************************************************************** 00396 * Tell the alarm daemon to enable/disable monitoring of the calendar file. 00397 */ 00398 void Daemon::enableCalendar(bool enable) 00399 { 00400 AlarmDaemonIface_stub s(DAEMON_APP_NAME, DAEMON_DCOP_OBJECT); 00401 s.enableCalendar(AlarmCalendar::activeCalendar()->urlString(), enable); 00402 mEnableCalPending = false; 00403 } 00404 00405 /****************************************************************************** 00406 * Tell the alarm daemon to enable/disable autostart at login. 00407 */ 00408 void Daemon::enableAutoStart(bool enable) 00409 { 00410 // Tell the alarm daemon in case it is running. 00411 AlarmDaemonIface_stub s(DAEMON_APP_NAME, DAEMON_DCOP_OBJECT); 00412 s.enableAutoStart(enable); 00413 00414 // The return status doesn't report failure even if the daemon isn't running, 00415 // so in case of failure, rewrite the config file in any case. 00416 TDEConfig adconfig(locate("config", DAEMON_APP_NAME"rc")); 00417 adconfig.setGroup(TQString::fromLatin1(DAEMON_AUTOSTART_SECTION)); 00418 adconfig.writeEntry(TQString::fromLatin1(DAEMON_AUTOSTART_KEY), enable); 00419 adconfig.sync(); 00420 } 00421 00422 /****************************************************************************** 00423 * Notify the alarm daemon that the start-of-day time for date-only alarms has 00424 * changed. 00425 */ 00426 void Daemon::notifyTimeChanged() 00427 { 00428 AlarmDaemonIface_stub s(DAEMON_APP_NAME, DAEMON_DCOP_OBJECT); 00429 s.timeConfigChanged(); 00430 if (!s.ok()) 00431 kdError(5950) << "Daemon::timeConfigChanged(): dcop send failed" << endl; 00432 } 00433 00434 /****************************************************************************** 00435 * Read the alarm daemon's autostart-at-login setting. 00436 */ 00437 bool Daemon::autoStart() 00438 { 00439 TDEConfig adconfig(locate("config", DAEMON_APP_NAME"rc")); 00440 adconfig.setGroup(TQString::fromLatin1(DAEMON_AUTOSTART_SECTION)); 00441 return adconfig.readBoolEntry(TQString::fromLatin1(DAEMON_AUTOSTART_KEY), true); 00442 } 00443 00444 /****************************************************************************** 00445 * Notification that the alarm daemon has enabled/disabled monitoring of the 00446 * calendar file. 00447 */ 00448 void Daemon::calendarIsEnabled(bool enabled) 00449 { 00450 mCalendarDisabled = !enabled; 00451 emit mInstance->daemonRunning(enabled); 00452 } 00453 00454 /****************************************************************************** 00455 * Tell the alarm daemon to stop or start monitoring the calendar file as 00456 * appropriate. 00457 */ 00458 void Daemon::setAlarmsEnabled(bool enable) 00459 { 00460 kdDebug(5950) << "Daemon::setAlarmsEnabled(" << enable << ")\n"; 00461 if (enable && !checkIfRunning()) 00462 { 00463 // The daemon is not running, so start it 00464 if (!start()) 00465 { 00466 emit daemonRunning(false); 00467 return; 00468 } 00469 mEnableCalPending = true; 00470 setFastCheck(); 00471 } 00472 00473 // If the daemon is now running, tell it to enable/disable the calendar 00474 if (checkIfRunning()) 00475 enableCalendar(enable); 00476 } 00477 00478 /****************************************************************************** 00479 * Return whether the alarm daemon is monitoring alarms. 00480 */ 00481 bool Daemon::monitoringAlarms() 00482 { 00483 bool ok = !mCalendarDisabled && isRunning(); 00484 emit mInstance->daemonRunning(ok); 00485 return ok; 00486 } 00487 00488 /****************************************************************************** 00489 * Check whether the alarm daemon is currently running and available. 00490 */ 00491 bool Daemon::isRunning(bool startdaemon) 00492 { 00493 static bool runState = false; 00494 updateRegisteredStatus(); 00495 bool newRunState = (mStatus == READY || mStatus == REGISTERED); 00496 if (newRunState != runState) 00497 { 00498 // Daemon's status has changed 00499 runState = newRunState; 00500 if (runState && startdaemon) 00501 start(); // re-register with the daemon 00502 } 00503 return runState && (mStatus == REGISTERED); 00504 } 00505 00506 /****************************************************************************** 00507 * Called by the timer to check whether the daemon is running. 00508 */ 00509 void Daemon::timerCheckIfRunning() 00510 { 00511 checkIfRunning(); 00512 // Limit how long we check at the fast rate 00513 if (mStatusTimerCount > 0 && --mStatusTimerCount <= 0) 00514 mStatusTimer->changeInterval(mStatusTimerInterval * 1000); 00515 } 00516 00517 /****************************************************************************** 00518 * Check whether the alarm daemon is currently running. 00519 * If its status has changed, trigger GUI updates. 00520 */ 00521 bool Daemon::checkIfRunning() 00522 { 00523 bool newstatus = isRunning(); 00524 if (newstatus != mRunning) 00525 { 00526 mRunning = newstatus; 00527 int status = mRunning && !mCalendarDisabled; 00528 emit mInstance->daemonRunning(status); 00529 mStatusTimer->changeInterval(mStatusTimerInterval * 1000); // exit from fast checking 00530 mStatusTimerCount = 0; 00531 if (mRunning) 00532 { 00533 // The alarm daemon has started up 00534 if (mEnableCalPending) 00535 enableCalendar(true); // tell it to monitor the calendar, if appropriate 00536 } 00537 } 00538 return mRunning; 00539 } 00540 00541 /****************************************************************************** 00542 * Starts checking at a faster rate whether the daemon is running. 00543 */ 00544 void Daemon::setFastCheck() 00545 { 00546 mStatusTimer->start(500); // check new status every half second 00547 mStatusTimerCount = 20; // don't check at this rate for more than 10 seconds 00548 } 00549 00550 /****************************************************************************** 00551 * Called when a program setting has changed. 00552 * If the system tray icon update interval has changed, reset the timer. 00553 */ 00554 void Daemon::slotPreferencesChanged() 00555 { 00556 int newInterval = Preferences::daemonTrayCheckInterval(); 00557 if (newInterval != mStatusTimerInterval) 00558 { 00559 // Daemon check interval has changed 00560 mStatusTimerInterval = newInterval; 00561 if (mStatusTimerCount <= 0) // don't change if on fast rate 00562 mStatusTimer->changeInterval(mStatusTimerInterval * 1000); 00563 } 00564 } 00565 00566 /****************************************************************************** 00567 * Create an "Alarms Enabled/Enable Alarms" action. 00568 */ 00569 AlarmEnableAction* Daemon::createAlarmEnableAction(TDEActionCollection* actions, const char* name) 00570 { 00571 AlarmEnableAction* a = new AlarmEnableAction(0, actions, name); 00572 connect(a, TQT_SIGNAL(userClicked(bool)), mInstance, TQT_SLOT(setAlarmsEnabled(bool))); 00573 connect(mInstance, TQT_SIGNAL(daemonRunning(bool)), a, TQT_SLOT(setCheckedActual(bool))); 00574 return a; 00575 } 00576 00577 /****************************************************************************** 00578 * Called when a calendar has been saved. 00579 * If it's the active alarm calendar, notify the alarm daemon. 00580 */ 00581 void Daemon::slotCalendarSaved(AlarmCalendar* cal) 00582 { 00583 if (cal == AlarmCalendar::activeCalendar()) 00584 { 00585 int n = mSavingEvents.count(); 00586 if (n) 00587 { 00588 // We have just saved a modified event originally triggered by the daemon. 00589 // Notify the daemon of the event, and tell it to reload the calendar. 00590 for (int i = 0; i < n - 1; ++i) 00591 notifyEventHandled(mSavingEvents[i], false); 00592 notifyEventHandled(mSavingEvents[n - 1], true); 00593 mSavingEvents.clear(); 00594 } 00595 else 00596 reload(); 00597 } 00598 } 00599 00600 /****************************************************************************** 00601 * Note an event ID which has been triggered by the alarm daemon. 00602 */ 00603 void Daemon::queueEvent(const TQString& eventId) 00604 { 00605 mQueuedEvents += eventId; 00606 } 00607 00608 /****************************************************************************** 00609 * Note an event ID which is currently being saved in the calendar file, if the 00610 * event was originally triggered by the alarm daemon. 00611 */ 00612 void Daemon::savingEvent(const TQString& eventId) 00613 { 00614 if (mQueuedEvents.remove(eventId) > 0) 00615 mSavingEvents += eventId; 00616 } 00617 00618 /****************************************************************************** 00619 * If the event ID has been triggered by the alarm daemon, tell the daemon that 00620 * it has been processed, and whether to reload its calendar. 00621 */ 00622 void Daemon::eventHandled(const TQString& eventId, bool reloadCal) 00623 { 00624 if (mQueuedEvents.remove(eventId) > 0) 00625 notifyEventHandled(eventId, reloadCal); // it's a daemon event, so tell daemon that it's been handled 00626 else if (reloadCal) 00627 reload(); // not a daemon event, so simply tell the daemon to reload the calendar 00628 } 00629 00630 /****************************************************************************** 00631 * Tell the daemon that an event has been processed, and whether to reload its 00632 * calendar. 00633 */ 00634 void Daemon::notifyEventHandled(const TQString& eventId, bool reloadCal) 00635 { 00636 kdDebug(5950) << "Daemon::notifyEventHandled(" << eventId << (reloadCal ? "): reload" : ")") << endl; 00637 AlarmDaemonIface_stub s(DAEMON_APP_NAME, DAEMON_DCOP_OBJECT); 00638 s.eventHandled(TQCString(kapp->aboutData()->appName()), AlarmCalendar::activeCalendar()->urlString(), eventId, reloadCal); 00639 if (!s.ok()) 00640 kdError(5950) << "Daemon::notifyEventHandled(): eventHandled dcop send failed" << endl; 00641 } 00642 00643 /****************************************************************************** 00644 * Return the maximum time (in seconds) elapsed since the last time the alarm 00645 * daemon must have checked alarms. 00646 */ 00647 int Daemon::maxTimeSinceCheck() 00648 { 00649 return DAEMON_CHECK_INTERVAL; 00650 } 00651 00652 00653 /*============================================================================= 00654 = Class: NotificationHandler 00655 =============================================================================*/ 00656 00657 NotificationHandler::NotificationHandler() 00658 : DCOPObject(NOTIFY_DCOP_OBJECT), 00659 TQObject() 00660 { 00661 kdDebug(5950) << "NotificationHandler::NotificationHandler()\n"; 00662 } 00663 00664 /****************************************************************************** 00665 * DCOP call from the alarm daemon to notify a change. 00666 * The daemon notifies calendar statuses when we first register as a GUI, and whenever 00667 * a calendar status changes. So we don't need to read its config files. 00668 */ 00669 void NotificationHandler::alarmDaemonUpdate(int calendarStatus, const TQString& calendarURL) 00670 { 00671 kdDebug(5950) << "NotificationHandler::alarmDaemonUpdate(" << calendarStatus << ")\n"; 00672 KAlarmd::CalendarStatus status = KAlarmd::CalendarStatus(calendarStatus); 00673 if (expandURL(calendarURL) != AlarmCalendar::activeCalendar()->urlString()) 00674 return; // it's not a notification about KAlarm's calendar 00675 bool enabled = false; 00676 switch (status) 00677 { 00678 case KAlarmd::CALENDAR_UNAVAILABLE: 00679 // Calendar is not available for monitoring 00680 kdDebug(5950) << "NotificationHandler::alarmDaemonUpdate(CALENDAR_UNAVAILABLE)\n"; 00681 break; 00682 case KAlarmd::CALENDAR_DISABLED: 00683 // Calendar is available for monitoring but is not currently being monitored 00684 kdDebug(5950) << "NotificationHandler::alarmDaemonUpdate(DISABLE_CALENDAR)\n"; 00685 break; 00686 case KAlarmd::CALENDAR_ENABLED: 00687 // Calendar is currently being monitored 00688 kdDebug(5950) << "NotificationHandler::alarmDaemonUpdate(ENABLE_CALENDAR)\n"; 00689 enabled = true; 00690 break; 00691 default: 00692 return; 00693 } 00694 Daemon::calendarIsEnabled(enabled); 00695 } 00696 00697 /****************************************************************************** 00698 * DCOP call from the alarm daemon to notify that an alarm is due. 00699 */ 00700 void NotificationHandler::handleEvent(const TQString& url, const TQString& eventId) 00701 { 00702 TQString id = eventId; 00703 if (id.startsWith(TQString::fromLatin1("ad:"))) 00704 { 00705 // It's a notification from the alarm deamon 00706 id = id.mid(3); 00707 Daemon::queueEvent(id); 00708 } 00709 theApp()->handleEvent(url, id); 00710 } 00711 00712 /****************************************************************************** 00713 * DCOP call from the alarm daemon to notify the success or failure of a 00714 * registration request from KAlarm. 00715 */ 00716 void NotificationHandler::registered(bool reregister, int result, int version) 00717 { 00718 Daemon::registrationResult(reregister, result, version); 00719 } 00720 00721 00722 /*============================================================================= 00723 = Class: AlarmEnableAction 00724 =============================================================================*/ 00725 00726 AlarmEnableAction::AlarmEnableAction(int accel, TQObject* parent, const char* name) 00727 : TDEToggleAction(i18n("Enable &Alarms"), accel, parent, name), 00728 mInitialised(false) 00729 { 00730 setCheckedState(i18n("Disable &Alarms")); 00731 setCheckedActual(false); // set the correct text 00732 mInitialised = true; 00733 } 00734 00735 /****************************************************************************** 00736 * Set the checked status and the correct text for the Alarms Enabled action. 00737 */ 00738 void AlarmEnableAction::setCheckedActual(bool running) 00739 { 00740 kdDebug(5950) << "AlarmEnableAction::setCheckedActual(" << running << ")\n"; 00741 if (running != isChecked() || !mInitialised) 00742 { 00743 TDEToggleAction::setChecked(running); 00744 emit switched(running); 00745 } 00746 } 00747 00748 /****************************************************************************** 00749 * Request a change in the checked status. 00750 * The status is only actually changed when the alarm daemon run state changes. 00751 */ 00752 void AlarmEnableAction::setChecked(bool check) 00753 { 00754 kdDebug(5950) << "AlarmEnableAction::setChecked(" << check << ")\n"; 00755 if (check != isChecked()) 00756 { 00757 if (check) 00758 Daemon::allowRegisterFailMsg(); 00759 emit userClicked(check); 00760 } 00761 } 00762 00763 00764 /****************************************************************************** 00765 * Expand a DCOP call parameter URL to a full URL. 00766 * (We must store full URLs in the calendar data since otherwise later calls to 00767 * reload or remove calendars won't necessarily find a match.) 00768 */ 00769 TQString expandURL(const TQString& urlString) 00770 { 00771 if (urlString.isEmpty()) 00772 return TQString(); 00773 return KURL(urlString).url(); 00774 }