kalarm

daemon.cpp
1 /*
2  * daemon.cpp - interface with alarm daemon
3  * Program: kalarm
4  * Copyright © 2001-2007 by David Jarvie <software@astrojar.org.uk>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  */
20 
21 #include "kalarm.h"
22 
23 #include <tqtimer.h>
24 #include <tqiconset.h>
25 
26 #include <kstandarddirs.h>
27 #include <tdeconfig.h>
28 #include <tdeaboutdata.h>
29 #include <tdemessagebox.h>
30 #include <dcopclient.h>
31 #include <kdebug.h>
32 
33 #include "kalarmd/kalarmd.h"
34 #include "kalarmd/alarmdaemoniface.h"
35 #include "kalarmd/alarmdaemoniface_stub.h"
36 #include "kalarmd/alarmguiiface.h"
37 
38 #include "alarmcalendar.h"
39 #include "kalarmapp.h"
40 #include "preferences.h"
41 #include "daemon.moc"
42 
43 
44 static const int REGISTER_TIMEOUT = 20; // seconds to wait before assuming registration with daemon has failed
45 static const char* NOTIFY_DCOP_OBJECT = "notify"; // DCOP name of KAlarm's interface for notification by alarm daemon
46 
47 static TQString expandURL(const TQString& urlString);
48 
49 
50 /*=============================================================================
51 = Class: NotificationHandler
52 = Handles the the alarm daemon's client notification DCOP interface.
53 =============================================================================*/
54 
55 class NotificationHandler : public TQObject, virtual public AlarmGuiIface
56 {
57  public:
58  NotificationHandler();
59  private:
60  // DCOP interface
61  void alarmDaemonUpdate(int calendarStatus, const TQString& calendarURL);
62  void handleEvent(const TQString& calendarURL, const TQString& eventID);
63  void registered(bool reregister, int result, int version);
64 };
65 
66 
67 Daemon* Daemon::mInstance = 0;
68 NotificationHandler* Daemon::mDcopHandler = 0;
69 TQValueList<TQString> Daemon::mQueuedEvents;
70 TQValueList<TQString> Daemon::mSavingEvents;
71 TQTimer* Daemon::mStartTimer = 0;
72 TQTimer* Daemon::mRegisterTimer = 0;
73 TQTimer* Daemon::mStatusTimer = 0;
74 int Daemon::mStatusTimerCount = 0;
75 int Daemon::mStatusTimerInterval;
76 int Daemon::mStartTimeout = 0;
77 Daemon::Status Daemon::mStatus = Daemon::STOPPED;
78 bool Daemon::mRunning = false;
79 bool Daemon::mCalendarDisabled = false;
80 bool Daemon::mEnableCalPending = false;
81 bool Daemon::mRegisterFailMsg = false;
82 
83 // How frequently to check the daemon's status after starting it.
84 // This is equal to the length of time we wait after the daemon is registered with DCOP
85 // before we assume that it is ready to accept DCOP calls.
86 static const int startCheckInterval = 500; // 500 milliseconds
87 
88 
89 /******************************************************************************
90 * Initialise.
91 * A Daemon instance needs to be constructed only in order for slots to work.
92 * All external access is via static methods.
93 */
94 void Daemon::initialise()
95 {
96  if (!mInstance)
97  mInstance = new Daemon();
98  connect(AlarmCalendar::activeCalendar(), TQ_SIGNAL(calendarSaved(AlarmCalendar*)), mInstance, TQ_SLOT(slotCalendarSaved(AlarmCalendar*)));
99 }
100 
101 /******************************************************************************
102 * Initialise the daemon status timer.
103 */
104 void Daemon::createDcopHandler()
105 {
106  if (mDcopHandler)
107  return;
108  mDcopHandler = new NotificationHandler();
109  // Check if the alarm daemon is running, but don't start it yet, since
110  // the program is still initialising.
111  mRunning = isRunning(false);
112 
113  mStatusTimerInterval = Preferences::daemonTrayCheckInterval();
114  Preferences::connect(TQ_SIGNAL(preferencesChanged()), mInstance, TQ_SLOT(slotPreferencesChanged()));
115 
116  mStatusTimer = new TQTimer(mInstance);
117  connect(mStatusTimer, TQ_SIGNAL(timeout()), mInstance, TQ_SLOT(timerCheckIfRunning()));
118  mStatusTimer->start(mStatusTimerInterval * 1000); // check regularly if daemon is running
119 }
120 
121 /******************************************************************************
122 * Start the alarm daemon if necessary, and register this application with it.
123 * Reply = false if the daemon definitely couldn't be started or registered with.
124 */
125 bool Daemon::start()
126 {
127  kdDebug(5950) << "Daemon::start()\n";
128  updateRegisteredStatus();
129  switch (mStatus)
130  {
131  case STOPPED:
132  {
133  if (mStartTimer)
134  return true; // we're currently waiting for the daemon to start
135  // Start the alarm daemon. It is a TDEUniqueApplication, which means that
136  // there is automatically only one instance of the alarm daemon running.
137  TQString execStr = locate("exe", TQString::fromLatin1(DAEMON_APP_NAME));
138  if (execStr.isEmpty())
139  {
140  KMessageBox::error(0, i18n("Alarm daemon not found."));
141  kdError() << "Daemon::startApp(): " DAEMON_APP_NAME " not found" << endl;
142  return false;
143  }
144  TDEApplication::tdeinitExec(execStr);
145  kdDebug(5950) << "Daemon::start(): Alarm daemon started" << endl;
146  mStartTimeout = 5000/startCheckInterval + 1; // check daemon status for 5 seconds before giving up
147  mStartTimer = new TQTimer(mInstance);
148  connect(mStartTimer, TQ_SIGNAL(timeout()), mInstance, TQ_SLOT(checkIfStarted()));
149  mStartTimer->start(startCheckInterval);
150  mInstance->checkIfStarted();
151  return true;
152  }
153  case RUNNING:
154  return true; // we're waiting for the daemon to be completely ready
155  case READY:
156  // Daemon is ready. Register this application with it.
157  if (!registerWith(false))
158  return false;
159  break;
160  case REGISTERED:
161  break;
162  }
163  return true;
164 }
165 
166 /******************************************************************************
167 * Register this application with the alarm daemon, and tell it to load the
168 * calendar.
169 * Set 'reregister' true in order to notify the daemon of a change in the
170 * 'disable alarms if stopped' setting.
171 */
172 bool Daemon::registerWith(bool reregister)
173 {
174  if (mRegisterTimer)
175  return true;
176  switch (mStatus)
177  {
178  case STOPPED:
179  case RUNNING:
180  return false;
181  case REGISTERED:
182  if (!reregister)
183  return true;
184  break;
185  case READY:
186  break;
187  }
188 
189  bool disabledIfStopped = theApp()->alarmsDisabledIfStopped();
190  kdDebug(5950) << (reregister ? "Daemon::reregisterWith(): " : "Daemon::registerWith(): ") << (disabledIfStopped ? "NO_START" : "COMMAND_LINE") << endl;
191  TQCString appname = kapp->aboutData()->appName();
192  AlarmDaemonIface_stub s(DAEMON_APP_NAME, DAEMON_DCOP_OBJECT);
193  if (reregister)
194  s.registerChange(appname, !disabledIfStopped);
195  else
196  s.registerApp(appname, kapp->aboutData()->programName(), TQCString(NOTIFY_DCOP_OBJECT), AlarmCalendar::activeCalendar()->urlString(), !disabledIfStopped);
197  if (!s.ok())
198  {
199  kdError(5950) << "Daemon::registerWith(" << reregister << "): DCOP error" << endl;
200  registrationResult(reregister, KAlarmd::FAILURE);
201  return false;
202  }
203  mRegisterTimer = new TQTimer(mInstance);
204  connect(mRegisterTimer, TQ_SIGNAL(timeout()), mInstance, TQ_SLOT(registerTimerExpired()));
205  mRegisterTimer->start(REGISTER_TIMEOUT * 1000); // wait for the reply
206  return true;
207 }
208 
209 /******************************************************************************
210 * Called when the daemon has notified us of the result of the register() DCOP call.
211 */
212 void Daemon::registrationResult(bool reregister, int result, int version)
213 {
214  kdDebug(5950) << "Daemon::registrationResult(" << reregister << ") version: " << version << endl;
215  delete mRegisterTimer;
216  mRegisterTimer = 0;
217  bool failed = false;
218  TQString errmsg;
219  if (version && version != DAEMON_VERSION_NUM)
220  {
221  failed = true;
222  kdError(5950) << "Daemon::registrationResult(" << reregister << "): kalarmd reports incompatible version " << version << endl;
223  errmsg = i18n("Cannot enable alarms.\nInstallation or configuration error: Alarm Daemon (%1) version is incompatible.")
224  .arg(TQString::fromLatin1(DAEMON_APP_NAME));
225  }
226  else
227  {
228  switch (result)
229  {
230  case KAlarmd::SUCCESS:
231  break;
232  case KAlarmd::NOT_FOUND:
233  // We've successfully registered with the daemon, but the daemon can't
234  // find the KAlarm executable so won't be able to restart KAlarm if
235  // KAlarm exits.
236  kdError(5950) << "Daemon::registrationResult(" << reregister << "): registerApp dcop call: " << kapp->aboutData()->appName() << " not found\n";
237  KMessageBox::error(0, i18n("Alarms will be disabled if you stop KAlarm.\n"
238  "(Installation or configuration error: %1 cannot locate %2 executable.)")
239  .arg(TQString::fromLatin1(DAEMON_APP_NAME))
240  .arg(kapp->aboutData()->appName()));
241  break;
242  case KAlarmd::FAILURE:
243  default:
244  // Either the daemon reported an error in the registration DCOP call,
245  // there was a DCOP error calling the daemon, or a timeout on the reply.
246  kdError(5950) << "Daemon::registrationResult(" << reregister << "): registerApp dcop call failed -> " << result << endl;
247  failed = true;
248  if (!reregister)
249  {
250  errmsg = i18n("Cannot enable alarms:\nFailed to register with Alarm Daemon (%1)")
251  .arg(TQString::fromLatin1(DAEMON_APP_NAME));
252  }
253  break;
254  }
255  }
256 
257  if (failed)
258  {
259  if (!errmsg.isEmpty())
260  {
261  if (mStatus == REGISTERED)
262  mStatus = READY;
263  if (!mRegisterFailMsg)
264  {
265  mRegisterFailMsg = true;
266  KMessageBox::error(0, errmsg);
267  }
268  }
269  return;
270  }
271 
272  if (!reregister)
273  {
274  // The alarm daemon has loaded the calendar
275  mStatus = REGISTERED;
276  mRegisterFailMsg = false;
277  kdDebug(5950) << "Daemon::start(): daemon startup complete" << endl;
278  }
279 }
280 
281 /******************************************************************************
282 * Check whether the alarm daemon has started yet, and if so, register with it.
283 */
284 void Daemon::checkIfStarted()
285 {
286  updateRegisteredStatus();
287  bool err = false;
288  switch (mStatus)
289  {
290  case STOPPED:
291  if (--mStartTimeout > 0)
292  return; // wait a bit more to check again
293  // Output error message, but delete timer first to prevent
294  // multiple messages.
295  err = true;
296  break;
297  case RUNNING:
298  case READY:
299  case REGISTERED:
300  break;
301  }
302  delete mStartTimer;
303  mStartTimer = 0;
304  if (err)
305  {
306  kdError(5950) << "Daemon::checkIfStarted(): failed to start daemon" << endl;
307  KMessageBox::error(0, i18n("Cannot enable alarms:\nFailed to start Alarm Daemon (%1)").arg(TQString::fromLatin1(DAEMON_APP_NAME)));
308  }
309 }
310 
311 /******************************************************************************
312 * Check whether the alarm daemon has started yet, and if so, whether it is
313 * ready to accept DCOP calls.
314 */
315 void Daemon::updateRegisteredStatus(bool timeout)
316 {
317  if (!kapp->dcopClient()->isApplicationRegistered(DAEMON_APP_NAME))
318  {
319  mStatus = STOPPED;
320  mRegisterFailMsg = false;
321  }
322  else
323  {
324  switch (mStatus)
325  {
326  case STOPPED:
327  // The daemon has newly been detected as registered with DCOP.
328  // Wait for a short time to ensure that it is ready for DCOP calls.
329  mStatus = RUNNING;
330  TQTimer::singleShot(startCheckInterval, mInstance, TQ_SLOT(slotStarted()));
331  break;
332  case RUNNING:
333  if (timeout)
334  {
335  mStatus = READY;
336  start();
337  }
338  break;
339  case READY:
340  case REGISTERED:
341  break;
342  }
343  }
344  kdDebug(5950) << "Daemon::updateRegisteredStatus() -> " << mStatus << endl;
345 }
346 
347 /******************************************************************************
348 * Stop the alarm daemon if it is running.
349 */
350 bool Daemon::stop()
351 {
352  kdDebug(5950) << "Daemon::stop()" << endl;
353  if (kapp->dcopClient()->isApplicationRegistered(DAEMON_APP_NAME))
354  {
355  AlarmDaemonIface_stub s(DAEMON_APP_NAME, DAEMON_DCOP_OBJECT);
356  s.quit();
357  if (!s.ok())
358  {
359  kdError(5950) << "Daemon::stop(): dcop call failed" << endl;
360  return false;
361  }
362  }
363  return true;
364 }
365 
366 /******************************************************************************
367 * Reset the alarm daemon.
368 * Reply = true if daemon was told to reset
369 * = false if daemon is not running.
370 */
371 bool Daemon::reset()
372 {
373  kdDebug(5950) << "Daemon::reset()" << endl;
374  if (!kapp->dcopClient()->isApplicationRegistered(DAEMON_APP_NAME))
375  return false;
376  AlarmDaemonIface_stub s(DAEMON_APP_NAME, DAEMON_DCOP_OBJECT);
377  s.resetCalendar(TQCString(kapp->aboutData()->appName()), AlarmCalendar::activeCalendar()->urlString());
378  if (!s.ok())
379  kdError(5950) << "Daemon::reset(): resetCalendar dcop send failed" << endl;
380  return true;
381 }
382 
383 /******************************************************************************
384 * Tell the alarm daemon to reread the calendar file.
385 */
386 void Daemon::reload()
387 {
388  kdDebug(5950) << "Daemon::reload()\n";
389  AlarmDaemonIface_stub s(DAEMON_APP_NAME, DAEMON_DCOP_OBJECT);
390  s.reloadCalendar(TQCString(kapp->aboutData()->appName()), AlarmCalendar::activeCalendar()->urlString());
391  if (!s.ok())
392  kdError(5950) << "Daemon::reload(): reloadCalendar dcop send failed" << endl;
393 }
394 
395 /******************************************************************************
396 * Tell the alarm daemon to enable/disable monitoring of the calendar file.
397 */
398 void Daemon::enableCalendar(bool enable)
399 {
400  AlarmDaemonIface_stub s(DAEMON_APP_NAME, DAEMON_DCOP_OBJECT);
401  s.enableCalendar(AlarmCalendar::activeCalendar()->urlString(), enable);
402  mEnableCalPending = false;
403 }
404 
405 /******************************************************************************
406 * Tell the alarm daemon to enable/disable autostart at login.
407 */
408 void Daemon::enableAutoStart(bool enable)
409 {
410  // Tell the alarm daemon in case it is running.
411  AlarmDaemonIface_stub s(DAEMON_APP_NAME, DAEMON_DCOP_OBJECT);
412  s.enableAutoStart(enable);
413 
414  // The return status doesn't report failure even if the daemon isn't running,
415  // so in case of failure, rewrite the config file in any case.
416  TDEConfig adconfig(locate("config", DAEMON_APP_NAME"rc"));
417  adconfig.setGroup(TQString::fromLatin1(DAEMON_AUTOSTART_SECTION));
418  adconfig.writeEntry(TQString::fromLatin1(DAEMON_AUTOSTART_KEY), enable);
419  adconfig.sync();
420 }
421 
422 /******************************************************************************
423 * Notify the alarm daemon that the start-of-day time for date-only alarms has
424 * changed.
425 */
426 void Daemon::notifyTimeChanged()
427 {
428  AlarmDaemonIface_stub s(DAEMON_APP_NAME, DAEMON_DCOP_OBJECT);
429  s.timeConfigChanged();
430  if (!s.ok())
431  kdError(5950) << "Daemon::timeConfigChanged(): dcop send failed" << endl;
432 }
433 
434 /******************************************************************************
435 * Read the alarm daemon's autostart-at-login setting.
436 */
437 bool Daemon::autoStart()
438 {
439  TDEConfig adconfig(locate("config", DAEMON_APP_NAME"rc"));
440  adconfig.setGroup(TQString::fromLatin1(DAEMON_AUTOSTART_SECTION));
441  return adconfig.readBoolEntry(TQString::fromLatin1(DAEMON_AUTOSTART_KEY), true);
442 }
443 
444 /******************************************************************************
445 * Notification that the alarm daemon has enabled/disabled monitoring of the
446 * calendar file.
447 */
448 void Daemon::calendarIsEnabled(bool enabled)
449 {
450  mCalendarDisabled = !enabled;
451  emit mInstance->daemonRunning(enabled);
452 }
453 
454 /******************************************************************************
455 * Tell the alarm daemon to stop or start monitoring the calendar file as
456 * appropriate.
457 */
458 void Daemon::setAlarmsEnabled(bool enable)
459 {
460  kdDebug(5950) << "Daemon::setAlarmsEnabled(" << enable << ")\n";
461  if (enable && !checkIfRunning())
462  {
463  // The daemon is not running, so start it
464  if (!start())
465  {
466  emit daemonRunning(false);
467  return;
468  }
469  mEnableCalPending = true;
470  setFastCheck();
471  }
472 
473  // If the daemon is now running, tell it to enable/disable the calendar
474  if (checkIfRunning())
475  enableCalendar(enable);
476 }
477 
478 /******************************************************************************
479 * Return whether the alarm daemon is monitoring alarms.
480 */
481 bool Daemon::monitoringAlarms()
482 {
483  bool ok = !mCalendarDisabled && isRunning();
484  emit mInstance->daemonRunning(ok);
485  return ok;
486 }
487 
488 /******************************************************************************
489 * Check whether the alarm daemon is currently running and available.
490 */
491 bool Daemon::isRunning(bool startdaemon)
492 {
493  static bool runState = false;
494  updateRegisteredStatus();
495  bool newRunState = (mStatus == READY || mStatus == REGISTERED);
496  if (newRunState != runState)
497  {
498  // Daemon's status has changed
499  runState = newRunState;
500  if (runState && startdaemon)
501  start(); // re-register with the daemon
502  }
503  return runState && (mStatus == REGISTERED);
504 }
505 
506 /******************************************************************************
507 * Called by the timer to check whether the daemon is running.
508 */
509 void Daemon::timerCheckIfRunning()
510 {
511  checkIfRunning();
512  // Limit how long we check at the fast rate
513  if (mStatusTimerCount > 0 && --mStatusTimerCount <= 0)
514  mStatusTimer->changeInterval(mStatusTimerInterval * 1000);
515 }
516 
517 /******************************************************************************
518 * Check whether the alarm daemon is currently running.
519 * If its status has changed, trigger GUI updates.
520 */
521 bool Daemon::checkIfRunning()
522 {
523  bool newstatus = isRunning();
524  if (newstatus != mRunning)
525  {
526  mRunning = newstatus;
527  int status = mRunning && !mCalendarDisabled;
528  emit mInstance->daemonRunning(status);
529  mStatusTimer->changeInterval(mStatusTimerInterval * 1000); // exit from fast checking
530  mStatusTimerCount = 0;
531  if (mRunning)
532  {
533  // The alarm daemon has started up
534  if (mEnableCalPending)
535  enableCalendar(true); // tell it to monitor the calendar, if appropriate
536  }
537  }
538  return mRunning;
539 }
540 
541 /******************************************************************************
542 * Starts checking at a faster rate whether the daemon is running.
543 */
544 void Daemon::setFastCheck()
545 {
546  mStatusTimer->start(500); // check new status every half second
547  mStatusTimerCount = 20; // don't check at this rate for more than 10 seconds
548 }
549 
550 /******************************************************************************
551 * Called when a program setting has changed.
552 * If the system tray icon update interval has changed, reset the timer.
553 */
554 void Daemon::slotPreferencesChanged()
555 {
556  int newInterval = Preferences::daemonTrayCheckInterval();
557  if (newInterval != mStatusTimerInterval)
558  {
559  // Daemon check interval has changed
560  mStatusTimerInterval = newInterval;
561  if (mStatusTimerCount <= 0) // don't change if on fast rate
562  mStatusTimer->changeInterval(mStatusTimerInterval * 1000);
563  }
564 }
565 
566 /******************************************************************************
567 * Create an "Alarms Enabled/Enable Alarms" action.
568 */
569 AlarmEnableAction* Daemon::createAlarmEnableAction(TDEActionCollection* actions, const char* name)
570 {
571  AlarmEnableAction* a = new AlarmEnableAction(0, actions, name);
572  connect(a, TQ_SIGNAL(userClicked(bool)), mInstance, TQ_SLOT(setAlarmsEnabled(bool)));
573  connect(mInstance, TQ_SIGNAL(daemonRunning(bool)), a, TQ_SLOT(setCheckedActual(bool)));
574  return a;
575 }
576 
577 /******************************************************************************
578 * Called when a calendar has been saved.
579 * If it's the active alarm calendar, notify the alarm daemon.
580 */
581 void Daemon::slotCalendarSaved(AlarmCalendar* cal)
582 {
583  if (cal == AlarmCalendar::activeCalendar())
584  {
585  int n = mSavingEvents.count();
586  if (n)
587  {
588  // We have just saved a modified event originally triggered by the daemon.
589  // Notify the daemon of the event, and tell it to reload the calendar.
590  for (int i = 0; i < n - 1; ++i)
591  notifyEventHandled(mSavingEvents[i], false);
592  notifyEventHandled(mSavingEvents[n - 1], true);
593  mSavingEvents.clear();
594  }
595  else
596  reload();
597  }
598 }
599 
600 /******************************************************************************
601 * Note an event ID which has been triggered by the alarm daemon.
602 */
603 void Daemon::queueEvent(const TQString& eventId)
604 {
605  mQueuedEvents += eventId;
606 }
607 
608 /******************************************************************************
609 * Note an event ID which is currently being saved in the calendar file, if the
610 * event was originally triggered by the alarm daemon.
611 */
612 void Daemon::savingEvent(const TQString& eventId)
613 {
614  if (mQueuedEvents.remove(eventId) > 0)
615  mSavingEvents += eventId;
616 }
617 
618 /******************************************************************************
619 * If the event ID has been triggered by the alarm daemon, tell the daemon that
620 * it has been processed, and whether to reload its calendar.
621 */
622 void Daemon::eventHandled(const TQString& eventId, bool reloadCal)
623 {
624  if (mQueuedEvents.remove(eventId) > 0)
625  notifyEventHandled(eventId, reloadCal); // it's a daemon event, so tell daemon that it's been handled
626  else if (reloadCal)
627  reload(); // not a daemon event, so simply tell the daemon to reload the calendar
628 }
629 
630 /******************************************************************************
631 * Tell the daemon that an event has been processed, and whether to reload its
632 * calendar.
633 */
634 void Daemon::notifyEventHandled(const TQString& eventId, bool reloadCal)
635 {
636  kdDebug(5950) << "Daemon::notifyEventHandled(" << eventId << (reloadCal ? "): reload" : ")") << endl;
637  AlarmDaemonIface_stub s(DAEMON_APP_NAME, DAEMON_DCOP_OBJECT);
638  s.eventHandled(TQCString(kapp->aboutData()->appName()), AlarmCalendar::activeCalendar()->urlString(), eventId, reloadCal);
639  if (!s.ok())
640  kdError(5950) << "Daemon::notifyEventHandled(): eventHandled dcop send failed" << endl;
641 }
642 
643 /******************************************************************************
644 * Return the maximum time (in seconds) elapsed since the last time the alarm
645 * daemon must have checked alarms.
646 */
647 int Daemon::maxTimeSinceCheck()
648 {
649  return DAEMON_CHECK_INTERVAL;
650 }
651 
652 
653 /*=============================================================================
654 = Class: NotificationHandler
655 =============================================================================*/
656 
657 NotificationHandler::NotificationHandler()
658  : DCOPObject(NOTIFY_DCOP_OBJECT),
659  TQObject()
660 {
661  kdDebug(5950) << "NotificationHandler::NotificationHandler()\n";
662 }
663 
664 /******************************************************************************
665  * DCOP call from the alarm daemon to notify a change.
666  * The daemon notifies calendar statuses when we first register as a GUI, and whenever
667  * a calendar status changes. So we don't need to read its config files.
668  */
669 void NotificationHandler::alarmDaemonUpdate(int calendarStatus, const TQString& calendarURL)
670 {
671  kdDebug(5950) << "NotificationHandler::alarmDaemonUpdate(" << calendarStatus << ")\n";
672  KAlarmd::CalendarStatus status = KAlarmd::CalendarStatus(calendarStatus);
673  if (expandURL(calendarURL) != AlarmCalendar::activeCalendar()->urlString())
674  return; // it's not a notification about KAlarm's calendar
675  bool enabled = false;
676  switch (status)
677  {
678  case KAlarmd::CALENDAR_UNAVAILABLE:
679  // Calendar is not available for monitoring
680  kdDebug(5950) << "NotificationHandler::alarmDaemonUpdate(CALENDAR_UNAVAILABLE)\n";
681  break;
682  case KAlarmd::CALENDAR_DISABLED:
683  // Calendar is available for monitoring but is not currently being monitored
684  kdDebug(5950) << "NotificationHandler::alarmDaemonUpdate(DISABLE_CALENDAR)\n";
685  break;
686  case KAlarmd::CALENDAR_ENABLED:
687  // Calendar is currently being monitored
688  kdDebug(5950) << "NotificationHandler::alarmDaemonUpdate(ENABLE_CALENDAR)\n";
689  enabled = true;
690  break;
691  default:
692  return;
693  }
694  Daemon::calendarIsEnabled(enabled);
695 }
696 
697 /******************************************************************************
698  * DCOP call from the alarm daemon to notify that an alarm is due.
699  */
700 void NotificationHandler::handleEvent(const TQString& url, const TQString& eventId)
701 {
702  TQString id = eventId;
703  if (id.startsWith(TQString::fromLatin1("ad:")))
704  {
705  // It's a notification from the alarm deamon
706  id = id.mid(3);
707  Daemon::queueEvent(id);
708  }
709  theApp()->handleEvent(url, id);
710 }
711 
712 /******************************************************************************
713  * DCOP call from the alarm daemon to notify the success or failure of a
714  * registration request from KAlarm.
715  */
716 void NotificationHandler::registered(bool reregister, int result, int version)
717 {
718  Daemon::registrationResult(reregister, result, version);
719 }
720 
721 
722 /*=============================================================================
723 = Class: AlarmEnableAction
724 =============================================================================*/
725 
726 AlarmEnableAction::AlarmEnableAction(int accel, TQObject* parent, const char* name)
727  : TDEToggleAction(i18n("Enable &Alarms"), accel, parent, name),
728  mInitialised(false)
729 {
730  setCheckedState(i18n("Disable &Alarms"));
731  setCheckedActual(false); // set the correct text
732  mInitialised = true;
733 }
734 
735 /******************************************************************************
736 * Set the checked status and the correct text for the Alarms Enabled action.
737 */
738 void AlarmEnableAction::setCheckedActual(bool running)
739 {
740  kdDebug(5950) << "AlarmEnableAction::setCheckedActual(" << running << ")\n";
741  if (running != isChecked() || !mInitialised)
742  {
743  TDEToggleAction::setChecked(running);
744  emit switched(running);
745  }
746 }
747 
748 /******************************************************************************
749 * Request a change in the checked status.
750 * The status is only actually changed when the alarm daemon run state changes.
751 */
752 void AlarmEnableAction::setChecked(bool check)
753 {
754  kdDebug(5950) << "AlarmEnableAction::setChecked(" << check << ")\n";
755  if (check != isChecked())
756  {
757  if (check)
758  Daemon::allowRegisterFailMsg();
759  emit userClicked(check);
760  }
761 }
762 
763 
764 /******************************************************************************
765  * Expand a DCOP call parameter URL to a full URL.
766  * (We must store full URLs in the calendar data since otherwise later calls to
767  * reload or remove calendars won't necessarily find a match.)
768  */
769 TQString expandURL(const TQString& urlString)
770 {
771  if (urlString.isEmpty())
772  return TQString();
773  return KURL(urlString).url();
774 }
Provides read and write access to calendar files.
Definition: alarmcalendar.h:37
the KAlarm application object