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 
00378     // The return status doesn't report failure even if the daemon isn't running,
00379     // so in case of failure, rewrite the config file in any case.
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 * Read the alarm daemon's autostart-at-login setting.
00388 */
00389 bool Daemon::autoStart()
00390 {
00391     KConfig adconfig(locate("config", DAEMON_APP_NAME"rc"));
00392     adconfig.setGroup(QString::fromLatin1(DAEMON_AUTOSTART_SECTION));
00393     return adconfig.readBoolEntry(QString::fromLatin1(DAEMON_AUTOSTART_KEY), true);
00394 }
00395 
00396 /******************************************************************************
00397 * Notification that the alarm daemon has enabled/disabled monitoring of the
00398 * calendar file.
00399 */
00400 void Daemon::calendarIsEnabled(bool enabled)
00401 {
00402     mCalendarDisabled = !enabled;
00403     emit mInstance->daemonRunning(enabled);
00404 }
00405 
00406 /******************************************************************************
00407 * Tell the alarm daemon to stop or start monitoring the calendar file as
00408 * appropriate.
00409 */
00410 void Daemon::setAlarmsEnabled(bool enable)
00411 {
00412     kdDebug(5950) << "Daemon::setAlarmsEnabled(" << enable << ")\n";
00413     if (enable  &&  !checkIfRunning())
00414     {
00415         // The daemon is not running, so start it
00416         if (!start())
00417         {
00418             emit daemonRunning(false);
00419             return;
00420         }
00421         mEnableCalPending = true;
00422         setFastCheck();
00423     }
00424 
00425     // If the daemon is now running, tell it to enable/disable the calendar
00426     if (checkIfRunning())
00427         enableCalendar(enable);
00428 }
00429 
00430 /******************************************************************************
00431 * Return whether the alarm daemon is monitoring alarms.
00432 */
00433 bool Daemon::monitoringAlarms()
00434 {
00435     bool ok = !mCalendarDisabled  &&  isRunning();
00436     emit mInstance->daemonRunning(ok);
00437     return ok;
00438 }
00439 
00440 /******************************************************************************
00441 * Check whether the alarm daemon is currently running and available.
00442 */
00443 bool Daemon::isRunning(bool startdaemon)
00444 {
00445     static bool runState = false;
00446     updateRegisteredStatus();
00447     bool newRunState = (mStatus == READY  ||  mStatus == REGISTERED);
00448     if (newRunState != runState)
00449     {
00450         // Daemon's status has changed
00451         runState = newRunState;
00452         if (runState  &&  startdaemon)
00453             start();      // re-register with the daemon
00454     }
00455     return runState  &&  (mStatus == REGISTERED);
00456 }
00457 
00458 /******************************************************************************
00459 * Called by the timer to check whether the daemon is running.
00460 */
00461 void Daemon::timerCheckIfRunning()
00462 {
00463     checkIfRunning();
00464     // Limit how long we check at the fast rate
00465     if (mStatusTimerCount > 0  &&  --mStatusTimerCount <= 0)
00466         mStatusTimer->changeInterval(mStatusTimerInterval * 1000);
00467 }
00468 
00469 /******************************************************************************
00470 * Check whether the alarm daemon is currently running.
00471 * If its status has changed, trigger GUI updates.
00472 */
00473 bool Daemon::checkIfRunning()
00474 {
00475     bool newstatus = isRunning();
00476     if (newstatus != mRunning)
00477     {
00478         mRunning = newstatus;
00479         int status = mRunning  &&  !mCalendarDisabled;
00480         emit mInstance->daemonRunning(status);
00481         mStatusTimer->changeInterval(mStatusTimerInterval * 1000);   // exit from fast checking
00482         mStatusTimerCount = 0;
00483         if (mRunning)
00484         {
00485             // The alarm daemon has started up
00486             if (mEnableCalPending)
00487                 enableCalendar(true);  // tell it to monitor the calendar, if appropriate
00488         }
00489     }
00490     return mRunning;
00491 }
00492 
00493 /******************************************************************************
00494 * Starts checking at a faster rate whether the daemon is running.
00495 */
00496 void Daemon::setFastCheck()
00497 {
00498     mStatusTimer->start(500);    // check new status every half second
00499     mStatusTimerCount = 20;      // don't check at this rate for more than 10 seconds
00500 }
00501 
00502 /******************************************************************************
00503 * Called when a program setting has changed.
00504 * If the system tray icon update interval has changed, reset the timer.
00505 */
00506 void Daemon::slotPreferencesChanged()
00507 {
00508     int newInterval = Preferences::daemonTrayCheckInterval();
00509     if (newInterval != mStatusTimerInterval)
00510     {
00511         // Daemon check interval has changed
00512         mStatusTimerInterval = newInterval;
00513         if (mStatusTimerCount <= 0)   // don't change if on fast rate
00514             mStatusTimer->changeInterval(mStatusTimerInterval * 1000);
00515     }
00516 }
00517 
00518 /******************************************************************************
00519 * Create an "Alarms Enabled/Enable Alarms" action.
00520 */
00521 AlarmEnableAction* Daemon::createAlarmEnableAction(KActionCollection* actions, const char* name)
00522 {
00523     AlarmEnableAction* a = new AlarmEnableAction(0, actions, name);
00524     connect(a, SIGNAL(userClicked(bool)), mInstance, SLOT(setAlarmsEnabled(bool)));
00525     connect(mInstance, SIGNAL(daemonRunning(bool)), a, SLOT(setCheckedActual(bool)));
00526     return a;
00527 }
00528 
00529 /******************************************************************************
00530 * Called when a calendar has been saved.
00531 * If it's the active alarm calendar, notify the alarm daemon.
00532 */
00533 void Daemon::slotCalendarSaved(AlarmCalendar* cal)
00534 {
00535     if (cal == AlarmCalendar::activeCalendar())
00536     {
00537         int n = mSavingEvents.count();
00538         if (n)
00539         {
00540             // We have just saved a modified event originally triggered by the daemon.
00541             // Notify the daemon of the event, and tell it to reload the calendar.
00542             for (int i = 0;  i < n - 1;  ++i)
00543                 notifyEventHandled(mSavingEvents[i], false);
00544             notifyEventHandled(mSavingEvents[n - 1], true);
00545             mSavingEvents.clear();
00546         }
00547         else
00548             reload();
00549     }
00550 }
00551 
00552 /******************************************************************************
00553 * Note an event ID which has been triggered by the alarm daemon.
00554 */
00555 void Daemon::queueEvent(const QString& eventId)
00556 {
00557     mQueuedEvents += eventId;
00558 }
00559 
00560 /******************************************************************************
00561 * Note an event ID which is currently being saved in the calendar file, if the
00562 * event was originally triggered by the alarm daemon.
00563 */
00564 void Daemon::savingEvent(const QString& eventId)
00565 {
00566     if (mQueuedEvents.remove(eventId) > 0)
00567         mSavingEvents += eventId;
00568 }
00569 
00570 /******************************************************************************
00571 * If the event ID has been triggered by the alarm daemon, tell the daemon that
00572 * it has been processed, and whether to reload its calendar.
00573 */
00574 void Daemon::eventHandled(const QString& eventId, bool reloadCal)
00575 {
00576     if (mQueuedEvents.remove(eventId) > 0)
00577         notifyEventHandled(eventId, reloadCal);    // it's a daemon event, so tell daemon that it's been handled
00578     else if (reloadCal)
00579         reload();    // not a daemon event, so simply tell the daemon to reload the calendar
00580 }
00581 
00582 /******************************************************************************
00583 * Tell the daemon that an event has been processed, and whether to reload its
00584 * calendar.
00585 */
00586 void Daemon::notifyEventHandled(const QString& eventId, bool reloadCal)
00587 {
00588     kdDebug(5950) << "Daemon::notifyEventHandled(" << eventId << (reloadCal ? "): reload" : ")") << endl;
00589     AlarmDaemonIface_stub s(DAEMON_APP_NAME, DAEMON_DCOP_OBJECT);
00590     s.eventHandled(QCString(kapp->aboutData()->appName()), AlarmCalendar::activeCalendar()->urlString(), eventId, reloadCal);
00591     if (!s.ok())
00592         kdError(5950) << "Daemon::notifyEventHandled(): eventHandled dcop send failed" << endl;
00593 }
00594 
00595 /******************************************************************************
00596 * Return the maximum time (in seconds) elapsed since the last time the alarm
00597 * daemon must have checked alarms.
00598 */
00599 int Daemon::maxTimeSinceCheck()
00600 {
00601     return DAEMON_CHECK_INTERVAL;
00602 }
00603 
00604 
00605 /*=============================================================================
00606 =  Class: NotificationHandler
00607 =============================================================================*/
00608 
00609 NotificationHandler::NotificationHandler()
00610     : DCOPObject(NOTIFY_DCOP_OBJECT), 
00611       QObject()
00612 {
00613     kdDebug(5950) << "NotificationHandler::NotificationHandler()\n";
00614 }
00615 
00616 /******************************************************************************
00617  * DCOP call from the alarm daemon to notify a change.
00618  * The daemon notifies calendar statuses when we first register as a GUI, and whenever
00619  * a calendar status changes. So we don't need to read its config files.
00620  */
00621 void NotificationHandler::alarmDaemonUpdate(int calendarStatus, const QString& calendarURL)
00622 {
00623     kdDebug(5950) << "NotificationHandler::alarmDaemonUpdate(" << calendarStatus << ")\n";
00624     KAlarmd::CalendarStatus status = KAlarmd::CalendarStatus(calendarStatus);
00625     if (expandURL(calendarURL) != AlarmCalendar::activeCalendar()->urlString())
00626         return;     // it's not a notification about KAlarm's calendar
00627     bool enabled = false;
00628     switch (status)
00629     {
00630         case KAlarmd::CALENDAR_UNAVAILABLE:
00631             // Calendar is not available for monitoring
00632             kdDebug(5950) << "NotificationHandler::alarmDaemonUpdate(CALENDAR_UNAVAILABLE)\n";
00633             break;
00634         case KAlarmd::CALENDAR_DISABLED:
00635             // Calendar is available for monitoring but is not currently being monitored
00636             kdDebug(5950) << "NotificationHandler::alarmDaemonUpdate(DISABLE_CALENDAR)\n";
00637             break;
00638         case KAlarmd::CALENDAR_ENABLED:
00639             // Calendar is currently being monitored
00640             kdDebug(5950) << "NotificationHandler::alarmDaemonUpdate(ENABLE_CALENDAR)\n";
00641             enabled = true;
00642             break;
00643         default:
00644             return;
00645     }
00646     Daemon::calendarIsEnabled(enabled);
00647 }
00648 
00649 /******************************************************************************
00650  * DCOP call from the alarm daemon to notify that an alarm is due.
00651  */
00652 void NotificationHandler::handleEvent(const QString& url, const QString& eventId)
00653 {
00654     QString id = eventId;
00655     if (id.startsWith(QString::fromLatin1("ad:")))
00656     {
00657         // It's a notification from the alarm deamon
00658         id = id.mid(3);
00659         Daemon::queueEvent(id);
00660     }
00661     theApp()->handleEvent(url, id);
00662 }
00663 
00664 /******************************************************************************
00665  * DCOP call from the alarm daemon to notify the success or failure of a
00666  * registration request from KAlarm.
00667  */
00668 void NotificationHandler::registered(bool reregister, int result)
00669 {
00670     Daemon::registrationResult(reregister, result);
00671 }
00672 
00673 
00674 /*=============================================================================
00675 =  Class: AlarmEnableAction
00676 =============================================================================*/
00677 
00678 AlarmEnableAction::AlarmEnableAction(int accel, QObject* parent, const char* name)
00679     : KToggleAction(i18n("Enable &Alarms"), accel, parent, name),
00680       mInitialised(false)
00681 {
00682     setCheckedState(i18n("Disable &Alarms"));
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         KToggleAction::setChecked(running);
00696         emit switched(running);
00697     }
00698 }
00699 
00700 /******************************************************************************
00701 *  Request a change in the checked status.
00702 *  The status is only actually changed when the alarm daemon run state changes.
00703 */
00704 void AlarmEnableAction::setChecked(bool check)
00705 {
00706     kdDebug(5950) << "AlarmEnableAction::setChecked(" << check << ")\n";
00707     if (check != isChecked())
00708     {
00709         if (check)
00710             Daemon::allowRegisterFailMsg();
00711         emit userClicked(check);
00712     }
00713 }
00714 
00715 
00716 /******************************************************************************
00717  * Expand a DCOP call parameter URL to a full URL.
00718  * (We must store full URLs in the calendar data since otherwise later calls to
00719  *  reload or remove calendars won't necessarily find a match.)
00720  */
00721 QString expandURL(const QString& urlString)
00722 {
00723     if (urlString.isEmpty())
00724         return QString();
00725     return KURL(urlString).url();
00726 }
KDE Home | KDE Accessibility Home | Description of Access Keys