summaryrefslogtreecommitdiffstats
path: root/kalarm/kalarmd
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commit460c52653ab0dcca6f19a4f492ed2c5e4e963ab0 (patch)
tree67208f7c145782a7e90b123b982ca78d88cc2c87 /kalarm/kalarmd
downloadtdepim-460c52653ab0dcca6f19a4f492ed2c5e4e963ab0.tar.gz
tdepim-460c52653ab0dcca6f19a4f492ed2c5e4e963ab0.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdepim@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kalarm/kalarmd')
-rw-r--r--kalarm/kalarmd/Makefile.am28
-rw-r--r--kalarm/kalarmd/adapp.cpp71
-rw-r--r--kalarm/kalarmd/adapp.h42
-rw-r--r--kalarm/kalarmd/adcalendar.cpp253
-rw-r--r--kalarm/kalarmd/adcalendar.h120
-rw-r--r--kalarm/kalarmd/adconfigdata.cpp146
-rw-r--r--kalarm/kalarmd/adconfigdata.h41
-rw-r--r--kalarm/kalarmd/admain.cpp59
-rw-r--r--kalarm/kalarmd/alarmdaemon.cpp614
-rw-r--r--kalarm/kalarmd/alarmdaemon.h79
-rw-r--r--kalarm/kalarmd/alarmdaemoniface.h45
-rw-r--r--kalarm/kalarmd/alarmguiiface.h71
-rw-r--r--kalarm/kalarmd/clientinfo.cpp110
-rw-r--r--kalarm/kalarmd/clientinfo.h72
-rw-r--r--kalarm/kalarmd/kalarmd.autostart.desktop103
-rw-r--r--kalarm/kalarmd/kalarmd.desktop55
-rw-r--r--kalarm/kalarmd/kalarmd.h40
17 files changed, 1949 insertions, 0 deletions
diff --git a/kalarm/kalarmd/Makefile.am b/kalarm/kalarmd/Makefile.am
new file mode 100644
index 00000000..7770c681
--- /dev/null
+++ b/kalarm/kalarmd/Makefile.am
@@ -0,0 +1,28 @@
+INCLUDES= -I$(top_srcdir) -I$(top_srcdir)/kalarm $(all_includes)
+
+noinst_LTLIBRARIES = libkalarmd.la
+
+libkalarmd_la_LDFLAGS = $(all_libraries) $(KDE_RPATH)
+libkalarmd_la_LIBADD = $(LIB_KDECORE) $(top_builddir)/libkcal/libkcal.la
+libkalarmd_la_SOURCES = alarmdaemoniface.stub alarmguiiface.stub
+
+bin_PROGRAMS = kalarmd
+
+kalarmd_LDFLAGS = $(all_libraries) $(KDE_RPATH)
+kalarmd_LDADD = $(LIB_KDEUI) $(top_builddir)/libkcal/libkcal.la libkalarmd.la
+kalarmd_SOURCES = alarmdaemon.cpp admain.cpp adapp.cpp \
+ adcalendar.cpp adconfigdata.cpp clientinfo.cpp \
+ alarmdaemoniface.skel
+kalarmd_COMPILE_FIRST = alarmguiiface_stub.h
+
+noinst_HEADERS = adapp.h alarmdaemon.h alarmdaemoniface.h alarmguiiface.h \
+ adcalendar.h adconfigdata.h clientinfo.h kalarmd.h
+
+METASOURCES = AUTO
+
+autostart_DATA = kalarmd.autostart.desktop
+autostartdir = $(datadir)/autostart
+
+app_DATA = kalarmd.desktop
+appdir = $(kde_appsdir)/.hidden
+
diff --git a/kalarm/kalarmd/adapp.cpp b/kalarm/kalarmd/adapp.cpp
new file mode 100644
index 00000000..77f31e4f
--- /dev/null
+++ b/kalarm/kalarmd/adapp.cpp
@@ -0,0 +1,71 @@
+/*
+ * adapp.cpp - kalarmd application
+ * Program: KAlarm's alarm daemon (kalarmd)
+ * Copyright (c) 2001, 2004, 2005 by David Jarvie <software@astrojar.org.uk>
+ * Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org>
+ * Copyright (c) 1997-1999 Preston Brown <pbrown@kde.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "kalarmd.h"
+
+#include <kcmdlineargs.h>
+#include <kdebug.h>
+
+#include "alarmdaemon.h"
+#include "adapp.moc"
+
+
+AlarmDaemonApp::AlarmDaemonApp()
+ : KUniqueApplication(false, false),
+ mAd(0)
+{
+ disableSessionManagement();
+}
+
+int AlarmDaemonApp::newInstance()
+{
+ kdDebug(5900) << "AlarmDaemonApp::newInstance()" << endl;
+
+ /* Prevent the application being restored automatically by the session manager
+ * at session startup. Instead, the KDE autostart facility is used to start
+ * the application. This allows the user to configure whether or not it is to
+ * be started automatically, and also ensures that it is started in the correct
+ * phase of session startup, i.e. after clients have been restored by the
+ * session manager.
+ */
+ disableSessionManagement();
+
+ // Check if we already have a running alarm daemon widget
+ if (mAd)
+ return 0;
+
+ // Check if we are starting up at session startup
+ static bool restored = false;
+ bool autostart = false;
+ if (!restored && isRestored())
+ restored = true; // make sure we restore only once
+ else
+ {
+ KCmdLineArgs* args = KCmdLineArgs::parsedArgs();
+ autostart = args->isSet("autostart");
+ args->clear(); // free up memory
+ }
+
+ mAd = new AlarmDaemon(autostart, 0, DAEMON_DCOP_OBJECT);
+
+ return 0;
+}
diff --git a/kalarm/kalarmd/adapp.h b/kalarm/kalarmd/adapp.h
new file mode 100644
index 00000000..83d11d29
--- /dev/null
+++ b/kalarm/kalarmd/adapp.h
@@ -0,0 +1,42 @@
+/*
+ * adapp.h - kalarmd application
+ * Program: KAlarm's alarm daemon (kalarmd)
+ * Copyright (C) 2001, 2004 by David Jarvie <software@astrojar.org.uk>
+ * Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org>
+ * Copyright (c) 1997-1999 Preston Brown <pbrown@kde.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef ADAPP_H
+#define ADAPP_H
+
+#include <kuniqueapplication.h>
+
+class AlarmDaemon;
+
+
+class AlarmDaemonApp : public KUniqueApplication
+{
+ Q_OBJECT
+ public:
+ AlarmDaemonApp();
+ virtual int newInstance();
+
+ private:
+ AlarmDaemon* mAd;
+};
+
+#endif // ADAPP_H
diff --git a/kalarm/kalarmd/adcalendar.cpp b/kalarm/kalarmd/adcalendar.cpp
new file mode 100644
index 00000000..8af97cc0
--- /dev/null
+++ b/kalarm/kalarmd/adcalendar.cpp
@@ -0,0 +1,253 @@
+/*
+ * adcalendar.cpp - calendar file access
+ * Program: KAlarm's alarm daemon (kalarmd)
+ * Copyright (c) 2001, 2004-2006 by David Jarvie <software@astrojar.org.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <unistd.h>
+#include <assert.h>
+
+#include <qfile.h>
+
+#include <ktempfile.h>
+#include <kio/job.h>
+#include <kio/jobclasses.h>
+#include <kdebug.h>
+
+#include "adcalendar.moc"
+
+QValueList<ADCalendar*> ADCalendar::mCalendars;
+ADCalendar::EventsMap ADCalendar::mEventsHandled;
+ADCalendar::EventsMap ADCalendar::mEventsPending;
+QStringList ADCalendar::mCalendarUrls; // never delete or reorder anything in this list!
+
+
+ADCalendar::ADCalendar(const QString& url, const QCString& appname)
+ : KCal::CalendarLocal(QString::fromLatin1("UTC")),
+ mUrlString(url),
+ mAppName(appname),
+ mLoaded(false),
+ mLoadedConnected(false),
+ mUnregistered(false),
+ mEnabled(true)
+{
+ ADCalendar* cal = getCalendar(url);
+ if (cal)
+ {
+ kdError(5900) << "ADCalendar::ADCalendar(" << url << "): calendar already exists" << endl;
+ assert(0);
+ }
+ mUrlIndex = mCalendarUrls.findIndex(url); // get unique index for this URL
+ if (mUrlIndex < 0)
+ {
+ mUrlIndex = static_cast<int>(mCalendarUrls.count());
+ mCalendarUrls.append(url);
+ }
+ loadFile(false);
+ mCalendars.append(this);
+}
+
+ADCalendar::~ADCalendar()
+{
+ clearEventsHandled();
+ mCalendars.remove(this);
+}
+
+/******************************************************************************
+* Load the calendar file.
+*/
+bool ADCalendar::loadFile(bool reset)
+{
+ if (reset)
+ clearEventsHandled();
+ if (!mTempFileName.isNull())
+ {
+ // Don't try to load the file if already downloading it
+ kdError(5900) << "ADCalendar::loadFile(): already downloading another file\n";
+ return false;
+ }
+ mLoaded = false;
+ KURL url(mUrlString);
+ if (url.isLocalFile())
+ {
+ // It's a local file
+ loadLocalFile(url.path());
+ emit loaded(this, mLoaded);
+ }
+ else
+ {
+ // It's a remote file. Download to a temporary file before loading it
+ KTempFile tempFile;
+ mTempFileName = tempFile.name();
+ KURL dest;
+ dest.setPath(mTempFileName);
+ KIO::FileCopyJob* job = KIO::file_copy(url, dest, -1, true);
+ connect(job, SIGNAL(result(KIO::Job*)), SLOT(slotDownloadJobResult(KIO::Job*)));
+ }
+ return true;
+}
+
+void ADCalendar::slotDownloadJobResult(KIO::Job *job)
+{
+ if (job->error())
+ {
+ KURL url(mUrlString);
+ kdDebug(5900) << "Error downloading calendar from " << url.prettyURL() << endl;
+ job->showErrorDialog(0);
+ }
+ else
+ {
+ kdDebug(5900) << "--- Downloaded to " << mTempFileName << endl;
+ loadLocalFile(mTempFileName);
+ }
+ unlink(QFile::encodeName(mTempFileName));
+ mTempFileName = QString::null;
+ emit loaded(this, mLoaded);
+}
+
+void ADCalendar::loadLocalFile(const QString& filename)
+{
+ mLoaded = load(filename);
+ if (!mLoaded)
+ kdDebug(5900) << "ADCalendar::loadLocalFile(): Error loading calendar file '" << filename << "'\n";
+ else
+ clearEventsHandled(true); // remove all events which no longer exist from handled list
+}
+
+bool ADCalendar::setLoadedConnected()
+{
+ if (mLoadedConnected)
+ return true;
+ mLoadedConnected = true;
+ return false;
+}
+
+/******************************************************************************
+* Check whether all the alarms for the event with the given ID have already
+* been handled.
+*/
+bool ADCalendar::eventHandled(const KCal::Event* event, const QValueList<QDateTime>& alarmtimes)
+{
+ EventsMap::ConstIterator it = mEventsHandled.find(EventKey(event->uid(), mUrlIndex));
+ if (it == mEventsHandled.end())
+ return false;
+
+ int oldCount = it.data().alarmTimes.count();
+ int count = alarmtimes.count();
+ for (int i = 0; i < count; ++i)
+ {
+ if (alarmtimes[i].isValid()
+ && (i >= oldCount // is it an additional alarm?
+ || !it.data().alarmTimes[i].isValid() // or has it just become due?
+ || it.data().alarmTimes[i].isValid() // or has it changed?
+ && alarmtimes[i] != it.data().alarmTimes[i]))
+ return false; // this alarm has changed
+ }
+ return true;
+}
+
+/******************************************************************************
+* Remember that the event with the given ID has been handled.
+* It must already be in the pending list.
+*/
+void ADCalendar::setEventHandled(const QString& eventID)
+{
+ kdDebug(5900) << "ADCalendar::setEventHandled(" << eventID << ")\n";
+ EventKey key(eventID, mUrlIndex);
+
+ // Remove it from the pending list, and add it to the handled list
+ EventsMap::Iterator it = mEventsPending.find(key);
+ if (it != mEventsPending.end())
+ {
+ setEventInMap(mEventsHandled, key, it.data().alarmTimes, it.data().eventSequence);
+ mEventsPending.remove(it);
+ }
+}
+
+/******************************************************************************
+* Remember that the specified alarms for the event with the given ID have been
+* notified to KAlarm, but no reply has come back yet.
+*/
+void ADCalendar::setEventPending(const KCal::Event* event, const QValueList<QDateTime>& alarmtimes)
+{
+ if (event)
+ {
+ kdDebug(5900) << "ADCalendar::setEventPending(" << event->uid() << ")\n";
+ EventKey key(event->uid(), mUrlIndex);
+ setEventInMap(mEventsPending, key, alarmtimes, event->revision());
+ }
+}
+
+/******************************************************************************
+* Add a specified entry to the events pending or handled list.
+*/
+void ADCalendar::setEventInMap(EventsMap& map, const EventKey& key, const QValueList<QDateTime>& alarmtimes, int sequence)
+{
+ EventsMap::Iterator it = map.find(key);
+ if (it != map.end())
+ {
+ // Update the existing entry for the event
+ it.data().alarmTimes = alarmtimes;
+ it.data().eventSequence = sequence;
+ }
+ else
+ map.insert(key, EventItem(sequence, alarmtimes));
+}
+
+/******************************************************************************
+* Clear all memory of events handled for the calendar.
+*/
+void ADCalendar::clearEventsHandled(bool nonexistentOnly)
+{
+ clearEventMap(mEventsPending, nonexistentOnly);
+ clearEventMap(mEventsHandled, nonexistentOnly);
+}
+
+/******************************************************************************
+* Clear the events pending or handled list of all events handled for the calendar.
+*/
+void ADCalendar::clearEventMap(EventsMap& map, bool nonexistentOnly)
+{
+ for (EventsMap::Iterator it = map.begin(); it != map.end(); )
+ {
+ if (it.key().calendarIndex == mUrlIndex
+ && (!nonexistentOnly || !event(it.key().eventID)))
+ {
+ EventsMap::Iterator i = it;
+ ++it; // prevent iterator becoming invalid with remove()
+ map.remove(i);
+ }
+ else
+ ++it;
+ }
+}
+
+/******************************************************************************
+* Look up the calendar with the specified full calendar URL.
+*/
+ADCalendar* ADCalendar::getCalendar(const QString& calendarURL)
+{
+ if (!calendarURL.isEmpty())
+ {
+ for (ConstIterator it = begin(); it != end(); ++it)
+ {
+ if ((*it)->urlString() == calendarURL)
+ return *it;
+ }
+ }
+ return 0;
+}
diff --git a/kalarm/kalarmd/adcalendar.h b/kalarm/kalarmd/adcalendar.h
new file mode 100644
index 00000000..656070be
--- /dev/null
+++ b/kalarm/kalarmd/adcalendar.h
@@ -0,0 +1,120 @@
+/*
+ * adcalendar.h - calendar file access
+ * Program: KAlarm's alarm daemon (kalarmd)
+ * Copyright (c) 2001, 2004-2006 by David Jarvie <software@astrojar.org.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef ADCALENDAR_H
+#define ADCALENDAR_H
+
+#include <libkcal/calendarlocal.h>
+namespace KIO { class Job; }
+class ADCalendar;
+
+
+// Alarm Daemon calendar access
+class ADCalendar : public KCal::CalendarLocal
+{
+ Q_OBJECT
+ public:
+ typedef QValueList<ADCalendar*>::ConstIterator ConstIterator;
+
+ ~ADCalendar();
+
+ const QString& urlString() const { return mUrlString; }
+ const QCString& appName() const { return mAppName; }
+
+ void setEnabled(bool enabled) { mEnabled = enabled; }
+ bool enabled() const { return mEnabled && !unregistered(); }
+ bool available() const { return loaded() && !unregistered(); }
+
+ // Client has registered since calendar was constructed, but
+ // has not since added the calendar. Monitoring is disabled.
+ void setUnregistered(bool u) { mUnregistered = u; }
+ bool unregistered() const { return mUnregistered; }
+
+ void setEventPending(const KCal::Event*, const QValueList<QDateTime>&);
+ void setEventHandled(const QString& eventID);
+ void clearEventsHandled(bool nonexistentOnly = false);
+ bool eventHandled(const KCal::Event*, const QValueList<QDateTime>&);
+
+ bool loadFile(bool reset);
+ bool setLoadedConnected(); // check status of mLoadedConnected and set it to true
+ bool downloading() const { return !mTempFileName.isNull(); }
+ bool loaded() const { return mLoaded; }
+
+
+ static ConstIterator begin() { return mCalendars.begin(); }
+ static ConstIterator end() { return mCalendars.end(); }
+ static ADCalendar* getCalendar(const QString& calendarURL);
+
+ signals:
+ void loaded(ADCalendar*, bool success);
+
+ protected:
+ // Only ClientInfo can construct ADCalendar objects
+ friend class ClientInfo;
+ ADCalendar(const QString& url, const QCString& appname);
+
+ private slots:
+ void slotDownloadJobResult(KIO::Job*);
+
+ private:
+ struct EventKey
+ {
+ EventKey() : calendarIndex(-1) { }
+ EventKey(const QString& id, int cal) : eventID(id), calendarIndex(cal) { }
+ bool operator<(const EventKey& k) const
+ { return (calendarIndex == k.calendarIndex)
+ ? (eventID < k.eventID) : (calendarIndex < k.calendarIndex);
+ }
+ QString eventID;
+ int calendarIndex;
+ };
+ struct EventItem
+ {
+ EventItem() : eventSequence(0) { }
+ EventItem(int seqno, const QValueList<QDateTime>& alarmtimes)
+ : eventSequence(seqno), alarmTimes(alarmtimes) {}
+ int eventSequence;
+ QValueList<QDateTime> alarmTimes;
+ };
+
+ typedef QMap<EventKey, EventItem> EventsMap; // calendar/event ID, event sequence num
+ static EventsMap mEventsHandled; // IDs of already triggered events which have been processed by KAlarm
+ static EventsMap mEventsPending; // IDs of already triggered events not yet processed by KAlarm
+ static QStringList mCalendarUrls; // URLs of all calendars ever opened
+ static QValueList<ADCalendar*> mCalendars; // list of all constructed calendars
+
+ ADCalendar(const ADCalendar&); // prohibit copying
+ ADCalendar& operator=(const ADCalendar&); // prohibit copying
+
+ void loadLocalFile(const QString& filename);
+ void clearEventMap(EventsMap&, bool nonexistentOnly);
+ void setEventInMap(EventsMap&, const EventKey&, const QValueList<QDateTime>& alarmtimes, int sequence);
+
+ QString mUrlString; // calendar file URL
+ QCString mAppName; // name of application owning this calendar
+ QString mTempFileName; // temporary file used if currently downloading, else null
+ int mUrlIndex; // unique index to URL in mCalendarUrls
+ bool mLoaded; // true if calendar file is currently loaded
+ bool mLoadedConnected; // true if the loaded() signal has been connected to AlarmDaemon
+ bool mUnregistered; // client has registered, but has not since added the calendar
+ bool mEnabled; // events are currently manually enabled
+};
+
+#endif // ADCALENDAR_H
diff --git a/kalarm/kalarmd/adconfigdata.cpp b/kalarm/kalarmd/adconfigdata.cpp
new file mode 100644
index 00000000..11dc6bf6
--- /dev/null
+++ b/kalarm/kalarmd/adconfigdata.cpp
@@ -0,0 +1,146 @@
+/*
+ * adcalendar.cpp - configuration file access
+ * Program: KAlarm's alarm daemon (kalarmd)
+ * Copyright (C) 2001, 2004 by David Jarvie <software@astrojar.org.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "kalarmd.h"
+
+#include <qregexp.h>
+#include <qstringlist.h>
+
+#include <kconfig.h>
+#include <kstandarddirs.h>
+#include <kdebug.h>
+
+#include "adcalendar.h"
+#include "adconfigdata.h"
+
+// Config file key strings
+const QString CLIENT_GROUP(QString::fromLatin1("Client "));
+const QRegExp CLIENT_GROUP_SEARCH("^Client ");
+// Client data file key strings
+const QString CALENDAR_KEY(QString::fromLatin1("Calendar"));
+const QString TITLE_KEY(QString::fromLatin1("Title"));
+const QString DCOP_OBJECT_KEY(QString::fromLatin1("DCOP object"));
+const QString START_CLIENT_KEY(QString::fromLatin1("Start"));
+
+
+/******************************************************************************
+* Read the configuration file.
+* Create the client list and open all calendar files.
+*/
+void ADConfigData::readConfig()
+{
+ kdDebug(5900) << "ADConfigData::readConfig()" << endl;
+ ClientInfo::clear();
+ KConfig* config = KGlobal::config();
+ QStringList clients = config->groupList().grep(CLIENT_GROUP_SEARCH);
+ for (QStringList::Iterator cl = clients.begin(); cl != clients.end(); ++cl)
+ {
+ // Read this client's configuration
+ config->setGroup(*cl);
+ QString client = *cl;
+ client.remove(CLIENT_GROUP_SEARCH);
+ QString title = config->readEntry(TITLE_KEY, client); // read app title (default = app name)
+ QCString dcopObject = config->readEntry(DCOP_OBJECT_KEY).local8Bit();
+ bool startClient = config->readBoolEntry(START_CLIENT_KEY, false);
+ QString calendar = config->readPathEntry(CALENDAR_KEY);
+
+ // Verify the configuration
+ bool ok = false;
+ if (client.isEmpty() || KStandardDirs::findExe(client).isNull())
+ kdError(5900) << "ADConfigData::readConfig(): group '" << *cl << "' deleted (client app not found)\n";
+ else if (calendar.isEmpty())
+ kdError(5900) << "ADConfigData::readConfig(): no calendar specified for '" << client << "'\n";
+ else if (dcopObject.isEmpty())
+ kdError(5900) << "ADConfigData::readConfig(): no DCOP object specified for '" << client << "'\n";
+ else
+ {
+ ADCalendar* cal = ADCalendar::getCalendar(calendar);
+ if (cal)
+ kdError(5900) << "ADConfigData::readConfig(): calendar registered by multiple clients: " << calendar << endl;
+ else
+ ok = true;
+ }
+ if (!ok)
+ {
+ config->deleteGroup(*cl, true);
+ continue;
+ }
+
+ // Create the client and calendar objects
+ new ClientInfo(client.local8Bit(), title, dcopObject, calendar, startClient);
+ kdDebug(5900) << "ADConfigData::readConfig(): client " << client << " : calendar " << calendar << endl;
+ }
+
+ // Remove obsolete CheckInterval entry (if it exists)
+ config->setGroup("General");
+ config->deleteEntry("CheckInterval");
+
+ // Save any updates
+ config->sync();
+}
+
+/******************************************************************************
+* Write a client application's details to the config file.
+*/
+void ADConfigData::writeClient(const QCString& appName, const ClientInfo* cinfo)
+{
+ KConfig* config = KGlobal::config();
+ config->setGroup(CLIENT_GROUP + QString::fromLocal8Bit(appName));
+ config->writeEntry(TITLE_KEY, cinfo->title());
+ config->writeEntry(DCOP_OBJECT_KEY, QString::fromLocal8Bit(cinfo->dcopObject()));
+ config->writeEntry(START_CLIENT_KEY, cinfo->startClient());
+ config->writePathEntry(CALENDAR_KEY, cinfo->calendar()->urlString());
+ config->sync();
+}
+
+/******************************************************************************
+* Remove a client application's details from the config file.
+*/
+void ADConfigData::removeClient(const QCString& appName)
+{
+ KConfig* config = KGlobal::config();
+ config->deleteGroup(CLIENT_GROUP + QString::fromLocal8Bit(appName));
+ config->sync();
+}
+
+/******************************************************************************
+* Set the calendar file URL for a specified application.
+*/
+void ADConfigData::setCalendar(const QCString& appName, ADCalendar* cal)
+{
+ KConfig* config = KGlobal::config();
+ config->setGroup(CLIENT_GROUP + QString::fromLocal8Bit(appName));
+ config->writePathEntry(CALENDAR_KEY, cal->urlString());
+ config->sync();
+}
+
+/******************************************************************************
+* DCOP call to set autostart at login on or off.
+*/
+void ADConfigData::enableAutoStart(bool on)
+{
+ kdDebug(5900) << "ADConfigData::enableAutoStart(" << on << ")\n";
+ KConfig* config = KGlobal::config();
+ config->reparseConfiguration();
+ config->setGroup(QString::fromLatin1(DAEMON_AUTOSTART_SECTION));
+ config->writeEntry(QString::fromLatin1(DAEMON_AUTOSTART_KEY), on);
+ config->sync();
+}
+
diff --git a/kalarm/kalarmd/adconfigdata.h b/kalarm/kalarmd/adconfigdata.h
new file mode 100644
index 00000000..2c841fdf
--- /dev/null
+++ b/kalarm/kalarmd/adconfigdata.h
@@ -0,0 +1,41 @@
+/*
+ * adconfigdata.h - configuration file access
+ * Program: KAlarm's alarm daemon (kalarmd)
+ * Copyright (C) 2001, 2004 by David Jarvie <software@astrojar.org.uk>
+ * Based on the original, (c) 1998, 1999 Preston Brown
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef ADCONFIGDATA_H
+#define ADCONFIGDATA_H
+
+#include "clientinfo.h"
+
+class ADCalendar;
+class ClientInfo;
+
+
+class ADConfigData
+{
+ public:
+ static void readConfig();
+ static void writeClient(const QCString& appName, const ClientInfo*);
+ static void removeClient(const QCString& appName);
+ static void setCalendar(const QCString& appName, ADCalendar*);
+ static void enableAutoStart(bool);
+};
+
+#endif // ADCONFIGDATA_H
diff --git a/kalarm/kalarmd/admain.cpp b/kalarm/kalarmd/admain.cpp
new file mode 100644
index 00000000..c0a7792f
--- /dev/null
+++ b/kalarm/kalarmd/admain.cpp
@@ -0,0 +1,59 @@
+/*
+ * admain.cpp - kalarmd main program
+ * Program: KAlarm's alarm daemon (kalarmd)
+ * Copyright (c) 2001,2004,2005 by David Jarvie <software@astrojar.org.uk>
+ * Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org>
+ * Copyright (c) 1997-1999 Preston Brown <pbrown@kde.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "kalarmd.h"
+
+#include <stdlib.h>
+
+#include <klocale.h>
+#include <kcmdlineargs.h>
+#include <kaboutdata.h>
+#include <kstartupinfo.h>
+
+#include "adapp.h"
+
+static const KCmdLineOptions options[] =
+{
+ { "autostart", "", 0 },
+ KCmdLineLastOption
+};
+
+int main(int argc, char** argv)
+{
+ KAboutData aboutData(DAEMON_APP_NAME, I18N_NOOP("KAlarm Daemon"),
+ DAEMON_VERSION, I18N_NOOP("KAlarm Alarm Daemon"), KAboutData::License_GPL,
+ "Copyright 1997-1999 Preston Brown\nCopyright 2000-2001 Cornelius Schumacher\nCopyright 2001,2004-2007 David Jarvie", 0,
+ "http://www.astrojar.org.uk/kalarm");
+ aboutData.addAuthor("David Jarvie", I18N_NOOP("Maintainer"), "software@astrojar.org.uk");
+ aboutData.addAuthor("Cornelius Schumacher", I18N_NOOP("Author"), "schumacher@kde.org");
+ aboutData.addAuthor("Preston Brown", I18N_NOOP("Original Author"), "pbrown@kde.org");
+
+ KCmdLineArgs::init(argc, argv, &aboutData);
+ KCmdLineArgs::addCmdLineOptions(options);
+ KUniqueApplication::addCmdLineOptions();
+ KStartupInfo::disableAutoAppStartedSending();
+
+ if (!AlarmDaemonApp::start())
+ exit(0);
+ AlarmDaemonApp app;
+ return app.exec();
+}
diff --git a/kalarm/kalarmd/alarmdaemon.cpp b/kalarm/kalarmd/alarmdaemon.cpp
new file mode 100644
index 00000000..57667857
--- /dev/null
+++ b/kalarm/kalarmd/alarmdaemon.cpp
@@ -0,0 +1,614 @@
+/*
+ * alarmdaemon.cpp - alarm daemon control routines
+ * Program: KAlarm's alarm daemon (kalarmd)
+ * Copyright © 2001,2004-2007 by David Jarvie <software@astrojar.org.uk>
+ * Based on the original, (c) 1998, 1999 Preston Brown
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "kalarmd.h"
+
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <qtimer.h>
+#include <qfile.h>
+#include <qdatetime.h>
+
+#include <kapplication.h>
+#include <kstandarddirs.h>
+#include <kprocess.h>
+#include <kio/netaccess.h>
+#include <dcopclient.h>
+#include <kconfig.h>
+#include <kdebug.h>
+
+#include <libkcal/calendarlocal.h>
+#include <libkcal/icalformat.h>
+
+#include "adcalendar.h"
+#include "adconfigdata.h"
+#include "alarmguiiface.h"
+#include "alarmguiiface_stub.h"
+#include "alarmdaemon.moc"
+
+
+#ifdef AUTOSTART_KALARM
+// Number of seconds to wait before autostarting KAlarm.
+// Allow plenty of time for session restoration to happen first.
+static const int KALARM_AUTOSTART_TIMEOUT = 30;
+#endif
+static const int SECS_PER_DAY = 3600 * 24;
+
+// KAlarm config file keys
+static const QString START_OF_DAY(QString::fromLatin1("StartOfDay"));
+static const QString AUTOSTART_TRAY(QString::fromLatin1("AutostartTray"));
+
+
+AlarmDaemon::AlarmDaemon(bool autostart, QObject *parent, const char *name)
+ : DCOPObject(name),
+ QObject(parent, name),
+ mAlarmTimer(0)
+{
+ kdDebug(5900) << "AlarmDaemon::AlarmDaemon()" << endl;
+ ADConfigData::readConfig();
+
+ ADConfigData::enableAutoStart(true); // switch autostart on whenever the program is run
+
+ readKAlarmConfig(); // read time-related KAlarm config items
+
+#ifdef AUTOSTART_KALARM
+ if (autostart)
+ {
+ /* The alarm daemon is being autostarted.
+ * Check if KAlarm needs to be autostarted in the system tray.
+ * This should ideally be handled internally by KAlarm, but is done by kalarmd
+ * for the following reason:
+ * KAlarm needs to be both session restored and autostarted, but KDE doesn't
+ * currently cater properly for this - there is no guarantee that the session
+ * restoration activation will come before the autostart activation. If they
+ * come in the wrong order, KAlarm won't know that it is supposed to restore
+ * itself and instead will simply open a new window.
+ */
+ KConfig kaconfig(locate("config", "kalarmrc"));
+ kaconfig.setGroup(QString::fromLatin1("General"));
+ autostart = kaconfig.readBoolEntry(AUTOSTART_TRAY, false);
+ if (autostart)
+ {
+ kdDebug(5900) << "AlarmDaemon::AlarmDaemon(): wait to autostart KAlarm\n";
+ QTimer::singleShot(KALARM_AUTOSTART_TIMEOUT * 1000, this, SLOT(autostartKAlarm()));
+ }
+ }
+ if (!autostart)
+#endif
+ startMonitoring(); // otherwise, start monitoring alarms now
+}
+
+/******************************************************************************
+* DCOP call to quit the program.
+*/
+void AlarmDaemon::quit()
+{
+ kdDebug(5900) << "AlarmDaemon::quit()" << endl;
+ exit(0);
+}
+
+/******************************************************************************
+* Called after a timer delay to autostart KAlarm in the system tray.
+*/
+void AlarmDaemon::autostartKAlarm()
+{
+#ifdef AUTOSTART_KALARM
+ if (mAlarmTimer)
+ {
+ kdDebug(5900) << "AlarmDaemon::autostartKAlarm(): KAlarm already registered\n";
+ return; // KAlarm has already registered with us
+ }
+ kdDebug(5900) << "AlarmDaemon::autostartKAlarm(): starting KAlarm\n";
+ QStringList args;
+ args << QString::fromLatin1("--tray");
+ int ret = KApplication::kdeinitExec(QString::fromLatin1("kalarm"), args);
+ if (ret)
+ kdError(5900) << "AlarmDaemon::autostartKAlarm(): error=" << ret << endl;
+ else
+ kdDebug(5900) << "AlarmDaemon::autostartKAlarm(): success" << endl;
+
+ startMonitoring();
+#endif
+}
+
+/******************************************************************************
+* Start monitoring alarms.
+*/
+void AlarmDaemon::startMonitoring()
+{
+ // Set up the alarm timer
+ mAlarmTimer = new QTimer(this);
+ connect(mAlarmTimer, SIGNAL(timeout()), SLOT(checkAlarmsSlot()));
+ setTimerStatus();
+
+ // Start monitoring calendar files.
+ // They are monitored until their client application registers, upon which
+ // monitoring ceases until KAlarm tells the daemon to monitor it.
+ checkAlarms();
+}
+
+/******************************************************************************
+* DCOP call to enable or disable monitoring of a calendar.
+*/
+void AlarmDaemon::enableCal(const QString& urlString, bool enable)
+{
+ kdDebug(5900) << "AlarmDaemon::enableCal(" << urlString << ")" << endl;
+ ADCalendar* cal = ADCalendar::getCalendar(urlString);
+ if (cal)
+ {
+ cal->setEnabled(enable);
+ notifyCalStatus(cal); // notify KAlarm
+ }
+}
+
+/******************************************************************************
+* DCOP call to reload, and optionally reset, the specified calendar.
+*/
+void AlarmDaemon::reloadCal(const QCString& appname, const QString& urlString, bool reset)
+{
+ kdDebug(5900) << "AlarmDaemon::reloadCal(" << urlString << ")" << endl;
+ ADCalendar* cal = ADCalendar::getCalendar(urlString);
+ if (!cal || cal->appName() != appname)
+ return;
+ reloadCal(cal, reset);
+}
+
+/******************************************************************************
+* Reload the specified calendar.
+* If 'reset' is true, the data associated with the calendar is reset.
+*/
+void AlarmDaemon::reloadCal(ADCalendar* cal, bool reset)
+{
+ kdDebug(5900) << "AlarmDaemon::reloadCal(): calendar" << endl;
+ if (!cal)
+ return;
+ if (!cal->downloading())
+ {
+ cal->close();
+ if (!cal->setLoadedConnected())
+ connect(cal, SIGNAL(loaded(ADCalendar*, bool)), SLOT(calendarLoaded(ADCalendar*, bool)));
+ cal->loadFile(reset);
+ }
+ else if (reset)
+ cal->clearEventsHandled();
+}
+
+void AlarmDaemon::calendarLoaded(ADCalendar* cal, bool success)
+{
+ if (success)
+ kdDebug(5900) << "Calendar reloaded" << endl;
+ notifyCalStatus(cal); // notify KAlarm
+ setTimerStatus();
+ checkAlarms(cal);
+}
+
+/******************************************************************************
+* DCOP call to notify the daemon that an event has been handled, and optionally
+* to tell it to reload the calendar.
+*/
+void AlarmDaemon::eventHandled(const QCString& appname, const QString& calendarUrl, const QString& eventID, bool reload)
+{
+ QString urlString = expandURL(calendarUrl);
+ kdDebug(5900) << "AlarmDaemon::eventHandled(" << urlString << (reload ? "): reload" : ")") << endl;
+ ADCalendar* cal = ADCalendar::getCalendar(urlString);
+ if (!cal || cal->appName() != appname)
+ return;
+ cal->setEventHandled(eventID);
+ if (reload)
+ reloadCal(cal, false);
+}
+
+/******************************************************************************
+* DCOP call to add an application to the list of client applications,
+* and add it to the config file.
+* N.B. This method must not return a bool because DCOPClient::call() can cause
+* a hang if the daemon happens to send a notification to KAlarm at the
+* same time as KAlarm calls this DCCOP method.
+*/
+void AlarmDaemon::registerApp(const QCString& appName, const QString& appTitle,
+ const QCString& dcopObject, const QString& calendarUrl,
+ bool startClient)
+{
+ kdDebug(5900) << "AlarmDaemon::registerApp(" << appName << ", " << appTitle << ", "
+ << dcopObject << ", " << startClient << ")" << endl;
+ KAlarmd::RegisterResult result;
+ if (appName.isEmpty())
+ result = KAlarmd::FAILURE;
+ else if (startClient && KStandardDirs::findExe(appName).isNull())
+ {
+ kdError() << "AlarmDaemon::registerApp(): app not found" << endl;
+ result = KAlarmd::NOT_FOUND;
+ }
+ else
+ {
+ ADCalendar* keepCal = 0;
+ ClientInfo* client = ClientInfo::get(appName);
+ if (client)
+ {
+ // The application is already a client.
+ // If it's the same calendar file, don't delete its calendar object.
+ if (client->calendar() && client->calendar()->urlString() == calendarUrl)
+ {
+ keepCal = client->calendar();
+ client->detachCalendar();
+ }
+ ClientInfo::remove(appName); // this deletes the calendar if not detached
+ }
+
+ if (keepCal)
+ client = new ClientInfo(appName, appTitle, dcopObject, keepCal, startClient);
+ else
+ client = new ClientInfo(appName, appTitle, dcopObject, calendarUrl, startClient);
+ client->calendar()->setUnregistered(false);
+ ADConfigData::writeClient(appName, client);
+
+ ADConfigData::enableAutoStart(true);
+ setTimerStatus();
+ notifyCalStatus(client->calendar());
+ result = KAlarmd::SUCCESS;
+ }
+
+ // Notify the client of whether the call succeeded.
+ AlarmGuiIface_stub stub(appName, dcopObject);
+ stub.registered(false, result, DAEMON_VERSION_NUM);
+ kdDebug(5900) << "AlarmDaemon::registerApp() -> " << result << endl;
+}
+
+/******************************************************************************
+* DCOP call to change whether KAlarm should be started when an event needs to
+* be notified to it.
+* N.B. This method must not return a bool because DCOPClient::call() can cause
+* a hang if the daemon happens to send a notification to KAlarm at the
+* same time as KAlarm calls this DCCOP method.
+*/
+void AlarmDaemon::registerChange(const QCString& appName, bool startClient)
+{
+ kdDebug(5900) << "AlarmDaemon::registerChange(" << appName << ", " << startClient << ")" << endl;
+ KAlarmd::RegisterResult result;
+ ClientInfo* client = ClientInfo::get(appName);
+ if (!client)
+ return; // can't access client to tell it the result
+ if (startClient && KStandardDirs::findExe(appName).isNull())
+ {
+ kdError() << "AlarmDaemon::registerChange(): app not found" << endl;
+ result = KAlarmd::NOT_FOUND;
+ }
+ else
+ {
+ client->setStartClient(startClient);
+ ADConfigData::writeClient(appName, client);
+ result = KAlarmd::SUCCESS;
+ }
+
+ // Notify the client of whether the call succeeded.
+ AlarmGuiIface_stub stub(appName, client->dcopObject());
+ stub.registered(true, result, DAEMON_VERSION_NUM);
+ kdDebug(5900) << "AlarmDaemon::registerChange() -> " << result << endl;
+}
+
+/******************************************************************************
+* DCOP call to set autostart at login on or off.
+*/
+void AlarmDaemon::enableAutoStart(bool on)
+{
+ ADConfigData::enableAutoStart(on);
+}
+
+/******************************************************************************
+* Check if any alarms are pending for any enabled calendar, and display the
+* pending alarms.
+* Called by the alarm timer.
+*/
+void AlarmDaemon::checkAlarmsSlot()
+{
+ kdDebug(5901) << "AlarmDaemon::checkAlarmsSlot()" << endl;
+ if (mAlarmTimerSyncing)
+ {
+ // We've synched to the minute boundary. Now set timer to the check interval.
+ mAlarmTimer->changeInterval(DAEMON_CHECK_INTERVAL * 1000);
+ mAlarmTimerSyncing = false;
+ mAlarmTimerSyncCount = 10; // resynch every 10 minutes, in case of glitches
+ }
+ else if (--mAlarmTimerSyncCount <= 0)
+ {
+ int interval = DAEMON_CHECK_INTERVAL + 1 - QTime::currentTime().second();
+ if (interval < DAEMON_CHECK_INTERVAL - 1)
+ {
+ // Need to re-synch to 1 second past the minute
+ mAlarmTimer->changeInterval(interval * 1000);
+ mAlarmTimerSyncing = true;
+ kdDebug(5900) << "Resynching alarm timer" << endl;
+ }
+ else
+ mAlarmTimerSyncCount = 10;
+ }
+ checkAlarms();
+}
+
+/******************************************************************************
+* Check if any alarms are pending for any enabled calendar, and display the
+* pending alarms.
+*/
+void AlarmDaemon::checkAlarms()
+{
+ kdDebug(5901) << "AlarmDaemon::checkAlarms()" << endl;
+ for (ADCalendar::ConstIterator it = ADCalendar::begin(); it != ADCalendar::end(); ++it)
+ checkAlarms(*it);
+}
+
+/******************************************************************************
+* Check if any alarms are pending for a specified calendar, and display the
+* pending alarms.
+*/
+void AlarmDaemon::checkAlarms(ADCalendar* cal)
+{
+ kdDebug(5901) << "AlarmDaemons::checkAlarms(" << cal->urlString() << ")" << endl;
+ if (!cal->loaded() || !cal->enabled())
+ return;
+
+ QDateTime now = QDateTime::currentDateTime();
+ kdDebug(5901) << " To: " << now.toString() << endl;
+ QValueList<KCal::Alarm*> alarms = cal->alarmsTo(now);
+ if (!alarms.count())
+ return;
+ QValueList<KCal::Event*> eventsDone;
+ for (QValueList<KCal::Alarm*>::ConstIterator it = alarms.begin(); it != alarms.end(); ++it)
+ {
+ KCal::Event* event = dynamic_cast<KCal::Event*>((*it)->parent());
+ if (!event || eventsDone.find(event) != eventsDone.end())
+ continue; // either not an event, or the event has already been processed
+ eventsDone += event;
+ const QString& eventID = event->uid();
+ kdDebug(5901) << "AlarmDaemon::checkAlarms(): event " << eventID << endl;
+
+ // Check which of the alarms for this event are due.
+ // The times in 'alarmtimes' corresponding to due alarms are set.
+ // The times for non-due alarms are set invalid in 'alarmtimes'.
+ bool recurs = event->doesRecur();
+ const QStringList cats = event->categories();
+ bool floats = (cats.find(QString::fromLatin1("DATE")) != cats.end());
+ QDateTime nextDateTime = event->dtStart();
+ if (recurs)
+ {
+ QString prop = event->customProperty("KALARM", "NEXTRECUR");
+ if (prop.length() >= 8)
+ {
+ // The next due recurrence time is specified
+ QDate d(prop.left(4).toInt(), prop.mid(4,2).toInt(), prop.mid(6,2).toInt());
+ if (d.isValid())
+ {
+ if (floats && prop.length() == 8)
+ nextDateTime = d;
+ else if (!floats && prop.length() == 15 && prop[8] == QChar('T'))
+ {
+ QTime t(prop.mid(9,2).toInt(), prop.mid(11,2).toInt(), prop.mid(13,2).toInt());
+ if (t.isValid())
+ nextDateTime = QDateTime(d, t);
+ }
+ }
+ }
+ }
+ if (floats)
+ nextDateTime.setTime(mStartOfDay);
+ QValueList<QDateTime> alarmtimes;
+ KCal::Alarm::List alarms = event->alarms();
+ for (KCal::Alarm::List::ConstIterator al = alarms.begin(); al != alarms.end(); ++al)
+ {
+ KCal::Alarm* alarm = *al;
+ QDateTime dt;
+ if (alarm->enabled())
+ {
+ QDateTime dt1;
+ if (!alarm->hasTime())
+ {
+ // Find the latest recurrence for the alarm.
+ // Need to do this for alarms with offsets in order to detect
+ // reminders due for recurrences.
+ int offset = alarm->hasStartOffset() ? alarm->startOffset().asSeconds()
+ : alarm->endOffset().asSeconds() + event->dtStart().secsTo(event->dtEnd());
+ if (offset)
+ {
+ dt1 = nextDateTime.addSecs(floats ? (offset/SECS_PER_DAY)*SECS_PER_DAY : offset);
+ if (dt1 > now)
+ dt1 = QDateTime();
+ }
+ }
+ // Get latest due repetition, or the recurrence time if none
+ dt = nextDateTime;
+ if (nextDateTime <= now && alarm->repeatCount() > 0)
+ {
+ int snoozeSecs = alarm->snoozeTime() * 60;
+ int offset = alarm->repeatCount() * snoozeSecs;
+ QDateTime lastRepetition = nextDateTime.addSecs(floats ? (offset/SECS_PER_DAY)*SECS_PER_DAY : offset);
+ if (lastRepetition <= now)
+ dt = lastRepetition;
+ else
+ {
+ int repetition = nextDateTime.secsTo(now) / snoozeSecs;
+ int offset = repetition * snoozeSecs;
+ dt = nextDateTime.addSecs(floats ? (offset/SECS_PER_DAY)*SECS_PER_DAY : offset);
+ }
+ }
+ if (!dt.isValid() || dt > now
+ || dt1.isValid() && dt1 > dt) // already tested dt1 <= now
+ dt = dt1;
+ }
+ alarmtimes.append(dt);
+ }
+ if (!cal->eventHandled(event, alarmtimes))
+ {
+ if (notifyEvent(cal, eventID))
+ cal->setEventPending(event, alarmtimes);
+ }
+ }
+}
+
+/******************************************************************************
+* Send a DCOP message to KAlarm telling it that an alarm should now be handled.
+* Reply = false if the event should be held pending until KAlarm can be started.
+*/
+bool AlarmDaemon::notifyEvent(ADCalendar* calendar, const QString& eventID)
+{
+ if (!calendar)
+ return true;
+ QCString appname = calendar->appName();
+ const ClientInfo* client = ClientInfo::get(appname);
+ if (!client)
+ {
+ kdDebug(5900) << "AlarmDaemon::notifyEvent(" << appname << "): unknown client" << endl;
+ return false;
+ }
+ kdDebug(5900) << "AlarmDaemon::notifyEvent(" << appname << ", " << eventID << "): notification type=" << client->startClient() << endl;
+ QString id = QString::fromLatin1("ad:") + eventID; // prefix to indicate that the notification if from the daemon
+
+ // Check if the client application is running and ready to receive notification
+ bool registered = kapp->dcopClient()->isApplicationRegistered(static_cast<const char*>(appname));
+ bool ready = registered;
+ if (registered)
+ {
+ // It's running, but check if it has created our DCOP interface yet
+ QCStringList objects = kapp->dcopClient()->remoteObjects(appname);
+ if (objects.find(client->dcopObject()) == objects.end())
+ ready = false;
+ }
+ if (!ready)
+ {
+ // KAlarm is not running, or is not yet ready to receive notifications.
+ if (!client->startClient())
+ {
+ if (registered)
+ kdDebug(5900) << "AlarmDaemon::notifyEvent(): client not ready\n";
+ else
+ kdDebug(5900) << "AlarmDaemon::notifyEvent(): don't start client\n";
+ return false;
+ }
+
+ // Start KAlarm, using the command line to specify the alarm
+ KProcess p;
+ QString cmd = locate("exe", appname);
+ if (cmd.isEmpty())
+ {
+ kdDebug(5900) << "AlarmDaemon::notifyEvent(): '" << appname << "' not found" << endl;
+ return true;
+ }
+ p << cmd;
+ p << "--handleEvent" << id << "--calendarURL" << calendar->urlString();
+ p.start(KProcess::DontCare);
+ kdDebug(5900) << "AlarmDaemon::notifyEvent(): used command line" << endl;
+ return true;
+ }
+
+ // Notify the client by telling it the calendar URL and event ID
+ AlarmGuiIface_stub stub(appname, client->dcopObject());
+ stub.handleEvent(calendar->urlString(), id);
+ if (!stub.ok())
+ {
+ kdDebug(5900) << "AlarmDaemon::notifyEvent(): dcop send failed" << endl;
+ return false;
+ }
+ return true;
+}
+
+/******************************************************************************
+* Starts or stops the alarm timer as necessary after a calendar is enabled/disabled.
+*/
+void AlarmDaemon::setTimerStatus()
+{
+#ifdef AUTOSTART_KALARM
+ if (!mAlarmTimer)
+ {
+ // KAlarm is now running, so start monitoring alarms
+ startMonitoring();
+ return; // startMonitoring() calls this method
+ }
+
+#endif
+ // Count the number of currently loaded calendars whose names should be displayed
+ int nLoaded = 0;
+ for (ADCalendar::ConstIterator it = ADCalendar::begin(); it != ADCalendar::end(); ++it)
+ if ((*it)->loaded())
+ ++nLoaded;
+
+ // Start or stop the alarm timer if necessary
+ if (!mAlarmTimer->isActive() && nLoaded)
+ {
+ // Timeout every minute.
+ // But first synchronise to one second after the minute boundary.
+ int firstInterval = DAEMON_CHECK_INTERVAL + 1 - QTime::currentTime().second();
+ mAlarmTimer->start(1000 * firstInterval);
+ mAlarmTimerSyncing = (firstInterval != DAEMON_CHECK_INTERVAL);
+ kdDebug(5900) << "Started alarm timer" << endl;
+ }
+ else if (mAlarmTimer->isActive() && !nLoaded)
+ {
+ mAlarmTimer->stop();
+ kdDebug(5900) << "Stopped alarm timer" << endl;
+ }
+}
+
+/******************************************************************************
+* Send a DCOP message to to the client which owns the specified calendar,
+* notifying it of a change in calendar status.
+*/
+void AlarmDaemon::notifyCalStatus(const ADCalendar* cal)
+{
+ ClientInfo* client = ClientInfo::get(cal);
+ if (!client)
+ return;
+ QCString appname = client->appName();
+ if (kapp->dcopClient()->isApplicationRegistered(static_cast<const char*>(appname)))
+ {
+ KAlarmd::CalendarStatus change = cal->available() ? (cal->enabled() ? KAlarmd::CALENDAR_ENABLED : KAlarmd::CALENDAR_DISABLED)
+ : KAlarmd::CALENDAR_UNAVAILABLE;
+ kdDebug(5900) << "AlarmDaemon::notifyCalStatus() sending:" << appname << " -> " << change << endl;
+ AlarmGuiIface_stub stub(appname, client->dcopObject());
+ stub.alarmDaemonUpdate(change, cal->urlString());
+ if (!stub.ok())
+ kdError(5900) << "AlarmDaemon::notifyCalStatus(): dcop send failed:" << appname << endl;
+ }
+}
+
+/******************************************************************************
+* Read all relevant items from KAlarm config.
+* Executed on DCOP call to notify a time related value change in the KAlarm
+* config file.
+*/
+void AlarmDaemon::readKAlarmConfig()
+{
+ KConfig config(locate("config", "kalarmrc"));
+ config.setGroup(QString::fromLatin1("General"));
+ QDateTime defTime(QDate(1900,1,1), QTime());
+ mStartOfDay = config.readDateTimeEntry(START_OF_DAY, &defTime).time();
+ kdDebug(5900) << "AlarmDaemon::readKAlarmConfig()" << endl;
+}
+
+/******************************************************************************
+* Expand a DCOP call parameter URL to a full URL.
+* (We must store full URLs in the calendar data since otherwise later calls to
+* reload or remove calendars won't necessarily find a match.)
+*/
+QString AlarmDaemon::expandURL(const QString& urlString)
+{
+ if (urlString.isEmpty())
+ return QString();
+ return KURL(urlString).url();
+}
diff --git a/kalarm/kalarmd/alarmdaemon.h b/kalarm/kalarmd/alarmdaemon.h
new file mode 100644
index 00000000..6ab5d0f9
--- /dev/null
+++ b/kalarm/kalarmd/alarmdaemon.h
@@ -0,0 +1,79 @@
+/*
+ * alarmdaemon.h - alarm daemon control routines
+ * Program: KAlarm's alarm daemon (kalarmd)
+ * Copyright © 2001,2004-2007 by David Jarvie <software@astrojar.org.uk>
+ * Based on the original, (c) 1998, 1999 Preston Brown
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef ALARMDAEMON_H
+#define ALARMDAEMON_H
+
+#include <libkcal/calendarlocal.h>
+
+#include "alarmdaemoniface.h"
+
+class ADCalendar;
+
+
+class AlarmDaemon : public QObject, virtual public AlarmDaemonIface
+{
+ Q_OBJECT
+ public:
+ AlarmDaemon(bool autostart, QObject* parent = 0, const char* name = 0);
+
+ private slots:
+//#ifdef AUTOSTART_KALARM
+ void autostartKAlarm();
+//#endif
+ void calendarLoaded(ADCalendar*, bool success);
+ void checkAlarmsSlot();
+ void checkAlarms();
+
+ private:
+ // DCOP interface
+ void enableAutoStart(bool enable);
+ void enableCalendar(const QString& urlString, bool enable)
+ { enableCal(expandURL(urlString), enable); }
+ void reloadCalendar(const QCString& appname, const QString& urlString)
+ { reloadCal(appname, expandURL(urlString), false); }
+ void resetCalendar(const QCString& appname, const QString& urlString)
+ { reloadCal(appname, expandURL(urlString), true); }
+ void registerApp(const QCString& appName, const QString& appTitle, const QCString& dcopObject,
+ const QString& calendarUrl, bool startClient);
+ void registerChange(const QCString& appName, bool startClient);
+ void eventHandled(const QCString& appname, const QString& calendarURL, const QString& eventID, bool reload);
+ void timeConfigChanged() { readKAlarmConfig(); }
+ void quit();
+ // Other methods
+ void readKAlarmConfig();
+ void startMonitoring();
+ void enableCal(const QString& urlString, bool enable);
+ void reloadCal(const QCString& appname, const QString& urlString, bool reset);
+ void reloadCal(ADCalendar*, bool reset);
+ void checkAlarms(ADCalendar*);
+ bool notifyEvent(ADCalendar*, const QString& eventID);
+ void notifyCalStatus(const ADCalendar*);
+ void setTimerStatus();
+ static QString expandURL(const QString& urlString);
+
+ QTimer* mAlarmTimer;
+ int mAlarmTimerSyncCount; // countdown to re-synching the alarm timer
+ bool mAlarmTimerSyncing; // true while alarm timer interval < 1 minute
+ QTime mStartOfDay; // start of day for date-only alarms
+};
+
+#endif // ALARMDAEMON_H
diff --git a/kalarm/kalarmd/alarmdaemoniface.h b/kalarm/kalarmd/alarmdaemoniface.h
new file mode 100644
index 00000000..708f5b28
--- /dev/null
+++ b/kalarm/kalarmd/alarmdaemoniface.h
@@ -0,0 +1,45 @@
+/*
+ * alarmdaemoniface.h - DCOP request interface
+ * Program: KAlarm's alarm daemon (kalarmd)
+ * Copyright © 2001,2004-2007 by David Jarvie <software@astrojar.org.uk>
+ * Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org>
+ * Copyright (c) 1997-1999 Preston Brown <pbrown@kde.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef ALARMDAEMONIFACE_H
+#define ALARMDAEMONIFACE_H
+
+#include <dcopobject.h>
+
+
+class AlarmDaemonIface : virtual public DCOPObject
+{
+ K_DCOP
+ k_dcop:
+ virtual ASYNC enableAutoStart(bool enable) = 0;
+ virtual ASYNC enableCalendar(const QString& urlString, bool enable) = 0;
+ virtual ASYNC reloadCalendar(const QCString& appname, const QString& urlString) = 0;
+ virtual ASYNC resetCalendar(const QCString& appname, const QString& urlString) = 0;
+ virtual ASYNC registerApp(const QCString& appName, const QString& appTitle, const QCString& dcopObject,
+ const QString& calendarUrl, bool startClient) = 0;
+ virtual ASYNC registerChange(const QCString& appName, bool startClient) = 0;
+ virtual ASYNC eventHandled(const QCString& appname, const QString& calendarURL, const QString& eventID, bool reload) = 0;
+ virtual ASYNC timeConfigChanged() = 0;
+ virtual ASYNC quit() = 0;
+};
+
+#endif
diff --git a/kalarm/kalarmd/alarmguiiface.h b/kalarm/kalarmd/alarmguiiface.h
new file mode 100644
index 00000000..7e98c831
--- /dev/null
+++ b/kalarm/kalarmd/alarmguiiface.h
@@ -0,0 +1,71 @@
+/*
+ * alarmguiiface.h - DCOP interface which alarm daemon clients must implement
+ * Program: KAlarm's alarm daemon (kalarmd)
+ * Copyright © 2001,2004,2007 by David Jarvie <software@astrojar.org.uk>
+ * Based on the original, (c) 1998, 1999 Preston Brown
+ * Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org>
+ * Copyright (c) 1997-1999 Preston Brown <pbrown@kde.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef DAEMONGUIIFACE_H
+#define DAEMONGUIIFACE_H
+
+#include <dcopobject.h>
+
+namespace KAlarmd
+{
+ enum RegisterResult // result code of registerApp() DCOP call
+ {
+ FAILURE = 0,
+ SUCCESS = 1,
+ NOT_FOUND = 2 // notification type requires client start, but client executable not found
+ };
+
+ enum CalendarStatus // parameters to client notification
+ {
+ CALENDAR_ENABLED, // calendar is now being monitored
+ CALENDAR_DISABLED, // calendar is available but not being monitored
+ CALENDAR_UNAVAILABLE // calendar is unavailable for monitoring
+ };
+}
+
+/*=============================================================================
+= Class: AlarmGuiIface
+= Client applications should inherit from this class to receive notifications
+* from the alarm daemon.
+=============================================================================*/
+class AlarmGuiIface : virtual public DCOPObject
+{
+ K_DCOP
+ k_dcop:
+ /** Called to notify a change in status of the calendar.
+ @param calendarStatus new calendar status. Value is of type CalendarStatus.
+ */
+ virtual ASYNC alarmDaemonUpdate(int calendarStatus, const QString& calendarURL) = 0;
+
+ /** Called to notify that an alarm is due.
+ */
+ virtual ASYNC handleEvent(const QString& calendarURL, const QString& eventID) = 0;
+
+ /** Called to indicate success/failure of (re)register() call.
+ @param result success/failure code. Value is of type RegisterResult.
+ @param version kalarmd version, e.g. 50101 indicates 5.1.1.
+ */
+ virtual ASYNC registered(bool reregister, int result, int version) = 0;
+};
+
+#endif
diff --git a/kalarm/kalarmd/clientinfo.cpp b/kalarm/kalarmd/clientinfo.cpp
new file mode 100644
index 00000000..21889082
--- /dev/null
+++ b/kalarm/kalarmd/clientinfo.cpp
@@ -0,0 +1,110 @@
+/*
+ * clientinfo.cpp - client application information
+ * Program: KAlarm's alarm daemon (kalarmd)
+ * Copyright (C) 2001, 2004 by David Jarvie <software@astrojar.org.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "adcalendar.h"
+#include "clientinfo.h"
+
+QMap<QCString, ClientInfo*> ClientInfo::mClients;
+
+
+ClientInfo::ClientInfo(const QCString& appName, const QString& title,
+ const QCString& dcopObj, const QString& calendar, bool startClient)
+ : mAppName(appName),
+ mTitle(title),
+ mDcopObject(dcopObj),
+ mCalendar(new ADCalendar(calendar, appName)),
+ mStartClient(startClient)
+{
+ mClients[mAppName] = this;
+}
+
+ClientInfo::ClientInfo(const QCString& appName, const QString& title,
+ const QCString& dcopObj, ADCalendar* calendar, bool startClient)
+ : mAppName(appName),
+ mTitle(title),
+ mDcopObject(dcopObj),
+ mCalendar(calendar),
+ mStartClient(startClient)
+{
+ mClients[mAppName] = this;
+}
+
+ClientInfo::~ClientInfo()
+{
+ delete mCalendar;
+ mClients.remove(mAppName);
+}
+
+/******************************************************************************
+* Set a new calendar for the specified client application.
+*/
+ADCalendar* ClientInfo::setCalendar(const QString& url)
+{
+ if (url != mCalendar->urlString())
+ {
+ delete mCalendar;
+ mCalendar = new ADCalendar(url, mAppName);
+ }
+ return mCalendar;
+}
+
+/******************************************************************************
+* Return the ClientInfo object for the specified client application.
+*/
+ClientInfo* ClientInfo::get(const QCString& appName)
+{
+ if (appName.isEmpty())
+ return 0;
+ QMap<QCString, ClientInfo*>::ConstIterator it = mClients.find(appName);
+ if (it == mClients.end())
+ return 0;
+ return it.data();
+}
+
+/******************************************************************************
+* Return the ClientInfo object for client which owns the specified calendar.
+*/
+ClientInfo* ClientInfo::get(const ADCalendar* cal)
+{
+ for (ClientInfo::ConstIterator it = ClientInfo::begin(); it != ClientInfo::end(); ++it)
+ if (it.data()->calendar() == cal)
+ return it.data();
+ return 0;
+}
+
+/******************************************************************************
+* Delete all clients.
+*/
+void ClientInfo::clear()
+{
+ QMap<QCString, ClientInfo*>::Iterator it;
+ while ((it = mClients.begin()) != mClients.end())
+ delete it.data();
+}
+
+/******************************************************************************
+* Delete the client with the specified name.
+*/
+void ClientInfo::remove(const QCString& appName)
+{
+ QMap<QCString, ClientInfo*>::Iterator it = mClients.find(appName);
+ if (it != mClients.end())
+ delete it.data();
+}
diff --git a/kalarm/kalarmd/clientinfo.h b/kalarm/kalarmd/clientinfo.h
new file mode 100644
index 00000000..fe6491d7
--- /dev/null
+++ b/kalarm/kalarmd/clientinfo.h
@@ -0,0 +1,72 @@
+/*
+ * clientinfo.h - client application information
+ * Program: KAlarm's alarm daemon (kalarmd)
+ * Copyright (C) 2001, 2004 by David Jarvie <software@astrojar.org.uk>
+ * Based on the original, (c) 1998, 1999 Preston Brown
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _CALCLIENT_H
+#define _CALCLIENT_H
+
+#include <qcstring.h>
+#include <qstring.h>
+#include <qmap.h>
+
+class ADCalendar;
+
+
+/*=============================================================================
+= Class: ClientInfo
+= Details of a KAlarm client application.
+=============================================================================*/
+class ClientInfo
+{
+ public:
+ typedef QMap<QCString, ClientInfo*>::ConstIterator ConstIterator;
+
+ ClientInfo(const QCString &appName, const QString &title, const QCString &dcopObj,
+ const QString& calendar, bool startClient);
+ ClientInfo(const QCString &appName, const QString &title, const QCString &dcopObj,
+ ADCalendar* calendar, bool startClient);
+ ~ClientInfo();
+ ADCalendar* setCalendar(const QString& url);
+ void detachCalendar() { mCalendar = 0; }
+ void setStartClient(bool start) { mStartClient = start; }
+
+ QCString appName() const { return mAppName; }
+ QString title() const { return mTitle; }
+ QCString dcopObject() const { return mDcopObject; }
+ ADCalendar* calendar() const { return mCalendar; }
+ bool startClient() const { return mStartClient; }
+
+ static ConstIterator begin() { return mClients.begin(); }
+ static ConstIterator end() { return mClients.end(); }
+ static ClientInfo* get(const QCString& appName);
+ static ClientInfo* get(const ADCalendar*);
+ static void remove(const QCString& appName);
+ static void clear();
+
+ private:
+ static QMap<QCString, ClientInfo*> mClients; // list of all constructed clients
+ QCString mAppName; // client's executable and DCOP name
+ QString mTitle; // application title for display purposes
+ QCString mDcopObject; // object to receive DCOP messages
+ ADCalendar* mCalendar; // this client's event calendar
+ bool mStartClient; // whether to notify events via command line if client app isn't running
+};
+
+#endif
diff --git a/kalarm/kalarmd/kalarmd.autostart.desktop b/kalarm/kalarmd/kalarmd.autostart.desktop
new file mode 100644
index 00000000..de5add48
--- /dev/null
+++ b/kalarm/kalarmd/kalarmd.autostart.desktop
@@ -0,0 +1,103 @@
+# KDE Config File
+[Desktop Entry]
+Name=KAlarm Daemon
+Name[af]=KAlarm Bediener
+Name[bg]=Демон на KAlarm
+Name[br]=Diaoul KAlarm
+Name[ca]=Dimoni KAlarm
+Name[cs]=KAlarm démon
+Name[da]=KAlarm Dæmon
+Name[de]=KAlarm Erinnerungsprogramm
+Name[el]=Δαίμονας KAlarm
+Name[eo]=KAlarm-demono
+Name[es]=Daemon de KAlarm
+Name[et]=KAlarmi häiredeemon
+Name[eu]=KAlarm deabrua
+Name[fa]=شبح KAlarm
+Name[fi]=Hälytyspalvelin
+Name[fr]=Démon d'alarme
+Name[ga]=Deamhan KAlarm
+Name[gl]=Daemon de KAlarm
+Name[he]=תהליך הרקע תזכורות
+Name[hu]=KAlarm szolgáltatás
+Name[is]=KAlarm þjónn
+Name[it]=Demone degli avvisi
+Name[ja]=KAlarm デーモン
+Name[ka]=KAlarm დემონი
+Name[kk]=KAlarm қызметі
+Name[km]=ដេមិន KAlarm
+Name[lt]=KAlarm tarnyba
+Name[mk]=Даемон за КАларм
+Name[ms]=Daemon KAlarm
+Name[nb]=KAlarm-nisse
+Name[nds]=KAlarm-Dämoon
+Name[ne]=केडीई संसूचक डेइमन
+Name[nn]=KAlarm-nisse
+Name[pl]=Demon alarmowy
+Name[pt]=Servidor do KAlarm
+Name[pt_BR]=Servidor do KAlarm
+Name[ru]=Служба уведомлений
+Name[sk]=KAlarm démon
+Name[sl]=Demon KAlarm
+Name[sr]=Демон KAlarm-а
+Name[sr@Latn]=Demon KAlarm-a
+Name[sv]=Alarmdemon
+Name[ta]=கேஅலாரம் டெமான்
+Name[tr]=KAlarm Servis Programı
+Name[uk]=Демон KAlarm
+Name[zh_CN]=KAlarm 进程
+Name[zh_TW]=KAlarm 守護程式
+Exec=kalarmd --autostart
+Icon=kalarmd
+Type=Application
+Comment=KAlarm alarm daemon autostart at login
+Comment[af]=Begin KAlarm bediener outomaties tydens aanteken
+Comment[bg]=Автоматично стартиране на процеса на алармата KAlarm при влизане в системата
+Comment[ca]=Dimoni d'inici automàtic de l'alarma KAlarm en connectar
+Comment[cs]=Automatické spouštění alarmovacího démona při startu
+Comment[da]=KAlarm-alarmdæmon autostart ved login
+Comment[de]=Autostart des KAlarm Erinnerungsprogramms von KOrganizer bei der Anmeldung
+Comment[el]=Αυτόματη εκκίνηση του δαίμονα KAlarm κατά τη σύνδεση
+Comment[es]=Inicio automático al ingresar del daemon de alarma de KAlarm
+Comment[et]=KAlarmi häiredeemoni automaatne käivitamine
+Comment[eu]=KAlarm alarma deabrua saioa hastean automatikoki abiatzen da
+Comment[fa]=آغاز خودکار هشدار KAlarm در ورود
+Comment[fi]=KOrganizer/KAlarm-hälytyspalvelimen automaattikäynnistys sisäänkirjautuessa
+Comment[fr]=Le démon d'alarme de KOrganizer et de KAlarm démarre automatiquement lors de la connexion
+Comment[fy]=KAlarm alarmdaemon automatysk begjinne by it oanmelden
+Comment[gl]=Autoinicio á entrada do daemon de KAlarm
+Comment[he]=הפעלה אוטומטית של תהליך הרקע תזכורות של KAlarm בעת ההפעלה
+Comment[hu]=A KAlarm emlékeztető szolgáltatás automatikus elindítása
+Comment[is]=Ræsa KAlarm áminningaþjónn sjálfkrafa við byrjun setu
+Comment[it]=Avvio automatico del demone degli avvisi
+Comment[ja]=KAlarm アラームデーモンのログイン時の自動起動
+Comment[ka]=KAlarm მაღვიძარას დემონის ავტოდაწყება შესვლისას
+Comment[kk]=KAlarm қызметі жүйеге кіргенде жегіледі
+Comment[km]=ចាប់ផ្ដើម​ដេមិន​រោទ៍​របស់ KAlarm ពេល​ចូល
+Comment[lt]=KOrganizer/KAlarm priminimų tarnybos automatinis paleidimas prisiregistruojant
+Comment[mk]=Даемон за аларми од КАларм - автом. старт при најава
+Comment[ms]= Automula daemon penggera KAlarm semasa log masuk
+Comment[nb]=start alarmnisse ved innlogging
+Comment[nds]=KAlarm-Dämoon bi't Anmellen automaatsch starten
+Comment[ne]=लगइनमा केडीई संसूचक संसूचक डेइमन स्वत: सुरुआत हुन्छ
+Comment[nl]=KAlarm alarmdaemon automatisch starten bij login
+Comment[nn]=Start alarmnisse ved innlogging
+Comment[pl]=Demon alarmu KOrganizera uruchamiany przy zalogowaniu
+Comment[pt]=Servidor de alarme do KAlarm auto-iniciado no arranque
+Comment[pt_BR]=Servidor de alarmes do KAlarm inicia automaticamente no login
+Comment[ru]=Служба уведомлений KDE
+Comment[sk]=Automatické spustenie kAlarm démona pri štarte
+Comment[sl]=Samodejni zagon alarmskega strežnika KAlarma ob zagonu
+Comment[sr]=Аутоматско покретање алармног демона KAlarm-а по пријављивању
+Comment[sr@Latn]=Automatsko pokretanje alarmnog demona KAlarm-a po prijavljivanju
+Comment[sv]=Kalarm-alarmdemon, automatisk start vid inloggning
+Comment[ta]=உள்நுழையும்போது கேஅலாரம் அலாரம் டெமான் தானாகவே துவங்கும்
+Comment[tr]=KAlarm alarm servis programı (açılışta başlar)
+Comment[uk]=Автозавантаження демона нагадувань KAlarm
+Comment[zh_CN]=登录时自动启动 KAlarm 定时守护进程
+Comment[zh_TW]=登入時自動啟動 KAlarm 鬧鐘守護程式
+Terminal=false
+NoDisplay=true
+X-KDE-autostart-phase=2
+X-KDE-autostart-condition=kalarmdrc:General:Autostart:false
+X-KDE-StartupNotify=true
diff --git a/kalarm/kalarmd/kalarmd.desktop b/kalarm/kalarmd/kalarmd.desktop
new file mode 100644
index 00000000..31d3a0fa
--- /dev/null
+++ b/kalarm/kalarmd/kalarmd.desktop
@@ -0,0 +1,55 @@
+# KDE Config File
+[Desktop Entry]
+Name=KAlarm Daemon
+Name[af]=KAlarm Bediener
+Name[bg]=Демон на KAlarm
+Name[br]=Diaoul KAlarm
+Name[ca]=Dimoni KAlarm
+Name[cs]=KAlarm démon
+Name[da]=KAlarm Dæmon
+Name[de]=KAlarm Erinnerungsprogramm
+Name[el]=Δαίμονας KAlarm
+Name[eo]=KAlarm-demono
+Name[es]=Daemon de KAlarm
+Name[et]=KAlarmi häiredeemon
+Name[eu]=KAlarm deabrua
+Name[fa]=شبح KAlarm
+Name[fi]=Hälytyspalvelin
+Name[fr]=Démon d'alarme
+Name[ga]=Deamhan KAlarm
+Name[gl]=Daemon de KAlarm
+Name[he]=תהליך הרקע תזכורות
+Name[hu]=KAlarm szolgáltatás
+Name[is]=KAlarm þjónn
+Name[it]=Demone degli avvisi
+Name[ja]=KAlarm デーモン
+Name[ka]=KAlarm დემონი
+Name[kk]=KAlarm қызметі
+Name[km]=ដេមិន KAlarm
+Name[lt]=KAlarm tarnyba
+Name[mk]=Даемон за КАларм
+Name[ms]=Daemon KAlarm
+Name[nb]=KAlarm-nisse
+Name[nds]=KAlarm-Dämoon
+Name[ne]=केडीई संसूचक डेइमन
+Name[nn]=KAlarm-nisse
+Name[pl]=Demon alarmowy
+Name[pt]=Servidor do KAlarm
+Name[pt_BR]=Servidor do KAlarm
+Name[ru]=Служба уведомлений
+Name[sk]=KAlarm démon
+Name[sl]=Demon KAlarm
+Name[sr]=Демон KAlarm-а
+Name[sr@Latn]=Demon KAlarm-a
+Name[sv]=Alarmdemon
+Name[ta]=கேஅலாரம் டெமான்
+Name[tr]=KAlarm Servis Programı
+Name[uk]=Демон KAlarm
+Name[zh_CN]=KAlarm 进程
+Name[zh_TW]=KAlarm 守護程式
+Exec=kalarmd
+Icon=kalarmd
+Type=Application
+Terminal=false
+X-DCOP-ServiceType=Unique
+NoDisplay=true
diff --git a/kalarm/kalarmd/kalarmd.h b/kalarm/kalarmd/kalarmd.h
new file mode 100644
index 00000000..5e45243b
--- /dev/null
+++ b/kalarm/kalarmd/kalarmd.h
@@ -0,0 +1,40 @@
+/*
+ * kalarmd.h - global header file
+ * Program: KAlarm's alarm daemon (kalarmd)
+ * Copyright © 2004,2005,2007 by David Jarvie <software@astrojar.org.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef KALARMD_H
+#define KALARMD_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define DAEMON_VERSION "4.3" // kalarmd version number string
+#define DAEMON_VERSION_NUM 40300 // kalarmd version number integer
+#define DAEMON_APP_NAME "kalarmd" // DCOP name of alarm daemon application
+#define DAEMON_DCOP_OBJECT "ad" // DCOP name of kalarmd's DCOP interface
+
+#define DAEMON_CHECK_INTERVAL 60 // the daemon checks calendar files every minute
+
+#define DAEMON_AUTOSTART_SECTION "General" // daemon's config file section for autostart-at-login
+#define DAEMON_AUTOSTART_KEY "Autostart" // daemon's config file entry for autostart-at-login
+
+#define AUTOSTART_KALARM // fix for KAlarm autostart before session restoration
+
+#endif // KALARMD_H