26 #include <tqtextstream.h>
30 #include <tdelocale.h>
31 #include <tdemessagebox.h>
32 #include <kstandarddirs.h>
33 #include <kstaticdeleter.h>
34 #include <tdeconfig.h>
35 #include <tdeaboutdata.h>
36 #include <tdeio/netaccess.h>
37 #include <tdefileitem.h>
38 #include <tdetempfile.h>
39 #include <tdefiledialog.h>
40 #include <dcopclient.h>
44 #include <libical/ical.h>
47 #include <libkcal/vcaldrag.h>
48 #include <libkcal/vcalformat.h>
49 #include <libkcal/icalformat.h>
51 #include "calendarcompat.h"
56 #include "preferences.h"
57 #include "startdaytimer.h"
58 #include "alarmcalendar.moc"
62 TQString AlarmCalendar::icalProductId()
64 return TQString::fromLatin1(
"-//K Desktop Environment//NONSGML " KALARM_NAME
" %1//EN").arg(KAlarm::currentCalendarVersionString());
68 KAEvent::ACTIVE, KAEvent::EXPIRED, KAEvent::DISPLAYING, KAEvent::TEMPLATE
70 static const TQString calendarNames[AlarmCalendar::NCALS] = {
71 TQString::fromLatin1(
"calendar.ics"),
72 TQString::fromLatin1(
"expired.ics"),
73 TQString::fromLatin1(
"displaying.ics"),
74 TQString::fromLatin1(
"template.ics")
76 static KStaticDeleter<AlarmCalendar> calendarDeleter[AlarmCalendar::NCALS];
78 AlarmCalendar* AlarmCalendar::mCalendars[NCALS] = { 0, 0, 0, 0 };
91 bool AlarmCalendar::initialiseCalendars()
93 TDEConfig* config = kapp->config();
94 config->setGroup(TQString::fromLatin1(
"General"));
95 TQString activeKey = TQString::fromLatin1(
"Calendar");
96 TQString expiredKey = TQString::fromLatin1(
"ExpiredCalendar");
97 TQString templateKey = TQString::fromLatin1(
"TemplateCalendar");
98 TQString displayCal, activeCal, expiredCal, templateCal;
99 calendarDeleter[ACTIVE].setObject(mCalendars[ACTIVE], createCalendar(ACTIVE, config, activeCal, activeKey));
100 calendarDeleter[EXPIRED].setObject(mCalendars[EXPIRED], createCalendar(EXPIRED, config, expiredCal, expiredKey));
101 calendarDeleter[DISPLAY].setObject(mCalendars[DISPLAY], createCalendar(DISPLAY, config, displayCal));
102 calendarDeleter[TEMPLATE].setObject(mCalendars[TEMPLATE], createCalendar(TEMPLATE, config, templateCal, templateKey));
104 TQString errorKey1, errorKey2;
105 if (activeCal == displayCal)
106 errorKey1 = activeKey;
107 else if (expiredCal == displayCal)
108 errorKey1 = expiredKey;
109 else if (templateCal == displayCal)
110 errorKey1 = templateKey;
111 if (!errorKey1.isNull())
113 kdError(5950) <<
"AlarmCalendar::initialiseCalendars(): '" << errorKey1 <<
"' calendar name = display calendar name\n";
114 TQString file = config->readPathEntry(errorKey1);
115 KAlarmApp::displayFatalError(i18n(
"%1: file name not permitted: %2").arg(errorKey1).arg(file));
118 if (activeCal == expiredCal)
120 errorKey1 = activeKey;
121 errorKey2 = expiredKey;
123 else if (activeCal == templateCal)
125 errorKey1 = activeKey;
126 errorKey2 = templateKey;
128 else if (expiredCal == templateCal)
130 errorKey1 = expiredKey;
131 errorKey2 = templateKey;
133 if (!errorKey1.isNull())
135 kdError(5950) <<
"AlarmCalendar::initialiseCalendars(): calendar names clash: " << errorKey1 <<
", " << errorKey2 << endl;
136 KAlarmApp::displayFatalError(i18n(
"%1, %2: file names must be different").arg(errorKey1).arg(errorKey2));
139 if (!mCalendars[ACTIVE]->valid())
141 TQString path = mCalendars[ACTIVE]->path();
142 kdError(5950) <<
"AlarmCalendar::initialiseCalendars(): invalid name: " << path << endl;
143 KAlarmApp::displayFatalError(i18n(
"Invalid calendar file name: %1").arg(path));
153 AlarmCalendar* AlarmCalendar::createCalendar(CalID type, TDEConfig* config, TQString& writePath,
const TQString& configKey)
155 static TQRegExp vcsRegExp(TQString::fromLatin1(
"\\.vcs$"));
156 static TQString ical = TQString::fromLatin1(
".ics");
158 if (configKey.isNull())
160 writePath = locateLocal(
"appdata", calendarNames[type]);
165 TQString readPath = config->readPathEntry(configKey, locateLocal(
"appdata", calendarNames[type]));
166 writePath = readPath;
167 writePath.replace(vcsRegExp, ical);
168 return new AlarmCalendar(readPath, type, writePath, configKey);
175 void AlarmCalendar::terminateCalendars()
177 for (
int i = 0; i < NCALS; ++i)
179 calendarDeleter[i].destructObject();
192 if (!cal->mPurgeDays)
196 kdError(5950) <<
"AlarmCalendar::calendarOpen(" << calendarNames[id] <<
"): open error\n";
204 const KCal::Event* AlarmCalendar::getEvent(
const TQString& uniqueID)
206 if (uniqueID.isEmpty())
209 switch (KAEvent::uidStatus(uniqueID))
211 case KAEvent::ACTIVE: calID = ACTIVE;
break;
212 case KAEvent::TEMPLATE: calID = TEMPLATE;
break;
213 case KAEvent::EXPIRED: calID = EXPIRED;
break;
214 case KAEvent::DISPLAYING: calID = DISPLAY;
break;
221 return cal->event(uniqueID);
231 AlarmCalendar::AlarmCalendar(
const TQString& path, CalID type,
const TQString& icalPath,
232 const TQString& configKey)
234 mConfigKey(icalPath.isNull() ? TQString() : configKey),
235 mType(eventTypes[type]),
238 mPurgeDaysQueued(-1),
243 mICalUrl.setPath(icalPath.isNull() ? path : icalPath);
244 mVCal = (icalPath.isNull() || path != icalPath);
247 AlarmCalendar::~AlarmCalendar()
255 bool AlarmCalendar::open()
262 kdDebug(5950) <<
"AlarmCalendar::open(" << mUrl.prettyURL() <<
")\n";
269 if (!TDEIO::NetAccess::exists(mUrl,
true, MainWindow::mainMainWindow()))
296 bool AlarmCalendar::create()
298 if (mICalUrl.isLocalFile())
299 return saveCal(mICalUrl.path());
303 return saveCal(tmpFile.name());
314 int AlarmCalendar::load()
319 kdDebug(5950) <<
"AlarmCalendar::load(): " << mUrl.prettyURL() << endl;
321 if (!TDEIO::NetAccess::download(mUrl, tmpFile, MainWindow::mainMainWindow()))
323 kdError(5950) <<
"AlarmCalendar::load(): Load failure" << endl;
324 KMessageBox::error(0, i18n(
"Cannot open calendar:\n%1").arg(mUrl.prettyURL()));
327 kdDebug(5950) <<
"AlarmCalendar::load(): --- Downloaded to " << tmpFile << endl;
329 bool loaded = mCalendar->
load(tmpFile);
334 TDEIO::NetAccess::removeTempFile(tmpFile);
336 TDEIO::NetAccess::stat(mUrl, uds, MainWindow::mainMainWindow());
337 KFileItem fi(uds, mUrl);
340 kdError(5950) <<
"AlarmCalendar::load(): Error loading calendar file '" << tmpFile <<
"'" << endl;
341 KMessageBox::error(0, i18n(
"Error loading calendar:\n%1\n\nPlease fix or delete the file.").arg(mUrl.prettyURL()));
348 if (!mLocalFile.isEmpty())
349 TDEIO::NetAccess::removeTempFile(mLocalFile);
350 mLocalFile = tmpFile;
352 CalendarCompat::fix(*mCalendar, mLocalFile);
360 bool AlarmCalendar::reload()
364 kdDebug(5950) <<
"AlarmCalendar::reload(): " << mUrl.prettyURL() << endl;
366 bool result = open();
374 bool AlarmCalendar::saveCal(
const TQString& newFile)
376 if (!mCalendar || (!mOpen && newFile.isNull()))
379 kdDebug(5950) <<
"AlarmCalendar::saveCal(\"" << newFile <<
"\", " << mType <<
")\n";
380 TQString saveFilename = newFile.isNull() ? mLocalFile : newFile;
381 if (mVCal && newFile.isNull() && mUrl.isLocalFile())
382 saveFilename = mICalUrl.path();
385 kdError(5950) <<
"AlarmCalendar::saveCal(" << saveFilename <<
"): failed.\n";
386 KMessageBox::error(0, i18n(
"Failed to save calendar to\n'%1'").arg(mICalUrl.prettyURL()));
390 if (!mICalUrl.isLocalFile())
392 if (!TDEIO::NetAccess::upload(saveFilename, mICalUrl, MainWindow::mainMainWindow()))
394 kdError(5950) <<
"AlarmCalendar::saveCal(" << saveFilename <<
"): upload failed.\n";
395 KMessageBox::error(0, i18n(
"Cannot upload calendar to\n'%1'").arg(mICalUrl.prettyURL()));
404 if (!mConfigKey.isNull())
406 TDEConfig* config = kapp->config();
407 config->setGroup(TQString::fromLatin1(
"General"));
408 config->writePathEntry(mConfigKey, mICalUrl.path());
416 emit calendarSaved(
this);
423 void AlarmCalendar::close()
425 if (!mLocalFile.isEmpty())
427 TDEIO::NetAccess::removeTempFile(mLocalFile);
446 bool AlarmCalendar::importAlarms(TQWidget* parent)
448 KURL url = KFileDialog::getOpenURL(TQString::fromLatin1(
":importalarms"),
449 TQString::fromLatin1(
"*.vcs *.ics|%1").arg(i18n(
"Calendar Files")), parent);
452 kdError(5950) <<
"AlarmCalendar::importAlarms(): Empty URL" << endl;
457 kdDebug(5950) <<
"AlarmCalendar::importAlarms(): Invalid URL" << endl;
460 kdDebug(5950) <<
"AlarmCalendar::importAlarms(" << url.prettyURL() <<
")" << endl;
464 bool local = url.isLocalFile();
467 filename = url.path();
468 if (!TDEStandardDirs::exists(filename))
470 kdDebug(5950) <<
"AlarmCalendar::importAlarms(): File '" << url.prettyURL() <<
"' not found" << endl;
471 KMessageBox::error(parent, i18n(
"Could not load calendar '%1'.").arg(url.prettyURL()));
477 if (!TDEIO::NetAccess::download(url, filename, MainWindow::mainMainWindow()))
479 kdError(5950) <<
"AlarmCalendar::importAlarms(): Download failure" << endl;
480 KMessageBox::error(parent, i18n(
"Cannot download calendar:\n%1").arg(url.prettyURL()));
483 kdDebug(5950) <<
"--- Downloaded to " << filename << endl;
489 success = cal.load(filename);
492 kdDebug(5950) <<
"AlarmCalendar::importAlarms(): error loading calendar '" << filename <<
"'" << endl;
493 KMessageBox::error(parent, i18n(
"Could not load calendar '%1'.").arg(url.prettyURL()));
497 CalendarCompat::fix(cal, filename);
498 bool saveActive =
false;
499 bool saveExpired =
false;
500 bool saveTemplate =
false;
505 Event::List events = cal.rawEvents();
506 for (Event::List::ConstIterator it = events.begin(); it != events.end(); ++it)
508 const Event*
event = *it;
514 case KAEvent::ACTIVE:
518 case KAEvent::EXPIRED:
522 case KAEvent::TEMPLATE:
524 templat = templateCalendarOpen();
538 if (type == KAEvent::ACTIVE && !newev->
summary().isEmpty())
540 const Alarm::List& alarms = newev->
alarms();
541 for (Alarm::List::ConstIterator ait = alarms.begin(); ait != alarms.end(); ++ait)
544 if (alarm->
type() == Alarm::Display && alarm->
text().isEmpty())
550 newev->
setUid(KAEvent::uid(CalFormat::createUniqueId(), type));
551 if (!acal->mCalendar->
addEvent(newev))
564 TDEIO::NetAccess::removeTempFile(filename);
572 void AlarmCalendar::startUpdate()
581 bool AlarmCalendar::endUpdate()
583 if (mUpdateCount > 0)
596 bool AlarmCalendar::save()
612 void AlarmCalendar::convertToICal()
616 if (!mConfigKey.isNull())
618 TDEConfig* config = kapp->config();
619 config->setGroup(TQString::fromLatin1(
"General"));
620 config->writePathEntry(mConfigKey, mICalUrl.path());
633 void AlarmCalendar::setPurgeDays(
int days)
635 if (days != mPurgeDays)
637 int oldDays = mPurgeDays;
641 if (oldDays < 0 || (days >= 0 && days < oldDays))
647 else if (mPurgeDays > 0)
656 void AlarmCalendar::slotPurge()
666 void AlarmCalendar::purge(
int daysToKeep)
668 if (mPurgeDaysQueued < 0 || daysToKeep < mPurgeDaysQueued)
669 mPurgeDaysQueued = daysToKeep;
672 theApp()->processQueue();
683 void AlarmCalendar::purgeIfQueued()
685 if (mPurgeDaysQueued >= 0)
689 kdDebug(5950) <<
"AlarmCalendar::purgeIfQueued(" << mPurgeDaysQueued <<
")\n";
690 bool changed =
false;
691 TQDate cutoff = TQDate::currentDate().addDays(-mPurgeDaysQueued);
692 Event::List events = mCalendar->
rawEvents();
693 for (Event::List::ConstIterator it = events.begin(); it != events.end(); ++it)
695 Event* kcalEvent = *it;
696 if (!mPurgeDaysQueued || kcalEvent->
created().date() < cutoff)
707 mPurgeDaysQueued = -1;
717 void AlarmCalendar::startPurgeTimer()
730 Event* AlarmCalendar::addEvent(
KAEvent& event,
bool useEventID)
734 TQString
id =
event.id();
736 if (mType == KAEvent::ACTIVE)
741 event.setEventID(kcalEvent->
uid());
746 id = kcalEvent->
uid();
751 id = KAEvent::uid(
id, mType);
752 event.setEventID(
id);
755 event.updateKCalEvent(*kcalEvent,
false, (mType == KAEvent::EXPIRED),
true);
757 event.clearUpdated();
765 void AlarmCalendar::updateEvent(
const KAEvent& evnt)
769 Event* kcalEvent = event(evnt.id());
772 evnt.updateKCalEvent(*kcalEvent);
774 if (mType == KAEvent::ACTIVE)
775 Daemon::savingEvent(evnt.id());
779 if (mType == KAEvent::ACTIVE)
780 Daemon::eventHandled(evnt.id(),
false);
787 bool AlarmCalendar::deleteEvent(
const TQString& eventID,
bool saveit)
791 Event* kcalEvent = event(eventID);
795 if (mType == KAEvent::ACTIVE)
796 Daemon::savingEvent(eventID);
802 if (mType == KAEvent::ACTIVE)
803 Daemon::eventHandled(eventID,
false);
810 void AlarmCalendar::emitEmptyStatus()
812 emit emptyStatus(events().isEmpty());
818 KCal::Event* AlarmCalendar::event(
const TQString& uniqueID)
820 return mCalendar ? mCalendar->
event(uniqueID) : 0;
826 KCal::Event::List AlarmCalendar::events()
829 return KCal::Event::List();
830 KCal::Event::List list = mCalendar->
rawEvents();
831 KCal::Event::List::Iterator it = list.begin();
832 while (it != list.end())
835 if (event->alarms().isEmpty() || !
KAEvent(*event).valid())
836 it = list.remove(it);
846 Event::List AlarmCalendar::eventsWithAlarms(
const TQDateTime& from,
const TQDateTime& to)
848 kdDebug(5950) <<
"AlarmCalendar::eventsWithAlarms(" << from.toString() <<
" - " << to.toString() <<
")\n";
851 Event::List allEvents = events();
852 for (Event::List::ConstIterator it = allEvents.begin(); it != allEvents.end(); ++it)
857 bool endOffsetValid =
false;
858 const Alarm::List& alarms = e->
alarms();
859 for (Alarm::List::ConstIterator ait = alarms.begin(); ait != alarms.end(); ++ait)
881 endOffsetValid =
true;
886 TQDateTime pre = from.addSecs(-offset - 1);
887 if (e->
doesFloat() && pre.time() < Preferences::startOfDay())
888 pre = pre.addDays(-1);
892 dt = dt.addSecs(offset);
897 if (dt >= from && dt <= to)
899 kdDebug(5950) <<
"AlarmCalendar::events() '" << e->
summary()
900 <<
"': " << dt.toString() << endl;
Provides read and write access to calendar files.
KAEvent corresponds to a KCal::Event instance.
Status
The category of an event, indicated by the middle part of its UID.
bool hasStartOffset() const
Duration endOffset() const
bool hasEndOffset() const
Duration startOffset() const
void setText(const TQString &text)
Event::List rawEvents(EventSortField sortField=EventSortUnsorted, SortDirection sortDirection=SortDirectionAscending)
bool deleteEvent(Event *event)
bool addEvent(Event *event)
Event * event(const TQString &uid)
bool load(const TQString &fileName, CalFormat *format=0)
bool save(const TQString &fileName, CalFormat *format=0)
void setTimeZoneId(const TQString &timeZoneId)
virtual TQDateTime dtEnd() const
void setUid(const TQString &)
virtual TQDateTime dtStart() const
const Alarm::List & alarms() const
void setSummary(const TQString &summary)
TQDateTime created() const
Recurrence * recurrence() const
TQDateTime getNextDateTime(const TQDateTime &preDateTime) const
static void disconnect(TQObject *receiver, const char *member=0)
Disconnect from the timer signal.
static void connect(TQObject *receiver, const char *member)
Connect to the timer signal.
the KAlarm application object