00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
#include <unistd.h>
00028
#include <stdlib.h>
00029
00030
#include <qtimer.h>
00031
#include <qfile.h>
00032
#include <qdatetime.h>
00033
00034
#include <kapplication.h>
00035
#include <kstandarddirs.h>
00036
#include <kdebug.h>
00037
#include <klocale.h>
00038
#include <ksimpleconfig.h>
00039
#include <kprocess.h>
00040
#include <kio/netaccess.h>
00041
#include <dcopclient.h>
00042
00043
#include <libkcal/calendarlocal.h>
00044
#include <libkcal/icalformat.h>
00045
00046
#include "alarmguiiface_stub.h"
00047
#include "alarmapp.h"
00048
00049
#include "alarmdaemon.h"
00050
#include "alarmdaemon.moc"
00051
00052
00053 AlarmDaemon::AlarmDaemon(
QObject *parent,
const char *name)
00054 : DCOPObject(name),
QObject(parent, name)
00055 {
00056 kdDebug(5900) <<
"AlarmDaemon::AlarmDaemon()" << endl;
00057
00058 readCheckInterval();
00059 readDaemonData(
false);
00060
00061 enableAutoStart(
true);
00062
00063
00064 mAlarmTimer =
new QTimer(
this);
00065 connect( mAlarmTimer, SIGNAL( timeout() ), SLOT( checkAlarmsSlot() ));
00066 setTimerStatus();
00067 checkAlarms();
00068 }
00069
00070 AlarmDaemon::~AlarmDaemon()
00071 {
00072 }
00073
00074
00075
00076
00077
void AlarmDaemon::quit()
00078 {
00079 kdDebug(5900) <<
"AlarmDaemon::quit()" << endl;
00080 exit(0);
00081 }
00082
00083
void AlarmDaemon::dumpDebug()
00084 {
00085 kdDebug(5900) <<
"AlarmDaemon::dumpDebug()" << endl;
00086
00087
for( ADCalendarBase *cal = mCalendars.first(); cal; cal = mCalendars.next() ) {
00088 cal->dump();
00089 }
00090
00091 kdDebug(5900) <<
"AlarmDaemon::dumpDebug() done" << endl;
00092 }
00093
00094
00095
00096
00097
void AlarmDaemon::enableCal_(
const QString& urlString,
bool enable)
00098 {
00099 kdDebug(5900) <<
"AlarmDaemon::enableCal_(" << urlString <<
")" << endl;
00100
00101 ADCalendarBase* cal = getCalendar(urlString);
00102
if (cal)
00103 {
00104 cal->setEnabled( enable );
00105 notifyGuiCalStatus(cal);
00106 }
00107 }
00108
00109
00110
00111
00112
00113
void AlarmDaemon::addCal_(
const QCString& appname,
const QString& urlString,
bool msgCal)
00114 {
00115 kdDebug(5900) <<
"AlarmDaemon::addCal_(" << urlString <<
"): " << (msgCal ?
"KALARM" :
"KORGANIZER") << endl;
00116
00117 ADCalendarBase* cal = getCalendar(urlString);
00118
if (cal)
00119 {
00120
00121
if (!cal->unregistered())
00122
return;
00123
if (cal->appName() == appname)
00124 {
00125 cal->setUnregistered(
false );
00126 reloadCal_(cal);
00127
return;
00128 }
00129
00130 mCalendars.remove(cal);
00131 }
00132
00133
00134 cal =
new ADCalendar(urlString, appname, (msgCal ? ADCalendar::KALARM : ADCalendar::KORGANIZER));
00135 mCalendars.append(cal);
00136
00137 addConfigCalendar(appname, cal);
00138
00139
if (cal->loaded())
00140 notifyGui((msgCal ? ADD_MSG_CALENDAR : ADD_CALENDAR), cal->urlString(), appname);
00141 kdDebug(5900) <<
"AlarmDaemon::addCal_(): calendar added" << endl;
00142
00143 setTimerStatus();
00144 checkAlarms(cal);
00145 }
00146
00147
00148
00149
00150
00151
void AlarmDaemon::reloadCal_(
const QCString& appname,
const QString& urlString,
bool msgCal)
00152 {
00153 kdDebug(5900) <<
"AlarmDaemon::reloadCal_(" << urlString <<
"): " << (msgCal ?
"KALARM" :
"KORGANIZER") << endl;
00154
00155
if (!urlString.isEmpty())
00156 {
00157 ADCalendarBase* cal = getCalendar(urlString);
00158
if (cal)
00159 reloadCal_(cal);
00160
else
00161 {
00162
00163
if (!appname.isEmpty())
00164 addCal_(appname, urlString, msgCal);
00165 }
00166 }
00167 }
00168
00169
00170
00171
00172
void AlarmDaemon::reloadCal_(ADCalendarBase* cal)
00173 {
00174 kdDebug(5900) <<
"AlarmDaemon::reloadCal_(): calendar" << endl;
00175
00176
if (cal && !cal->downloading())
00177 {
00178 cal->close();
00179
if (!cal->setLoadedConnected()) {
00180 connect( cal, SIGNAL( loaded(ADCalendarBase*,
bool) ),
00181 SLOT( calendarLoaded(ADCalendarBase*,
bool) ) );
00182 }
00183 cal->loadFile();
00184 }
00185 }
00186
00187
void AlarmDaemon::calendarLoaded(ADCalendarBase* cal,
bool success)
00188 {
00189
if (success)
00190 kdDebug(5900) <<
"Calendar reloaded" << endl;
00191 notifyGuiCalStatus(cal);
00192 setTimerStatus();
00193 checkAlarms(cal);
00194 }
00195
00196
00197
00198
00199
00200
void AlarmDaemon::resetMsgCal_(
const QCString& appname,
const QString& urlString)
00201 {
00202 kdDebug(5900) <<
"AlarmDaemon::resetMsgCal_(" << urlString <<
")\n";
00203
00204
if (!urlString.isEmpty())
00205 {
00206 reloadCal_(appname, urlString,
true);
00207 ADCalendar::clearEventsHandled(urlString);
00208 ADCalendarBase* cal = getCalendar(urlString);
00209
if (cal)
00210 checkAlarms(cal);
00211 }
00212 }
00213
00214
00215
void AlarmDaemon::removeCal_(
const QString& urlString)
00216 {
00217 kdDebug(5900) <<
"AlarmDaemon::removeCal_(" << urlString <<
")\n";
00218
00219 ADCalendarBase* cal = getCalendar(urlString);
00220
if (cal)
00221 {
00222 deleteConfigCalendar(cal);
00223 mCalendars.remove(cal);
00224 kdDebug(5900) <<
"AlarmDaemon::removeCal_(): calendar removed" << endl;
00225 notifyGui(DELETE_CALENDAR, urlString);
00226 setTimerStatus();
00227 }
00228 }
00229
00230
00231
00232
00233
00234
void AlarmDaemon::registerApp_(
const QCString& appName,
const QString& appTitle,
00235
const QCString& dcopObject,
int notificationType,
00236
bool displayCalendarName,
bool reregister)
00237 {
00238 kdDebug(5900) <<
"AlarmDaemon::registerApp_(" << appName <<
", " << appTitle <<
", "
00239 << dcopObject <<
", " << notificationType <<
", " << reregister <<
")" << endl;
00240
bool result =
true;
00241
if (appName.isEmpty())
00242 result =
false;
00243
else if (KStandardDirs::findExe(appName).isNull()) {
00244 kdError() <<
"AlarmDaemon::registerApp(): app not found\n";
00245 result =
false;
00246 }
00247
else {
00248 ClientInfo c = getClientInfo(appName);
00249
if (c.isValid())
00250 {
00251
00252
if (!reregister) {
00253
00254
for (ADCalendarBase* cal = mCalendars.first(); cal; cal = mCalendars.next())
00255 {
00256
if (cal->appName() == appName)
00257 cal->setUnregistered(
true );
00258 }
00259 }
00260 removeClientInfo(appName);
00261 }
00262 ClientInfo cinfo(appName, appTitle, dcopObject, notificationType,
00263 displayCalendarName);
00264 mClients.append(cinfo);
00265
00266 writeConfigClient(appName, cinfo);
00267
00268 enableAutoStart(
true);
00269 notifyGui(CHANGE_CLIENT);
00270 setTimerStatus();
00271 }
00272
00273
00274
00275
00276
00277
00278 AlarmGuiIface_stub stub( appName, dcopObject );
00279 stub.registered( reregister, result );
00280 kdDebug(5900) <<
"AlarmDaemon::registerApp_() -> " << result << endl;
00281 }
00282
00283
00284
00285
00286
void AlarmDaemon::enableAutoStart(
bool on)
00287 {
00288 kdDebug(5900) <<
"AlarmDaemon::enableAutoStart(" << (
int)on <<
")\n";
00289 KConfig* config = kapp->config();
00290 config->setGroup(
"General");
00291 config->writeEntry(
"Autostart", on);
00292 config->sync();
00293 notifyGui(CHANGE_STATUS);
00294 }
00295
00296
00297
00298
00299
void AlarmDaemon::readConfig()
00300 {
00301 kdDebug(5900) <<
"AlarmDaemon::readConfig()\n";
00302 kapp->config()->reparseConfiguration();
00303
int oldCheckInterval = mCheckInterval;
00304 readCheckInterval();
00305
if (mCheckInterval != oldCheckInterval) {
00306 mAlarmTimer->stop();
00307 setTimerStatus();
00308 notifyGui(CHANGE_STATUS);
00309
00310
00311
00312
00313
00314 checkAlarms();
00315 }
00316 }
00317
00318
00319
00320
00321
void AlarmDaemon::readCheckInterval()
00322 {
00323 KConfig* config = kapp->config();
00324 config->setGroup(
"General");
00325 mCheckInterval = config->readNumEntry(
"CheckInterval", 1);
00326
if (mCheckInterval < 1)
00327 mCheckInterval = 1;
00328 }
00329
00330
00331
00332
00333
00334
00335
void AlarmDaemon::checkAlarmsSlot()
00336 {
00337 kdDebug(5901) <<
"AlarmDaemon::checkAlarmsSlot()" << endl;
00338
00339
if (mAlarmTimerSyncing)
00340 {
00341
00342 mAlarmTimer->changeInterval(mCheckInterval * 60 * 1000);
00343 mAlarmTimerSyncing =
false;
00344 }
00345 checkAlarms();
00346 }
00347
00348
00349
00350
00351
00352
void AlarmDaemon::checkAlarms()
00353 {
00354 kdDebug(5901) <<
"AlarmDaemon::checkAlarms()" << endl;
00355
00356
for( ADCalendarBase *cal = mCalendars.first(); cal; cal = mCalendars.next() ) {
00357 checkAlarms( cal );
00358 }
00359 }
00360
00361
00362
00363
00364
00365
void AlarmDaemon::checkAlarms(
const QCString& appName)
00366 {
00367
for (ADCalendarBase* cal = mCalendars.first(); cal; cal = mCalendars.next()) {
00368
if (cal->appName() == appName) {
00369 checkAlarms( cal );
00370 }
00371 }
00372 }
00373
00374
00375
00376
00377
00378
00379
bool AlarmDaemon::checkAlarms( ADCalendarBase* cal )
00380 {
00381 kdDebug(5901) <<
"AlarmDaemons::checkAlarms(" << cal->urlString() <<
")" << endl;
00382
00383
if ( !cal->loaded() || !cal->enabled() )
00384
return false;
00385
00386
QDateTime to = QDateTime::currentDateTime();
00387
00388
QPtrList<Event> alarmEvents;
00389
QValueList<Alarm*> alarms;
00390
QValueList<Alarm*>::ConstIterator it;
00391
switch ( cal->actionType() ) {
00392
case ADCalendar::KORGANIZER: {
00393
QDateTime from = cal->lastCheck().addSecs(1);
00394 kdDebug(5901) <<
" From: " << from.toString() <<
" To: " << to.toString() << endl;
00395
00396
bool pending =
false;
00397 alarms = cal->alarms( from, to );
00398
for ( it = alarms.begin(); it != alarms.end(); ++it ) {
00399 kdDebug(5901) <<
"AlarmDaemon::checkAlarms(): KORGANIZER event "
00400 << (*it)->parent()->uid() << endl;
00401
if (!notifyEvent(cal, (*it)->parent()->uid()))
00402 pending =
true;
00403 }
00404
00405
if (!pending) {
00406 cal->setLastCheck(to);
00407 writeConfigCalendar(cal);
00408
return true;
00409 }
00410
break;
00411 }
00412
case ADCalendar::KALARM:
00413 kdDebug(5901) <<
" To: " << to.toString() << endl;
00414 alarms = cal->alarmsTo( to );
00415
if (alarms.count()) {
00416 kdDebug(5901) <<
"Kalarm alarms=" << alarms.count() << endl;
00417
for ( it = alarms.begin(); it != alarms.end(); ++it ) {
00418 Event *event = dynamic_cast<Event *>( (*it)->parent() );
00419
if ( event ) {
00420
const QString& eventID = event->uid();
00421 kdDebug(5901) <<
"AlarmDaemon::checkAlarms(): KALARM event " << eventID << endl;
00422
QValueList<QDateTime> alarmtimes;
00423 checkEventAlarms(*event, alarmtimes);
00424
if (!cal->eventHandled(event, alarmtimes)) {
00425
if (notifyEvent(cal, eventID))
00426 cal->setEventHandled(event, alarmtimes);
00427
else
00428 ;
00429 }
00430 }
00431 }
00432 }
00433
break;
00434 }
00435
00436
return false;
00437 }
00438
00439
00440
00441
00442
00443
void AlarmDaemon::checkEventAlarms(
const Event& event,
QValueList<QDateTime>& alarmtimes)
00444 {
00445 alarmtimes.clear();
00446
QDateTime now = QDateTime::currentDateTime();
00447 Alarm::List alarms = event.alarms();
00448 Alarm::List::ConstIterator it;
00449
for ( it = alarms.begin(); it != alarms.end(); ++it ) {
00450 Alarm *alarm = *it;
00451 alarmtimes.append((alarm->enabled() && alarm->time() <= now) ? alarm->time() :
QDateTime());
00452 }
00453 }
00454
00455
00456
00457
00458
00459
00460
00461
bool AlarmDaemon::notifyEvent(ADCalendarBase* calendar,
const QString& eventID)
00462 {
00463 kdDebug(5900) <<
"AlarmDaemon::notifyEvent(" << eventID <<
")\n";
00464
if (calendar)
00465 {
00466 ClientInfo client = getClientInfo(calendar->appName());
00467 kdDebug(5900) <<
" appName: " << calendar->appName()
00468 <<
" notification type=" << client.notificationType << endl;
00469
if (!client.isValid()) {
00470 kdDebug(5900) <<
"AlarmDaemon::notifyEvent(): unknown client" << endl;
00471
return false;
00472 }
00473
if (client.waitForRegistration)
00474 {
00475
00476
00477
00478
00479
00480
00481 kdDebug(5900) <<
"AlarmDaemon::notifyEvent(): wait for session startup" << endl;
00482
return false;
00483 }
00484
00485
bool registered = kapp->dcopClient()->isApplicationRegistered(static_cast<const char*>(calendar->appName()));
00486
bool ready = registered;
00487
if (registered)
00488 {
00489 QCStringList objects = kapp->dcopClient()->remoteObjects(calendar->appName());
00490
if (objects.find(client.dcopObject) == objects.end())
00491 ready =
false;
00492 }
00493
if (!ready)
00494 {
00495
00496
00497
if (client.notificationType == ClientInfo::NO_START_NOTIFY
00498 || client.notificationType == ClientInfo::DCOP_SIMPLE_NOTIFY) {
00499
if (registered)
00500 kdDebug(5900) <<
"AlarmDaemon::notifyEvent(): client not ready\n";
00501
else
00502 kdDebug(5900) <<
"AlarmDaemon::notifyEvent(): don't start client\n";
00503
return false;
00504 }
00505
00506
00507 KProcess p;
00508
QString cmd = locate(
"exe", calendar->appName());
00509
if (cmd.isEmpty()) {
00510 kdDebug(5900) <<
"AlarmDaemon::notifyEvent(): '"
00511 << calendar->appName() <<
"' not found" << endl;
00512
return true;
00513 }
00514 p << cmd;
00515
if (client.notificationType == ClientInfo::COMMAND_LINE_NOTIFY)
00516 {
00517
00518 p <<
"--handleEvent" << eventID <<
"--calendarURL" << calendar->urlString();
00519 p.start(KProcess::Block);
00520 kdDebug(5900) <<
"AlarmDaemon::notifyEvent(): used command line" << endl;
00521
return true;
00522 }
00523
00524
00525 p.start(KProcess::Block);
00526 kdDebug(5900) <<
"AlarmDaemon::notifyEvent(): started " << cmd << endl;
00527
return false;
00528 }
00529
00530
if (client.notificationType == ClientInfo::DCOP_SIMPLE_NOTIFY)
00531 {
00532 Incidence *incidence = calendar->event( eventID );
00533
if (!incidence) {
00534 incidence = calendar->todo( eventID );
00535
if(!incidence) {
00536 kdDebug(5900) <<
"AlarmDaemon::notifyEvent(): null incidence\n";
00537
return true;
00538 }
00539 }
00540
00541 kdDebug() <<
"--- DCOP send: handleEvent(): " << incidence->summary() << endl;
00542
00543 CalendarLocal cal;
00544 cal.addIncidence( incidence->clone() );
00545
00546 ICalFormat format;
00547
00548 AlarmGuiIface_stub stub( calendar->appName(), client.dcopObject );
00549 stub.handleEvent( format.toString( &cal ) );
00550
if ( !stub.ok() ) {
00551 kdDebug(5900) <<
"AlarmDaemon::notifyEvent(): dcop send failed" << endl;
00552
return false;
00553 }
00554 }
00555
else
00556 {
00557 AlarmGuiIface_stub stub( calendar->appName(), client.dcopObject );
00558 stub.handleEvent( calendar->urlString(), eventID );
00559
if ( !stub.ok() ) {
00560 kdDebug(5900) <<
"AlarmDaemon::notifyEvent(): dcop send failed" << endl;
00561
return false;
00562 }
00563 }
00564 }
00565
return true;
00566 }
00567
00568
00569
00570
00571
void AlarmDaemon::setTimerStatus()
00572 {
00573
00574
int nLoaded = 0;
00575
for (ADCalendarBase* cal = mCalendars.first(); cal; cal = mCalendars.next()) {
00576
if (cal->loaded())
00577 ++nLoaded;
00578 }
00579
00580
00581
if (!mAlarmTimer->isActive() && nLoaded)
00582 {
00583
00584
00585
int checkInterval = mCheckInterval * 60;
00586
int firstInterval = checkInterval + 1 - QTime::currentTime().second();
00587 mAlarmTimer->start(1000 * firstInterval);
00588 mAlarmTimerSyncing = (firstInterval != checkInterval);
00589 kdDebug(5900) <<
"Started alarm timer" << endl;
00590 }
00591
else if (mAlarmTimer->isActive() && !nLoaded)
00592 {
00593 mAlarmTimer->stop();
00594 kdDebug(5900) <<
"Stopped alarm timer" << endl;
00595 }
00596 }
00597
00598
00599
00600
00601
00602
void AlarmDaemon::registerGui(
const QCString& appName,
const QCString& dcopObject)
00603 {
00604 kdDebug(5900) <<
"AlarmDaemon::registerGui(" << appName <<
")\n";
00605
if (appName.isEmpty())
00606
return;
00607
const GuiInfo* g = getGuiInfo(appName);
00608
if (g)
00609 mGuis.remove(appName);
00610 mGuis.insert(appName, GuiInfo(dcopObject));
00611
00612 writeConfigClientGui(appName, dcopObject);
00613
00614
for (ADCalendarBase* cal = mCalendars.first(); cal; cal = mCalendars.next()) {
00615 notifyGuiCalStatus(cal);
00616 }
00617 }
00618
00619
00620
00621
00622
00623
void AlarmDaemon::notifyGuiCalStatus(
const ADCalendarBase* cal)
00624 {
00625 notifyGui((cal->available() ? (cal->enabled() ? ENABLE_CALENDAR : DISABLE_CALENDAR) : CALENDAR_UNAVAILABLE),
00626 cal->urlString());
00627 }
00628
00629
00630
00631
00632
void AlarmDaemon::notifyGui(AlarmGuiChangeType change,
const QString& calendarURL)
00633 {
00634 notifyGui( change, calendarURL,
"" );
00635 }
00636
00637
void AlarmDaemon::notifyGui(AlarmGuiChangeType change,
const QString& calendarURL,
const QCString& appName)
00638 {
00639 kdDebug(5900) <<
"AlarmDaemon::notifyGui(" << change <<
")\n";
00640
00641
for (GuiMap::ConstIterator g = mGuis.begin(); g != mGuis.end(); ++g)
00642 {
00643
QCString dcopObject = g.data().dcopObject;
00644
if (kapp->dcopClient()->isApplicationRegistered(static_cast<const char*>(g.key())))
00645 {
00646 kdDebug(5900)<<
"AlarmDaemon::notifyGui() sending:" << g.key()<<
" ->" << dcopObject <<endl;
00647
00648 AlarmGuiIface_stub stub( g.key(), dcopObject );
00649 stub.alarmDaemonUpdate( change, calendarURL, appName );
00650
if ( !stub.ok() )
00651 kdDebug(5900) <<
"AlarmDaemon::guiNotify(): dcop send failed:" << g.key() << endl;
00652 }
00653 }
00654 }
00655
00656
00657
const AlarmDaemon::GuiInfo* AlarmDaemon::getGuiInfo(
const QCString& appName)
const
00658
{
00659
if (!appName.isEmpty())
00660 {
00661 GuiMap::ConstIterator g = mGuis.find(appName);
00662
if (g != mGuis.end())
00663
return &g.data();
00664 }
00665
return 0;
00666 }
00667
00668
QStringList AlarmDaemon::dumpAlarms()
00669 {
00670
QDateTime start =
QDateTime( QDateTime::currentDateTime().date(),
00671
QTime( 0, 0 ) );
00672
QDateTime end = start.addDays( 1 ).addSecs( -1 );
00673
00674
QStringList lst;
00675
00676 lst <<
QString(
"AlarmDeamon::dumpAlarms() from ")+start.toString()+
" to " + end.toString();
00677
00678
CalendarList cals = calendars();
00679 ADCalendarBase *cal;
00680
for( cal = cals.first(); cal; cal = cals.next() ) {
00681 lst <<
QString(
" Cal: ") + cal->urlString();
00682
QValueList<Alarm*> alarms = cal->alarms( start, end );
00683
QValueList<Alarm*>::ConstIterator it;
00684
for( it = alarms.begin(); it != alarms.end(); ++it ) {
00685 Alarm *a = *it;
00686 lst <<
QString(
" ") + a->parent()->summary() +
" ("
00687 + a->time().toString() +
")";
00688 }
00689 }
00690
return lst;
00691 }