kalarm

daemon.cpp

00001 /*
00002  *  daemon.cpp  -  interface with alarm daemon
00003  *  Program:  kalarm
00004  *  Copyright (c) 2001-2006 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 <qtimer.h>
00024 #include <qiconset.h>
00025 
00026 #include <kstandarddirs.h>
00027 #include <kconfig.h>
00028 #include <kaboutdata.h>
00029 #include <kmessagebox.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 QString expandURL(const QString& urlString);
00048 
00049 
00050 /*=============================================================================
00051 =  Class: NotificationHandler
00052 =  Handles the the alarm daemon's client notification DCOP interface.
00053 =============================================================================*/
00054 
00055 class NotificationHandler : public QObject, virtual public AlarmGuiIface
00056 {
00057     public:
00058         NotificationHandler();
00059     private:
00060         // DCOP interface
00061         void  alarmDaemonUpdate(int calendarStatus, const QString& calendarURL);
00062         void  handleEvent(const QString& calendarURL, const QString& eventID);
00063         void  registered(bool reregister, int result);
00064 };
00065 
00066 
00067 Daemon*              Daemon::mInstance = 0;
00068 NotificationHandler* Daemon::mDcopHandler = 0;
00069 QValueList<QString>  Daemon::mQueuedEvents;
00070 QValueList<QString>  Daemon::mSavingEvents;
00071 QTimer*              Daemon::mStartTimer = 0;
00072 QTimer*              Daemon::mRegisterTimer = 0;
00073 QTimer*              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(), SIGNAL(calendarSaved(AlarmCalendar*)), mInstance, 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(SIGNAL(preferencesChanged()), mInstance, SLOT(slotPreferencesChanged()));
00115 
00116     mStatusTimer = new QTimer(mInstance);
00117     connect(mStatusTimer, SIGNAL(timeout()), mInstance, 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             QString execStr = locate("exe", QString::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             KApplication::kdeinitExec(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 QTimer(mInstance);
00148             connect(mStartTimer, SIGNAL(timeout()), mInstance, 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     if (mStatus == STOPPED  ||  mStatus == RUNNING)
00177         return false;
00178     if (mStatus == REGISTERED  &&  !reregister)
00179         return true;
00180 
00181     bool disabledIfStopped = theApp()->alarmsDisabledIfStopped();
00182     kdDebug(5950) << (reregister ? "Daemon::reregisterWith(): " : "Daemon::registerWith(): ") << (disabledIfStopped ? "NO_START" : "COMMAND_LINE") << endl;
00183     QCString appname  = kapp->aboutData()->appName();
00184     AlarmDaemonIface_stub s(DAEMON_APP_NAME, DAEMON_DCOP_OBJECT);
00185     if (reregister)
00186         s.registerChange(appname, !disabledIfStopped);
00187     else
00188         s.registerApp(appname, kapp->aboutData()->programName(), QCString(NOTIFY_DCOP_OBJECT), AlarmCalendar::activeCalendar()->urlString(), !disabledIfStopped);
00189     if (!s.ok())
00190     {
00191         registrationResult(reregister, KAlarmd::FAILURE);
00192         return false;
00193     }
00194     mRegisterTimer = new QTimer(mInstance);
00195     connect(mRegisterTimer, SIGNAL(timeout()), mInstance, SLOT(registerTimerExpired()));
00196     mRegisterTimer->start(REGISTER_TIMEOUT * 1000);     // wait for the reply
00197     return true;
00198 }
00199 
00200 /******************************************************************************
00201 * Called when the daemon has notified us of the result of the register() DCOP call.
00202 */
00203 void Daemon::registrationResult(bool reregister, int result)
00204 {
00205     kdDebug(5950) << "Daemon::registrationResult(" << reregister << ")\n";
00206     delete mRegisterTimer;
00207     mRegisterTimer = 0;
00208     switch (result)
00209     {
00210         case KAlarmd::SUCCESS:
00211             break;
00212         case KAlarmd::NOT_FOUND:
00213             kdError(5950) << "Daemon::registrationResult(" << reregister << "): registerApp dcop call: " << kapp->aboutData()->appName() << " not found\n";
00214             KMessageBox::error(0, i18n("Alarms will be disabled if you stop KAlarm.\n"
00215                                        "(Installation or configuration error: %1 cannot locate %2 executable.)")
00216                                        .arg(QString::fromLatin1(DAEMON_APP_NAME))
00217                                        .arg(kapp->aboutData()->appName()));
00218             break;
00219         case KAlarmd::FAILURE:
00220         default:
00221             kdError(5950) << "Daemon::registrationResult(" << reregister << "): registerApp dcop call failed -> " << result << endl;
00222             if (!reregister)
00223             {
00224                 if (mStatus == REGISTERED)
00225                     mStatus = READY;
00226                 if (!mRegisterFailMsg)
00227                 {
00228                     mRegisterFailMsg = true;
00229                     KMessageBox::error(0, i18n("Cannot enable alarms:\nFailed to register with Alarm Daemon (%1)")
00230                                                .arg(QString::fromLatin1(DAEMON_APP_NAME)));
00231                 }
00232             }
00233             return;
00234     }
00235 
00236     if (!reregister)
00237     {
00238         // The alarm daemon has loaded the calendar
00239         mStatus = REGISTERED;
00240         mRegisterFailMsg = false;
00241         kdDebug(5950) << "Daemon::start(): daemon startup complete" << endl;
00242     }
00243 }
00244 
00245 /******************************************************************************
00246 * Check whether the alarm daemon has started yet, and if so, register with it.
00247 */
00248 void Daemon::checkIfStarted()
00249 {
00250     updateRegisteredStatus();
00251     bool err = false;
00252     switch (mStatus)
00253     {
00254         case STOPPED:
00255             if (--mStartTimeout > 0)
00256                 return;     // wait a bit more to check again
00257             // Output error message, but delete timer first to prevent
00258             // multiple messages.
00259             err = true;
00260             break;
00261         case RUNNING:
00262         case READY:
00263         case REGISTERED:
00264             break;
00265     }
00266     delete mStartTimer;
00267     mStartTimer = 0;
00268     if (err)
00269     {
00270         kdError(5950) << "Daemon::checkIfStarted(): failed to start daemon" << endl;
00271         KMessageBox::error(0, i18n("Cannot enable alarms:\nFailed to start Alarm Daemon (%1)").arg(QString::fromLatin1(DAEMON_APP_NAME)));
00272     }
00273 }
00274 
00275 /******************************************************************************
00276 * Check whether the alarm daemon has started yet, and if so, whether it is
00277 * ready to accept DCOP calls.
00278 */
00279 void Daemon::updateRegisteredStatus(bool timeout)
00280 {
00281     if (!kapp->dcopClient()->isApplicationRegistered(DAEMON_APP_NAME))
00282     {
00283         mStatus = STOPPED;
00284         mRegisterFailMsg = false;
00285     }
00286     else
00287     {
00288         switch (mStatus)
00289         {
00290             case STOPPED:
00291                 // The daemon has newly been detected as registered with DCOP.
00292                 // Wait for a short time to ensure that it is ready for DCOP calls.
00293                 mStatus = RUNNING;
00294                 QTimer::singleShot(startCheckInterval, mInstance, SLOT(slotStarted()));
00295                 break;
00296             case RUNNING:
00297                 if (timeout)
00298                 {
00299                     mStatus = READY;
00300                     start();
00301                 }
00302                 break;
00303             case READY:
00304             case REGISTERED:
00305                 break;
00306         }
00307     }
00308     kdDebug(5950) << "Daemon::updateRegisteredStatus() -> " << mStatus << endl;
00309 }
00310 
00311 /******************************************************************************
00312 * Stop the alarm daemon if it is running.
00313 */
00314 bool Daemon::stop()
00315 {
00316     kdDebug(5950) << "Daemon::stop()" << endl;
00317     if (kapp->dcopClient()->isApplicationRegistered(DAEMON_APP_NAME))
00318     {
00319         AlarmDaemonIface_stub s(DAEMON_APP_NAME, DAEMON_DCOP_OBJECT);
00320         s.quit();
00321         if (!s.ok())
00322         {
00323             kdError(5950) << "Daemon::stop(): dcop call failed" << endl;
00324             return false;
00325         }
00326     }
00327     return true;
00328 }
00329 
00330 /******************************************************************************
00331 * Reset the alarm daemon.
00332 * Reply = true if daemon was told to reset
00333 *       = false if daemon is not running.
00334 */
00335 bool Daemon::reset()
00336 {
00337     kdDebug(5950) << "Daemon::reset()" << endl;
00338     if (!kapp->dcopClient()->isApplicationRegistered(DAEMON_APP_NAME))
00339         return false;
00340     AlarmDaemonIface_stub s(DAEMON_APP_NAME, DAEMON_DCOP_OBJECT);
00341     s.resetCalendar(QCString(kapp->aboutData()->appName()), AlarmCalendar::activeCalendar()->urlString());
00342     if (!s.ok())
00343         kdError(5950) << "Daemon::reset(): resetCalendar dcop send failed" << endl;
00344     return true;
00345 }
00346 
00347 /******************************************************************************
00348 * Tell the alarm daemon to reread the calendar file.
00349 */
00350 void Daemon::reload()
00351 {
00352     kdDebug(5950) << "Daemon::reload()\n";
00353     AlarmDaemonIface_stub s(DAEMON_APP_NAME, DAEMON_DCOP_OBJECT);
00354     s.reloadCalendar(QCString(kapp->aboutData()->appName()), AlarmCalendar::activeCalendar()->urlString());
00355     if (!s.ok())
00356         kdError(5950) << "Daemon::reload(): reloadCalendar dcop send failed" << endl;
00357 }
00358 
00359 /******************************************************************************
00360 * Tell the alarm daemon to enable/disable monitoring of the calendar file.
00361 */
00362 void Daemon::enableCalendar(bool enable)
00363 {
00364     AlarmDaemonIface_stub s(DAEMON_APP_NAME, DAEMON_DCOP_OBJECT);
00365     s.enableCalendar(AlarmCalendar::activeCalendar()->urlString(), enable);
00366     mEnableCalPending = false;
00367 }
00368 
00369 /******************************************************************************
00370 * Tell the alarm daemon to enable/disable autostart at login.
00371 */
00372 void Daemon::enableAutoStart(bool enable)
00373 {
00374     // Tell the alarm daemon in case it is running.
00375     AlarmDaemonIface_stub s(DAEMON_APP_NAME, DAEMON_DCOP_OBJECT);
00376     s.enableAutoStart(enable);
00377     if (!s.ok())
00378     {
00379         // Failure - the daemon probably isn't running, so rewrite its config file for it
00380         KConfig adconfig(locate("config", DAEMON_APP_NAME"rc"));
00381         adconfig.setGroup(QString::fromLatin1(DAEMON_AUTOSTART_SECTION));
00382         adconfig.writeEntry(QString::fromLatin1(DAEMON_AUTOSTART_KEY), enable);
00383         adconfig.sync();
00384     }
00385 }
00386 
00387 /******************************************************************************
00388 * Read the alarm daemon's autostart-at-login setting.
00389 */
00390 bool Daemon::autoStart(bool defaultAutoStart)
00391 {
00392     KConfig adconfig(locate("config", DAEMON_APP_NAME"rc"));
00393     adconfig.setGroup(QString::fromLatin1(DAEMON_AUTOSTART_SECTION));
00394     return adconfig.readBoolEntry(QString::fromLatin1(DAEMON_AUTOSTART_KEY), defaultAutoStart);
00395 }
00396 
00397 /******************************************************************************
00398 * Notification that the alarm daemon has enabled/disabled monitoring of the
00399 * calendar file.
00400 */
00401 void Daemon::calendarIsEnabled(bool enabled)
00402 {
00403     mCalendarDisabled = !enabled;
00404     emit mInstance->daemonRunning(enabled);
00405 }
00406 
00407 /******************************************************************************
00408 * Tell the alarm daemon to stop or start monitoring the calendar file as
00409 * appropriate.
00410 */
00411 void Daemon::setAlarmsEnabled(bool enable)
00412 {
00413     kdDebug(5950) << "Daemon::setAlarmsEnabled(" << enable << ")\n";
00414     if (enable  &&  !checkIfRunning())
00415     {
00416         // The daemon is not running, so start it
00417         if (!start())
00418         {
00419             emit daemonRunning(false);
00420             return;
00421         }
00422         mEnableCalPending = true;
00423         setFastCheck();
00424     }
00425 
00426     // If the daemon is now running, tell it to enable/disable the calendar
00427     if (checkIfRunning())
00428         enableCalendar(enable);
00429 }
00430 
00431 /******************************************************************************
00432 * Return whether the alarm daemon is monitoring alarms.
00433 */
00434 bool Daemon::monitoringAlarms()
00435 {
00436     bool ok = !mCalendarDisabled  &&  isRunning();
00437     emit mInstance->daemonRunning(ok);
00438     return ok;
00439 }
00440 
00441 /******************************************************************************
00442 * Check whether the alarm daemon is currently running and available.
00443 */
00444 bool Daemon::isRunning(bool startdaemon)
00445 {
00446     static bool runState = false;
00447     updateRegisteredStatus();
00448     bool newRunState = (mStatus == READY  ||  mStatus == REGISTERED);
00449     if (newRunState != runState)
00450     {
00451         // Daemon's status has changed
00452         runState = newRunState;
00453         if (runState  &&  startdaemon)
00454             start();      // re-register with the daemon
00455     }
00456     return runState  &&  (mStatus == REGISTERED);
00457 }
00458 
00459 /******************************************************************************
00460 * Called by the timer to check whether the daemon is running.
00461 */
00462 void Daemon::timerCheckIfRunning()
00463 {
00464     checkIfRunning();
00465     // Limit how long we check at the fast rate
00466     if (mStatusTimerCount > 0  &&  --mStatusTimerCount <= 0)
00467         mStatusTimer->changeInterval(mStatusTimerInterval * 1000);
00468 }
00469 
00470 /******************************************************************************
00471 * Check whether the alarm daemon is currently running.
00472 * If its status has changed, trigger GUI updates.
00473 */
00474 bool Daemon::checkIfRunning()
00475 {
00476     bool newstatus = isRunning();
00477     if (newstatus != mRunning)
00478     {
00479         mRunning = newstatus;
00480         int status = mRunning  &&  !mCalendarDisabled;
00481         emit mInstance->daemonRunning(status);
00482         mStatusTimer->changeInterval(mStatusTimerInterval * 1000);   // exit from fast checking
00483         mStatusTimerCount = 0;
00484         if (mRunning)
00485         {
00486             // The alarm daemon has started up
00487             if (mEnableCalPending)
00488                 enableCalendar(true);  // tell it to monitor the calendar, if appropriate
00489         }
00490     }
00491     return mRunning;
00492 }
00493 
00494 /******************************************************************************
00495 * Starts checking at a faster rate whether the daemon is running.
00496 */
00497 void Daemon::setFastCheck()
00498 {
00499     mStatusTimer->start(500);    // check new status every half second
00500     mStatusTimerCount = 20;      // don't check at this rate for more than 10 seconds
00501 }
00502 
00503 /******************************************************************************
00504 * Called when a program setting has changed.
00505 * If the system tray icon update interval has changed, reset the timer.
00506 */
00507 void Daemon::slotPreferencesChanged()
00508 {
00509     int newInterval = Preferences::daemonTrayCheckInterval();
00510     if (newInterval != mStatusTimerInterval)
00511     {
00512         // Daemon check interval has changed
00513         mStatusTimerInterval = newInterval;
00514         if (mStatusTimerCount <= 0)   // don't change if on fast rate
00515             mStatusTimer->changeInterval(mStatusTimerInterval * 1000);
00516     }
00517 }
00518 
00519 /******************************************************************************
00520 * Create an "Alarms Enabled/Enable Alarms" action.
00521 */
00522 AlarmEnableAction* Daemon::createAlarmEnableAction(KActionCollection* actions, const char* name)
00523 {
00524     AlarmEnableAction* a = new AlarmEnableAction(0, actions, name);
00525     connect(a, SIGNAL(userClicked(bool)), mInstance, SLOT(setAlarmsEnabled(bool)));
00526     connect(mInstance, SIGNAL(daemonRunning(bool)), a, SLOT(setCheckedActual(bool)));
00527     return a;
00528 }
00529 
00530 /******************************************************************************
00531 * Called when a calendar has been saved.
00532 * If it's the active alarm calendar, notify the alarm daemon.
00533 */
00534 void Daemon::slotCalendarSaved(AlarmCalendar* cal)
00535 {
00536     if (cal == AlarmCalendar::activeCalendar())
00537     {
00538         int n = mSavingEvents.count();
00539         if (n)
00540         {
00541             // We have just saved a modified event originally triggered by the daemon.
00542             // Notify the daemon of the event, and tell it to reload the calendar.
00543             for (int i = 0;  i < n - 1;  ++i)
00544                 notifyEventHandled(mSavingEvents[i], false);
00545             notifyEventHandled(mSavingEvents[n - 1], true);
00546             mSavingEvents.clear();
00547         }
00548         else
00549             reload();
00550     }
00551 }
00552 
00553 /******************************************************************************
00554 * Note an event ID which has been triggered by the alarm daemon.
00555 */
00556 void Daemon::queueEvent(const QString& eventId)
00557 {
00558     mQueuedEvents += eventId;
00559 }
00560 
00561 /******************************************************************************
00562 * Note an event ID which is currently being saved in the calendar file, if the
00563 * event was originally triggered by the alarm daemon.
00564 */
00565 void Daemon::savingEvent(const QString& eventId)
00566 {
00567     if (mQueuedEvents.remove(eventId) > 0)
00568         mSavingEvents += eventId;
00569 }
00570 
00571 /******************************************************************************
00572 * If the event ID has been triggered by the alarm daemon, tell the daemon that
00573 * it has been processed, and whether to reload its calendar.
00574 */
00575 void Daemon::eventHandled(const QString& eventId, bool reloadCal)
00576 {
00577     if (mQueuedEvents.remove(eventId) > 0)
00578         notifyEventHandled(eventId, reloadCal);    // it's a daemon event, so tell daemon that it's been handled
00579     else if (reloadCal)
00580         reload();    // not a daemon event, so simply tell the daemon to reload the calendar
00581 }
00582 
00583 /******************************************************************************
00584 * Tell the daemon that an event has been processed, and whether to reload its
00585 * calendar.
00586 */
00587 void Daemon::notifyEventHandled(const QString& eventId, bool reloadCal)
00588 {
00589     kdDebug(5950) << "Daemon::notifyEventHandled(" << eventId << (reloadCal ? "): reload" : ")") << endl;
00590     AlarmDaemonIface_stub s(DAEMON_APP_NAME, DAEMON_DCOP_OBJECT);
00591     s.eventHandled(QCString(kapp->aboutData()->appName()), AlarmCalendar::activeCalendar()->urlString(), eventId, reloadCal);
00592     if (!s.ok())
00593         kdError(5950) << "Daemon::notifyEventHandled(): eventHandled dcop send failed" << endl;
00594 }
00595 
00596 /******************************************************************************
00597 * Return the maximum time (in seconds) elapsed since the last time the alarm
00598 * daemon must have checked alarms.
00599 */
00600 int Daemon::maxTimeSinceCheck()
00601 {
00602     return DAEMON_CHECK_INTERVAL;
00603 }
00604 
00605 
00606 /*=============================================================================
00607 =  Class: NotificationHandler
00608 =============================================================================*/
00609 
00610 NotificationHandler::NotificationHandler()
00611     : DCOPObject(NOTIFY_DCOP_OBJECT), 
00612       QObject()
00613 {
00614     kdDebug(5950) << "NotificationHandler::NotificationHandler()\n";
00615 }
00616 
00617 /******************************************************************************
00618  * DCOP call from the alarm daemon to notify a change.
00619  * The daemon notifies calendar statuses when we first register as a GUI, and whenever
00620  * a calendar status changes. So we don't need to read its config files.
00621  */
00622 void NotificationHandler::alarmDaemonUpdate(int calendarStatus, const QString& calendarURL)
00623 {
00624     kdDebug(5950) << "NotificationHandler::alarmDaemonUpdate(" << calendarStatus << ")\n";
00625     KAlarmd::CalendarStatus status = KAlarmd::CalendarStatus(calendarStatus);
00626     if (expandURL(calendarURL) != AlarmCalendar::activeCalendar()->urlString())
00627         return;     // it's not a notification about KAlarm's calendar
00628     bool enabled = false;
00629     switch (status)
00630     {
00631         case KAlarmd::CALENDAR_UNAVAILABLE:
00632             // Calendar is not available for monitoring
00633             kdDebug(5950) << "NotificationHandler::alarmDaemonUpdate(CALENDAR_UNAVAILABLE)\n";
00634             break;
00635         case KAlarmd::CALENDAR_DISABLED:
00636             // Calendar is available for monitoring but is not currently being monitored
00637             kdDebug(5950) << "NotificationHandler::alarmDaemonUpdate(DISABLE_CALENDAR)\n";
00638             break;
00639         case KAlarmd::CALENDAR_ENABLED:
00640             // Calendar is currently being monitored
00641             kdDebug(5950) << "NotificationHandler::alarmDaemonUpdate(ENABLE_CALENDAR)\n";
00642             enabled = true;
00643             break;
00644         default:
00645             return;
00646     }
00647     Daemon::calendarIsEnabled(enabled);
00648 }
00649 
00650 /******************************************************************************
00651  * DCOP call from the alarm daemon to notify that an alarm is due.
00652  */
00653 void NotificationHandler::handleEvent(const QString& url, const QString& eventId)
00654 {
00655     QString id = eventId;
00656     if (id.startsWith(QString::fromLatin1("ad:")))
00657     {
00658         // It's a notification from the alarm deamon
00659         id = id.mid(3);
00660         Daemon::queueEvent(id);
00661     }
00662     theApp()->handleEvent(url, id);
00663 }
00664 
00665 /******************************************************************************
00666  * DCOP call from the alarm daemon to notify the success or failure of a
00667  * registration request from KAlarm.
00668  */
00669 void NotificationHandler::registered(bool reregister, int result)
00670 {
00671     Daemon::registrationResult(reregister, result);
00672 }
00673 
00674 
00675 /*=============================================================================
00676 =  Class: AlarmEnableAction
00677 =============================================================================*/
00678 
00679 AlarmEnableAction::AlarmEnableAction(int accel, QObject* parent, const char* name)
00680     : KToggleAction(QString::null, accel, parent, name),
00681       mInitialised(false)
00682 {
00683     setCheckedActual(false);    // set the correct text
00684     mInitialised = true;
00685 }
00686 
00687 /******************************************************************************
00688 *  Set the checked status and the correct text for the Alarms Enabled action.
00689 */
00690 void AlarmEnableAction::setCheckedActual(bool running)
00691 {
00692     kdDebug(5950) << "AlarmEnableAction::setCheckedActual(" << running << ")\n";
00693     if (running != isChecked()  ||  !mInitialised)
00694     {
00695         setText(running ? i18n("&Alarms Enabled") : i18n("Enable &Alarms"));
00696         KToggleAction::setChecked(running);
00697         emit switched(running);
00698     }
00699 }
00700 
00701 /******************************************************************************
00702 *  Request a change in the checked status.
00703 *  The status is only actually changed when the alarm daemon run state changes.
00704 */
00705 void AlarmEnableAction::setChecked(bool check)
00706 {
00707     kdDebug(5950) << "AlarmEnableAction::setChecked(" << check << ")\n";
00708     if (check != isChecked())
00709     {
00710         if (check)
00711             Daemon::allowRegisterFailMsg();
00712         emit userClicked(check);
00713     }
00714 }
00715 
00716 
00717 /******************************************************************************
00718  * Expand a DCOP call parameter URL to a full URL.
00719  * (We must store full URLs in the calendar data since otherwise later calls to
00720  *  reload or remove calendars won't necessarily find a match.)
00721  */
00722 QString expandURL(const QString& urlString)
00723 {
00724     if (urlString.isEmpty())
00725         return QString();
00726     return KURL(urlString).url();
00727 }
KDE Home | KDE Accessibility Home | Description of Access Keys