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 <tdestandarddirs.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
44static const int REGISTER_TIMEOUT = 20; // seconds to wait before assuming registration with daemon has failed
45static const char* NOTIFY_DCOP_OBJECT = "notify"; // DCOP name of KAlarm's interface for notification by alarm daemon
46
47static TQString expandURL(const TQString& urlString);
48
49
50/*=============================================================================
51= Class: NotificationHandler
52= Handles the the alarm daemon's client notification DCOP interface.
53=============================================================================*/
54
55class 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
67Daemon* Daemon::mInstance = 0;
68NotificationHandler* Daemon::mDcopHandler = 0;
69TQValueList<TQString> Daemon::mQueuedEvents;
70TQValueList<TQString> Daemon::mSavingEvents;
71TQTimer* Daemon::mStartTimer = 0;
72TQTimer* Daemon::mRegisterTimer = 0;
73TQTimer* Daemon::mStatusTimer = 0;
74int Daemon::mStatusTimerCount = 0;
75int Daemon::mStatusTimerInterval;
76int Daemon::mStartTimeout = 0;
77Daemon::Status Daemon::mStatus = Daemon::STOPPED;
78bool Daemon::mRunning = false;
79bool Daemon::mCalendarDisabled = false;
80bool Daemon::mEnableCalPending = false;
81bool 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.
86static 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*/
94void 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*/
104void 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*/
125bool 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*/
172bool 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 = tdeApp->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, tdeApp->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*/
212void 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: " << tdeApp->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(tdeApp->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*/
284void 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*/
315void Daemon::updateRegisteredStatus(bool timeout)
316{
317 if (!tdeApp->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*/
350bool Daemon::stop()
351{
352 kdDebug(5950) << "Daemon::stop()" << endl;
353 if (tdeApp->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*/
371bool Daemon::reset()
372{
373 kdDebug(5950) << "Daemon::reset()" << endl;
374 if (!tdeApp->dcopClient()->isApplicationRegistered(DAEMON_APP_NAME))
375 return false;
376 AlarmDaemonIface_stub s(DAEMON_APP_NAME, DAEMON_DCOP_OBJECT);
377 s.resetCalendar(TQCString(tdeApp->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*/
386void Daemon::reload()
387{
388 kdDebug(5950) << "Daemon::reload()\n";
389 AlarmDaemonIface_stub s(DAEMON_APP_NAME, DAEMON_DCOP_OBJECT);
390 s.reloadCalendar(TQCString(tdeApp->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*/
398void 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*/
408void 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*/
426void 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*/
437bool 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*/
448void 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*/
458void 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*/
481bool 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*/
491bool 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*/
509void 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*/
521bool 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*/
544void 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*/
554void 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*/
569AlarmEnableAction* 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*/
581void 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*/
603void 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*/
612void 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*/
622void 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*/
634void 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(tdeApp->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*/
647int Daemon::maxTimeSinceCheck()
648{
649 return DAEMON_CHECK_INTERVAL;
650}
651
652
653/*=============================================================================
654= Class: NotificationHandler
655=============================================================================*/
656
657NotificationHandler::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 */
669void 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 */
700void 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 */
716void NotificationHandler::registered(bool reregister, int result, int version)
717{
718 Daemon::registrationResult(reregister, result, version);
719}
720
721
722/*=============================================================================
723= Class: AlarmEnableAction
724=============================================================================*/
725
726AlarmEnableAction::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*/
738void 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*/
752void 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 */
769TQString 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